Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r59381 - in sandbox/geometry/boost: . geometry geometry/algorithms geometry/algorithms/detail geometry/algorithms/detail/overlay geometry/algorithms/detail/sections geometry/algorithms/overlay geometry/arithmetic geometry/core geometry/extensions geometry/extensions/gis geometry/extensions/gis/geographic geometry/extensions/gis/geographic/detail geometry/extensions/gis/geographic/strategies geometry/extensions/gis/io geometry/extensions/gis/io/wkb geometry/extensions/gis/io/wkb/detail geometry/extensions/gis/io/wkt geometry/extensions/gis/io/wkt/detail geometry/extensions/io geometry/extensions/io/svg geometry/geometries geometry/geometries/adapted geometry/geometries/concepts geometry/geometries/concepts/detail geometry/geometries/register geometry/iterators geometry/multi geometry/multi/algorithms geometry/multi/algorithms/detail geometry/multi/algorithms/detail/sections geometry/multi/algorithms/overlay geometry/multi/core geometry/multi/geometries geometry/multi/geometries/adapted geometry/multi/geometries/concepts geometry/multi/iterators geometry/multi/strategies geometry/multi/strategies/cartesian geometry/multi/util geometry/policies geometry/policies/relate geometry/strategies geometry/strategies/agnostic geometry/strategies/cartesian geometry/strategies/concepts geometry/strategies/spherical geometry/strategies/transform geometry/util
From: barend.gehrels_at_[hidden]
Date: 2010-01-31 16:11:34


Author: barendgehrels
Date: 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
New Revision: 59381
URL: http://svn.boost.org/trac/boost/changeset/59381

Log:
First update after acceptance, renamed to Boost.Geometry, revised intersections, plus more changes
Added:
   sandbox/geometry/boost/
   sandbox/geometry/boost/geometry/
   sandbox/geometry/boost/geometry/algorithms/
   sandbox/geometry/boost/geometry/algorithms/append.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/area.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/assign.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/centroid.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/clear.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/combine.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/convert.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/convex_hull.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/correct.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/detail/
   sandbox/geometry/boost/geometry/algorithms/detail/calculate_null.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/detail/calculate_sum.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/detail/disjoint.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/detail/not.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/detail/overlay/
   sandbox/geometry/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/detail/overlay/get_relative_order.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/detail/overlay/ring_properties.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/detail/overlay/traversal_info.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/detail/overlay/turn_info.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/detail/overlay/visit_info.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/detail/point_on_border.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/detail/ring_identifier.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/detail/sections/
   sandbox/geometry/boost/geometry/algorithms/detail/sections/get_full_section.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/disjoint.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/distance.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/envelope.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/equals.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/for_each.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/get_section.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/intersection.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/intersects.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/length.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/make.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/num_points.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/overlaps.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/overlay/
   sandbox/geometry/boost/geometry/algorithms/overlay/assemble.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/overlay/clip_linestring.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/overlay/copy_segment_point.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/overlay/copy_segments.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/overlay/enrich_intersection_points.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/overlay/get_intersection_points.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/overlay/get_turns.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/overlay/intersection_point.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/overlay/msm_state.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/overlay/segment_identifier.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/overlay/self_intersection_points.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/overlay/self_turn_points.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/overlay/traverse.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/parse.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/perimeter.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/sectionalize.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/simplify.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/transform.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/union.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/unique.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/algorithms/within.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/arithmetic/
   sandbox/geometry/boost/geometry/arithmetic/arithmetic.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/arithmetic/cross_product.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/arithmetic/dot_product.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/
   sandbox/geometry/boost/geometry/core/access.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/coordinate_dimension.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/coordinate_system.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/coordinate_type.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/cs.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/exception.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/exterior_ring.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/geometry_id.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/interior_rings.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/is_linear.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/is_multi.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/point_order.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/point_type.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/radian_access.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/replace_point_type.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/reverse_dispatch.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/ring_type.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/tag.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/tags.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/core/topological_dimension.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/
   sandbox/geometry/boost/geometry/extensions/gis/
   sandbox/geometry/boost/geometry/extensions/gis/geographic/
   sandbox/geometry/boost/geometry/extensions/gis/geographic/detail/
   sandbox/geometry/boost/geometry/extensions/gis/geographic/detail/ellipsoid.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/
   sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/andoyer.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/area_huiller_earth.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/dms_parser.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/vincenty.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/io/
   sandbox/geometry/boost/geometry/extensions/gis/io/wkb/
   sandbox/geometry/boost/geometry/extensions/gis/io/wkb/detail/
   sandbox/geometry/boost/geometry/extensions/gis/io/wkb/detail/endian.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/io/wkb/detail/ogc.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/io/wkb/detail/parser.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/io/wkb/read_wkb.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/io/wkb/utility.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/io/wkt/
   sandbox/geometry/boost/geometry/extensions/gis/io/wkt/detail/
   sandbox/geometry/boost/geometry/extensions/gis/io/wkt/detail/wkt.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/io/wkt/detail/wkt_multi.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/io/wkt/read_wkt.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/io/wkt/read_wkt_multi.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/io/wkt/stream_wkt.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/io/wkt/wkt.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/io/wkt/write_wkt.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/gis/io/wkt/write_wkt_multi.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/io/
   sandbox/geometry/boost/geometry/extensions/io/svg/
   sandbox/geometry/boost/geometry/extensions/io/svg/write_svg.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/extensions/io/svg/write_svg_multi.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/
   sandbox/geometry/boost/geometry/geometries/adapted/
   sandbox/geometry/boost/geometry/geometries/adapted/boost_array_as_linestring.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/adapted/boost_array_as_ring.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/adapted/c_array.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/adapted/c_array_as_linestring.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/adapted/c_array_as_ring.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/adapted/c_array_cartesian.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/adapted/std_as_linestring.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/adapted/std_as_ring.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/adapted/std_pair_as_segment.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/adapted/tuple.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/adapted/tuple_cartesian.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/box.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/cartesian2d.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/cartesian3d.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/concepts/
   sandbox/geometry/boost/geometry/geometries/concepts/box_concept.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/concepts/check.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/concepts/detail/
   sandbox/geometry/boost/geometry/geometries/concepts/detail/check_append.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/concepts/detail/check_clear.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/concepts/linestring_concept.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/concepts/point_concept.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/concepts/polygon_concept.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/concepts/ring_concept.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/concepts/segment_concept.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/geometries.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/linear_ring.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/linestring.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/point.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/point_xy.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/polygon.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/register/
   sandbox/geometry/boost/geometry/geometries/register/box.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/register/linestring.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/register/point.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/register/ring.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/register/segment.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometries/segment.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/geometry.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/iterators/
   sandbox/geometry/boost/geometry/iterators/base.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/iterators/circular_iterator.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/iterators/ever_circling_iterator.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/iterators/range_type.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/iterators/segment_iterator.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/
   sandbox/geometry/boost/geometry/multi/algorithms/
   sandbox/geometry/boost/geometry/multi/algorithms/area.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/centroid.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/convex_hull.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/correct.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/detail/
   sandbox/geometry/boost/geometry/multi/algorithms/detail/modify_with_predicate.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/detail/multi_sum.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/detail/point_on_border.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/detail/sections/
   sandbox/geometry/boost/geometry/multi/algorithms/detail/sections/get_full_section.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/distance.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/envelope.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/equals.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/for_each.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/get_section.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/intersection.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/length.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/num_points.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/overlay/
   sandbox/geometry/boost/geometry/multi/algorithms/overlay/assemble.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/overlay/copy_segment_point.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/overlay/copy_segments.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/overlay/get_intersection_points.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/overlay/get_turns.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/perimeter.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/sectionalize.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/simplify.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/transform.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/union.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/algorithms/within.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/core/
   sandbox/geometry/boost/geometry/multi/core/geometry_id.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/core/is_multi.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/core/point_type.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/core/ring_type.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/core/tags.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/core/topological_dimension.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/geometries/
   sandbox/geometry/boost/geometry/multi/geometries/adapted/
   sandbox/geometry/boost/geometry/multi/geometries/adapted/boost_array_as_multi_point.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/geometries/adapted/c_array_as_multi_point.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/geometries/adapted/std_as_multi_point.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/geometries/concepts/
   sandbox/geometry/boost/geometry/multi/geometries/concepts/check.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/geometries/concepts/multi_linestring_concept.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/geometries/concepts/multi_point_concept.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/geometries/concepts/multi_polygon_concept.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/geometries/multi_linestring.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/geometries/multi_point.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/geometries/multi_polygon.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/iterators/
   sandbox/geometry/boost/geometry/multi/iterators/range_type.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/multi.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/strategies/
   sandbox/geometry/boost/geometry/multi/strategies/cartesian/
   sandbox/geometry/boost/geometry/multi/strategies/cartesian/centroid_average.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/strategies/centroid.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/util/
   sandbox/geometry/boost/geometry/multi/util/for_each_range.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/multi/util/write_dsv.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/policies/
   sandbox/geometry/boost/geometry/policies/compare.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/policies/relate/
   sandbox/geometry/boost/geometry/policies/relate/direction.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/policies/relate/intersection_points.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/policies/relate/intersection_points_determinant.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/policies/relate/intersection_points_slope.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/policies/relate/tupled.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/
   sandbox/geometry/boost/geometry/strategies/agnostic/
   sandbox/geometry/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/area.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/area_result.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/cartesian/
   sandbox/geometry/boost/geometry/strategies/cartesian/area_by_triangles.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/cartesian/cart_intersect.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/cartesian/distance_projected_point.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/cartesian/distance_pythagoras.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/cartesian/side_by_triangle.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/centroid.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/compare.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/concepts/
   sandbox/geometry/boost/geometry/strategies/concepts/area_concept.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/concepts/centroid_concept.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/concepts/convex_hull_concept.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/concepts/distance_concept.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/concepts/segment_intersect_concept.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/concepts/simplify_concept.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/concepts/within_concept.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/convex_hull.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/distance.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/distance_result.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/intersection.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/intersection_result.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/length_result.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/parse.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/point_in_poly.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/side.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/side_info.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/spherical/
   sandbox/geometry/boost/geometry/strategies/spherical/area_huiller.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/spherical/compare_circular.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/spherical/distance_cross_track.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/spherical/distance_haversine.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/spherical/side_by_cross_track.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/strategies.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/strategy_transform.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/tags.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/transform/
   sandbox/geometry/boost/geometry/strategies/transform.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/transform/inverse_transformer.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/transform/map_transformer.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/strategies/transform/matrix_transformers.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/util/
   sandbox/geometry/boost/geometry/util/add_const_if_c.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/util/as_range.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/util/copy.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/util/for_each_coordinate.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/util/for_each_range.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/util/math.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/util/range_iterator_const_if_c.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/util/select_calculation_type.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/util/select_coordinate_type.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/util/select_most_precise.hpp (contents, props changed)
   sandbox/geometry/boost/geometry/util/write_dsv.hpp (contents, props changed)

Added: sandbox/geometry/boost/geometry/algorithms/append.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/append.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,189 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/util/copy.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace append {
+
+template <typename Geometry, typename Point, bool UseStd>
+struct append_point {};
+
+template <typename Geometry, typename Point>
+struct append_point<Geometry, Point, true>
+{
+ static inline void apply(Geometry& geometry, Point const& point, int , int )
+ {
+ typename point_type<Geometry>::type point_type;
+
+ copy_coordinates(point, point_type);
+ geometry.push_back(point_type);
+ }
+};
+
+template <typename Geometry, typename Point>
+struct append_point<Geometry, Point, false>
+{
+ static inline void apply(Geometry& geometry, Point const& point,
+ int ring_index, int multi_index)
+ {
+ traits::append_point<Geometry, Point>::apply(geometry, point,
+ ring_index, multi_index);
+ }
+};
+
+template <typename Geometry, typename Range, bool UseStd>
+struct append_range
+{
+ typedef typename boost::range_value<Range>::type point_type;
+
+ static inline void apply(Geometry& geometry, Range const& range,
+ int ring_index, int multi_index)
+ {
+ for (typename boost::range_const_iterator<Range>::type
+ it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ append_point<Geometry, point_type, UseStd>::apply(geometry, *it,
+ ring_index, multi_index);
+ }
+ }
+};
+
+template <typename Polygon, typename Point, bool Std>
+struct point_to_poly
+{
+ typedef typename ring_type<Polygon>::type range_type;
+
+ static inline void apply(Polygon& polygon, Point const& point,
+ int ring_index, int )
+ {
+ if (ring_index == -1)
+ {
+ append_point<range_type, Point, Std>::apply(
+ exterior_ring(polygon), point, -1, -1);
+ }
+ else if (ring_index < int(num_interior_rings(polygon)))
+ {
+ append_point<range_type, Point, Std>::apply(
+ interior_rings(polygon)[ring_index], point, -1, -1);
+ }
+ }
+};
+
+template <typename Polygon, typename Range, bool Std>
+struct range_to_poly
+{
+ typedef typename ring_type<Polygon>::type ring_type;
+
+ static inline void apply(Polygon& polygon, Range const& range,
+ int ring_index, int )
+ {
+ if (ring_index == -1)
+ {
+ append_range<ring_type, Range, Std>::apply(
+ exterior_ring(polygon), range, -1, -1);
+ }
+ else if (ring_index < int(num_interior_rings(polygon)))
+ {
+ append_range<ring_type, Range, Std>::apply(
+ interior_rings(polygon)[ring_index], range, -1, -1);
+ }
+ }
+};
+
+}} // namespace detail::append
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// (RoP = range or point, Std = use std library)
+
+// Default case (where RoP will be range/array/etc)
+template <typename Tag, typename TagRoP, typename G, typename RoP, bool Std>
+struct append : detail::append::append_range<G, RoP, Std> {};
+
+// Append a point to any geometry
+template <typename Tag, typename G, typename P, bool Std>
+struct append<Tag, point_tag, G, P, Std>
+ : detail::append::append_point<G, P, Std> {};
+
+// Never possible to append anything to a point/box/n-sphere
+template <typename TagRoP, typename Point, typename RoP, bool Std>
+struct append<point_tag, TagRoP, Point, RoP, Std> {};
+
+template <typename TagRoP, typename Box, typename RoP, bool Std>
+struct append<box_tag, TagRoP, Box, RoP, Std> {};
+
+
+template <typename Polygon, typename TagRange, typename Range, bool Std>
+struct append<polygon_tag, TagRange, Polygon, Range, Std>
+ : detail::append::range_to_poly<Polygon, Range, Std> {};
+
+template <typename Polygon, typename Point, bool Std>
+struct append<polygon_tag, point_tag, Polygon, Point, Std>
+ : detail::append::point_to_poly<Polygon, Point, Std> {};
+
+// Multi-linestring and multi-polygon might either implement traits
+// or use standard...
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Appends one or more points to a linestring, ring, polygon, multi
+ \ingroup access
+ \param geometry a geometry
+ \param range_or_point the point or range to add
+ \param ring_index the index of the ring in case of a polygon:
+ exterior ring (-1, the default) or interior ring index
+ \param multi_index reserved for multi polygons
+ */
+template <typename Geometry, typename RoP>
+inline void append(Geometry& geometry, RoP const& range_or_point,
+ int ring_index = -1, int multi_index = 0)
+{
+ concept::check<Geometry>();
+
+ typedef typename boost::remove_const<Geometry>::type ncg_type;
+
+ dispatch::append
+ <
+ typename tag<Geometry>::type,
+ typename tag<RoP>::type,
+ ncg_type,
+ RoP,
+ traits::use_std<ncg_type>::value
+ >::apply(geometry, range_or_point, ring_index, multi_index);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP

Added: sandbox/geometry/boost/geometry/algorithms/area.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/area.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,259 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
+
+#include <boost/mpl/if.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <boost/geometry/core/point_order.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/detail/calculate_null.hpp>
+#include <boost/geometry/algorithms/detail/calculate_sum.hpp>
+
+#include <boost/geometry/strategies/area.hpp>
+#include <boost/geometry/strategies/area_result.hpp>
+
+#include <boost/geometry/strategies/concepts/area_concept.hpp>
+
+#include <boost/geometry/util/math.hpp>
+
+/*!
+\defgroup area area: calculate area of a geometry
+
+\par Performance
+2776 * 1000 area calculations are done in 0.11 seconds
+(http://trac.osgeo.org/ggl/wiki/Performance#Area1)
+
+\par Coordinate systems and strategies
+Area calculation can be done in Cartesian and in spherical/geographic
+coordinate systems.
+
+\par Geometries
+The area algorithm calculates the surface area of all geometries
+having a surface: box, 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.
+
+\par Example:
+Example showing area calculation of polygons built
+\dontinclude doxygen_1.cpp
+\skip example_area_polygon()
+\line {
+\until }
+
+*/
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace area {
+
+template<typename Box, typename Strategy>
+struct box_area
+{
+ typedef typename coordinate_type<Box>::type return_type;
+
+ static inline return_type apply(Box const& box, Strategy const&)
+ {
+ // Currently only works for 2D Cartesian boxes
+ assert_dimension<Box, 2>();
+
+ return_type const dx = get<max_corner, 0>(box)
+ - get<min_corner, 0>(box);
+ return_type const dy = get<max_corner, 1>(box)
+ - get<min_corner, 1>(box);
+
+ return dx * dy;
+ }
+};
+
+
+
+
+/*!
+ \brief Calculate area of a ring, specialized per order
+ */
+template
+<
+ typename Ring,
+ order_selector Order,
+ // closing_selector Closed -- for now assuming CLOSED, p(0) == p(n-1)
+ typename Strategy
+>
+struct ring_area
+{};
+
+
+template<typename Ring, typename Strategy>
+struct ring_area<Ring, clockwise, Strategy>
+{
+ BOOST_CONCEPT_ASSERT( (geometry::concept::AreaStrategy<Strategy>) );
+
+ typedef typename Strategy::return_type type;
+
+ static inline type apply(Ring const& ring, Strategy const& strategy)
+ {
+ assert_dimension<Ring, 2>();
+
+ // A closed linear_ring has at least four points,
+ // if not, there is no (zero) area
+ if (boost::size(ring) < 4)
+ {
+ return type();
+ }
+
+ typedef typename boost::range_const_iterator<Ring>::type iterator_type;
+
+ typename Strategy::state_type state;
+
+ iterator_type it = boost::begin(ring);
+ for (iterator_type previous = it++;
+ it != boost::end(ring);
+ previous = it++)
+ {
+ strategy.apply(*previous, *it, state);
+ }
+ return strategy.result(state);
+
+ }
+};
+
+template<typename Ring, typename Strategy>
+struct ring_area<Ring, counterclockwise, Strategy>
+{
+ typedef typename Strategy::return_type type;
+ static inline type apply(Ring const& ring, Strategy const& strategy)
+ {
+ // Counter clockwise rings negate the area result
+ return -ring_area<Ring, clockwise, Strategy>::apply(ring, strategy);
+ }
+};
+
+
+}} // namespace detail::area
+
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+template
+<
+ typename Tag,
+ typename Geometry,
+ order_selector Order,
+ typename Strategy
+>
+struct area
+ : detail::calculate_null
+ <
+ typename Strategy::return_type,
+ Geometry,
+ Strategy
+ > {};
+
+
+template <typename Geometry, order_selector Order, typename Strategy>
+struct area<box_tag, Geometry, Order, Strategy>
+ : detail::area::box_area<Geometry, Strategy>
+{};
+
+
+// Area of ring currently returns area of closed rings but it might be argued
+// that it is 0.0, because a ring is just a line.
+template <typename Geometry, order_selector Order, typename Strategy>
+struct area<ring_tag, Geometry, Order, Strategy>
+ : detail::area::ring_area<Geometry, Order, Strategy>
+{};
+
+template <typename Polygon, order_selector Order, typename Strategy>
+struct area<polygon_tag, Polygon, Order, Strategy>
+ : detail::calculate_polygon_sum
+ <
+ typename Strategy::return_type,
+ Polygon,
+ Strategy,
+ detail::area::ring_area
+ <
+ typename ring_type<Polygon>::type,
+ Order,
+ Strategy
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+/*!
+ \brief Calculate area of a geometry
+ \ingroup area
+ \details The function area returns the area of a polygon, ring, box
+ using the default area-calculation strategy. Strategies are
+ provided for cartesian and spherical coordinate systems
+ The geometries should correct, polygons should be closed
+ and according to the specified orientation (clockwise/counter clockwise)
+ \param geometry a geometry
+ \return the area
+ */
+template <typename Geometry>
+inline typename area_result<Geometry>::type area(Geometry const& geometry)
+{
+ concept::check<const Geometry>();
+
+ typedef typename area_result<Geometry>::strategy_type strategy_type;
+
+ return dispatch::area
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ geometry::point_order<Geometry>::value,
+ strategy_type
+ >::apply(geometry, strategy_type());
+}
+
+/*!
+ \brief Calculate area of a geometry using a specified strategy
+ \ingroup area
+ \details This version of area calculation takes a strategy
+ \param geometry a geometry
+ \param strategy the strategy to calculate area.
+ Especially for spherical areas there are some approaches.
+ \return the area
+ */
+template <typename Geometry, typename Strategy>
+inline typename Strategy::return_type area(
+ Geometry const& geometry, Strategy const& strategy)
+{
+ concept::check<const Geometry>();
+
+ return dispatch::area
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ geometry::point_order<Geometry>::value,
+ Strategy
+ >::apply(geometry, strategy);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_AREA_HPP

Added: sandbox/geometry/boost/geometry/algorithms/assign.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/assign.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,531 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP
+
+#include <cstddef>
+
+#include <boost/concept/requires.hpp>
+#include <boost/concept_check.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/numeric/conversion/bounds.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/algorithms/append.hpp>
+#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+
+#include <boost/geometry/util/copy.hpp>
+#include <boost/geometry/util/for_each_coordinate.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace assign {
+
+template <typename CoordinateType>
+struct assign_operation
+{
+ inline assign_operation(CoordinateType const& value)
+ : m_value(value)
+ {}
+
+ template <typename P, std::size_t I>
+ inline void apply(P& point) const
+ {
+ set<I>(point, m_value);
+ }
+
+private:
+
+ CoordinateType m_value;
+};
+
+
+/*!
+ \brief Assigns all coordinates of a specific point to a value
+ \ingroup access
+ \details
+ \param p Point
+ \param value Value which is assigned to all coordinates of point p
+ */
+template <typename Point>
+inline void assign_value(Point& p,
+ typename coordinate_type<Point>::type const& value)
+{
+ for_each_coordinate(p,
+ assign_operation<typename coordinate_type<Point>::type>(value));
+}
+
+
+
+template
+<
+ typename Box, std::size_t Index,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct initialize
+{
+ typedef typename coordinate_type<Box>::type coordinate_type;
+
+ static inline void apply(Box& box, coordinate_type const& value)
+ {
+ set<Index, Dimension>(box, value);
+ initialize<Box, Index, Dimension + 1, DimensionCount>::apply(box, value);
+ }
+};
+
+
+template <typename Box, std::size_t Index, std::size_t DimensionCount>
+struct initialize<Box, Index, DimensionCount, DimensionCount>
+{
+ typedef typename coordinate_type<Box>::type coordinate_type;
+
+ static inline void apply(Box&, coordinate_type const& )
+ {}
+};
+
+
+template <typename Point>
+struct assign_zero_point
+{
+ static inline void apply(Point& point)
+ {
+ typedef typename coordinate_type<Point>::type coordinate_type;
+ assign_value(point, 0);
+ }
+};
+
+
+template <typename Box>
+struct assign_inverse_box
+{
+ typedef typename point_type<Box>::type point_type;
+
+ static inline void apply(Box& box)
+ {
+ typedef typename coordinate_type<point_type>::type coordinate_type;
+
+ typedef typename boost::mpl::if_
+ <
+ typename boost::is_arithmetic<coordinate_type>::type,
+ coordinate_type,
+ double
+ >::type bound_type;
+
+ initialize
+ <
+ Box, min_corner, 0, dimension<Box>::type::value
+ >::apply(
+ box, boost::numeric::bounds<bound_type>::highest());
+ initialize
+ <
+ Box, max_corner, 0, dimension<Box>::type::value
+ >::apply(
+ box, boost::numeric::bounds<bound_type>::lowest());
+ }
+};
+
+
+template <typename Box>
+struct assign_zero_box
+{
+ static inline void apply(Box& box)
+ {
+ typedef typename coordinate_type<Box>::type coordinate_type;
+
+ initialize
+ <
+ Box, min_corner, 0, dimension<Box>::type::value
+ >::apply(box, coordinate_type());
+ initialize
+ <
+ Box, max_corner, 0, dimension<Box>::type::value
+ >::apply(box, coordinate_type());
+ }
+};
+
+
+template
+<
+ std::size_t Corner1, std::size_t Corner2,
+ typename Box, typename Point
+>
+inline void assign_box_2d_corner(Box const& box, Point& point)
+{
+ // Be sure both are 2-Dimensional
+ assert_dimension<Box, 2>();
+ assert_dimension<Point, 2>();
+
+ // Copy coordinates
+ typedef typename coordinate_type<Point>::type coordinate_type;
+
+ set<0>(point, boost::numeric_cast<coordinate_type>(get<Corner1, 0>(box)));
+ set<1>(point, boost::numeric_cast<coordinate_type>(get<Corner2, 1>(box)));
+}
+
+
+
+template
+<
+ typename Geometry, typename Point,
+ std::size_t Index,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct assign_point_to_index
+{
+
+ static inline void apply(Point const& point, Geometry& geometry)
+ {
+ geometry::set<Index, Dimension>(geometry, boost::numeric_cast
+ <
+ typename coordinate_type<Geometry>::type
+ >(geometry::get<Dimension>(point)));
+
+ assign_point_to_index
+ <
+ Geometry, Point, Index, Dimension + 1, DimensionCount
+ >::apply(point, geometry);
+ }
+};
+
+template
+<
+ typename Geometry, typename Point,
+ std::size_t Index,
+ std::size_t DimensionCount
+>
+struct assign_point_to_index
+ <
+ Geometry, Point,
+ Index,
+ DimensionCount, DimensionCount
+ >
+{
+ static inline void apply(Point const& , Geometry& )
+ {
+ }
+};
+
+
+template
+<
+ typename Geometry, typename Point,
+ std::size_t Index,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct assign_point_from_index
+{
+
+ static inline void apply(Geometry const& geometry, Point& point)
+ {
+ geometry::set<Dimension>( point, boost::numeric_cast
+ <
+ typename coordinate_type<Geometry>::type
+ >(geometry::get<Index, Dimension>(geometry)));
+
+ assign_point_from_index
+ <
+ Geometry, Point, Index, Dimension + 1, DimensionCount
+ >::apply(geometry, point);
+ }
+};
+
+template
+<
+ typename Geometry, typename Point,
+ std::size_t Index,
+ std::size_t DimensionCount
+>
+struct assign_point_from_index
+ <
+ Geometry, Point,
+ Index,
+ DimensionCount, DimensionCount
+ >
+{
+ static inline void apply(Geometry const&, Point&)
+ {
+ }
+};
+
+
+
+}} // namespace detail::assign
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename GeometryTag, typename Geometry, std::size_t DimensionCount>
+struct assign {};
+
+template <typename Point>
+struct assign<point_tag, Point, 2>
+{
+ typedef typename coordinate_type<Point>::type coordinate_type;
+
+ template <typename T>
+ static inline void apply(Point& point, T const& c1, T const& c2)
+ {
+ set<0>(point, boost::numeric_cast<coordinate_type>(c1));
+ set<1>(point, boost::numeric_cast<coordinate_type>(c2));
+ }
+};
+
+template <typename Point>
+struct assign<point_tag, Point, 3>
+{
+ typedef typename coordinate_type<Point>::type coordinate_type;
+
+ template <typename T>
+ static inline void apply(Point& point, T const& c1, T const& c2, T const& c3)
+ {
+ set<0>(point, boost::numeric_cast<coordinate_type>(c1));
+ set<1>(point, boost::numeric_cast<coordinate_type>(c2));
+ set<2>(point, boost::numeric_cast<coordinate_type>(c3));
+ }
+};
+
+template <typename Box>
+struct assign<box_tag, Box, 2>
+{
+ typedef typename coordinate_type<Box>::type coordinate_type;
+
+ // Here we assign 4 coordinates to a box.
+ // -> Most logical is: x1,y1,x2,y2
+ // In case the user reverses x1/x2 or y1/y2, we could reverse them (THAT IS NOT IMPLEMENTED)
+
+ // Note also comment in util/assign_box_corner ->
+ // ("Most logical is LOWER, UPPER and sub-order LEFT, RIGHT")
+ // (That is assigning 4 points from a box. So lower-left, lower-right, upper-left, upper-right)
+ template <typename T>
+ static inline void apply(Box& box,
+ T const& x1, T const& y1, T const& x2, T const& y2)
+ {
+ set<min_corner, 0>(box, boost::numeric_cast<coordinate_type>(x1));
+ set<min_corner, 1>(box, boost::numeric_cast<coordinate_type>(y1));
+ set<max_corner, 0>(box, boost::numeric_cast<coordinate_type>(x2));
+ set<max_corner, 1>(box, boost::numeric_cast<coordinate_type>(y2));
+ }
+};
+
+
+
+template <typename GeometryTag, typename Geometry>
+struct assign_zero {};
+
+
+template <typename Point>
+struct assign_zero<point_tag, Point>
+ : detail::assign::assign_zero_point<Point>
+{};
+
+template <typename Box>
+struct assign_zero<box_tag, Box>
+ : detail::assign::assign_zero_box<Box>
+{};
+
+
+template <typename GeometryTag, typename Geometry>
+struct assign_inverse {};
+
+template <typename Box>
+struct assign_inverse<box_tag, Box>
+ : detail::assign::assign_inverse_box<Box>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief assign two values to a 2D point
+ \ingroup access
+ */
+template <typename Geometry, typename Type>
+inline void assign(Geometry& geometry, Type const& c1, Type const& c2)
+{
+ concept::check<Geometry>();
+
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ geometry::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2);
+}
+
+/*!
+ \brief assign three values to a 3D point [or the center + radius to a circle]
+ \ingroup access
+ */
+template <typename Geometry, typename Type>
+inline void assign(Geometry& geometry,
+ Type const& c1, Type const& c2, Type const& c3)
+{
+ concept::check<Geometry>();
+
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ geometry::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2, c3);
+}
+
+/*!
+ \brief assign center + radius to a sphere [for extension]
+ \ingroup access
+ */
+template <typename Geometry, typename Type>
+inline void assign(Geometry& geometry,
+ Type const& c1, Type const& c2, Type const& c3, Type const& c4)
+{
+ concept::check<Geometry>();
+
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ geometry::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2, c3, c4);
+}
+
+
+/*!
+ \brief assign a range of points to a linestring, ring or polygon
+ \note The point-type of the range might be different from the point-type of the geometry
+ \ingroup access
+ */
+template <typename Geometry, typename Range>
+inline void assign(Geometry& geometry, Range const& range)
+{
+ concept::check<Geometry>();
+
+ clear(geometry);
+ geometry::append(geometry, range, -1, 0);
+}
+
+
+/*!
+ \brief assign to a box inverse infinite
+ \details The assign_inverse function initialize a 2D or 3D box with large coordinates, the
+ min corner is very large, the max corner is very small. This is a convenient starting point to
+ collect the minimum bounding box of a geometry.
+ \ingroup access
+ */
+template <typename Geometry>
+inline void assign_inverse(Geometry& geometry)
+{
+ concept::check<Geometry>();
+
+ dispatch::assign_inverse
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::apply(geometry);
+}
+
+/*!
+ \brief assign zero values to a box, point
+ \ingroup access
+ \details The assign_zero function initializes a 2D or 3D point or box with coordinates of zero
+ \tparam Geometry the geometry type
+ */
+template <typename Geometry>
+inline void assign_zero(Geometry& geometry)
+{
+ concept::check<Geometry>();
+
+ dispatch::assign_zero
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::apply(geometry);
+}
+
+
+/*!
+ \brief Assign the 4 points of a 2D box
+ \ingroup access
+ \note The order is crucial. Most logical is LOWER, UPPER and sub-order LEFT, RIGHT
+ so this is how it is implemented.
+*/
+template <typename Box, typename Point>
+inline void assign_box_corners(Box const& box,
+ Point& lower_left, Point& lower_right,
+ Point& upper_left, Point& upper_right)
+{
+ concept::check<const Box>();
+ concept::check<Point>();
+
+ detail::assign::assign_box_2d_corner
+ <min_corner, min_corner>(box, lower_left);
+ detail::assign::assign_box_2d_corner
+ <max_corner, min_corner>(box, lower_right);
+ detail::assign::assign_box_2d_corner
+ <min_corner, max_corner>(box, upper_left);
+ detail::assign::assign_box_2d_corner
+ <max_corner, max_corner>(box, upper_right);
+}
+
+
+
+/*!
+ \brief Assign a box or segment with the value of a point
+ \ingroup access
+ \tparam Index indicates which box-corner, min_corner (0) or max_corner (1)
+ or which point of segment (0/1)
+*/
+template <std::size_t Index, typename Geometry, typename Point>
+inline void assign_point_to_index(Point const& point, Geometry& geometry)
+{
+ concept::check<const Point>();
+ concept::check<Geometry>();
+
+ detail::assign::assign_point_to_index
+ <
+ Geometry, Point, Index, 0, dimension<Geometry>::type::value
+ >::apply(point, geometry);
+}
+
+
+/*!
+ \brief Assign a point with a point of a box or segment
+ \ingroup access
+ \tparam Index indicates which box-corner, min_corner (0) or max_corner (1)
+ or which point of segment (0/1)
+*/
+template <std::size_t Index, typename Point, typename Geometry>
+inline void assign_point_from_index(Geometry const& geometry, Point& point)
+{
+ concept::check<const Geometry>();
+ concept::check<Point>();
+
+ detail::assign::assign_point_from_index
+ <
+ Geometry, Point, Index, 0, dimension<Geometry>::type::value
+ >::apply(geometry, point);
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP

Added: sandbox/geometry/boost/geometry/algorithms/centroid.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/centroid.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,468 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Copyright (c) 2009 Mateusz Loskot <mateusz_at_[hidden]>
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP
+
+#include <cstddef>
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/distance.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/exception.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/iterators/segment_iterator.hpp>
+#include <boost/geometry/strategies/centroid.hpp>
+#include <boost/geometry/strategies/concepts/centroid_concept.hpp>
+#include <boost/geometry/util/copy.hpp>
+#include <boost/geometry/util/for_each_coordinate.hpp>
+
+
+/*!
+\defgroup centroid centroid: calculate centroid (center of gravity) of a geometry
+\par Source descriptions:
+- OGC description: The mathematical centroid for this Surface as a Point. The
+ result is not guaranteed to be on this Surface.
+- From Wikipedia: Informally, it is the "average" of all points
+\see http://en.wikipedia.org/wiki/Centroid
+\note Polygon should be closed, and can be orientated either way
+\note The "centroid" functions are taking a non const reference to the centroid.
+ The "make_centroid" functions return the centroid, the type has to be
+ specified.
+\note Both of them have an overloaded version where
+ a centroid calculation strategy can be specified
+\exception centroid_exception if calculation is not successful,
+ e.g. because polygon didn't contain points
+
+\par Example:
+Example showing centroid calculation
+\dontinclude doxygen_1.cpp
+\skip example_centroid_polygon
+\line {
+\until }
+
+\par Performance
+2776 * 1000 centroid calculations are done in 0.16 seconds
+(http://trac.osgeo.org/ggl/wiki/Performance#Centroid1)
+
+\par Geometries:
+- RING: \image html centroid_ring.png
+- BOX: the centroid of a 2D or 3D box is the center of the box
+- POLYGON \image html centroid_polygon.png
+- POINT: the point is the centroid
+- LINESTRING: the average of the centers of its segments
+- MULTIPOINT: the average of the points
+*/
+
+namespace boost { namespace geometry
+{
+
+class centroid_exception : public geometry::exception
+{
+public:
+
+ inline centroid_exception() {}
+
+ virtual char const* what() const throw()
+ {
+ return "GGL Centroid calculation exception";
+ }
+};
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace centroid {
+
+template<typename Point, typename PointCentroid, typename Strategy>
+struct centroid_point
+{
+ static inline void apply(Point const& point, PointCentroid& centroid,
+ Strategy const&)
+ {
+ copy_coordinates(point, centroid);
+ }
+};
+
+template
+<
+ typename Box,
+ typename Point,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct centroid_box_calculator
+{
+ typedef typename select_coordinate_type
+ <
+ Box, Point
+ >::type coordinate_type;
+ static inline void apply(Box const& box, Point& centroid)
+ {
+ coordinate_type const c1 = get<min_corner, Dimension>(box);
+ coordinate_type const c2 = get<max_corner, Dimension>(box);
+ coordinate_type m = c1 + c2;
+ m /= 2.0;
+
+ set<Dimension>(centroid, m);
+
+ centroid_box_calculator
+ <
+ Box, Point,
+ Dimension + 1, DimensionCount
+ >::apply(box, centroid);
+ }
+};
+
+template<typename Box, typename Point, std::size_t DimensionCount>
+struct centroid_box_calculator<Box, Point, DimensionCount, DimensionCount>
+{
+ static inline void apply(Box const& , Point& )
+ {
+ }
+};
+
+template<typename Box, typename Point, typename Strategy>
+struct centroid_box
+{
+ static inline void apply(Box const& box, Point& centroid,
+ Strategy const&)
+ {
+ centroid_box_calculator
+ <
+ Box, Point,
+ 0, dimension<Box>::type::value
+ >::apply(box, centroid);
+ }
+};
+
+// There is one thing where centroid is different from e.g. within.
+// If the ring has only one point, it might make sense that
+// that point is the centroid.
+template<typename Point, typename Range>
+inline bool range_ok(Range const& range, Point& centroid)
+{
+ std::size_t const n = boost::size(range);
+ if (n > 1)
+ {
+ return true;
+ }
+ else if (n <= 0)
+ {
+#if defined(CENTROID_WITH_CATCH)
+ throw centroid_exception();
+#endif
+ return false;
+ }
+ else // if (n == 1)
+ {
+ // Take over the first point in a "coordinate neutral way"
+ copy_coordinates(range.front(), centroid);
+ return false;
+ }
+ return true;
+}
+
+
+/*!
+ \brief Calculate the centroid of a ring.
+*/
+template<typename Ring, typename Strategy>
+struct centroid_ring_state
+{
+ static inline void apply(Ring const& ring,
+ Strategy const& strategy, typename Strategy::state_type& state)
+ {
+ typedef typename boost::range_const_iterator<Ring>::type iterator_type;
+ iterator_type it = boost::begin(ring);
+ for (iterator_type previous = it++;
+ it != boost::end(ring);
+ previous = it++)
+ {
+ Strategy::apply(*previous, *it, state);
+ }
+
+ /* using segment_iterator: nice, well looking, but much slower...
+ normal iterator: 0.156 s
+ segment iterator: 1.985 s...
+ typedef segment_iterator
+ <
+ typename boost::range_const_iterator<Ring>::type,
+ typename point_type<Ring>::type
+ > iterator_type;
+
+ iterator_type it(boost::begin(ring), boost::end(ring));
+ iterator_type end(boost::end(ring));
+ for(; it != end; ++it)
+ {
+ Strategy::apply(it->first, it->second, state);
+ }
+ */
+ }
+};
+
+template<typename Ring, typename Point, typename Strategy>
+struct centroid_ring
+{
+ static inline void apply(Ring const& ring, Point& centroid,
+ Strategy const& strategy)
+ {
+ if (range_ok(ring, centroid))
+ {
+ typename Strategy::state_type state;
+ centroid_ring_state
+ <
+ Ring,
+ Strategy
+ >::apply(ring, strategy, state);
+ Strategy::result(state, centroid);
+ }
+ }
+};
+
+/*!
+ \brief Centroid of a linestring.
+*/
+template<typename Linestring, typename Point, typename Strategy>
+struct centroid_linestring
+{
+ static inline void apply(Linestring const& line, Point& centroid,
+ Strategy const& strategy)
+ {
+ // First version, should
+ // - be moved to a strategy
+ // - be made dim-agnostic
+
+ typedef typename point_type<Linestring>::type point_type;
+ typedef typename boost::range_const_iterator<Linestring>::type point_iterator_type;
+ typedef segment_iterator<point_iterator_type, point_type> segment_iterator;
+
+ double length = double();
+ std::pair<double, double> average_sum;
+
+ segment_iterator it(boost::begin(line), boost::end(line));
+ segment_iterator end(boost::end(line));
+ while (it != end)
+ {
+ double const d = geometry::distance(it->first, it->second);
+ length += d;
+
+ double const mx = (get<0>(it->first) + get<0>(it->second)) / 2;
+ double const my = (get<1>(it->first) + get<1>(it->second)) / 2;
+ average_sum.first += d * mx;
+ average_sum.second += d * my;
+ ++it;
+ }
+
+ set<0>(centroid, average_sum.first / length );
+ set<1>(centroid, average_sum.second / length );
+ }
+};
+
+/*!
+ \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 Polygon, typename Strategy>
+struct centroid_polygon_state
+{
+ static inline void apply(Polygon const& poly,
+ Strategy const& strategy, typename Strategy::state_type& state)
+ {
+ typedef centroid_ring_state
+ <
+ typename ring_type<Polygon>::type,
+ Strategy
+ > per_ring;
+
+ per_ring::apply(exterior_ring(poly), strategy, state);
+
+ for (typename boost::range_const_iterator
+ <
+ typename interior_type<Polygon>::type
+ >::type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly));
+ ++it)
+ {
+ per_ring::apply(*it, strategy, state);
+ }
+ }
+};
+
+template<typename Polygon, typename Point, typename Strategy>
+struct centroid_polygon
+{
+ static inline void apply(Polygon const& poly, Point& centroid,
+ Strategy const& strategy)
+ {
+ if (range_ok(exterior_ring(poly), centroid))
+ {
+ typename Strategy::state_type state;
+ centroid_polygon_state
+ <
+ Polygon,
+ Strategy
+ >::apply(poly, strategy, state);
+ Strategy::result(state, centroid);
+ }
+ }
+};
+
+
+}} // namespace detail::centroid
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag,
+ typename Geometry,
+ typename Point,
+ typename Strategy
+>
+struct centroid {};
+
+template
+<
+ typename Geometry,
+ typename Point,
+ typename Strategy
+>
+struct centroid<point_tag, Geometry, Point, Strategy>
+ : detail::centroid::centroid_point<Geometry, Point, Strategy>
+{};
+
+template
+<
+ typename Box,
+ typename Point,
+ typename Strategy
+>
+struct centroid<box_tag, Box, Point, Strategy>
+ : detail::centroid::centroid_box<Box, Point, Strategy>
+{};
+
+template <typename Ring, typename Point, typename Strategy>
+struct centroid<ring_tag, Ring, Point, Strategy>
+ : detail::centroid::centroid_ring<Ring, Point, Strategy>
+{};
+
+template <typename Linestring, typename Point, typename Strategy>
+struct centroid<linestring_tag, Linestring, Point, Strategy>
+ : detail::centroid::centroid_linestring<Linestring, Point, Strategy>
+ {};
+
+template <typename Polygon, typename Point, typename Strategy>
+struct centroid<polygon_tag, Polygon, Point, Strategy>
+ : detail::centroid::centroid_polygon<Polygon, Point, Strategy>
+ {};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Calculate centroid using a specified strategy
+ \ingroup centroid
+ \param geometry the geometry to calculate centroid from
+ \param c reference to point which will contain the centroid
+ \param strategy Calculation strategy for centroid
+ */
+template<typename Geometry, typename Point, typename Strategy>
+inline void centroid(Geometry const& geometry, Point& c,
+ Strategy const& strategy)
+{
+ //BOOST_CONCEPT_ASSERT( (geometry::concept::CentroidStrategy<Strategy>) );
+
+ concept::check_concepts_and_equal_dimensions<Point, const Geometry>();
+
+ typedef typename point_type<Geometry>::type point_type;
+
+ // Call dispatch apply method. That one returns true if centroid
+ // should be taken from state.
+ dispatch::centroid
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Point,
+ Strategy
+ >::apply(geometry, c, strategy);
+}
+
+
+/*!
+ \brief Calculate centroid
+ \ingroup centroid
+ \param geometry a geometry (e.g. closed ring or polygon)
+ \param c reference to point which will contain the centroid
+ */
+template<typename Geometry, typename Point>
+inline void centroid(Geometry const& geometry, Point& c)
+{
+ concept::check_concepts_and_equal_dimensions<Point, const Geometry>();
+
+ typedef typename strategy_centroid
+ <
+ typename cs_tag<Geometry>::type,
+ typename tag<Geometry>::type,
+ dimension<Geometry>::type::value,
+ Point,
+ Geometry
+ >::type strategy_type;
+
+ centroid(geometry, c, strategy_type());
+}
+
+
+/*!
+ \brief Calculate and return centroid
+ \ingroup centroid
+ \param geometry the geometry to calculate centroid from
+ \return the centroid
+ */
+template<typename Point, typename Geometry>
+inline Point make_centroid(Geometry const& geometry)
+{
+ concept::check_concepts_and_equal_dimensions<Point, const Geometry>();
+
+ Point c;
+ centroid(geometry, c);
+ return c;
+}
+
+/*!
+ \brief Calculate and return centroid, using a specified strategy
+ \ingroup centroid
+ \param geometry the geometry to calculate centroid from
+ \param strategy Calculation strategy for centroid
+ \return the centroid
+ */
+template<typename Point, typename Geometry, typename Strategy>
+inline Point make_centroid(Geometry const& geometry, Strategy const& strategy)
+{
+ //BOOST_CONCEPT_ASSERT( (geometry::concept::CentroidStrategy<Strategy>) );
+
+ concept::check_concepts_and_equal_dimensions<Point, const Geometry>();
+
+ Point c;
+ centroid(geometry, c, strategy);
+ return c;
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP

Added: sandbox/geometry/boost/geometry/algorithms/clear.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/clear.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,141 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP
+
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace clear {
+
+template <typename Geometry>
+struct use_std_clear
+{
+ static inline void apply(Geometry& geometry)
+ {
+ geometry.clear();
+ }
+};
+
+template <typename Geometry>
+struct use_traits_clear
+{
+ static inline void apply(Geometry& geometry)
+ {
+ traits::clear<Geometry>::apply(geometry);
+ }
+};
+
+template <typename Polygon>
+struct polygon_clear
+{
+ static inline void apply(Polygon& polygon)
+ {
+ interior_rings(polygon).clear();
+ exterior_ring(polygon).clear();
+ }
+};
+
+template <typename Geometry>
+struct no_action
+{
+ static inline void apply(Geometry& geometry)
+ {
+ }
+};
+
+}} // namespace detail::clear
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, bool UseStd, typename Geometry>
+struct clear
+{};
+
+// True (default for all geometry types, unless otherwise implemented in traits)
+// uses std::clear
+template <typename Tag, typename Geometry>
+struct clear<Tag, true, Geometry>
+ : detail::clear::use_std_clear<Geometry>
+{};
+
+// If any geometry specializes use_std<Geometry> to false, specialize to use the traits clear.
+template <typename Tag, typename Geometry>
+struct clear<Tag, false, Geometry>
+ : detail::clear::use_traits_clear<Geometry>
+{};
+
+// Point/box/segment do not have clear. So specialize to do nothing.
+template <typename Geometry>
+struct clear<point_tag, true, Geometry>
+ : detail::clear::no_action<Geometry>
+{};
+
+template <typename Geometry>
+struct clear<box_tag, true, Geometry>
+ : detail::clear::no_action<Geometry>
+{};
+
+template <typename Geometry>
+struct clear<segment_tag, true, Geometry>
+ : detail::clear::no_action<Geometry>
+{};
+
+
+
+
+// Polygon can (indirectly) use std for clear
+template <typename Polygon>
+struct clear<polygon_tag, true, Polygon>
+ : detail::clear::polygon_clear<Polygon>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Clears a linestring, linear ring or polygon (exterior+interiors) or multi*
+ \details Generic function to clear a geometry
+ \ingroup access
+ \note points and boxes cannot be cleared, instead they can be set to zero by "assign_zero"
+*/
+template <typename Geometry>
+inline void clear(Geometry& geometry)
+{
+ concept::check<Geometry>();
+
+ dispatch::clear
+ <
+ typename tag<Geometry>::type,
+ traits::use_std
+ <
+ typename boost::remove_const<Geometry>::type
+ >::value,
+ Geometry
+ >::apply(geometry);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP

Added: sandbox/geometry/boost/geometry/algorithms/combine.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/combine.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,321 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_COMBINE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_COMBINE_HPP
+
+#include <cstddef>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+#include <boost/geometry/strategies/compare.hpp>
+#include <boost/geometry/policies/compare.hpp>
+
+
+/*!
+\defgroup combine combine: add a geometry to a bounding box
+\par Geometries:
+- \b box + \b box -> \b box: the box will be combined with the other box
+ \image html combine_box_box.png
+ \note Also if the input box is incorrect, the box will correctly updated
+- \b box + \b point -> \b box: the box will combined with the point
+ \image html combine_box_point.png
+- \b box + \b segment -> \b box
+*/
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace combine {
+
+
+template
+<
+ typename Box, typename Point,
+ typename StrategyLess, typename StrategyGreater,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct point_loop
+{
+ typedef typename strategy::compare::detail::select_strategy
+ <
+ StrategyLess, 1, Point, Dimension
+ >::type less_type;
+
+ typedef typename strategy::compare::detail::select_strategy
+ <
+ StrategyGreater, -1, Point, Dimension
+ >::type greater_type;
+
+ typedef typename select_coordinate_type<Point, Box>::type coordinate_type;
+
+ static inline void apply(Box& box, Point const& source)
+ {
+ less_type less;
+ greater_type greater;
+
+ coordinate_type const coord = get<Dimension>(source);
+
+ if (less(coord, get<min_corner, Dimension>(box)))
+ {
+ set<min_corner, Dimension>(box, coord);
+ }
+
+ if (greater(coord, get<max_corner, Dimension>(box)))
+ {
+ set<max_corner, Dimension>(box, coord);
+ }
+
+ point_loop
+ <
+ Box, Point,
+ StrategyLess, StrategyGreater,
+ Dimension + 1, DimensionCount
+ >::apply(box, source);
+ }
+};
+
+
+template
+<
+ typename Box, typename Point,
+ typename StrategyLess, typename StrategyGreater,
+ std::size_t DimensionCount
+>
+struct point_loop
+ <
+ Box, Point,
+ StrategyLess, StrategyGreater,
+ DimensionCount, DimensionCount
+ >
+{
+ static inline void apply(Box&, Point const&) {}
+};
+
+
+template
+<
+ typename Box, typename Geometry,
+ typename StrategyLess, typename StrategyGreater,
+ std::size_t Index,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct indexed_loop
+{
+ typedef typename strategy::compare::detail::select_strategy
+ <
+ StrategyLess, 1, Box, Dimension
+ >::type less_type;
+
+ typedef typename strategy::compare::detail::select_strategy
+ <
+ StrategyGreater, -1, Box, Dimension
+ >::type greater_type;
+
+ typedef typename select_coordinate_type
+ <
+ Box,
+ Geometry
+ >::type coordinate_type;
+
+
+ static inline void apply(Box& box, Geometry const& source)
+ {
+ less_type less;
+ greater_type greater;
+
+ coordinate_type const coord = get<Index, Dimension>(source);
+
+ if (less(coord, get<min_corner, Dimension>(box)))
+ {
+ set<min_corner, Dimension>(box, coord);
+ }
+
+ if (greater(coord, get<max_corner, Dimension>(box)))
+ {
+ set<max_corner, Dimension>(box, coord);
+ }
+
+ indexed_loop
+ <
+ Box, Geometry,
+ StrategyLess, StrategyGreater,
+ Index, Dimension + 1, DimensionCount
+ >::apply(box, source);
+ }
+};
+
+
+template
+<
+ typename Box, typename Geometry,
+ typename StrategyLess, typename StrategyGreater,
+ std::size_t Index, std::size_t DimensionCount
+>
+struct indexed_loop
+ <
+ Box, Geometry,
+ StrategyLess, StrategyGreater,
+ Index, DimensionCount, DimensionCount
+ >
+{
+ static inline void apply(Box&, Geometry const&) {}
+};
+
+
+
+// Changes a box such that the other box is also contained by the box
+template
+<
+ typename Box, typename Geometry,
+ typename StrategyLess, typename StrategyGreater
+>
+struct combine_indexed
+{
+ static inline void apply(Box& box, Geometry const& geometry)
+ {
+ indexed_loop
+ <
+ Box, Geometry,
+ StrategyLess, StrategyGreater,
+ 0, 0, dimension<Geometry>::type::value
+ >::apply(box, geometry);
+
+ indexed_loop
+ <
+ Box, Geometry,
+ StrategyLess, StrategyGreater,
+ 1, 0, dimension<Geometry>::type::value
+ >::apply(box, geometry);
+ }
+};
+
+}} // namespace detail::combine
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag,
+ typename BoxOut, typename Geometry,
+ typename StrategyLess, typename StrategyGreater
+>
+struct combine
+{};
+
+
+// Box + point -> new box containing also point
+template
+<
+ typename BoxOut, typename Point,
+ typename StrategyLess, typename StrategyGreater
+>
+struct combine<point_tag, BoxOut, Point, StrategyLess, StrategyGreater>
+ : detail::combine::point_loop
+ <
+ BoxOut, Point,
+ StrategyLess, StrategyGreater,
+ 0, dimension<Point>::type::value
+ >
+{};
+
+
+// Box + box -> new box containing two input boxes
+template
+<
+ typename BoxOut, typename BoxIn,
+ typename StrategyLess, typename StrategyGreater
+>
+struct combine<box_tag, BoxOut, BoxIn, StrategyLess, StrategyGreater>
+ : detail::combine::combine_indexed
+ <BoxOut, BoxIn, StrategyLess, StrategyGreater>
+{};
+
+template
+<
+ typename Box, typename Segment,
+ typename StrategyLess, typename StrategyGreater
+>
+struct combine<segment_tag, Box, Segment, StrategyLess, StrategyGreater>
+ : detail::combine::combine_indexed
+ <Box, Segment, StrategyLess, StrategyGreater>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/***
+*!
+ \brief Combines a box with another geometry (box, point)
+ \ingroup combine
+ \tparam Box type of the box
+ \tparam Geometry of second geometry, to be combined with the box
+ \param box box to combine another geometry with, might be changed
+ \param geometry other geometry
+ \param strategy_less
+ \param strategy_greater
+ \note Strategy is currently ignored
+ \todo Handle strategy
+ *
+template
+<
+ typename Box, typename Geometry,
+ typename StrategyLess, typename StrategyGreater
+>
+inline void combine(Box& box, Geometry const& geometry,
+ StrategyLess const& strategy_less,
+ StrategyGreater const& strategy_greater)
+{
+ concept::check_concepts_and_equal_dimensions<Box, const Geometry>();
+
+ dispatch::combine
+ <
+ typename tag<Geometry>::type,
+ Box,
+ Geometry,
+ StrategyLess, StrategyGreater
+ >::apply(box, geometry);
+}
+***/
+
+
+/*!
+ \brief Combines a box with another geometry (box, point)
+ \ingroup combine
+ \tparam Box type of the box
+ \tparam Geometry of second geometry, to be combined with the box
+ \param box box to combine another geometry with, might be changed
+ \param geometry other geometry
+ */
+template <typename Box, typename Geometry>
+inline void combine(Box& box, Geometry const& geometry)
+{
+ concept::check_concepts_and_equal_dimensions<Box, const Geometry>();
+
+ dispatch::combine
+ <
+ typename tag<Geometry>::type,
+ Box, Geometry,
+ strategy::compare::default_strategy,
+ strategy::compare::default_strategy
+ >::apply(box, geometry);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_COMBINE_HPP

Added: sandbox/geometry/boost/geometry/algorithms/convert.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/convert.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,272 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
+
+#include <cstddef>
+
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/append.hpp>
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/for_each.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+
+/*!
+\defgroup convert convert: convert geometries from one type to another
+\details Convert from one geometry type to another type,
+ for example from BOX to POLYGON
+\par Geometries:
+- \b point to \b box -> a zero-area box of a point
+- \b box to \b ring -> a rectangular ring
+- \b box to \b polygon -> a rectangular polygon
+- \b ring to \b polygon -> polygon with an exterior ring (the input ring)
+- \b polygon to \b ring -> ring, interior rings (if any) are ignored
+*/
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace convert {
+
+template
+<
+ typename Point,
+ typename Box,
+ std::size_t Index,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct point_to_box
+{
+ static inline void apply(Point const& point, Box& box)
+ {
+ typedef typename coordinate_type<Box>::type coordinate_type;
+
+ set<Index, Dimension>(box,
+ boost::numeric_cast<coordinate_type>(get<Dimension>(point)));
+ point_to_box
+ <
+ Point, Box,
+ Index, Dimension + 1, DimensionCount
+ >::apply(point, box);
+ }
+};
+
+
+template
+<
+ typename Point,
+ typename Box,
+ std::size_t Index,
+ std::size_t DimensionCount
+>
+struct point_to_box<Point, Box, Index, DimensionCount, DimensionCount>
+{
+ static inline void apply(Point const& point, Box& box)
+ {}
+};
+
+
+}} // namespace detail::convert
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag1, typename Tag2,
+ std::size_t Dimensions,
+ typename Geometry1, typename Geometry2
+>
+struct convert
+{
+};
+
+
+template
+<
+ typename Tag,
+ std::size_t Dimensions,
+ typename Geometry1, typename Geometry2
+>
+struct convert<Tag, Tag, Dimensions, Geometry1, Geometry2>
+{
+ // Same geometry type -> copy coordinates from G1 to G2
+ // Actually: we try now to just copy it
+ static inline void apply(Geometry1 const& source, Geometry2& destination)
+ {
+ destination = source;
+ }
+};
+
+template
+<
+ std::size_t Dimensions,
+ typename Geometry1, typename Geometry2
+>
+struct convert<point_tag, point_tag, Dimensions, Geometry1, Geometry2>
+{
+ static inline void apply(Geometry1 const& source, Geometry2& destination)
+ {
+ geometry::copy_coordinates(source, destination);
+ }
+};
+
+
+template <std::size_t Dimensions, typename Ring1, typename Ring2>
+struct convert<ring_tag, ring_tag, Dimensions, Ring1, Ring2>
+{
+ static inline void apply(Ring1 const& source, Ring2& destination)
+ {
+ geometry::clear(destination);
+ for (typename boost::range_const_iterator<Ring1>::type it
+ = boost::begin(source);
+ it != boost::end(source);
+ ++it)
+ {
+ typename geometry::point_type<Ring2>::type p;
+ geometry::copy_coordinates(*it, p);
+ geometry::append(destination, p);
+ }
+ }
+};
+
+
+template <typename Box, typename Ring>
+struct convert<box_tag, ring_tag, 2, Box, Ring>
+{
+ static inline void apply(Box const& box, Ring& ring)
+ {
+ // go from box to ring -> add coordinates in correct order
+ geometry::clear(ring);
+ typename point_type<Box>::type point;
+
+ geometry::assign(point, get<min_corner, 0>(box), get<min_corner, 1>(box));
+ geometry::append(ring, point);
+
+ geometry::assign(point, get<min_corner, 0>(box), get<max_corner, 1>(box));
+ geometry::append(ring, point);
+
+ geometry::assign(point, get<max_corner, 0>(box), get<max_corner, 1>(box));
+ geometry::append(ring, point);
+
+ geometry::assign(point, get<max_corner, 0>(box), get<min_corner, 1>(box));
+ geometry::append(ring, point);
+
+ geometry::assign(point, get<min_corner, 0>(box), get<min_corner, 1>(box));
+ geometry::append(ring, point);
+ }
+};
+
+
+template <typename Box, typename Polygon>
+struct convert<box_tag, polygon_tag, 2, Box, Polygon>
+{
+ static inline void apply(Box const& box, Polygon& polygon)
+ {
+ typedef typename ring_type<Polygon>::type ring_type;
+
+ convert
+ <
+ box_tag, ring_tag,
+ 2, Box, ring_type
+ >::apply(box, exterior_ring(polygon));
+ }
+};
+
+
+template <typename Point, std::size_t Dimensions, typename Box>
+struct convert<point_tag, box_tag, Dimensions, Point, Box>
+{
+ static inline void apply(Point const& point, Box& box)
+ {
+ detail::convert::point_to_box
+ <
+ Point, Box, min_corner, 0, Dimensions
+ >::apply(point, box);
+ detail::convert::point_to_box
+ <
+ Point, Box, max_corner, 0, Dimensions
+ >::apply(point, box);
+ }
+};
+
+
+template <typename Ring, std::size_t Dimensions, typename Polygon>
+struct convert<ring_tag, polygon_tag, Dimensions, Ring, Polygon>
+{
+ static inline void apply(Ring const& ring, Polygon& polygon)
+ {
+ typedef typename ring_type<Polygon>::type ring_type;
+ convert
+ <
+ ring_tag, ring_tag, Dimensions,
+ Ring, ring_type
+ >::apply(ring, exterior_ring(polygon));
+ }
+};
+
+
+template <typename Polygon, std::size_t Dimensions, typename Ring>
+struct convert<polygon_tag, ring_tag, Dimensions, Polygon, Ring>
+{
+ static inline void apply(Polygon const& polygon, Ring& ring)
+ {
+ typedef typename ring_type<Polygon>::type ring_type;
+
+ convert
+ <
+ ring_tag, ring_tag, Dimensions,
+ ring_type, Ring
+ >::apply(exterior_ring(polygon), ring);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+/*!
+ \brief Converts one geometry to another geometry
+ \details The convert algorithm converts one geometry, e.g. a BOX, to another geometry, e.g. a RING. This only
+ if it is possible and applicable.
+ \ingroup convert
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \param geometry1 first geometry (source)
+ \param geometry2 second geometry (target)
+ */
+template <typename Geometry1, typename Geometry2>
+inline void convert(Geometry1 const& geometry1, Geometry2& geometry2)
+{
+ concept::check_concepts_and_equal_dimensions<const Geometry1, Geometry2>();
+
+ dispatch::convert
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ dimension<Geometry1>::type::value,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP

Added: sandbox/geometry/boost/geometry/algorithms/convex_hull.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/convex_hull.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,279 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/is_multi.hpp>
+#include <boost/geometry/core/point_order.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/iterators/range_type.hpp>
+
+#include <boost/geometry/strategies/convex_hull.hpp>
+#include <boost/geometry/strategies/concepts/convex_hull_concept.hpp>
+
+#include <boost/geometry/util/as_range.hpp>
+
+
+/*!
+\defgroup convex_hull convex hull: calculate the convex hull of a geometry
+\par Source descriptions:
+- OGC description: Returns a geometric object that represents the convex hull of
+ this geometric object. Convex hulls, being dependent on straight lines, can
+ be accurately represented in linear interpolations
+ for any geometry restricted to linear interpolations.
+\see http://en.wikipedia.org/wiki/Convex_hull
+
+\par Performance
+2776 counties of US are "hulled" in 0.9 seconds
+(http://trac.osgeo.org/ggl/wiki/Performance#Convexhull1)
+
+\note The convex hull is always a ring, holes are not possible. Therefore it is
+ can also be used in combination with an output iterator.
+
+\par Geometries supported:
+In the images below the convex hull is painted in red.
+
+- \b point: will not compile
+
+- \b linestring:
+
+- \b polygon: will deliver a polygon without holes
+ \image html svg_convex_hull_country.png
+
+- \b multi_point:
+ \image html svg_convex_hull_cities.png
+
+- \b multi_linestring:
+
+- \b multi_polygon:
+
+\par Output geometries supported:
+
+- \b polygon
+
+- \b ring
+
+- inserter version (with output iterator) can output to any array supporting
+ points of same type as the input geometry type
+
+*/
+namespace boost { namespace geometry {
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace convex_hull {
+
+template
+<
+ typename Geometry,
+ order_selector Order,
+ typename Strategy
+>
+struct hull_inserter
+{
+
+ // Member template function, to avoid inconvenient declaration
+ // of output-iterator-type, from hull_to_geometry
+ template <typename OutputIterator>
+ static inline OutputIterator apply(Geometry const& geometry,
+ OutputIterator out, Strategy const& strategy)
+ {
+ typename Strategy::state_type state;
+
+ strategy.apply(geometry, state);
+ strategy.result(state, out, Order == clockwise);
+ return out;
+ }
+};
+
+template
+<
+ typename Geometry,
+ typename OutputGeometry,
+ typename Strategy
+>
+struct hull_to_geometry
+{
+ static inline void apply(Geometry const& geometry, OutputGeometry& out,
+ Strategy const& strategy)
+ {
+ hull_inserter
+ <
+ Geometry,
+ geometry::point_order<OutputGeometry>::value,
+ Strategy
+ >::apply(geometry,
+ std::back_inserter(
+ // Handle both ring and polygon the same:
+ geometry::as_range
+ <
+ typename geometry::range_type<OutputGeometry>::type
+ >(out)), strategy);
+ }
+};
+
+
+}} // namespace detail::convex_hull
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Tag1,
+ bool IsMulti,
+ typename Geometry,
+ typename Output,
+ typename Strategy
+>
+struct convex_hull
+ : detail::convex_hull::hull_to_geometry<Geometry, Output, Strategy>
+{};
+
+
+template
+<
+ typename GeometryTag,
+ order_selector Order,
+ bool IsMulti,
+ typename GeometryIn, typename Strategy
+ >
+struct convex_hull_inserter
+ : detail::convex_hull::hull_inserter<GeometryIn, Order, Strategy>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+template<typename Geometry1, typename Geometry2, typename Strategy>
+inline void convex_hull(Geometry1 const& geometry,
+ Geometry2& out, Strategy const& strategy)
+{
+ concept::check_concepts_and_equal_dimensions
+ <
+ const Geometry1,
+ Geometry2
+ >();
+
+ BOOST_CONCEPT_ASSERT( (geometry::concept::ConvexHullStrategy<Strategy>) );
+
+
+ dispatch::convex_hull
+ <
+ typename tag<Geometry1>::type,
+ is_multi<Geometry1>::type::value,
+ Geometry1,
+ Geometry2,
+ Strategy
+ >::apply(geometry, out, strategy);
+}
+
+
+/*!
+ \brief Calculate the convex hull of a geometry
+ \ingroup convex_hull
+ \tparam Geometry1 the input geometry type
+ \tparam Geometry2: the output geometry type
+ \param geometry the geometry to calculate convex hull from
+ \param out a geometry receiving points of the convex hull
+ */
+template<typename Geometry1, typename Geometry2>
+inline void convex_hull(Geometry1 const& geometry,
+ Geometry2& out)
+{
+ concept::check_concepts_and_equal_dimensions
+ <
+ const Geometry1,
+ Geometry2
+ >();
+
+ //typedef typename range_type<Geometry1>::type range_type;
+ typedef typename point_type<Geometry2>::type point_type;
+
+ typedef typename strategy_convex_hull
+ <
+ typename cs_tag<point_type>::type,
+ Geometry1,
+ point_type
+ >::type strategy_type;
+
+ convex_hull(geometry, out, strategy_type());
+}
+
+
+template<typename Geometry, typename OutputIterator, typename Strategy>
+inline OutputIterator convex_hull_inserter(Geometry const& geometry,
+ OutputIterator out, Strategy const& strategy)
+{
+ // Concept: output point type = point type of input geometry
+ concept::check<const Geometry>();
+ concept::check<typename point_type<Geometry>::type>();
+
+ BOOST_CONCEPT_ASSERT( (geometry::concept::ConvexHullStrategy<Strategy>) );
+
+ return dispatch::convex_hull_inserter
+ <
+ typename tag<Geometry>::type,
+ geometry::point_order<Geometry>::value,
+ is_multi<Geometry>::type::value,
+ Geometry, Strategy
+ >::apply(geometry, out, strategy);
+}
+
+
+/*!
+ \brief Calculate the convex hull of a geometry, output-iterator version
+ \ingroup convex_hull
+ \tparam Geometry the input geometry type
+ \tparam OutputIterator: an output-iterator
+ \param geometry the geometry to calculate convex hull from
+ \param out an output iterator outputing points of the convex hull
+ \note This overloaded version outputs to an output iterator.
+ In this case, nothing is known about its point-type or
+ about its clockwise order. Therefore, the input point-type
+ and order are copied
+
+ */
+template<typename Geometry, typename OutputIterator>
+inline OutputIterator convex_hull_inserter(Geometry const& geometry,
+ OutputIterator out)
+{
+ // Concept: output point type = point type of input geometry
+ concept::check<const Geometry>();
+ concept::check<typename point_type<Geometry>::type>();
+
+ typedef typename range_type<Geometry>::type range_type;
+ typedef typename point_type<Geometry>::type point_type;
+
+ typedef typename strategy_convex_hull
+ <
+ typename cs_tag<point_type>::type,
+ Geometry,
+ point_type
+ >::type strategy_type;
+
+ return convex_hull_inserter(geometry, out, strategy_type());
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP

Added: sandbox/geometry/boost/geometry/algorithms/correct.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/correct.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,194 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP
+
+#include <cstddef>
+#include <algorithm>
+#include <functional>
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/algorithms/disjoint.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace correct {
+
+
+template <typename Box, std::size_t Dimension, std::size_t DimensionCount>
+struct correct_box_loop
+{
+ typedef typename coordinate_type<Box>::type coordinate_type;
+
+ static inline void apply(Box& box)
+ {
+ if (get<min_corner, Dimension>(box) > get<max_corner, Dimension>(box))
+ {
+ // Swap the coordinates
+ coordinate_type max_value = get<min_corner, Dimension>(box);
+ coordinate_type min_value = get<max_corner, Dimension>(box);
+ set<min_corner, Dimension>(box, min_value);
+ set<max_corner, Dimension>(box, max_value);
+ }
+
+ correct_box_loop
+ <
+ Box, Dimension + 1, DimensionCount
+ >::apply(box);
+ }
+};
+
+
+
+template <typename Box, std::size_t DimensionCount>
+struct correct_box_loop<Box, DimensionCount, DimensionCount>
+{
+ static inline void apply(Box& box)
+ {}
+
+};
+
+
+// correct an box: make min/max are correct
+template <typename Box>
+struct correct_box
+{
+
+ static inline void apply(Box& box)
+ {
+ // Currently only for Cartesian coordinates
+ // TODO: adapt using strategies
+ correct_box_loop
+ <
+ Box, 0, dimension<Box>::type::value
+ >::apply(box);
+ }
+};
+
+
+// close a linear_ring, if not closed
+template <typename Ring, typename Predicate>
+struct correct_ring
+{
+ typedef typename point_type<Ring>::type point_type;
+
+ typedef typename strategy_area
+ <
+ typename cs_tag<point_type>::type,
+ point_type
+ >::type strategy_type;
+
+ typedef detail::area::ring_area
+ <
+ Ring,
+ geometry::point_order<Ring>::value,
+ strategy_type
+ > ring_area_type;
+
+
+ static inline void apply(Ring& r)
+ {
+ // Check close-ness
+ if (boost::size(r) > 2)
+ {
+ // check if closed, if not, close it
+ if (geometry::disjoint(*boost::begin(r), *(boost::end(r) - 1)))
+ {
+ point_type first;
+ geometry::copy_coordinates(*boost::begin(r), first);
+ *(std::back_inserter(r)++) = first;
+ }
+ }
+ // Check area
+ Predicate predicate;
+ if (predicate(ring_area_type::apply(r, strategy_type()), 0))
+ {
+ std::reverse(boost::begin(r), boost::end(r));
+ }
+ }
+};
+
+// correct a polygon: normalizes all rings, sets outer linear_ring clockwise, sets all
+// inner rings counter clockwise
+template <typename Polygon>
+struct correct_polygon
+{
+ typedef typename ring_type<Polygon>::type ring_type;
+
+ static inline void apply(Polygon& poly)
+ {
+ correct_ring<ring_type, std::less<double> >::apply(exterior_ring(poly));
+
+ typedef typename boost::range_iterator
+ <
+ typename interior_type<Polygon>::type
+ >::type iterator_type;
+
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly)); ++it)
+ {
+ correct_ring<ring_type, std::greater<double> >::apply(*it);
+ }
+ }
+};
+
+
+}} // namespace detail::correct
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, typename Geometry>
+struct correct {};
+
+template <typename Box>
+struct correct<box_tag, Box>
+ : detail::correct::correct_box<Box>
+{};
+
+template <typename Ring>
+struct correct<ring_tag, Ring>
+ : detail::correct::correct_ring<Ring, std::less<double> >
+{};
+
+template <typename Polygon>
+struct correct<polygon_tag, Polygon>
+ : detail::correct::correct_polygon<Polygon>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+template <typename Geometry>
+inline void correct(Geometry& geometry)
+{
+ concept::check<const Geometry>();
+
+ dispatch::correct<typename tag<Geometry>::type, Geometry>::apply(geometry);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP

Added: sandbox/geometry/boost/geometry/algorithms/detail/calculate_null.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/detail/calculate_null.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,33 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template<typename ReturnType, typename Geometry, typename Strategy>
+struct calculate_null
+{
+ static inline ReturnType apply(Geometry const& , Strategy const&)
+ {
+ return ReturnType();
+ }
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP

Added: sandbox/geometry/boost/geometry/algorithms/detail/calculate_sum.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/detail/calculate_sum.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,51 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template
+<
+ typename ReturnType,
+ typename Polygon,
+ typename Strategy,
+ typename Policy
+>
+struct calculate_polygon_sum
+{
+ static inline ReturnType apply(Polygon const& poly, Strategy const& strategy)
+ {
+ ReturnType sum = Policy::apply(exterior_ring(poly), strategy);
+
+ for (typename boost::range_const_iterator
+ <
+ typename interior_type<Polygon>::type
+ >::type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly));
+ ++it)
+ {
+ sum += Policy::apply(*it, strategy);
+ }
+ return sum;
+ }
+};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP

Added: sandbox/geometry/boost/geometry/algorithms/detail/disjoint.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/detail/disjoint.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,194 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_HPP
+
+// Note: contrary to most files, the geometry::detail::disjoint namespace
+// is partly implemented in a separate file, to avoid circular references
+// disjoint -> get_intersection_points -> disjoint
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/is_multi.hpp>
+#include <boost/geometry/core/reverse_dispatch.hpp>
+
+
+#include <boost/geometry/util/math.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace disjoint {
+
+
+template
+<
+ typename Point1, typename Point2,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct point_point
+{
+ static inline bool apply(Point1 const& p1, Point2 const& p2)
+ {
+ if (! geometry::math::equals(get<Dimension>(p1), get<Dimension>(p2)))
+ {
+ return true;
+ }
+ return point_point
+ <
+ Point1, Point2,
+ Dimension + 1, DimensionCount
+ >::apply(p1, p2);
+ }
+};
+
+
+template <typename Point1, typename Point2, std::size_t DimensionCount>
+struct point_point<Point1, Point2, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Point1 const& , Point2 const& )
+ {
+ return false;
+ }
+};
+
+
+template
+<
+ typename Point, typename Box,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct point_box
+{
+ static inline bool apply(Point const& point, Box const& box)
+ {
+ if (get<Dimension>(point) < get<min_corner, Dimension>(box)
+ || get<Dimension>(point) > get<max_corner, Dimension>(box))
+ {
+ return true;
+ }
+ return point_box
+ <
+ Point, Box,
+ Dimension + 1, DimensionCount
+ >::apply(point, box);
+ }
+};
+
+
+template <typename Point, typename Box, std::size_t DimensionCount>
+struct point_box<Point, Box, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Point const& , Box const& )
+ {
+ return false;
+ }
+};
+
+
+template
+<
+ typename Box1, typename Box2,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct box_box
+{
+ static inline bool apply(Box1 const& box1, Box2 const& box2)
+ {
+ if (get<max_corner, Dimension>(box1) < get<min_corner, Dimension>(box2))
+ {
+ return true;
+ }
+ if (get<min_corner, Dimension>(box1) > get<max_corner, Dimension>(box2))
+ {
+ return true;
+ }
+ return box_box
+ <
+ Box1, Box2,
+ Dimension + 1, DimensionCount
+ >::apply(box1, box2);
+ }
+};
+
+
+template <typename Box1, typename Box2, std::size_t DimensionCount>
+struct box_box<Box1, Box2, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Box1 const& , Box2 const& )
+ {
+ return false;
+ }
+};
+
+
+
+/*!
+ \brief Internal utility function to detect of boxes are disjoint
+ \note Is used from other algorithms, declared separately
+ to avoid circular references
+ */
+template <typename Box1, typename Box2>
+inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2)
+{
+ return box_box
+ <
+ Box1, Box2,
+ 0, dimension<Box1>::type::value
+ >::apply(box1, box2);
+}
+
+
+
+/*!
+ \brief Internal utility function to detect of points are disjoint
+ \note To avoid circular references
+ */
+template <typename Point1, typename Point2>
+inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2)
+{
+ return point_point
+ <
+ Point1, Point2,
+ 0, dimension<Point1>::type::value
+ >::apply(point1, point2);
+}
+
+
+
+
+}} // namespace detail::disjoint
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace equals {
+
+/*!
+ \brief Internal utility function to detect of points are disjoint
+ \note To avoid circular references
+ */
+template <typename Point1, typename Point2>
+inline bool equals_point_point(Point1 const& point1, Point2 const& point2)
+{
+ return ! detail::disjoint::disjoint_point_point(point1, point2);
+}
+
+
+}} // namespace detail::equals
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_HPP

Added: sandbox/geometry/boost/geometry/algorithms/detail/not.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/detail/not.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,45 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_NOT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_NOT_HPP
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+
+/*!
+ \brief Structure negating the result of specified policy
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \tparam Policy
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \return Negation of the result of the policy
+ */
+template <typename Geometry1, typename Geometry2, typename Policy>
+struct not_
+{
+ static inline bool apply(Geometry1 const &geometry1, Geometry2 const& geometry2)
+ {
+ return ! Policy::apply(geometry1, geometry2);
+ }
+};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_NOT_HPP

Added: sandbox/geometry/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,48 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CALCULATE_DISTANCE_POLICY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CALCULATE_DISTANCE_POLICY_HPP
+
+
+#include <boost/geometry/algorithms/distance.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay {
+
+
+/*!
+ \brief Policy calculating distance
+ \details get_turn_info has an optional policy to get some
+ extra information.
+ This policy calculates the distance (using default distance strategy)
+ */
+struct CalculateDistancePolicy
+{
+ template <typename Point1, typename Point2, typename Info>
+ static inline void apply(Info& info, Point1 const& p1, Point2 const& p2)
+ {
+ info.operations[0].enriched.distance = boost::geometry::distance(info.point, p1);
+ info.operations[1].enriched.distance = boost::geometry::distance(info.point, p2);
+ }
+
+};
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CALCULATE_DISTANCE_POLICY_HPP

Added: sandbox/geometry/boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,51 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2010, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DEBUG_TURN_INFO_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DEBUG_TURN_INFO_HPP
+
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+inline char method_char(detail::overlay::method_type const& method)
+{
+ using namespace detail::overlay;
+ switch(method)
+ {
+ case method_none : return '-';
+ case method_disjoint : return 'd';
+ case method_crosses : return 'i';
+ case method_touch : return 't';
+ case method_touch_interior : return 'm';
+ case method_collinear : return 'c';
+ case method_equal : return 'e';
+ default : return '?';
+ }
+}
+
+inline char operation_char(detail::overlay::operation_type const& operation)
+{
+ using namespace detail::overlay;
+ switch(operation)
+ {
+ case operation_none : return '-';
+ case operation_union : return 'u';
+ case operation_intersection : return 'i';
+ case operation_blocked : return 'x';
+ case operation_continue : return 'c';
+ default : return '?';
+ }
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DEBUG_TURN_INFO_HPP

Added: sandbox/geometry/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,64 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICHMENT_INFO_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICHMENT_INFO_HPP
+
+
+#include <boost/geometry/strategies/distance_result.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay {
+
+
+/*!
+ \brief Keeps info to enrich intersection info (per source)
+ \details Class to keep information necessary for traversal phase (a phase
+ of the overlay process). The information is gathered during the
+ enrichment phase
+ */
+template<typename P>
+struct enrichment_info
+{
+ typedef typename distance_result<P, P>::type distance_type;
+
+ inline enrichment_info()
+ : travels_to_vertex_index(-1)
+ , travels_to_ip_index(-1)
+ , next_ip_index(-1)
+ , distance(geometry::make_distance_result<distance_type>(0))
+ {}
+
+ // vertex to which is free travel after this IP,
+ // so from "segment_index+1" to "travels_to_vertex_index", without IP-s,
+ // can be -1
+ int travels_to_vertex_index;
+
+ // same but now IP index, so "next IP index" but not on THIS segment
+ int travels_to_ip_index;
+
+ // index of next IP on this segment, -1 if there is no one
+ int next_ip_index;
+
+ distance_type distance; // distance-measurement from segment.first to IP
+};
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICHMENT_INFO_HPP

Added: sandbox/geometry/boost/geometry/algorithms/detail/overlay/get_relative_order.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/detail/overlay/get_relative_order.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,104 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RELATIVE_ORDER_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RELATIVE_ORDER_HPP
+
+
+#include <boost/geometry/algorithms/distance.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay {
+
+
+/*!
+ \brief Get relative order
+ \details Can indicate which of two segments R and S,
+ both crossing a common segment P, comes first.
+ If the two segments cross P very close (e.g. in a spike),
+ the distance between the intersection points can be zero,
+ but we still need to know which comes first.
+ Therefore, it is useful that using sides we are able to discover this.
+ */
+template <typename Point1>
+struct get_relative_order
+{
+ typedef strategy_intersection
+ <
+ typename cs_tag<Point1>::type,
+ Point1,
+ Point1,
+ Point1
+ > si;
+
+ typedef typename si::side_strategy_type strategy;
+
+ template <typename Point>
+ static inline int value_via_product(Point const& ti, Point const& tj,
+ Point const& ui, Point const& uj, int factor)
+ {
+ int const side_ti_u = strategy::apply(ti, tj, ui);
+ int const side_tj_u = strategy::apply(ti, tj, uj);
+
+#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
+ std::cout << (factor == 1 ? " r//s " : " s//r ")
+ << side_ti_u << " / " << side_tj_u;
+#endif
+
+ return side_ti_u * side_tj_u >= 0
+ ? factor * (side_ti_u != 0 ? side_ti_u : side_tj_u)
+ : 0;
+ }
+
+
+ static inline int apply(
+ Point1 const& pi, Point1 const& pj,
+ Point1 const& ri, Point1 const& rj,
+ Point1 const& si, Point1 const& sj)
+ {
+ int const side_ri_p = strategy::apply(pi, pj, ri);
+ int const side_si_p = strategy::apply(pi, pj, si);
+
+#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
+ int const side_rj_p = strategy::apply(pi, pj, rj);
+ int const side_sj_p = strategy::apply(pi, pj, sj);
+ std::cout << "r//p: " << side_ri_p << " / " << side_rj_p;
+ std::cout << " s//p: " << side_si_p << " / " << side_sj_p;
+#endif
+
+ int value = value_via_product(si, sj, ri, rj, 1);
+ if (value == 0)
+ {
+ value = value_via_product(ri, rj, si, sj, -1);
+ }
+
+ int const order = side_ri_p * side_ri_p * side_si_p * value;
+
+#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
+ std::cout
+ << " o: " << order
+ << std::endl << std::endl;
+#endif
+
+ return order;
+ }
+};
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RELATIVE_ORDER_HPP

Added: sandbox/geometry/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,870 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP
+
+
+#include <boost/assert.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+struct base_turn_handler
+{
+ // Returns true if both sides are opposite
+ static inline bool opposite(int side1, int side2)
+ {
+ // We cannot state side1 == -side2, because 0 == -0
+ // So either side1*side2==-1 or side1==-side2 && side1 != 0
+ return side1 * side2 == -1;
+ }
+
+ // Same side of a segment (not being 0)
+ static inline bool same(int side1, int side2)
+ {
+ return side1 * side2 == 1;
+ }
+
+ // Both continue
+ template <typename TurnInfo>
+ static inline void both(TurnInfo& ti, operation_type const op)
+ {
+ ti.operations[0].operation = op;
+ ti.operations[1].operation = op;
+ }
+
+ // If condition, first union/second intersection, else vice versa
+ template <typename TurnInfo>
+ static inline void ui_else_iu(bool condition, TurnInfo& ti)
+ {
+ ti.operations[0].operation = condition
+ ? operation_union : operation_intersection;
+ ti.operations[1].operation = condition
+ ? operation_intersection : operation_union;
+ }
+
+ // If condition, both union, else both intersection
+ template <typename TurnInfo>
+ static inline void uu_else_ii(bool condition, TurnInfo& ti)
+ {
+ ti.operations[0].operation = condition
+ ? operation_union : operation_intersection;
+ ti.operations[1].operation = condition
+ ? operation_union : operation_intersection;
+ }
+};
+
+
+template
+<
+ typename TurnInfo,
+ typename SideStrategy
+>
+struct touch_interior : public base_turn_handler
+{
+ // Index: 0, P is the interior, Q is touching and vice versa
+ template
+ <
+ int Index,
+ typename Point1,
+ typename Point2,
+ typename IntersectionInfo,
+ typename DirInfo
+ >
+ static inline void apply(
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ TurnInfo& ti,
+ IntersectionInfo const& intersection_info,
+ DirInfo const& dir_info)
+ {
+ ti.method = method_touch_interior;
+ copy_coordinates(intersection_info.intersections[0], ti.point);
+
+ // Both segments of q touch segment p somewhere in its interior
+ // 1) We know: if q comes from LEFT or RIGHT
+ // (i.e. dir_info.sides.get<Index,0>() == 1 or -1)
+ // 2) Important is: if q_k goes to LEFT, RIGHT, COLLINEAR
+ // and, if LEFT/COLL, if it is lying LEFT or RIGHT w.r.t. q_i
+
+ static int const index_p = Index;
+ static int const index_q = 1 - Index;
+
+ int const side_qi_p = dir_info.sides.get<index_q, 0>();
+ int const side_qk_p = SideStrategy::apply(pi, pj, qk);
+
+ if (side_qi_p == -side_qk_p)
+ {
+ // Q crosses P from left->right or from right->left (test "ML1")
+ // Union: folow P (left->right) or Q (right->left)
+ // Intersection: other turn
+ int index = side_qk_p == -1 ? index_p : index_q;
+ ti.operations[index].operation = operation_union;
+ ti.operations[1 - index].operation = operation_intersection;
+ return;
+ }
+
+ int const side_qk_q = SideStrategy::apply(qi, qj, qk);
+
+ if (side_qi_p == -1 && side_qk_p == -1 && side_qk_q == 1)
+ {
+ // Q turns left on the right side of P (test "MR3")
+ // Both directions for "intersection"
+ both(ti, operation_intersection);
+ }
+ else if (side_qi_p == 1 && side_qk_p == 1 && side_qk_q == -1)
+ {
+ // Q turns right on the left side of P (test "ML3")
+ // Union: take both operation
+ // Intersection: skip
+ both(ti, operation_union);
+ }
+ else if (side_qi_p == side_qk_p && side_qi_p == side_qk_q)
+ {
+ // Q turns left on the left side of P (test "ML2")
+ // or Q turns right on the right side of P (test "MR2")
+ // Union: take left turn (Q if Q turns left, P if Q turns right)
+ // Intersection: other turn
+ int index = side_qk_q == 1 ? index_q : index_p;
+ ti.operations[index].operation = operation_union;
+ ti.operations[1 - index].operation = operation_intersection;
+ }
+ else if (side_qk_p == 0)
+ {
+ // Q intersects on interior of P and continues collinearly
+ if (side_qk_q == side_qi_p)
+ {
+ // Collinearly in the same direction
+ // (Q comes from left of P and turns left,
+ // OR Q comes from right of P and turns right)
+ // Omit intersection point.
+ // Union: just continue
+ // Intersection: just continue
+ both(ti, operation_continue);
+ }
+ else
+ {
+ // Opposite direction, which is never travelled.
+ // If Q turns left, P continues for intersection
+ // If Q turns right, P continues for union
+ ti.operations[Index].operation = side_qk_q == 1
+ ? operation_intersection
+ : operation_union;
+ ti.operations[1 - Index].operation = operation_blocked;
+ }
+ }
+ else
+ {
+ // Should not occur!
+ ti.method = method_error;
+ }
+ }
+};
+
+
+template
+<
+ typename TurnInfo,
+ typename SideStrategy
+>
+struct touch : public base_turn_handler
+{
+ static inline bool between(int side1, int side2, int turn)
+ {
+ return side1 == side2 && ! opposite(side1, turn);
+ }
+
+ static inline void block_second(bool block, TurnInfo& ti)
+ {
+ if (block)
+ {
+ ti.operations[1].operation = operation_blocked;
+ }
+ }
+
+
+ template
+ <
+ typename Point1,
+ typename Point2,
+ typename IntersectionInfo,
+ typename DirInfo
+ >
+ static inline void apply(
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ TurnInfo& ti,
+ IntersectionInfo const& intersection_info,
+ DirInfo const& dir_info)
+ {
+ ti.method = method_touch;
+ copy_coordinates(intersection_info.intersections[0], ti.point);
+
+ int const side_qi_p1 = dir_info.sides.get<1, 0>();
+ int const side_qk_p1 = SideStrategy::apply(pi, pj, qk);
+
+
+ // If Qi and Qk are both at same side of Pi-Pj,
+ // or collinear (so: not opposite sides)
+ if (! opposite(side_qi_p1, side_qk_p1))
+ {
+ int const side_pk_q2 = SideStrategy::apply(qj, qk, pk);
+ int const side_pk_p = SideStrategy::apply(pi, pj, pk);
+ int const side_qk_q = SideStrategy::apply(qi, qj, qk);
+ bool const q_turns_left = side_qk_q == 1;
+ bool const block_q = side_qk_p1 == 0
+ && ! same(side_qi_p1, side_qk_q);
+
+ // If Pk at same side as Qi/Qk
+ // (the "or" is for collinear case)
+ // or Q is fully collinear && P turns not to left
+ if (side_pk_p == side_qi_p1
+ || side_pk_p == side_qk_p1
+ || (side_qi_p1 == 0 && side_qk_p1 == 0 && side_pk_p != -1)
+ )
+ {
+ // Collinear -> lines join, continue
+ // (#BRL2)
+ if (side_pk_q2 == 0)
+ {
+ both(ti, operation_continue);
+ return;
+ }
+
+ int const side_pk_q1 = SideStrategy::apply(qi, qj, pk);
+
+
+ // Collinear opposite case -> block P
+ // (#BRL4, #BLR8)
+ if (side_pk_q1 == 0)
+ {
+ ti.operations[0].operation = operation_blocked;
+ // Q turns right -> union (both independant),
+ // Q turns left -> intersection
+ ti.operations[1].operation = block_q ? operation_blocked
+ : q_turns_left ? operation_intersection
+ : operation_union;
+ return;
+ }
+
+ // Pk between Qi and Qk
+ // (#BRL3, #BRL7)
+ if (between(side_pk_q1, side_pk_q2, side_qk_q))
+ {
+ ui_else_iu(q_turns_left, ti);
+ block_second(block_q, ti);
+ return;
+ }
+
+ // Pk between Qk and P, so left of Qk (if Q turns right) and vv
+ // (#BRL1)
+ if (side_pk_q2 == -side_qk_q)
+ {
+ ui_else_iu(! q_turns_left, ti);
+ return;
+ }
+
+ //
+ // (#BRL5, #BRL9)
+ if (side_pk_q1 == -side_qk_q)
+ {
+ uu_else_ii(! q_turns_left, ti);
+ block_second(block_q, ti);
+ return;
+ }
+ }
+ else
+ {
+ // Pk at other side than Qi/Pk
+ int const side_qk_q = SideStrategy::apply(qi, qj, qk);
+ bool const q_turns_left = side_qk_q == 1;
+
+ ti.operations[0].operation = q_turns_left
+ ? operation_intersection
+ : operation_union;
+ ti.operations[1].operation = block_q
+ ? operation_blocked
+ : side_qi_p1 == 1 || side_qk_p1 == 1
+ ? operation_union
+ : operation_intersection;
+
+ return;
+ }
+ }
+ else
+ {
+ // From left to right or from right to left
+ int const side_pk_p = SideStrategy::apply(pi, pj, pk);
+ bool const right_to_left = side_qk_p1 == 1;
+
+ // If p turns into direction of qi (1,2)
+ if (side_pk_p == side_qi_p1)
+ {
+ int const side_pk_q1 = SideStrategy::apply(qi, qj, pk);
+
+ // Collinear opposite case -> block P
+ if (side_pk_q1 == 0)
+ {
+ ti.operations[0].operation = operation_blocked;
+ ti.operations[1].operation = right_to_left
+ ? operation_union : operation_intersection;
+ return;
+ }
+
+ if (side_pk_q1 == side_qk_p1)
+ {
+ uu_else_ii(right_to_left, ti);
+ return;
+ }
+ }
+
+ // If p turns into direction of qk (4,5)
+ if (side_pk_p == side_qk_p1)
+ {
+ int const side_pk_q2 = SideStrategy::apply(qj, qk, pk);
+
+ // Collinear case -> lines join, continue
+ if (side_pk_q2 == 0)
+ {
+ both(ti, operation_continue);
+ return;
+ }
+ if (side_pk_q2 == side_qk_p1)
+ {
+ ui_else_iu(right_to_left, ti);
+ return;
+ }
+ }
+ // otherwise (3)
+ ui_else_iu(! right_to_left, ti);
+ return;
+ }
+
+ std::cout << "Not yet handled" << std::endl;
+ }
+};
+
+
+template
+<
+ typename TurnInfo,
+ typename SideStrategy
+>
+struct equal : public base_turn_handler
+{
+ template
+ <
+ typename Point1,
+ typename Point2,
+ typename IntersectionInfo,
+ typename DirInfo
+ >
+ static inline void apply(
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ TurnInfo& ti,
+ IntersectionInfo const& intersection_info,
+ DirInfo const& dir_info)
+ {
+ ti.method = method_equal;
+ // Copy the SECOND intersection point
+ copy_coordinates(intersection_info.intersections[1], ti.point);
+
+ int const side_pk_q2 = SideStrategy::apply(qj, qk, pk);
+ int const side_pk_p = SideStrategy::apply(pi, pj, pk);
+ int const side_qk_p = SideStrategy::apply(pi, pj, qk);
+
+ // If pk is collinear with qj-qk, they continue collinearly.
+ // This can be on either side of p1 (== q1), or collinear
+ // The second condition checks if they do not continue
+ // oppositely
+ if (side_pk_q2 == 0 && side_pk_p == side_qk_p)
+ {
+ both(ti, operation_continue);
+ return;
+ }
+
+
+ // If they turn to same side (not opposite sides)
+ if (! opposite(side_pk_p, side_qk_p))
+ {
+ int const side_pk_q2 = SideStrategy::apply(qj, qk, pk);
+
+ // If pk is left of q2 or collinear: p: union, q: intersection
+ ui_else_iu(side_pk_q2 != -1, ti);
+ }
+ else
+ {
+ // They turn opposite sides. If p turns left (or collinear),
+ // p: union, q: intersection
+ ui_else_iu(side_pk_p != -1, ti);
+ }
+ }
+};
+
+
+template
+<
+ typename TurnInfo,
+ typename SideStrategy
+>
+struct collinear : public base_turn_handler
+{
+ /*
+ arrival P pk//p1 qk//q1 product* case result
+ 1 1 1 CLL1 ui
+ -1 1 -1 CLL2 iu
+ 1 1 1 CLR1 ui
+ -1 -1 1 CLR2 ui
+
+ 1 -1 -1 CRL1 iu
+ -1 1 -1 CRL2 iu
+ 1 -1 -1 CRR1 iu
+ -1 -1 1 CRR2 ui
+
+ 1 0 0 CC1 cc
+ -1 0 0 CC2 cc
+
+ *product = arrival * (pk//p1 or qk//q1)
+
+ Stated otherwise:
+ - if P arrives: look at turn P
+ - if Q arrives: look at turn Q
+ - if P arrives and P turns left: union for P
+ - if P arrives and P turns right: intersection for P
+ - if Q arrives and Q turns left: union for Q (=intersection for P)
+ - if Q arrives and Q turns right: intersection for Q (=union for P)
+ */
+ template
+ <
+ typename Point1,
+ typename Point2,
+ typename IntersectionInfo,
+ typename DirInfo
+ >
+ static inline void apply(
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ TurnInfo& ti,
+ IntersectionInfo const& intersection_info,
+ DirInfo const& dir_info)
+ {
+ ti.method = method_collinear;
+ copy_coordinates(intersection_info.intersections[1], ti.point);
+
+ int const arrival = dir_info.arrival[0];
+ // Should not be 0, this is checked before
+ BOOST_ASSERT(arrival != 0);
+
+ // If p arrives, use p, else use q
+ int const side_p_or_q = arrival == 1
+ ? SideStrategy::apply(pi, pj, pk)
+ : SideStrategy::apply(qi, qj, qk)
+ ;
+
+ // See comments above,
+ // resulting in a strange sort of mathematic rule here:
+ // The arrival-info multiplied by the relevant side
+ // delivers a consistent result.
+
+ int const product = arrival * side_p_or_q;
+
+ if(product == 0)
+ {
+ both(ti, operation_continue);
+ }
+ else
+ {
+ ui_else_iu(product == 1, ti);
+ }
+ }
+};
+
+template
+<
+ typename TurnInfo,
+ typename SideStrategy,
+ typename AssignPolicy
+>
+struct collinear_opposite : public base_turn_handler
+{
+private :
+ /*
+ arrival P arrival Q pk//p1 qk//q1 case result2 result
+ --------------------------------------------------------------
+ 1 1 1 -1 CLO1 ix xu
+ 1 1 1 0 CLO2 ix (xx)
+ 1 1 1 1 CLO3 ix xi
+
+ 1 1 0 -1 CCO1 (xx) xu
+ 1 1 0 0 CCO2 (xx) (xx)
+ 1 1 0 1 CCO3 (xx) xi
+
+ 1 1 -1 -1 CRO1 ux xu
+ 1 1 -1 0 CRO2 ux (xx)
+ 1 1 -1 1 CRO3 ux xi
+
+ -1 1 -1 CXO1 xu
+ -1 1 0 CXO2 (xx)
+ -1 1 1 CXO3 xi
+
+ 1 -1 1 CXO1 ix
+ 1 -1 0 CXO2 (xx)
+ 1 -1 -1 CXO3 ux
+ */
+
+ template
+ <
+ int Index,
+ typename Point,
+ typename IntersectionInfo
+ >
+ static inline bool set_tp(Point const& ri, Point const& rj, Point const& rk,
+ TurnInfo& tp, IntersectionInfo const& intersection_info)
+ {
+ int const side_rk_r = SideStrategy::apply(ri, rj, rk);
+ switch(side_rk_r)
+ {
+
+ case 1 :
+ // Turning left on opposite collinear: intersection
+ tp.operations[Index].operation = operation_intersection;
+ break;
+ case -1 :
+ // Turning right on opposite collinear: union
+ tp.operations[Index].operation = operation_union;
+ break;
+ case 0 :
+ // No turn on opposite collinear: block, do not traverse
+ // But this "xx" is ignored here, it is useless to include
+ // two operation blocked, so the whole point does not need
+ // to be generated.
+ // So return false to indicate nothing is to be done.
+ return false;
+ }
+
+ // The other direction is always blocked when collinear opposite
+ tp.operations[1 - Index].operation = operation_blocked;
+
+ // If P arrives within Q, set info on P (which is done above, index=0),
+ // this turn-info belongs to the second intersection point, index=1
+ // (see e.g. figure CLO1)
+ copy_coordinates(intersection_info.intersections[1 - Index], tp.point);
+ return true;
+ }
+
+public:
+ template
+ <
+ typename Point1,
+ typename Point2,
+ typename OutputIterator,
+ typename IntersectionInfo,
+ typename DirInfo
+ >
+ static inline void apply(
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,
+
+ // Opposite collinear can deliver 2 intersection points,
+ TurnInfo const& tp_model,
+ OutputIterator& out,
+
+ IntersectionInfo const& intersection_info,
+ DirInfo const& dir_info)
+ {
+ /*
+ std::cout << "arrivals: "
+ << dir_info.arrival[0]
+ << "/" << dir_info.arrival[1]
+ << std::endl;
+ */
+
+ TurnInfo tp = tp_model;
+
+ tp.method = method_collinear;
+
+ // If P arrives within Q, there is a turn dependant on P
+ if (dir_info.arrival[0] == 1
+ && set_tp<0>(pi, pj, pk, tp, intersection_info))
+ {
+ AssignPolicy::apply(tp, pi, qi);
+ *out++ = tp;
+ }
+
+ // If Q arrives within P, there is a turn dependant on Q
+ if (dir_info.arrival[1] == 1
+ && set_tp<1>(qi, qj, qk, tp, intersection_info))
+ {
+ AssignPolicy::apply(tp, pi, qi);
+ *out++ = tp;
+ }
+ }
+};
+
+
+template
+<
+ typename TurnInfo,
+ typename SideStrategy
+>
+struct crosses : public base_turn_handler
+{
+ template
+ <
+ typename Point1,
+ typename Point2,
+ typename IntersectionInfo,
+ typename DirInfo
+ >
+ static inline void apply(
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ TurnInfo& ti,
+ IntersectionInfo const& intersection_info,
+ DirInfo const& dir_info)
+ {
+ ti.method = method_crosses;
+ copy_coordinates(intersection_info.intersections[0], ti.point);
+
+ // In all casees:
+ // If Q crosses P from left to right
+ // Union: take P
+ // Intersection: take Q
+ // Otherwise: vice versa
+ int const side_qi_p1 = dir_info.sides.get<1, 0>();
+ int const index = side_qi_p1 == 1 ? 0 : 1;
+ ti.operations[index].operation = operation_union;
+ ti.operations[1 - index].operation = operation_intersection;
+ }
+};
+
+
+/*!
+ \brief Policy doing nothing
+ \details get_turn_info can have an optional policy to get some
+ extra information. By default it does not, and this class
+ is that default.
+ */
+struct NullPolicy
+{
+ template <typename Point1, typename Point2, typename Info>
+ static inline void apply(Info& info, Point1 const& p1, Point2 const& p2)
+ {}
+
+};
+
+
+/*!
+ \brief Turn information: intersection point, method, and turn information
+ \details Information necessary for traversal phase (a phase
+ of the overlay process). The information is gathered during the
+ get_turns (segment intersection) phase.
+ \tparam Point1 point type of first segment
+ \tparam Point2 point type of second segment
+ \tparam TurnInfo type of class getting intersection and turn info
+ \tparam AssignPolicy optional policy to assign extra info,
+ e.g. to calculate distance from segment's first points
+ to intersection points
+ */
+template
+<
+ typename Point1,
+ typename Point2,
+ typename TurnInfo,
+ typename AssignPolicy = NullPolicy
+>
+struct get_turn_info
+{
+ typedef strategy_intersection
+ <
+ typename cs_tag<typename TurnInfo::point_type>::type,
+ Point1,
+ Point2,
+ typename TurnInfo::point_type
+ > si;
+
+ typedef typename si::segment_intersection_strategy_type strategy;
+
+
+
+ template <typename OutputIterator>
+ static inline void apply(
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ TurnInfo const& tp_model,
+ OutputIterator out)
+ {
+ typedef segment<Point1 const> segment_type1;
+ typedef segment<Point1 const> segment_type2;
+ segment_type1 p1(pi, pj), p2(pj, pk);
+ segment_type2 q1(qi, qj), q2(qj, qk);
+
+ typename strategy::return_type result = strategy::apply(p1, q1);
+
+ char const method = result.get<1>().how;
+
+ // Copy, to copy possibly extended fields
+ TurnInfo tp = tp_model;
+
+
+ // Select method and apply
+ switch(method)
+ {
+ case 'a' :
+ case 'f' :
+ case 's' :
+ case 'd' :
+ break;
+
+ case 'm' :
+ {
+ typedef touch_interior
+ <
+ TurnInfo,
+ typename si::side_strategy_type
+ > policy;
+
+ // If Q (1) arrives (1)
+ if (result.get<1>().arrival[1] == 1)
+ {
+ policy::template apply<0>(pi, pj, pk, qi, qj, qk,
+ tp, result.get<0>(), result.get<1>());
+ }
+ else
+ {
+ // Swap p/q
+ policy::template apply<1>(qi, qj, qk, pi, pj, pk,
+ tp, result.get<0>(), result.get<1>());
+ }
+ AssignPolicy::apply(tp, pi, qi);
+ *out++ = tp;
+ }
+ break;
+ case 'i' :
+ {
+ typedef crosses
+ <
+ TurnInfo,
+ typename si::side_strategy_type
+ > policy;
+
+ policy::apply(pi, pj, pk, qi, qj, qk,
+ tp, result.get<0>(), result.get<1>());
+ AssignPolicy::apply(tp, pi, qi);
+ *out++ = tp;
+ }
+ break;
+ case 't' :
+ {
+ // Both touch (both arrive there)
+ typedef touch
+ <
+ TurnInfo,
+ typename si::side_strategy_type
+ > policy;
+
+ policy::apply(pi, pj, pk, qi, qj, qk,
+ tp, result.get<0>(), result.get<1>());
+ AssignPolicy::apply(tp, pi, qi);
+ *out++ = tp;
+ }
+ break;
+ case 'e':
+ {
+ if (! result.get<1>().opposite)
+ {
+ // Both equal
+ // or collinear-and-ending at intersection point
+ typedef equal
+ <
+ TurnInfo,
+ typename si::side_strategy_type
+ > policy;
+
+ policy::apply(pi, pj, pk, qi, qj, qk,
+ tp, result.get<0>(), result.get<1>());
+ AssignPolicy::apply(tp, pi, qi);
+ *out++ = tp;
+ }
+ // If they ARE opposite, don't do anything.
+ }
+ break;
+ case 'c' :
+ {
+ // Collinear
+ if (! result.get<1>().opposite)
+ {
+
+ if (result.get<1>().arrival[0] == 0)
+ {
+ // Collinear, but similar thus handled as equal
+ equal
+ <
+ TurnInfo,
+ typename si::side_strategy_type
+ >::apply(pi, pj, pk, qi, qj, qk,
+ tp, result.get<0>(), result.get<1>());
+
+ // override assigned method
+ tp.method = method_collinear;
+ }
+ else
+ {
+ collinear
+ <
+ TurnInfo,
+ typename si::side_strategy_type
+ >::apply(pi, pj, pk, qi, qj, qk,
+ tp, result.get<0>(), result.get<1>());
+ }
+
+ AssignPolicy::apply(tp, pi, qi);
+ *out++ = tp;
+ }
+ else
+ {
+ collinear_opposite
+ <
+ TurnInfo,
+ typename si::side_strategy_type,
+ AssignPolicy
+ >::apply(pi, pj, pk, qi, qj, qk,
+ tp, out, result.get<0>(), result.get<1>());
+ }
+ }
+ break;
+ case '0' :
+ // degenerate points
+ break;
+ default :
+ std::cout << "get_turns, nyi: " << method << std::endl;
+ }
+ }
+};
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP

Added: sandbox/geometry/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/detail/overlay/ring_properties.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,245 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2010, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALG_DET_OV_RING_PROPERTIES_HPP
+#define BOOST_GEOMETRY_ALG_DET_OV_RING_PROPERTIES_HPP
+
+#define BOOST_GEOMETRY_ASSEMBLE_PARENT_DEQUE
+#ifdef BOOST_GEOMETRY_ASSEMBLE_PARENT_DEQUE
+#include <deque>
+#else
+#include <boost/array.hpp>
+#endif
+
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>
+
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
+
+#include <boost/geometry/geometries/box.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+template <typename Point>
+struct ring_properties
+{
+ struct parent
+ {
+ int c;
+ ring_identifier id;
+
+ inline parent()
+ : c(0)
+ {}
+
+ inline parent(int c_, ring_identifier i)
+ : c(c_), id(i)
+ {}
+ };
+
+#ifdef BOOST_GEOMETRY_ASSEMBLE_PARENT_DEQUE
+ inline void push(parent const& p)
+ {
+ parents.push_back(p);
+ }
+ inline void pop()
+ {
+ parents.pop_back();
+ }
+ inline bool parent_stack_empty() const
+ {
+ return parents.empty();
+ }
+#else
+ inline void push(parent const& p)
+ {
+ parents[array_size++] = p;
+ }
+ inline void pop()
+ {
+ array_size--;
+ }
+ inline bool parent_stack_empty() const
+ {
+ return array_size == 0;
+ }
+#endif
+
+
+ inline bool interior_included(int direction) const
+ {
+ if (area < 0 && ! parent_stack_empty())
+ {
+ // Inner rings are included if the last encountered parent
+ // matches the operation
+#ifdef BOOST_GEOMETRY_ASSEMBLE_PARENT_DEQUE
+ int d = parents.back().c;
+ if (d == 0
+ && parents.size() == 2
+ && parents.front().c == 0)
+#else
+ int d = parents[array_size - 1].c;
+ if (d == 0
+ && array_size == 2
+ && parents[0].c == 0)
+#endif
+ {
+ // It is contained by two outer rings, both of them
+ // are not included in the other. So they must be
+ // equal. Then always included, both in union and
+ // in intersection.
+ return direction == -1;
+ }
+
+ if (d == 0)
+ {
+ d = 1;
+ }
+ return d * direction == 1;
+ }
+ return false;
+ }
+
+ inline bool included(int direction) const
+ {
+ if (produced)
+ {
+ // Traversed rings are included in all operations,
+ // because traversal was direction-dependant.
+ return true;
+ }
+ if (intersects)
+ {
+ // Original rings which have intersections should
+ // always be skipped
+ return false;
+ }
+
+ if (area > 0)
+ {
+ // Outer rings are included if they don't have parents
+ // (union) or have parents (intersection)
+ return (parent_stack_empty() ? 1 : -1) * direction == 1;
+ }
+ else if (area < 0 && ! parent_stack_empty())
+ {
+ // Inner rings are included if the last encountered parent
+ // matches the operation
+ return interior_included(direction);
+ }
+ return false;
+ }
+
+ typedef Point point_type;
+ typedef geometry::box<Point> box_type;
+
+ ring_identifier ring_id;
+ typename area_result<Point>::type area;
+
+ int c;
+ bool intersects;
+ bool produced;
+
+ // Stack of non-intersecting parent rings.
+ // This denotes if it a negative ring should be included,
+ // and which is the parent.
+#ifdef BOOST_GEOMETRY_ASSEMBLE_PARENT_DEQUE
+ std::deque<parent> parents;
+#else
+ parent parents[3];
+ int array_size;
+#endif
+
+ // If the parent is an intersecting ring, take
+ // this as the parent.
+ ring_identifier parent_id;
+ bool has_parent_id;
+
+
+ box_type box;
+
+ point_type point;
+ bool has_point;
+
+ inline ring_properties()
+ : c(0)
+ , intersects(false)
+ , produced(false)
+ , has_point(false)
+ , has_parent_id(false)
+#ifndef BOOST_GEOMETRY_ASSEMBLE_PARENT_DEQUE
+ , array_size(0)
+#endif
+ {}
+
+ template <typename Geometry>
+ inline ring_properties(ring_identifier id, Geometry const& geometry,
+ bool i, bool p = false)
+ : ring_id(id)
+ , area(geometry::area(geometry))
+ , c(0)
+ , intersects(i)
+ , produced(p)
+ , has_parent_id(false)
+ , box(geometry::make_envelope<box_type>(geometry))
+#ifndef BOOST_GEOMETRY_ASSEMBLE_PARENT_DEQUE
+ , array_size(0)
+#endif
+ {
+ has_point = geometry::point_on_border(point, geometry);
+ }
+
+ inline bool operator<(ring_properties<Point> const& other) const
+ {
+ // Normal sorting: in reverse order
+ return std::abs(area) > std::abs(other.area);
+ }
+
+ inline ring_identifier const& id() const
+ {
+ if (has_parent_id)
+ {
+ return parent_id;
+ }
+ return parent_stack_empty() || area > 0
+ ? ring_id
+#ifdef BOOST_GEOMETRY_ASSEMBLE_PARENT_DEQUE
+ : parents.back().id;
+#else
+ : parents[array_size - 1].id;
+#endif
+ }
+
+
+};
+
+
+template<typename Prop>
+struct sort_on_id_or_parent_id
+{
+ inline bool operator()(Prop const& left, Prop const& right) const
+ {
+ ring_identifier const& left_id = left.id();
+ ring_identifier const& right_id = right.id();
+
+ // If it is the same, sort on size descending
+ return left_id == right_id
+ ? std::abs(left.area) > std::abs(right.area)
+ : left_id < right_id;
+ }
+};
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALG_DET_OV_RING_PROPERTIES_HPP

Added: sandbox/geometry/boost/geometry/algorithms/detail/overlay/traversal_info.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/detail/overlay/traversal_info.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,47 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_INFO_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_INFO_HPP
+
+
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
+#include <boost/geometry/algorithms/detail/overlay/visit_info.hpp>
+#include <boost/geometry/algorithms/overlay/segment_identifier.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay {
+
+
+template <typename P>
+struct traversal_turn_operation : public turn_operation
+{
+ segment_identifier seg_id;
+ segment_identifier other_id;
+ enrichment_info<P> enriched;
+ visit_info visited;
+};
+
+template <typename P>
+struct traversal_turn_info : public turn_info<P, traversal_turn_operation<P> >
+{};
+
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_INFO_HPP

Added: sandbox/geometry/boost/geometry/algorithms/detail/overlay/turn_info.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/detail/overlay/turn_info.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,103 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TURN_INFO_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TURN_INFO_HPP
+
+#include <boost/array.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay {
+
+
+enum operation_type
+{
+ operation_none,
+ operation_union,
+ operation_intersection,
+ operation_blocked,
+ operation_continue
+};
+
+
+enum method_type
+{
+ method_none,
+ method_disjoint,
+ method_crosses,
+ method_touch,
+ method_touch_interior,
+ method_collinear,
+ method_equal,
+ method_error
+};
+
+
+/*!
+ \brief Turn operation: operation
+ \details Information necessary for traversal phase (a phase
+ of the overlay process). The information is gathered during the
+ get_turns (segment intersection) phase.
+ The class is to be included in the turn_info class, either direct
+ or a derived or similar class with more (e.g. enrichment) information.
+ */
+struct turn_operation
+{
+ operation_type operation;
+
+ turn_operation()
+ : operation(operation_none)
+ {}
+};
+
+
+/*!
+ \brief Turn information: intersection point, method, and turn information
+ \details Information necessary for traversal phase (a phase
+ of the overlay process). The information is gathered during the
+ get_turns (segment intersection) phase.
+ \tparam Point point type of intersection point
+ \tparam Operation gives classes opportunity to add additional info
+ \tparam Container gives classes opportunity to define how operations are stored
+ */
+template
+<
+ typename Point,
+ typename Operation = turn_operation,
+ typename Container = boost::array<Operation, 2>
+>
+struct turn_info
+{
+ typedef Point point_type;
+ typedef Operation operation_type;
+ typedef Container container_type;
+
+ Point point;
+ method_type method;
+
+ Container operations;
+
+ turn_info()
+ : method(method_none)
+ {}
+
+};
+
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TURN_INFO_HPP

Added: sandbox/geometry/boost/geometry/algorithms/detail/overlay/visit_info.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/detail/overlay/visit_info.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,115 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_VISIT_INFO_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_VISIT_INFO_HPP
+
+
+#ifdef BOOST_GEOMETRY_USE_MSM
+# include <boost/geometry/algorithms/overlay/msm_state.hpp>
+#endif
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay {
+
+
+#if ! defined(BOOST_GEOMETRY_USE_MSM)
+
+class visit_info
+{
+private :
+ static const int NONE = 0;
+ static const int STARTED = 1;
+ static const int VISITED = 2;
+ static const int FINISHED = 3;
+
+ int visit_code;
+
+public:
+ inline visit_info()
+ : visit_code(0)
+ {}
+
+ inline void set_none() { visit_code = NONE; }
+ inline void set_visited() { visit_code = VISITED; }
+ inline void set_started() { visit_code = STARTED; }
+ inline void set_finished() { visit_code = FINISHED; }
+
+ inline bool none() const { return visit_code == NONE; }
+ inline bool visited() const { return visit_code == VISITED; }
+ inline bool started() const { return visit_code == STARTED; }
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ friend std::ostream& operator<<(std::ostream &os, visit_info const& v)
+ {
+ if (v.visit_code != 0)
+ {
+ os << " VIS: " << int(v.visit_code);
+ }
+ return os;
+ }
+#endif
+
+};
+
+
+#else
+
+
+class visit_info
+{
+
+private :
+
+#ifndef USE_MSM_MINI
+ mutable
+#endif
+ traverse_state state;
+
+public :
+ inline visit_info()
+ {
+ state.start();
+ }
+
+ inline void set_none() { state.process_event(none()); } // Not Yet Implemented!
+ inline void set_visited() { state.process_event(visit()); }
+ inline void set_started() { state.process_event(starting()); }
+ inline void set_finished() { state.process_event(finish()); }
+
+#ifdef USE_MSM_MINI
+ inline bool none() const { return state.flag_none(); }
+ inline bool visited() const { return state.flag_visited(); }
+ inline bool started() const { return state.flag_started(); }
+#else
+ inline bool none() const { return state.is_flag_active<is_init>(); }
+ inline bool visited() const { return state.is_flag_active<is_visited>(); }
+ inline bool started() const { return state.is_flag_active<is_started>(); }
+#endif
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ friend std::ostream& operator<<(std::ostream &os, visit_info const& v)
+ {
+ return os;
+ }
+#endif
+};
+#endif
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_VISIT_INFO_HPP

Added: sandbox/geometry/boost/geometry/algorithms/detail/point_on_border.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/detail/point_on_border.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,235 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2010, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.Dimension. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
+
+
+#include <boost/range/functions.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/detail/disjoint.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace point_on_border
+{
+
+
+template<typename Point>
+struct get_point
+{
+ static inline bool apply(Point& destination, Point const& source, bool)
+ {
+ destination = source;
+ return true;
+ }
+};
+
+template<typename Point, std::size_t Dimension, std::size_t DimensionCount>
+struct midpoint_helper
+{
+ static inline bool apply(Point& p, Point const& p1, Point const& p2)
+ {
+ typename coordinate_type<Point>::type const two = 2;
+ set<Dimension>(p,
+ (get<Dimension>(p1) + get<Dimension>(p2)) / two);
+ return midpoint_helper<Point, Dimension + 1, DimensionCount>::apply(p, p1, p2);
+ }
+};
+
+
+template <typename Point, std::size_t DimensionCount>
+struct midpoint_helper<Point, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Point& , Point const& , Point const& )
+ {
+ return true;
+ }
+};
+
+
+template<typename Point, typename Range>
+struct point_on_range
+{
+ static inline bool apply(Point& point, Range const& range, bool midpoint)
+ {
+ const std::size_t n = boost::size(range);
+ if (midpoint && n > 1)
+ {
+ typedef typename boost::range_iterator
+ <
+ Range const
+ >::type iterator;
+
+ iterator it = boost::begin(range);
+ iterator prev = it++;
+ while (detail::equals::equals_point_point(*it, *prev)
+ && it != boost::end(range))
+ {
+ prev = it++;
+ }
+ if (it != boost::end(range))
+ {
+ return midpoint_helper
+ <
+ Point,
+ 0, dimension<Point>::value
+ >::apply(point, *prev, *it);
+ }
+ }
+
+ if (n > 0)
+ {
+ point = *boost::begin(range);
+ return true;
+ }
+ return false;
+ }
+};
+
+
+template<typename Point, typename Polygon>
+struct point_on_polygon
+{
+ static inline bool apply(Point& point, Polygon const& polygon, bool midpoint)
+ {
+ return point_on_range
+ <
+ Point,
+ typename ring_type<Polygon>::type
+ >::apply(point, exterior_ring(polygon), midpoint);
+ }
+};
+
+
+template<typename Point, typename Box>
+struct point_on_box
+{
+ static inline bool apply(Point& point, Box const& box, bool midpoint)
+ {
+ if (midpoint)
+ {
+ Point p1, p2;
+ detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, p1);
+ detail::assign::assign_box_2d_corner<max_corner, min_corner>(box, p2);
+ midpoint_helper
+ <
+ Point,
+ 0, dimension<Point>::value
+ >::apply(point, p1, p2);
+ }
+ else
+ {
+ detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, point);
+ }
+
+ return true;
+ }
+};
+
+
+}} // namespace detail::point_on_border
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename GeometryTag,
+ typename Point,
+ typename Geometry
+
+>
+struct point_on_border
+{};
+
+
+template<typename Point>
+struct point_on_border<point_tag, Point, Point>
+ : detail::point_on_border::get_point<Point>
+{};
+
+
+template<typename Point, typename Linestring>
+struct point_on_border<linestring_tag, Point, Linestring>
+ : detail::point_on_border::point_on_range<Point, Linestring>
+{};
+
+
+template<typename Point, typename Ring>
+struct point_on_border<ring_tag, Point, Ring>
+ : detail::point_on_border::point_on_range<Point, Ring>
+{};
+
+
+template<typename Point, typename Polygon>
+struct point_on_border<polygon_tag, Point, Polygon>
+ : detail::point_on_border::point_on_polygon<Point, Polygon>
+{};
+
+
+template<typename Point, typename Box>
+struct point_on_border<box_tag, Point, Box>
+ : detail::point_on_border::point_on_box<Point, Box>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Take point on a border
+\ingroup overlay
+\tparam Geometry geometry type. This also defines the type of the output point
+\param point to assign
+\param geometry geometry to take point from
+\param midpoint boolean flag, true if the point should not be a vertex, but some point
+ in between of two vertices
+\return TRUE if successful, else false.
+ It is only false if polygon/line have no points
+\note for a polygon, it is always a point on the exterior ring
+\note for take_midpoint, it is not taken from two consecutive duplicate vertices,
+ (unless there are no other).
+ */
+template <typename Point, typename Geometry>
+inline bool point_on_border(Point& point,
+ Geometry const& geometry,
+ bool midpoint = false)
+{
+ concept::check<Point>();
+ concept::check<Geometry const>();
+
+ typedef typename point_type<Geometry>::type point_type;
+
+ return dispatch::point_on_border
+ <
+ typename tag<Geometry>::type,
+ Point,
+ Geometry
+ >::apply(point, geometry, midpoint);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP

Added: sandbox/geometry/boost/geometry/algorithms/detail/ring_identifier.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/detail/ring_identifier.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,58 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2010, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RING_IDENTIFIER_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RING_IDENTIFIER_HPP
+
+
+namespace boost { namespace geometry
+{
+
+
+// Ring Identifier. It is currently: source,multi,ring
+struct ring_identifier
+{
+
+ inline ring_identifier()
+ : source_index(-1)
+ , multi_index(-1)
+ , ring_index(-1)
+ {}
+
+ inline ring_identifier(int src, int mul, int rin)
+ : source_index(src)
+ , multi_index(mul)
+ , ring_index(rin)
+ {
+ }
+
+ inline bool operator<(ring_identifier const& other) const
+ {
+ return source_index != other.source_index ? source_index < other.source_index
+ : multi_index !=other.multi_index ? multi_index < other.multi_index
+ : ring_index < other.ring_index
+ ;
+ }
+
+ inline bool operator==(ring_identifier const& other) const
+ {
+ return source_index == other.source_index
+ && ring_index == other.ring_index
+ && multi_index == other.multi_index
+ ;
+ }
+
+ int source_index;
+ int multi_index;
+ int ring_index;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RING_IDENTIFIER_HPP

Added: sandbox/geometry/boost/geometry/algorithms/detail/sections/get_full_section.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/detail/sections/get_full_section.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,147 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_GET_FULL_SECTION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_GET_FULL_SECTION_HPP
+
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+
+#include <boost/geometry/iterators/range_type.hpp>
+
+#include <boost/geometry/geometries/segment.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace section
+{
+
+
+template <typename Range, typename Section, typename Iterator>
+struct full_section_range
+{
+ static inline void apply(Range const& range, Section const& section,
+ Iterator& begin, Iterator& end)
+ {
+ begin = boost::begin(range);
+ end = boost::end(range);
+ }
+};
+
+
+template <typename Polygon, typename Section, typename Iterator>
+struct full_section_polygon
+{
+ static inline void apply(Polygon const& polygon, Section const& section,
+ Iterator& begin, Iterator& end)
+ {
+ typedef typename geometry::ring_type<Polygon>::type ring_type;
+ ring_type const& ring = section.ring_index < 0
+ ? geometry::exterior_ring(polygon)
+ : geometry::interior_rings(polygon)[section.ring_index];
+
+ begin = boost::begin(ring);
+ end = boost::end(ring);
+ }
+};
+
+
+}} // namespace detail::section
+#endif
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Tag,
+ typename Geometry,
+ typename Section,
+ typename Iterator
+>
+struct get_full_section
+{};
+
+
+template <typename LineString, typename Section, typename Iterator>
+struct get_full_section<linestring_tag, LineString, Section, Iterator>
+ : detail::section::full_section_range<LineString, Section, Iterator>
+{};
+
+
+template <typename Ring, typename Section, typename Iterator>
+struct get_full_section<ring_tag, Ring, Section, Iterator>
+ : detail::section::full_section_range<Ring, Section, Iterator>
+{};
+
+
+template <typename Polygon, typename Section, typename Iterator>
+struct get_full_section<polygon_tag, Polygon, Section, Iterator>
+ : detail::section::full_section_polygon<Polygon, Section, Iterator>
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+/*!
+ \brief Get iterators for a specified section
+ \ingroup sectionalize
+ \tparam Geometry type
+ \tparam Section type of section to get from
+ \param geometry geometry which might be located in the neighborhood
+ \param section structure with section
+ \param begin begin-iterator (const iterator over points of section)
+ \param end end-iterator (const iterator over points of section)
+ \todo Create non-const version as well
+
+ */
+template <typename Geometry, typename Section>
+inline void get_full_section(Geometry const& geometry, Section const& section,
+ typename boost::range_iterator
+ <
+ typename geometry::range_type<Geometry>::type const
+ >::type& begin,
+ typename boost::range_iterator
+ <
+ typename geometry::range_type<Geometry>::type const
+ >::type& end)
+{
+ concept::check<const Geometry>();
+
+ typedef typename boost::range_iterator
+ <
+ typename geometry::range_type<Geometry>::type const
+ >::type iterator_type;
+
+ dispatch::get_full_section
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Section,
+ iterator_type
+ >::apply(geometry, section, begin, end);
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_GET_FULL_SECTION_HPP

Added: sandbox/geometry/boost/geometry/algorithms/disjoint.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/disjoint.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,215 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DISJOINT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DISJOINT_HPP
+
+
+/*!
+\defgroup disjoint disjoint: detect if geometries are not spatially related
+\details disjoint means spatially disjoint, there is no overlap of interiors
+ and boundaries, the intersection of interiors or boundaries is empty.
+
+\par Geometries:
+- \b point + \b point (= ! equals)
+- \b point + \b box (= not within or on border)
+- \b box + \b box
+- \b ring + \b box
+- \b polygon + \b box
+- \b polygon + \b ring
+- \b polygon + \b polygon
+
+*/
+
+#include <deque>
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/is_multi.hpp>
+#include <boost/geometry/core/reverse_dispatch.hpp>
+
+#include <boost/geometry/algorithms/detail/disjoint.hpp>
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>
+#include <boost/geometry/algorithms/overlay/get_intersection_points.hpp>
+#include <boost/geometry/algorithms/within.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/util/math.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace disjoint {
+
+
+template <typename Geometry1, typename Geometry2>
+struct general
+{
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ {
+
+ typedef typename geometry::point_type<Geometry1>::type point_type;
+ typedef detail::intersection::intersection_point<point_type> ip_type;
+ std::deque<ip_type> ips; // intersection points
+
+ // Get any intersection
+ geometry::get_intersection_points(geometry1, geometry2, ips);
+ if (ips.size() > 0)
+ {
+ return false;
+ }
+ // If there is no intersection of segments, they might located
+ // inside each other
+ point_type p1;
+ geometry::point_on_border(p1, geometry1);
+ if (geometry::within(p1, geometry2))
+ {
+ return false;
+ }
+
+ typename geometry::point_type<Geometry1>::type p2;
+ geometry::point_on_border(p2, geometry2);
+ if (geometry::within(p2, geometry1))
+ {
+ return false;
+ }
+
+ return true;
+ }
+};
+
+
+}} // namespace detail::disjoint
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2,
+ typename Geometry1, typename Geometry2,
+ bool IsMulti1, bool IsMulti2,
+ std::size_t DimensionCount
+>
+struct disjoint
+ : detail::disjoint::general<Geometry1, Geometry2>
+{};
+
+
+template <typename Point1, typename Point2, std::size_t DimensionCount>
+struct disjoint<point_tag, point_tag, Point1, Point2, false, false, DimensionCount>
+ : detail::disjoint::point_point<Point1, Point2, 0, DimensionCount>
+{};
+
+
+template <typename Box1, typename Box2, std::size_t DimensionCount>
+struct disjoint<box_tag, box_tag, Box1, Box2, false, false, DimensionCount>
+ : detail::disjoint::box_box<Box1, Box2, 0, DimensionCount>
+{};
+
+
+template <typename Point, typename Box, std::size_t DimensionCount>
+struct disjoint<point_tag, box_tag, Point, Box, false, false, DimensionCount>
+ : detail::disjoint::point_box<Point, Box, 0, DimensionCount>
+{};
+
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2,
+ typename G1, typename G2,
+ bool IsMulti1, bool IsMulti2,
+ std::size_t DimensionCount
+>
+struct disjoint_reversed
+{
+ static inline bool apply(G1 const& g1, G2 const& g2)
+ {
+ return disjoint
+ <
+ GeometryTag2, GeometryTag1,
+ G2, G1,
+ IsMulti2, IsMulti1,
+ DimensionCount
+ >::apply(g2, g1);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+/*!
+ \brief Calculate if two geometries are disjoint
+ \ingroup disjoint
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \return true if disjoint, else false
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool disjoint(const Geometry1& geometry1,
+ const Geometry2& geometry2)
+{
+ concept::check_concepts_and_equal_dimensions
+ <
+ const Geometry1,
+ const Geometry2
+ >();
+
+ typedef typename boost::remove_const<Geometry1>::type ncg1_type;
+ typedef typename boost::remove_const<Geometry2>::type ncg2_type;
+
+ return boost::mpl::if_c
+ <
+ reverse_dispatch<Geometry1, Geometry2>::type::value,
+ dispatch::disjoint_reversed
+ <
+ typename tag<ncg1_type>::type,
+ typename tag<ncg2_type>::type,
+ ncg1_type,
+ ncg2_type,
+ is_multi<ncg1_type>::type::value,
+ is_multi<ncg2_type>::type::value,
+ dimension<ncg1_type>::type::value
+ >,
+ dispatch::disjoint
+ <
+ typename tag<ncg1_type>::type,
+ typename tag<ncg2_type>::type,
+ ncg1_type,
+ ncg2_type,
+ is_multi<ncg1_type>::type::value,
+ is_multi<ncg2_type>::type::value,
+ dimension<ncg1_type>::type::value
+ >
+ >::type::apply(geometry1, geometry2);
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DISJOINT_HPP

Added: sandbox/geometry/boost/geometry/algorithms/distance.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/distance.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,394 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DISTANCE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DISTANCE_HPP
+
+#include <boost/mpl/if.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/is_multi.hpp>
+#include <boost/geometry/core/reverse_dispatch.hpp>
+
+#include <boost/geometry/geometries/segment.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/distance_result.hpp>
+
+/*!
+\defgroup distance distance: calculate distance between two geometries
+The distance algorithm returns the distance between two geometries.
+\par Coordinate systems and strategies:
+With help of strategies the distance function returns the appropriate distance.
+If the input is in cartesian coordinates, the Euclidian distance (Pythagoras) is calculated.
+If the input is in spherical coordinates (either degree or radian), the distance over the sphere is returned.
+If the input is in geographic coordinates, distance is calculated over the globe and returned in meters.
+
+\par Distance result:
+Depending on calculation type the distance result is either a structure, convertable
+to a double, or a double value. In case of Pythagoras it makes sense to not draw the square root in the
+strategy itself. Taking a square root is relative expensive and is not necessary when comparing distances.
+
+\par Geometries:
+Currently implemented, for both cartesian and spherical/geographic:
+- POINT - POINT
+- POINT - SEGMENT and v.v.
+- POINT - LINESTRING and v.v.
+
+Not yet implemented:
+- POINT - RING etc, note that it will return a zero if the point is anywhere within the ring
+
+\par Example:
+Example showing distance calculation of two points, in xy and in latlong coordinates
+\dontinclude doxygen_1.cpp
+\skip example_distance_point_point
+\line {
+\until }
+*/
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace distance {
+
+template <typename P1, typename P2, typename Strategy>
+struct point_to_point
+{
+ static inline typename Strategy::return_type apply(P1 const& p1,
+ P2 const& p2, Strategy const& strategy)
+ {
+ return strategy.apply(p1, p2);
+ }
+};
+
+
+template<typename Point, typename Segment, typename Strategy>
+struct point_to_segment
+{
+ static inline typename Strategy::return_type apply(Point const& point,
+ Segment const& segment, Strategy const& strategy)
+ {
+ typename strategy_distance_segment
+ <
+ typename cs_tag<Point>::type,
+ typename cs_tag<Segment>::type,
+ Point,
+ typename point_type<Segment>::type
+ >::type segment_strategy;
+
+ // See remark below.
+ // TODO: avoid .first, .second
+ return segment_strategy.apply(point, segment.first, segment.second);
+ }
+};
+
+
+template<typename P, typename L, typename PPStrategy, typename PSStrategy>
+struct point_to_linestring
+{
+ typedef typename PPStrategy::return_type return_type;
+
+ static inline return_type apply(P const& point, L const& linestring,
+ PPStrategy const& pp_strategy, PSStrategy const& ps_strategy)
+ {
+ typedef segment<const typename point_type<L>::type> segment_type;
+
+ if (boost::begin(linestring) == boost::end(linestring))
+ {
+ return return_type(0);
+ }
+
+ // line of one point: return point square_distance
+ typedef typename boost::range_const_iterator<L>::type iterator_type;
+ iterator_type it = boost::begin(linestring);
+ iterator_type prev = it++;
+ if (it == boost::end(linestring))
+ {
+ return pp_strategy.apply(point, *boost::begin(linestring));
+ }
+
+
+ // start with first segment distance
+ return_type d = ps_strategy.apply(point, *prev, *it);
+
+ // check if other segments are closer
+ prev = it++;
+ while(it != boost::end(linestring))
+ {
+ return_type ds = ps_strategy.apply(point, *prev, *it);
+ if (geometry::close_to_zero(ds))
+ {
+ return return_type(0);
+ }
+ else if (ds < d)
+ {
+ d = ds;
+ }
+ prev = it++;
+ }
+
+ return d;
+ }
+};
+
+
+
+}} // namespace detail::distance
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2,
+ typename G1, typename G2,
+ typename StrategyTag, typename Strategy,
+ bool IsMulti1, bool IsMulti2
+>
+struct distance
+{};
+
+
+template <typename P1, typename P2, typename Strategy>
+struct distance
+<
+ point_tag, point_tag,
+ P1, P2,
+ strategy_tag_distance_point_point, Strategy,
+ false, false
+> : detail::distance::point_to_point<P1, P2, Strategy>
+{};
+
+/// Point-line version 1, where point-point strategy is specified
+template <typename Point, typename Linestring, typename Strategy>
+struct distance
+<
+ point_tag, linestring_tag,
+ Point, Linestring,
+ strategy_tag_distance_point_point, Strategy,
+ false, false
+>
+{
+
+ static inline typename Strategy::return_type apply(Point const& point,
+ Linestring const& linestring,
+ Strategy const& strategy)
+ {
+ //typedef segment<const > segment_type;
+ typedef typename geometry::strategy_distance_segment
+ <
+ typename cs_tag<Point>::type,
+ typename cs_tag<Linestring>::type,
+ Point,
+ typename point_type<Linestring>::type
+ >::type ps_strategy_type;
+
+ return detail::distance::point_to_linestring
+ <
+ Point, Linestring, Strategy, ps_strategy_type
+ >::apply(point, linestring, strategy, ps_strategy_type());
+ }
+};
+
+
+/// Point-line version 2, where point-segment strategy is specified
+template <typename Point, typename Linestring, typename Strategy>
+struct distance
+<
+ point_tag, linestring_tag,
+ Point, Linestring,
+ strategy_tag_distance_point_segment, Strategy,
+ false, false
+>
+{
+ static inline typename Strategy::return_type apply(Point const& point,
+ Linestring const& linestring,
+ Strategy const& strategy)
+ {
+ typedef typename Strategy::point_strategy_type pp_strategy_type;
+ return detail::distance::point_to_linestring
+ <
+ Point, Linestring, pp_strategy_type, Strategy
+ >::apply(point, linestring, pp_strategy_type(), strategy);
+ }
+};
+
+// Point-segment version 1, with point-point strategy
+template <typename Point, typename Segment, typename Strategy>
+struct distance
+<
+ point_tag, segment_tag,
+ Point, Segment,
+ strategy_tag_distance_point_point, Strategy,
+ false, false
+> : detail::distance::point_to_segment<Point, Segment, Strategy>
+{};
+
+// Point-segment version 2, with point-segment strategy
+template <typename Point, typename Segment, typename Strategy>
+struct distance
+<
+ point_tag, segment_tag,
+ Point, Segment,
+ strategy_tag_distance_point_segment, Strategy,
+ false, false
+>
+{
+ static inline typename Strategy::return_type apply(Point const& point,
+ Segment const& segment, Strategy const& strategy)
+ {
+ // TODO: We cannot use .first and .second here.
+ // Segment strategy does not operate on segment (anymore), because:
+ // all strategies do not operate on segments anymore, because
+ // it turned out to be inconvenient (wrapping up things in segments);
+ // The SIDE strategy must operate on three different point types,
+ // and that might be for distance segment strategy as well
+ // (though not very probable).
+
+ return strategy.apply(point, segment.first, segment.second);
+ }
+};
+
+
+
+// Strictly spoken this might be in namespace <impl> again
+template
+<
+ typename GeometryTag1, typename GeometryTag2,
+ typename G1, typename G2,
+ typename StrategyTag, typename Strategy,
+ bool IsMulti1, bool IsMulti2
+>
+struct distance_reversed
+{
+ static inline typename Strategy::return_type apply(G1 const& g1,
+ G2 const& g2, Strategy const& strategy)
+ {
+ return distance
+ <
+ GeometryTag2, GeometryTag1,
+ G2, G1,
+ StrategyTag, Strategy,
+ IsMulti2, IsMulti1
+ >::apply(g2, g1, strategy);
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+/*!
+ \brief Calculate distance between two geometries with a specified strategy
+ \ingroup distance
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \tparam S point-point-distance strategy type
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \param strategy strategy to calculate distance between two points
+ \return the distance (either a double or a distance_result, (convertable to double))
+ \note The strategy can be a point-point strategy. In case of distance point-line/point-polygon
+ it may also be a point-segment strategy.
+ \par Example:
+ Example showing distance calculation of two lat long points, using the accurate Vincenty approximation
+ \dontinclude doxygen_1.cpp
+ \skip example_distance_point_point_strategy
+ \line {
+ \until }
+ */
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline typename Strategy::return_type distance(Geometry1 const& geometry1,
+ Geometry2 const& geometry2, Strategy const& strategy)
+{
+ typedef typename boost::remove_const<Geometry1>::type ncg1_type;
+ typedef typename boost::remove_const<Geometry2>::type ncg2_type;
+
+ return boost::mpl::if_
+ <
+ typename geometry::reverse_dispatch<Geometry1, Geometry2>::type,
+ dispatch::distance_reversed
+ <
+ typename tag<ncg1_type>::type,
+ typename tag<ncg2_type>::type,
+ ncg1_type,
+ ncg2_type,
+ typename strategy_tag<Strategy>::type,
+ Strategy,
+ is_multi<ncg1_type>::value,
+ is_multi<ncg2_type>::value
+ >,
+ dispatch::distance
+ <
+ typename tag<ncg1_type>::type,
+ typename tag<ncg2_type>::type,
+ ncg1_type,
+ ncg2_type,
+ typename strategy_tag<Strategy>::type,
+ Strategy,
+ is_multi<ncg1_type>::value,
+ is_multi<ncg2_type>::value
+ >
+ >::type::apply(geometry1, geometry2, strategy);
+}
+
+
+/*!
+ \brief Calculate distance between two geometries
+ \ingroup distance
+ \details The default strategy is used, belonging to the corresponding coordinate system of the geometries
+ \tparam G1 first geometry type
+ \tparam G2 second geometry type
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \return the distance (either a double or a distance result, convertable to double)
+ */
+template <typename Geometry1, typename Geometry2>
+inline typename distance_result<Geometry1, Geometry2>::type distance(
+ Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ typedef typename point_type<Geometry1>::type point1_type;
+ typedef typename point_type<Geometry2>::type point2_type;
+
+ // Define a point-point-distance-strategy
+ // for either the normal case, either the reversed case
+ typedef typename boost::mpl::if_c
+ <
+ geometry::reverse_dispatch<Geometry1, Geometry2>::type::value,
+ typename strategy_distance
+ <
+ typename cs_tag<point2_type>::type,
+ typename cs_tag<point1_type>::type,
+ point2_type,
+ point1_type
+ >::type,
+ typename strategy_distance
+ <
+ typename cs_tag<point1_type>::type,
+ typename cs_tag<point2_type>::type,
+ point1_type,
+ point2_type
+ >::type
+ >::type strategy;
+
+ return distance(geometry1, geometry2, strategy());
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DISTANCE_HPP

Added: sandbox/geometry/boost/geometry/algorithms/envelope.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/envelope.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,282 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_ENVELOPE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_ENVELOPE_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/algorithms/combine.hpp>
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+/*!
+\defgroup envelope envelope: calculate envelope (minimum bounding rectangle) of a geometry
+\par Source descriptions:
+- OGC: Envelope (): Geometry - The minimum bounding rectangle (MBR) 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)].
+
+\note Implemented in the Generic Geometry Library: The minimum bounding box,
+ always as a box, having min <= max
+
+The envelope algorithm calculates the bounding box, or envelope, of a geometry.
+There are two versions:
+- envelope, taking a reference to a box as second parameter
+- make_envelope, returning a newly constructed box (type as a template parameter
+ in the function call)
+
+\par Geometries:
+- \b point: a box with zero area, the maximum and the minimum point of the box are
+set to the point itself.
+- \b linestring, \b ring or \b range is the smallest box that contains all points of the
+ specified point sequence.
+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).
+- \b polygon, the envelope of the outer ring
+\image html envelope_polygon.png
+
+\par Example:
+Example showing envelope calculation
+\dontinclude doxygen_1.cpp
+\skip example_envelope_linestring
+\line {
+\until }
+*/
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace envelope {
+
+
+/// Calculate envelope of an 2D or 3D segment
+template<typename Geometry, typename Box>
+struct envelope_combine_one
+{
+ static inline void apply(Geometry const& geometry, Box& mbr)
+ {
+ assign_inverse(mbr);
+ geometry::combine(mbr, geometry);
+ }
+};
+
+
+/// Iterate through range (also used in multi*)
+template<typename Range, typename Box>
+inline void envelope_range_additional(Range const& range, Box& mbr)
+{
+ typedef typename boost::range_const_iterator<Range>::type iterator_type;
+
+ for (iterator_type it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ geometry::combine(mbr, *it);
+ }
+}
+
+
+
+/// Generic range dispatching struct
+template <typename Range, typename Box>
+struct envelope_range
+{
+ /// Calculate envelope of range using a strategy
+ static inline void apply(Range const& range, Box& mbr)
+ {
+ assign_inverse(mbr);
+ envelope_range_additional(range, mbr);
+ }
+};
+
+}} // namespace detail::envelope
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+// Note, the strategy is for future use (less/greater -> compare spherical
+// using other methods), defaults are OK for now.
+// However, they are already in the template methods
+
+template
+<
+ typename Tag1, typename Tag2,
+ typename Geometry, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope {};
+
+
+template
+<
+ typename Point, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope
+ <
+ point_tag, box_tag,
+ Point, Box,
+ StrategyLess, StrategyGreater
+ >
+ : detail::envelope::envelope_combine_one<Point, Box>
+{};
+
+
+template
+<
+ typename BoxIn, typename BoxOut,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope
+ <
+ box_tag, box_tag,
+ BoxIn, BoxOut,
+ StrategyLess, StrategyGreater
+ >
+ : detail::envelope::envelope_combine_one<BoxIn, BoxOut>
+{};
+
+
+template
+<
+ typename Segment, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope
+ <
+ segment_tag, box_tag,
+ Segment, Box,
+ StrategyLess, StrategyGreater
+ >
+ : detail::envelope::envelope_combine_one<Segment, Box>
+{};
+
+
+template
+<
+ typename Linestring, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope
+ <
+ linestring_tag, box_tag,
+ Linestring, Box,
+ StrategyLess, StrategyGreater
+ >
+ : detail::envelope::envelope_range<Linestring, Box>
+{};
+
+
+template
+<
+ typename Ring, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope
+ <
+ ring_tag, box_tag,
+ Ring, Box,
+ StrategyLess, StrategyGreater
+ >
+ : detail::envelope::envelope_range<Ring, Box>
+{};
+
+
+template
+<
+ typename Polygon, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope
+ <
+ polygon_tag, box_tag,
+ Polygon, Box,
+ StrategyLess, StrategyGreater
+ >
+{
+ static inline void apply(Polygon const& poly, Box& mbr)
+ {
+ // For polygon, inspecting outer ring is sufficient
+
+ detail::envelope::envelope_range
+ <
+ typename ring_type<Polygon>::type,
+ Box
+ >::apply(exterior_ring(poly), mbr);
+ }
+
+};
+
+
+} // namespace dispatch
+#endif
+
+
+/*!
+\brief Calculate envelope of a geometry
+\ingroup envelope
+\param geometry the geometry
+\param mbr the box receiving the envelope
+\par Example:
+Example showing envelope calculation, using point_ll latlong points
+\dontinclude doxygen_1.cpp
+\skip example_envelope_polygon
+\line {
+\until }
+*/
+template<typename Geometry, typename Box>
+inline void envelope(Geometry const& geometry, Box& mbr)
+{
+ concept::check<const Geometry>();
+ concept::check<Box>();
+
+ dispatch::envelope
+ <
+ typename tag<Geometry>::type, typename tag<Box>::type,
+ Geometry, Box,
+ void, void
+ >::apply(geometry, mbr);
+}
+
+
+/*!
+\brief Calculate and return envelope of a geometry
+\ingroup envelope
+\param geometry the geometry
+*/
+template<typename Box, typename Geometry>
+inline Box make_envelope(Geometry const& geometry)
+{
+ concept::check<const Geometry>();
+ concept::check<Box>();
+
+ Box mbr;
+ dispatch::envelope
+ <
+ typename tag<Geometry>::type, typename tag<Box>::type,
+ Geometry, Box,
+ void, void
+ >::apply(geometry, mbr);
+ return mbr;
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_ENVELOPE_HPP

Added: sandbox/geometry/boost/geometry/algorithms/equals.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/equals.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,436 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP
+
+/*!
+\defgroup equals equals: detect if two geometries are spatially equal
+\details Equals returns true if geometries are spatially equal. Spatially equal
+means including the same point-set. A linestring can be spatially equal to
+another linestring, even if both do not have the same amount of points.
+A polygon can be spatially equal to a multi-polygon (which then has
+only one element).
+
+\par Geometries:
+- \b point + \b point
+- \b box + \b box
+
+\note There is a functor \ref compare "compare" as well, which can be used
+for std:: library compatibility.
+
+*/
+
+
+#include <cstddef>
+#include <deque>
+
+#include <boost/mpl/if.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/is_multi.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/reverse_dispatch.hpp>
+
+#include <boost/geometry/algorithms/detail/disjoint.hpp>
+#include <boost/geometry/algorithms/detail/not.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
+
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/algorithms/overlay/get_turns.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/util/math.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace equals {
+
+
+template
+<
+ typename Box1,
+ typename Box2,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct box_box
+{
+ static inline bool apply(Box1 const& box1, Box2 const& box2)
+ {
+ if (!geometry::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2))
+ || !geometry::math::equals(get<max_corner, Dimension>(box1), get<max_corner, Dimension>(box2)))
+ {
+ return false;
+ }
+ return box_box<Box1, Box2, Dimension + 1, DimensionCount>::apply(box1, box2);
+ }
+};
+
+template <typename Box1, typename Box2, std::size_t DimensionCount>
+struct box_box<Box1, Box2, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Box1 const& , Box2 const& )
+ {
+ return true;
+ }
+};
+
+
+template <typename Ring1, typename Ring2>
+struct ring_ring
+{
+ static inline bool apply(Ring1 const& ring1, Ring2 const& ring2, bool check_area = true)
+ {
+ // Note: this implementation makes use of getting interections (turns)
+ // and merge them. If all IP's disappear, the ring should be the same
+ // (because merging removes collinear or non-collinear
+ // IP's following the same path)
+
+ // However, this implementation should be re-done using
+ // a linear time algorithm (getting left-most points of both
+ // and follow them using circular iterator and distance/side)
+
+ // obvious check, area's should be the same.
+ if (check_area && geometry::area(ring1) != geometry::area(ring2))
+ {
+ return false;
+ }
+ // We could check more (perimeter,centroid,envelope)
+ // For now we go directly to intersection points
+
+ typedef typename geometry::point_type<Ring1>::type point_type;
+ typedef detail::overlay::traversal_turn_info<point_type> turn_info;
+ typedef std::deque<turn_info> container_type;
+
+ container_type ips;
+ boost::geometry::get_turns<detail::overlay::NullPolicy>(ring1, ring2, ips);
+
+ if (ips.size() == 0)
+ {
+ return false;
+ }
+ for (typename boost::range_iterator<container_type const>::type
+ it = boost::begin(ips);
+ it != boost::end(ips);
+ ++it)
+ {
+ if (it->method == detail::overlay::method_collinear
+ || it->method == detail::overlay::method_equal
+ )
+ {
+ // If it is not such that both turns are collinear, the rings are not equal
+ for (typename boost::range_iterator
+ <
+ typename turn_info::container_type const
+ >::type oit = boost::begin(it->operations);
+ oit != boost::end(it->operations);
+ oit++)
+ {
+ if (oit->operation != detail::overlay::operation_continue)
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+};
+
+
+template <typename T>
+struct equal_sortable
+{
+ int index;
+ T area;
+ bool counterpart_found;
+ inline equal_sortable(int i, T const& a)
+ : index(i)
+ , area(a)
+ , counterpart_found(false)
+ {}
+
+ inline bool operator<(equal_sortable<T> const& other) const
+ {
+ return area < other.area;
+ }
+};
+
+
+template <typename Range, typename Collection>
+inline void fill_equal_sortable(Range const& range,
+ Collection& v)
+{
+ typedef typename boost::range_value<Collection>::type item_type;
+ int i = 0;
+ for (typename boost::range_iterator<Range const>::type
+ it = boost::begin(range);
+ it != boost::end(range);
+ ++it, ++i)
+ {
+ v.push_back(item_type(i, geometry::area(*it)));
+ }
+ std::sort(v.begin(), v.end());
+ /***
+ for (typename std::vector<sortable>::iterator it = v.begin();
+ it != v.end();
+ ++it)
+ {
+ std::cout << "Ring: " << it->index << " area: " << it->area << std::endl;
+ }
+ ***/
+}
+
+
+template
+<
+ typename Policy,
+ typename Range1,
+ typename Range2
+>
+inline bool range_range(Range1 const& range1, Range2 const& range2)
+{
+ typedef typename boost::range_value<Range1>::type geometry1;
+ // Check interior rings -> first sort them on area ,
+ // for performance reasons (area is not re-calculated in ring-compare)
+ typedef std::vector
+ <
+ equal_sortable<typename geometry::area_result<geometry1>::type>
+ > collection;
+
+ collection sorted1, sorted2;
+
+ fill_equal_sortable(range1, sorted1);
+ fill_equal_sortable(range2, sorted2);
+
+ typedef typename boost::range_iterator<collection>::type iterator;
+
+ // Compare all items (e.g. rings having equal area)
+ for (iterator it1 = sorted1.begin(); it1 != sorted1.end(); ++it1)
+ {
+ for (iterator it2 = sorted2.begin();
+ ! it1->counterpart_found
+ && it2 != sorted2.end()
+ && it2->area <= it1->area; //+epsilon
+ ++it2)
+ {
+ if (! it2->counterpart_found
+ && geometry::math::equals(it1->area, it2->area))
+ {
+ // Call policy, without checking area
+ if (Policy::apply(range1[it1->index], range2[it2->index], false))
+ {
+ it1->counterpart_found = true;
+ it2->counterpart_found = true;
+ }
+ }
+ }
+
+ if (! it1->counterpart_found)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+template <typename Polygon1, typename Polygon2>
+struct polygon_polygon
+{
+ static inline bool apply(Polygon1 const& polygon1, Polygon2 const& polygon2,
+ bool compare_area = false)
+ {
+ // Check number of rings (area check is done in exterior ring check)
+ if (geometry::num_interior_rings(polygon1) != geometry::num_interior_rings(polygon2))
+ {
+ return false;
+ }
+
+ typedef typename geometry::ring_type<Polygon1>::type ring_type1;
+ typedef typename geometry::ring_type<Polygon2>::type ring_type2;
+ typedef ring_ring<ring_type1, ring_type2> compare;
+
+ // Check exterior ring
+ if (! compare::apply(exterior_ring(polygon1), exterior_ring(polygon2)))
+ {
+ return false;
+ }
+
+ return range_range<compare>(
+ interior_rings(polygon1),
+ interior_rings(polygon2));
+
+ }
+};
+
+
+template <typename Polygon, typename Ring>
+struct polygon_ring
+{
+ static inline bool apply(Polygon const& polygon, Ring const& ring)
+ {
+ // A polygon can be equal to a ring if there are no interior rings
+ return boost::size(interior_rings(polygon)) == 0
+ ? ring_ring
+ <
+ typename geometry::ring_type<Polygon>::type,
+ Ring
+ >::apply(exterior_ring(polygon), ring)
+ : false;
+ }
+};
+
+
+}} // namespace detail::equals
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag1, typename Tag2,
+ bool IsMulti1, bool IsMulti2,
+ typename Geometry1,
+ typename Geometry2,
+ std::size_t DimensionCount
+>
+struct equals
+{};
+
+
+template <typename P1, typename P2, std::size_t DimensionCount>
+struct equals<point_tag, point_tag, false, false, P1, P2, DimensionCount>
+ : geometry::detail::not_
+ <
+ P1,
+ P2,
+ detail::disjoint::point_point<P1, P2, 0, DimensionCount>
+ >
+{};
+
+
+template <typename Box1, typename Box2, std::size_t DimensionCount>
+struct equals<box_tag, box_tag, false, false, Box1, Box2, DimensionCount>
+ : detail::equals::box_box<Box1, Box2, 0, DimensionCount>
+{};
+
+
+template <typename Ring1, typename Ring2>
+struct equals<ring_tag, ring_tag, false, false, Ring1, Ring2, 2>
+ : detail::equals::ring_ring<Ring1, Ring2>
+{};
+
+
+template <typename Polygon1, typename Polygon2>
+struct equals<polygon_tag, polygon_tag, false, false, Polygon1, Polygon2, 2>
+ : detail::equals::polygon_polygon<Polygon1, Polygon2>
+{};
+
+
+template <typename Polygon, typename Ring>
+struct equals<polygon_tag, ring_tag, false, false, Polygon, Ring, 2>
+ : detail::equals::polygon_ring<Polygon, Ring>
+{};
+
+
+template
+<
+ typename Tag1, typename Tag2,
+ bool IsMulti1, bool IsMulti2,
+ typename Geometry1,
+ typename Geometry2,
+ std::size_t DimensionCount
+>
+struct equals_reversed
+{
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ {
+ return equals
+ <
+ Tag2, Tag1,
+ IsMulti2, IsMulti1,
+ Geometry2, Geometry1,
+ DimensionCount
+ >::apply(g2, g1);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Detect if two geometries are spatially equal
+ \ingroup equals
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \return true if geometries are spatially equal, else false
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concept::check_concepts_and_equal_dimensions
+ <
+ Geometry1 const,
+ Geometry2 const
+ >();
+
+ return boost::mpl::if_c
+ <
+ reverse_dispatch<Geometry1, Geometry2>::type::value,
+ dispatch::equals_reversed
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ is_multi<Geometry1>::type::value,
+ is_multi<Geometry2>::type::value,
+ Geometry1,
+ Geometry2,
+ dimension<Geometry1>::type::value
+ >,
+ dispatch::equals
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ is_multi<Geometry1>::type::value,
+ is_multi<Geometry2>::type::value,
+ Geometry1,
+ Geometry2,
+ dimension<Geometry1>::type::value
+ >
+ >::type::apply(geometry1, geometry2);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP
+

Added: sandbox/geometry/boost/geometry/algorithms/for_each.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/for_each.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,357 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_FOR_EACH_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_FOR_EACH_HPP
+
+/*!
+\defgroup for_each for_each: apply a functor to each point or segment of a geometry
+\details There are two 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
+\note For both for_each algorithms there is a \b const and a non-const version provided.
+*/
+
+#include <algorithm>
+
+
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/is_multi.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/geometries/segment.hpp>
+
+#include <boost/geometry/util/add_const_if_c.hpp>
+#include <boost/geometry/util/range_iterator_const_if_c.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace for_each {
+
+
+template <typename Point, typename Functor, bool IsConst>
+struct fe_point_per_point
+{
+ static inline Functor apply(
+ typename add_const_if_c<IsConst, Point>::type& point, Functor f)
+ {
+ f(point);
+ return f;
+ }
+};
+
+
+template <typename Point, typename Functor, bool IsConst>
+struct fe_point_per_segment
+{
+ static inline Functor apply(
+ typename add_const_if_c<IsConst, Point>::type& point, Functor f)
+ {
+ return f;
+ }
+};
+
+
+template <typename Range, typename Functor, bool IsConst>
+struct fe_range_per_point
+{
+ static inline Functor apply(
+ typename add_const_if_c<IsConst, Range>::type& range,
+ Functor f)
+ {
+ return (std::for_each(boost::begin(range), boost::end(range), f));
+ }
+};
+
+
+template <typename Range, typename Functor, bool IsConst>
+struct fe_range_per_segment
+{
+ static inline Functor apply(
+ typename add_const_if_c<IsConst, Range>::type& range,
+ Functor f)
+ {
+ typedef typename range_iterator_const_if_c
+ <
+ IsConst,
+ Range
+ >::type iterator_type;
+
+ typedef typename add_const_if_c
+ <
+ IsConst,
+ typename point_type<Range>::type
+ >::type point_type;
+
+ iterator_type it = boost::begin(range);
+ iterator_type previous = it++;
+ while(it != boost::end(range))
+ {
+ segment<point_type> s(*previous, *it);
+ f(s);
+ previous = it++;
+ }
+
+ return f;
+ }
+};
+
+
+template <typename Polygon, typename Functor, bool IsConst>
+struct fe_polygon_per_point
+{
+ static inline Functor apply(
+ typename add_const_if_c<IsConst, Polygon>::type& poly,
+ Functor f)
+ {
+ typedef typename range_iterator_const_if_c
+ <
+ IsConst,
+ typename interior_type<Polygon>::type
+ >::type iterator_type;
+
+ typedef fe_range_per_point
+ <
+ typename ring_type<Polygon>::type,
+ Functor,
+ IsConst
+ > per_ring;
+
+ f = per_ring::apply(exterior_ring(poly), f);
+
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly));
+ ++it)
+ {
+ f = per_ring::apply(*it, f);
+ }
+
+ return f;
+ }
+
+};
+
+
+template <typename Polygon, typename Functor, bool IsConst>
+struct fe_polygon_per_segment
+{
+ static inline Functor apply(
+ typename add_const_if_c<IsConst, Polygon>::type& poly,
+ Functor f)
+ {
+ typedef typename range_iterator_const_if_c
+ <
+ IsConst,
+ typename interior_type<Polygon>::type
+ >::type iterator_type;
+
+ typedef fe_range_per_segment
+ <
+ typename ring_type<Polygon>::type,
+ Functor,
+ IsConst
+ > per_ring;
+
+ f = per_ring::apply(exterior_ring(poly), f);
+
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly));
+ ++it)
+ {
+ f = per_ring::apply(*it, f);
+ }
+
+ return f;
+ }
+
+};
+
+
+}} // namespace detail::for_each
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag,
+ bool IsMulti,
+ typename Geometry,
+ typename Functor,
+ bool IsConst
+>
+struct for_each_point {};
+
+
+template <typename Point, typename Functor, bool IsConst>
+struct for_each_point<point_tag, false, Point, Functor, IsConst>
+ : detail::for_each::fe_point_per_point<Point, Functor, IsConst>
+{};
+
+
+template <typename Linestring, typename Functor, bool IsConst>
+struct for_each_point<linestring_tag, false, Linestring, Functor, IsConst>
+ : detail::for_each::fe_range_per_point<Linestring, Functor, IsConst>
+{};
+
+
+template <typename Ring, typename Functor, bool IsConst>
+struct for_each_point<ring_tag, false, Ring, Functor, IsConst>
+ : detail::for_each::fe_range_per_point<Ring, Functor, IsConst>
+{};
+
+
+template <typename Polygon, typename Functor, bool IsConst>
+struct for_each_point<polygon_tag, false, Polygon, Functor, IsConst>
+ : detail::for_each::fe_polygon_per_point<Polygon, Functor, IsConst>
+{};
+
+
+template
+<
+ typename Tag,
+ bool IsMulti,
+ typename Geometry,
+ typename Functor,
+ bool IsConst
+>
+struct for_each_segment {};
+
+template <typename Point, typename Functor, bool IsConst>
+struct for_each_segment<point_tag, false, Point, Functor, IsConst>
+ : detail::for_each::fe_point_per_segment<Point, Functor, IsConst>
+{};
+
+
+template <typename Linestring, typename Functor, bool IsConst>
+struct for_each_segment<linestring_tag, false, Linestring, Functor, IsConst>
+ : detail::for_each::fe_range_per_segment<Linestring, Functor, IsConst>
+{};
+
+
+template <typename Ring, typename Functor, bool IsConst>
+struct for_each_segment<ring_tag, false, Ring, Functor, IsConst>
+ : detail::for_each::fe_range_per_segment<Ring, Functor, IsConst>
+{};
+
+
+template <typename Polygon, typename Functor, bool IsConst>
+struct for_each_segment<polygon_tag, false, Polygon, Functor, IsConst>
+ : detail::for_each::fe_polygon_per_segment<Polygon, Functor, IsConst>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Calls functor for geometry
+ \ingroup for_each
+ \param geometry geometry to loop through
+ \param f functor to use
+ \details Calls the functor the specified \b const geometry
+*/
+template<typename Geometry, typename Functor>
+inline Functor for_each_point(Geometry const& geometry, Functor f)
+{
+ concept::check<const Geometry>();
+
+ return dispatch::for_each_point
+ <
+ typename tag<Geometry>::type,
+ is_multi<Geometry>::type::value,
+ Geometry,
+ Functor,
+ true
+ >::apply(geometry, f);
+}
+
+
+/*!
+ \brief Calls functor for geometry
+ \ingroup for_each
+ \param geometry geometry to loop through
+ \param f functor to use
+ \details Calls the functor for the specified geometry
+*/
+template<typename Geometry, typename Functor>
+inline Functor for_each_point(Geometry& geometry, Functor f)
+{
+ concept::check<Geometry>();
+
+ return dispatch::for_each_point
+ <
+ typename tag<Geometry>::type,
+ is_multi<Geometry>::type::value,
+ Geometry,
+ Functor,
+ false
+ >::apply(geometry, f);
+}
+
+
+/*!
+ \brief Calls functor for segments on linestrings, rings, polygons, ...
+ \ingroup for_each
+ \param geometry geometry to loop through
+ \param f functor to use
+ \details Calls the functor all \b const segments of the
+ specified \b const geometry
+*/
+template<typename Geometry, typename Functor>
+inline Functor for_each_segment(Geometry const& geometry, Functor f)
+{
+ concept::check<const Geometry>();
+
+ return dispatch::for_each_segment
+ <
+ typename tag<Geometry>::type,
+ is_multi<Geometry>::type::value,
+ Geometry,
+ Functor,
+ true
+ >::apply(geometry, f);
+}
+
+
+/*!
+ \brief Calls functor for segments on linestrings, rings, polygons, ...
+ \ingroup for_each
+ \param geometry geometry to loop through
+ \param f functor to use
+ \details Calls the functor all segments of the specified geometry
+*/
+template<typename Geometry, typename Functor>
+inline Functor for_each_segment(Geometry& geometry, Functor f)
+{
+ concept::check<Geometry>();
+
+ return dispatch::for_each_segment
+ <
+ typename tag<Geometry>::type,
+ is_multi<Geometry>::type::value,
+ Geometry,
+ Functor,
+ false
+ >::apply(geometry, f);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_FOR_EACH_HPP

Added: sandbox/geometry/boost/geometry/algorithms/get_section.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/get_section.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,116 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_GET_SECTION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_GET_SECTION_HPP
+
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+
+#include <boost/geometry/iterators/range_type.hpp>
+
+#include <boost/geometry/geometries/segment.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, typename Geometry, typename Section>
+struct get_section
+{
+ typedef typename boost::range_const_iterator
+ <
+ typename geometry::range_type<Geometry>::type
+ >::type iterator_type;
+
+ static inline void apply(Geometry const& geometry, Section const& section,
+ iterator_type& begin, iterator_type& end)
+ {
+ begin = boost::begin(geometry) + section.begin_index;
+ end = boost::begin(geometry) + section.end_index + 1;
+ }
+};
+
+template <typename Polygon, typename Section>
+struct get_section<polygon_tag, Polygon, Section>
+{
+ typedef typename boost::range_const_iterator
+ <
+ typename geometry::range_type<Polygon>::type
+ >::type iterator_type;
+
+ static inline void apply(Polygon const& polygon, Section const& section,
+ iterator_type& begin, iterator_type& end)
+ {
+ typedef typename geometry::ring_type<Polygon>::type ring_type;
+ ring_type const& ring = section.ring_index < 0
+ ? geometry::exterior_ring(polygon)
+ : geometry::interior_rings(polygon)[section.ring_index];
+
+ begin = boost::begin(ring) + section.begin_index;
+ end = boost::begin(ring) + section.end_index + 1;
+ }
+};
+
+} // namespace dispatch
+#endif
+
+
+
+
+/*!
+ \brief Get iterators for a specified section
+ \ingroup sectionalize
+ \tparam Geometry type
+ \tparam Section type of section to get from
+ \param geometry geometry which might be located in the neighborhood
+ \param section structure with section
+ \param begin begin-iterator (const iterator over points of section)
+ \param end end-iterator (const iterator over points of section)
+ \todo Create non-const version as well
+
+ */
+template <typename Geometry, typename Section>
+inline void get_section(Geometry const& geometry, Section const& section,
+ typename boost::range_const_iterator
+ <
+ typename geometry::range_type<Geometry>::type
+ >::type& begin,
+ typename boost::range_const_iterator
+ <
+ typename geometry::range_type<Geometry>::type
+ >::type& end)
+{
+ concept::check<const Geometry>();
+
+ dispatch::get_section
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Section
+ >::apply(geometry, section, begin, end);
+}
+
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_GET_SECTION_HPP

Added: sandbox/geometry/boost/geometry/algorithms/intersection.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/intersection.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,303 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_INTERSECTION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_INTERSECTION_HPP
+
+
+#include <boost/mpl/if.hpp>
+
+#include <boost/geometry/core/reverse_dispatch.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/overlay/clip_linestring.hpp>
+#include <boost/geometry/algorithms/overlay/assemble.hpp>
+
+
+
+/*!
+\defgroup intersection intersection: calculate new geometry
+ containing geometries A and B
+\details The intersection of two geometries A and B is the geometry containing
+ all points of A also belonging to B, but no other elements. The so-called
+ clip is an intersection of a geometry with a box.
+\par Source description:
+- OGC: Returns a geometric object that represents the Point set intersection of
+ this geometric object with another Geometry.
+\see http://en.wikipedia.org/wiki/Intersection_(set_theory)
+\note Any intersection can result in no geometry at all
+
+\par Performance
+- 2776 counties of US are intersected with a 100-points ellipse in 1.1 seconds
+(http://trac.osgeo.org/ggl/wiki/Performance#Interesection)
+- 2776 counties of US are clipped in 0.2 seconds
+(http://trac.osgeo.org/ggl/wiki/Performance#Clip)
+
+
+\par Geometries:
+- \b polygon + \b box (clip) -> \b polygon(s)
+\image html svg_intersection_polygon_box.png
+\image html svg_intersection_countries.png
+- \b ring + \b box (clip) -> \b polygon(s)
+\image html svg_intersection_ring_box.png
+- \b ring + \b ring -> \b polygon(s)
+\image html svg_intersection_ring_ring.png
+- \b polygon + \b ring -> \b polygon(s)
+\image html svg_intersection_polygon_ring.png
+- combinations above -> \b ring(s).
+ <i>If the output is an ouput iterator of rings, holes are omitted</i>
+- \b linestring + \b box (clip)
+\image html svg_intersection_roads.png
+
+\par Example:
+Example showing clipping of linestring with box
+\dontinclude doxygen_1.cpp
+\skip example_clip_linestring1
+\line {
+\until }
+\par Example:
+Example showing clipping of vector, outputting vectors, with box
+\dontinclude doxygen_1.cpp
+\skip example_clip_linestring2
+\line {
+\until }
+\par Example:
+Example showing clipping of polygon with box
+\dontinclude doxygen_1.cpp
+\skip example_intersection_polygon1
+\line {
+\until }
+*/
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag1, typename Tag2, typename Tag3,
+ typename G1, typename G2,
+ typename OutputIterator,
+ typename GeometryOut,
+ typename Strategy
+>
+struct intersection_inserter
+ : detail::overlay::overlay_and_assemble
+ <G1, G2, OutputIterator, GeometryOut, -1, Strategy>
+{};
+
+
+template
+<
+ typename Segment1, typename Segment2,
+ typename OutputIterator, typename GeometryOut,
+ typename Strategy
+>
+struct intersection_inserter
+ <
+ segment_tag, segment_tag, point_tag,
+ Segment1, Segment2,
+ OutputIterator, GeometryOut,
+ Strategy
+ >
+{
+ static inline OutputIterator apply(Segment1 const& segment1,
+ Segment2 const& segment2, OutputIterator out,
+ Strategy const& strategy)
+ {
+ typedef typename point_type<GeometryOut>::type point_type;
+
+ // Get the intersection point (or two points)
+ segment_intersection_points<point_type> is
+ = strategy::intersection::relate_cartesian_segments
+ <
+ policies::relate::segments_intersection_points
+ <
+ Segment1,
+ Segment2,
+ segment_intersection_points<point_type>
+ >
+ >::apply(segment1, segment2);
+
+ for (std::size_t i = 0; i < is.count; i++)
+ {
+ GeometryOut p;
+ geometry::copy_coordinates(is.intersections[i], p);
+ *out = p;
+ out++;
+ }
+ return out;
+ }
+};
+
+
+template
+<
+ typename Linestring, typename Box,
+ typename OutputIterator, typename GeometryOut,
+ typename Strategy
+>
+struct intersection_inserter
+ <
+ linestring_tag, box_tag, linestring_tag,
+ Linestring, Box,
+ OutputIterator, GeometryOut,
+ Strategy
+ >
+{
+ static inline OutputIterator apply(Linestring const& linestring,
+ Box const& box, OutputIterator out, Strategy const& strategy)
+ {
+ typedef typename point_type<GeometryOut>::type point_type;
+ strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
+ return detail::intersection::clip_linestring_with_box
+ <GeometryOut>(box, linestring, out, lb_strategy);
+ }
+};
+
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2, typename GeometryTag3,
+ typename Geometry1, typename Geometry2,
+ typename OutputIterator, typename GeometryOut,
+ typename Strategy
+>
+struct intersection_inserter_reversed
+{
+ static inline OutputIterator apply(Geometry1 const& g1,
+ Geometry2 const& g2, OutputIterator out,
+ Strategy const& strategy)
+ {
+ return intersection_inserter
+ <
+ GeometryTag2, GeometryTag1, GeometryTag3,
+ Geometry2, Geometry1,
+ OutputIterator, GeometryOut,
+ Strategy
+ >::apply(g2, g1, out, strategy);
+ }
+};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+/*!
+ \brief Intersects two geometries
+ \ingroup intersection
+ \details The two input geometries are intersected and the resulting
+ linestring(s), ring(s) or polygon(s) are sent
+ to the specified output operator.
+ \tparam GeometryOut output geometry type, must be specified
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \tparam OutputIterator output iterator
+ \tparam Strategy compound strategy for intersection
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \param out the output iterator, outputting linestrings or polygons
+ \param strategy the strategy
+ \return the output iterator
+*/
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename OutputIterator,
+ typename Strategy
+>
+inline OutputIterator intersection_inserter(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ OutputIterator out,
+ Strategy const& strategy)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ return boost::mpl::if_c
+ <
+ reverse_dispatch<Geometry1, Geometry2>::type::value,
+ dispatch::intersection_inserter_reversed
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ typename tag<GeometryOut>::type,
+ Geometry1,
+ Geometry2,
+ OutputIterator, GeometryOut,
+ Strategy
+ >,
+ dispatch::intersection_inserter
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ typename tag<GeometryOut>::type,
+ Geometry1,
+ Geometry2,
+ OutputIterator, GeometryOut,
+ Strategy
+ >
+ >::type::apply(geometry1, geometry2, out, strategy);
+}
+
+
+/*!
+ \brief Intersects two geometries
+ \ingroup intersection
+ \details The two input geometries are intersected and the resulting
+ linestring(s), ring(s) or polygon(s) are sent
+ to the specified output operator.
+ \tparam GeometryOut output geometry type, must be specified
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \tparam OutputIterator output iterator
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \param out the output iterator, outputting linestrings or polygons
+ \return the output iterator
+*/
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename OutputIterator
+>
+inline OutputIterator intersection_inserter(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ OutputIterator out)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ typedef typename geometry::point_type<GeometryOut>::type point_type;
+ typedef detail::intersection::intersection_point<point_type> ip_type;
+
+ typedef strategy_intersection
+ <
+ typename cs_tag<point_type>::type,
+ Geometry1,
+ Geometry2,
+ ip_type
+ > strategy;
+
+ return intersection_inserter<GeometryOut>(geometry1, geometry2, out,
+ strategy());
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif //GGL_ALGORITHMS_INTERSECTION_HPP

Added: sandbox/geometry/boost/geometry/algorithms/intersects.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/intersects.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,113 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_INTERSECTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_INTERSECTS_HPP
+
+
+/*!
+\defgroup intersects intersects: detect if a geometry self-intersects or if two geometries intersect
+\par Source descriptions:
+- OGC description: Returns 1 (TRUE) if this geometric object spatially
+ intersects anotherGeometry.
+- OGC: a.Intersects(b) <=> ! a.Disjoint(b)
+\note There are two overloaded versions:
+- with one geometry, detecting self-intersections
+- with two geometries, deferring to disjoint, returning !disjoint
+
+\par Geometries:
+- \b ring
+- \b polygon
+- for two geometries: same is disjoint
+
+\note if one geometry is completely within another geometry, it "intersects"
+
+*/
+
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+
+#include <boost/geometry/algorithms/overlay/get_intersection_points.hpp>
+#include <boost/geometry/algorithms/overlay/self_intersection_points.hpp>
+#include <boost/geometry/algorithms/overlay/adapt_turns.hpp>
+#include <boost/geometry/algorithms/overlay/enrich_intersection_points.hpp>
+#include <boost/geometry/algorithms/overlay/traverse.hpp>
+
+#include <boost/geometry/algorithms/disjoint.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief Determine if there is at least one intersection
+ (crossing or self-tangency)
+ \note This function can be called for one geometry (self-intersection) and
+ also for two geometries (intersection)
+ \ingroup intersects
+ \tparam Geometry geometry type
+ \param geometry geometry
+ \return true if there are intersections, else false
+ */
+template <typename Geometry>
+inline bool intersects(Geometry const& geometry)
+{
+ concept::check<const Geometry>();
+
+ typedef typename boost::remove_const<Geometry>::type ncg_type;
+
+ typedef geometry::detail::intersection::intersection_point
+ <typename geometry::point_type<Geometry>::type> ip;
+ typedef std::vector<ip> ip_vector;
+
+ ip_vector ips;
+
+ typedef typename strategy_intersection
+ <
+ typename cs_tag<Geometry>::type,
+ Geometry,
+ Geometry,
+ ip
+ >::segment_intersection_strategy_type segment_intersection_strategy_type;
+
+ dispatch::self_intersection_points
+ <
+ typename tag<ncg_type>::type,
+ is_multi<ncg_type>::type::value,
+ ncg_type,
+ ip_vector, segment_intersection_strategy_type
+ >::apply(geometry, true, ips);
+ return ips.size() > 0;
+}
+
+
+/*!
+ \brief Determine if there is at least one intersection
+ \ingroup intersects
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \return true if there are intersection(s), else false
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool intersects(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ return ! geometry::disjoint(geometry1, geometry2);
+}
+
+
+
+}} // namespace boost::geometry
+
+#endif //GGL_ALGORITHMS_INTERSECTS_HPP

Added: sandbox/geometry/boost/geometry/algorithms/length.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/length.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,212 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_LENGTH_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_LENGTH_HPP
+
+#include <iterator>
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+
+#include <boost/geometry/core/cs.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/detail/calculate_null.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/length_result.hpp>
+
+/*!
+\defgroup length length: calculate length of a linear geometry
+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.
+\par Example:
+Example showing length calculation
+\dontinclude doxygen_1.cpp
+\skip example_length_linestring_iterators1
+\line {
+\until }
+*/
+
+namespace boost { namespace geometry
+{
+
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace length {
+
+
+template<typename Segment, typename Strategy>
+struct segment_length
+{
+ static inline typename length_result<Segment>::type apply(
+ Segment const& segment, Strategy const& strategy)
+ {
+ typedef typename point_type<Segment>::type point_type;
+ point_type p1, p2;
+ assign_point_from_index<0>(segment, p1);
+ assign_point_from_index<1>(segment, p2);
+ return strategy.apply(p1, p2);
+ }
+};
+
+/*!
+\brief Internal, calculates length of a linestring using iterator pairs and
+ specified strategy
+\note for_each could be used here, now that point_type is changed by boost
+ range iterator
+*/
+template<typename Range, typename Strategy>
+struct range_length
+{
+ typedef typename length_result<Range>::type return_type;
+
+ static inline return_type apply(
+ Range const& range, Strategy const& strategy)
+ {
+ return_type sum = return_type();
+
+ typedef typename boost::range_const_iterator<Range>::type iterator_type;
+ iterator_type it = boost::begin(range);
+ if (it != boost::end(range))
+ {
+ iterator_type previous = it++;
+ while(it != boost::end(range))
+ {
+ // Add point-point distance using the return type belonging
+ // to strategy
+ sum += strategy.apply(*previous, *it);
+ previous = it++;
+ }
+ }
+
+ return sum;
+ }
+};
+
+}} // namespace detail::length
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Tag, typename Geometry, typename Strategy>
+struct length : detail::calculate_null
+ <
+ typename length_result<Geometry>::type,
+ Geometry,
+ Strategy
+ >
+{};
+
+
+template <typename Geometry, typename Strategy>
+struct length<linestring_tag, Geometry, Strategy>
+ : detail::length::range_length<Geometry, Strategy>
+{};
+
+
+// RING: length is currently 0; it might be argued that it is the "perimeter"
+
+
+template <typename Geometry, typename Strategy>
+struct length<segment_tag, Geometry, Strategy>
+ : detail::length::segment_length<Geometry, Strategy>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Calculate length of a geometry
+ \ingroup length
+ \details The function length returns the length of a geometry, using the
+ default distance-calculation-strategy
+ \param geometry the geometry, being a geometry::linestring, vector,
+ iterator pair, or any other boost compatible range
+ \return the length
+ Example showing length calculation on a vector
+ \dontinclude doxygen_1.cpp
+ \skip example_length_linestring_iterators2
+ \line {
+ \until }
+ */
+template<typename Geometry>
+inline typename length_result<Geometry>::type length(
+ Geometry const& geometry)
+{
+ concept::check<const Geometry>();
+
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename cs_tag<point_type>::type cs_tag;
+ typedef typename strategy_distance
+ <
+ cs_tag,
+ cs_tag,
+ point_type,
+ point_type
+ >::type strategy_type;
+
+ return dispatch::length
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ strategy_type
+ >::apply(geometry, strategy_type());
+}
+
+
+/*!
+ \brief Calculate length of a geometry
+ \ingroup length
+ \details The function length returns the length of a geometry,
+ using specified strategy
+ \param geometry the geometry, being a geometry::linestring, vector,
+ iterator pair, or any other boost compatible range
+ \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_1.cpp
+ \skip example_length_linestring_iterators3
+ \line {
+ \until }
+ */
+template<typename Geometry, typename Strategy>
+inline typename length_result<Geometry>::type length(
+ Geometry const& geometry, Strategy const& strategy)
+{
+ concept::check<const Geometry>();
+
+ return dispatch::length
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Strategy
+ >::apply(geometry, strategy);
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_LENGTH_HPP

Added: sandbox/geometry/boost/geometry/algorithms/make.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/make.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,138 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_MAKE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_MAKE_HPP
+
+#include <boost/geometry/algorithms/assign.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief Make a geometry
+ \ingroup access
+ \details the Generic Geometry Library uses concepts for all its geometries. Therefore it does not rely
+ on constructors. The "make" functions are object generators creating geometries. There are overloads
+ with two, three, four or six values, which are implemented depending on the geometry specified.
+ \note It does not work with array-point types, like int[2]
+ \tparam G the geometry type
+ \tparam T the coordinate type
+ \return the geometry
+ */
+template <typename Geometry, typename T>
+inline Geometry make(T const& c1, T const& c2)
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ geometry::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2);
+ return geometry;
+}
+
+/*!
+ \brief Make a geometry
+ \ingroup access
+ \return a 3D point
+ */
+template <typename Geometry, typename T>
+inline Geometry make(T const& c1, T const& c2, T const& c3)
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ geometry::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2, c3);
+ return geometry;
+}
+
+template <typename Geometry, typename T>
+inline Geometry make(T const& c1, T const& c2, T const& c3, T const& c4)
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ geometry::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2, c3, c4);
+ return geometry;
+}
+
+
+
+template <typename Geometry, typename Range>
+inline Geometry make(Range const& range)
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ append(geometry, range);
+ return geometry;
+}
+
+
+/*!
+ \brief Create a box with inverse infinite coordinates
+ \ingroup access
+ \details The make_inverse function initialize a 2D or 3D box with large coordinates, the
+ min corner is very large, the max corner is very small
+ \tparam Geometry the geometry type
+ \return the box
+ */
+template <typename Geometry>
+inline Geometry make_inverse()
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ dispatch::assign_inverse
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::apply(geometry);
+ return geometry;
+}
+
+/*!
+ \brief Create a geometry with "zero" coordinates
+ \ingroup access
+ \details The make_zero function initializes a 2D or 3D point or box with coordinates of zero
+ \tparam Geometry the geometry type
+ \return the geometry
+ */
+template <typename Geometry>
+inline Geometry make_zero()
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ dispatch::assign_zero
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::apply(geometry);
+ return geometry;
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_MAKE_HPP

Added: sandbox/geometry/boost/geometry/algorithms/num_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/num_points.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,146 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_NUM_POINTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_NUM_POINTS_HPP
+
+#include <cstddef>
+
+#include <boost/range.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/is_linear.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace num_points {
+
+
+template <typename Range>
+struct range_count
+{
+ static inline std::size_t apply(Range const& range)
+ {
+ return boost::size(range);
+ }
+};
+
+template <typename Geometry, std::size_t D>
+struct other_count
+{
+ static inline std::size_t apply(Geometry const& geometry)
+ {
+ return D;
+ }
+};
+
+template <typename Polygon>
+struct polygon_count
+{
+ static inline std::size_t apply(Polygon const& poly)
+ {
+ std::size_t n = boost::size(exterior_ring(poly));
+ typedef typename boost::range_const_iterator
+ <
+ typename interior_type<Polygon>::type
+ >::type iterator;
+
+ for (iterator it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly));
+ ++it)
+ {
+ n += boost::size(*it);
+ }
+
+ return n;
+ }
+};
+
+}} // namespace detail::num_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename GeometryTag, bool Linear, typename Geometry>
+struct num_points
+{
+};
+
+template <typename GeometryTag, typename Geometry>
+struct num_points<GeometryTag, true, Geometry>
+ : detail::num_points::range_count<Geometry>
+{
+};
+
+template <typename Geometry>
+struct num_points<point_tag, false, Geometry>
+ : detail::num_points::other_count<Geometry, 1>
+{
+};
+
+template <typename Geometry>
+struct num_points<box_tag, false, Geometry>
+ : detail::num_points::other_count<Geometry, 4>
+{
+};
+
+template <typename Geometry>
+struct num_points<segment_tag, false, Geometry>
+ : detail::num_points::other_count<Geometry, 2>
+{
+};
+
+
+template <typename Geometry>
+struct num_points<polygon_tag, false, Geometry>
+ : detail::num_points::polygon_count<Geometry>
+{
+};
+
+} // namespace dispatch
+#endif
+
+
+/*!
+ \brief get number of points
+ \ingroup access
+ \tparam Geometry geometry type
+ \param geometry the geometry to get number of points from
+ \return number of points
+ \note For linestrings/rings also boost::size or .size() could be used, however,
+ for polygons this is less obvious. So this function is provided. Besides that
+ it is described by OGC (numPoints)
+*/
+template <typename Geometry>
+inline std::size_t num_points(Geometry const& geometry)
+{
+ concept::check<const Geometry>();
+
+ typedef typename boost::remove_const<Geometry>::type ncg_type;
+
+ return dispatch::num_points
+ <
+ typename tag<Geometry>::type,
+ is_linear<ncg_type>::value,
+ ncg_type
+ >::apply(geometry);
+}
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_NUM_POINTS_HPP

Added: sandbox/geometry/boost/geometry/algorithms/overlaps.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/overlaps.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,193 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_OVERLAPS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_OVERLAPS_HPP
+
+/*!
+\defgroup overlaps overlaps: detect overlap between two geometries
+\par Source descriptions:
+- Egenhofer: Two objects overlap if they have common interior faces and the bounding faces have common parts
+with the opposite interior faces.
+
+\par Geometries:
+- \b box + \b box
+
+*/
+
+
+#include <boost/geometry/core/access.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlaps {
+
+template
+<
+ typename Box1,
+ typename Box2,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct box_box_loop
+{
+ static inline void apply(Box1 const& b1, Box2 const& b2,
+ bool& overlaps, bool& one_in_two, bool& two_in_one)
+ {
+ assert_dimension_equal<Box1, Box2>();
+
+ typedef typename coordinate_type<Box1>::type coordinate_type1;
+ typedef typename coordinate_type<Box2>::type coordinate_type2;
+
+ coordinate_type1 const& min1 = get<min_corner, Dimension>(b1);
+ coordinate_type1 const& max1 = get<max_corner, Dimension>(b1);
+ coordinate_type2 const& min2 = get<min_corner, Dimension>(b2);
+ coordinate_type2 const& max2 = get<max_corner, Dimension>(b2);
+
+ // We might use the (not yet accepted) Boost.Interval
+ // submission in the future
+
+ // If:
+ // B1: |-------|
+ // B2: |------|
+ // in any dimension -> no overlap
+ if (max1 <= min2 || min1 >= max2)
+ {
+ overlaps = false;
+ return;
+ }
+
+ // If:
+ // B1: |--------------------|
+ // B2: |-------------|
+ // in all dimensions -> within, then no overlap
+ // B1: |--------------------|
+ // B2: |-------------|
+ // this is "within-touch" -> then no overlap. So use < and >
+ if (min1 < min2 || max1 > max2)
+ {
+ one_in_two = false;
+ }
+ // Same other way round
+ if (min2 < min1 || max2 > max1)
+ {
+ two_in_one = false;
+ }
+
+ box_box_loop
+ <
+ Box1,
+ Box2,
+ Dimension + 1,
+ DimensionCount
+ >::apply(b1, b2, overlaps, one_in_two, two_in_one);
+ }
+};
+
+template
+<
+ typename Box1,
+ typename Box2,
+ std::size_t DimensionCount
+>
+struct box_box_loop<Box1, Box2, DimensionCount, DimensionCount>
+{
+ static inline void apply(Box1 const& , Box2 const&, bool&, bool&, bool&)
+ {
+ }
+};
+
+template
+<
+ typename Box1,
+ typename Box2
+>
+struct box_box
+{
+ static inline bool apply(Box1 const& b1, Box2 const& b2)
+ {
+ bool overlaps = true;
+ bool within1 = true;
+ bool within2 = true;
+ box_box_loop
+ <
+ Box1,
+ Box2,
+ 0,
+ dimension<Box1>::type::value
+ >::apply(b1, b2, overlaps, within1, within2);
+
+ /*
+ \see http://docs.codehaus.org/display/GEOTDOC/02+Geometry+Relationships#02GeometryRelationships-Overlaps
+ where is stated that "inside" is not an "overlap",
+ this is true and is implemented as such.
+ */
+ return overlaps && ! within1 && ! within2;
+ }
+};
+
+
+
+}} // namespace detail::overlaps
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag1,
+ typename Tag2,
+ typename Geometry1,
+ typename Geometry2
+>
+struct overlaps
+{};
+
+
+template <typename Box1, typename Box2>
+struct overlaps<box_tag, box_tag, Box1, Box2>
+ : detail::overlaps::box_box<Box1, Box2>
+{};
+
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Determines overlap between two geometries
+ \ingroup overlaps
+ \return true if there is overlap
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ return dispatch::overlaps
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_OVERLAPS_HPP

Added: sandbox/geometry/boost/geometry/algorithms/overlay/assemble.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/overlay/assemble.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,810 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2010, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_OVERLAY_ASSEMBLE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_OVERLAY_ASSEMBLE_HPP
+
+#include <deque>
+#include <vector>
+
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
+#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
+#include <boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/ring_properties.hpp>
+
+
+#include <boost/geometry/algorithms/overlay/get_turns.hpp>
+#include <boost/geometry/algorithms/overlay/enrich_intersection_points.hpp>
+//#include <boost/geometry/algorithms/detail/overlay/enrich.hpp>
+#include <boost/geometry/algorithms/overlay/traverse.hpp>
+
+
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/algorithms/combine.hpp>
+#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/algorithms/num_points.hpp>
+#include <boost/geometry/algorithms/within.hpp>
+
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>
+
+#include <boost/geometry/iterators/range_type.hpp>
+
+#include <boost/geometry/strategies/intersection.hpp>
+
+//#define BOOST_GEOMETRY_DEBUG_ASSEMBLE
+
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+# include <boost/geometry/util/write_dsv.hpp>
+#endif
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay {
+
+
+
+template<typename Tag>
+struct get_ring
+{};
+
+template<>
+struct get_ring<ring_tag>
+{
+ template<typename Ring>
+ static inline Ring const& apply(ring_identifier const& id, Ring const& ring)
+ {
+ return ring;
+ }
+};
+
+
+template<>
+struct get_ring<void>
+{
+ template<typename Container>
+ static inline typename boost::range_value<Container>::type const&
+ apply(ring_identifier const& id, Container const& container)
+ {
+ return container[id.multi_index];
+ }
+};
+
+
+template<>
+struct get_ring<box_tag>
+{
+ template<typename Box>
+ static inline Box const& apply(ring_identifier const& id,
+ Box const& box)
+ {
+ return box;
+ }
+};
+
+
+template<>
+struct get_ring<polygon_tag>
+{
+ template<typename Polygon>
+ static inline typename ring_type<Polygon>::type const& apply(
+ ring_identifier const& id,
+ Polygon const& polygon)
+ {
+ BOOST_ASSERT
+ (
+ id.ring_index >= -1
+ && id.ring_index < boost::size(interior_rings(polygon))
+ );
+ return id.ring_index < 0
+ ? exterior_ring(polygon)
+ : interior_rings(polygon)[id.ring_index];
+ }
+};
+
+
+
+
+template<typename Tag>
+struct convert_ring
+{};
+
+template<>
+struct convert_ring<ring_tag>
+{
+ template<typename Destination, typename Source>
+ static inline void apply(Destination& destination, Source const& source,
+ bool append = false)
+ {
+ if (! append)
+ {
+ geometry::convert(source, destination);
+ }
+ }
+};
+
+
+
+
+template<>
+struct convert_ring<polygon_tag>
+{
+ template<typename Destination, typename Source>
+ static inline void apply(Destination& destination, Source const& source,
+ bool append = false)
+ {
+ if (! append)
+ {
+ geometry::convert(source, exterior_ring(destination));
+ }
+ else
+ {
+ interior_rings(destination).resize(
+ interior_rings(destination).size() + 1);
+ geometry::convert(source, interior_rings(destination).back());
+ }
+ }
+};
+
+
+
+template <typename Tag, typename Geometry>
+struct add_to_containment
+{};
+
+template <typename Ring>
+struct add_to_containment<ring_tag, Ring>
+{
+ template <typename ContainmentContainer, typename Map>
+ static inline void apply(ContainmentContainer& container,
+ ring_identifier const& id, Ring const& ring, Map const& map)
+ {
+ typedef typename range_value<ContainmentContainer>::type prop;
+ container.push_back(prop(id, ring, map.find(id) != map.end()));
+ }
+};
+
+template <typename Box>
+struct add_to_containment<box_tag, Box>
+{
+ template <typename ContainmentContainer, typename Map>
+ static inline void apply(ContainmentContainer& container,
+ ring_identifier const& id, Box const& box, Map const& map)
+ {
+ typedef typename range_value<ContainmentContainer>::type prop;
+ container.push_back(prop(id, box, map.find(id) != map.end()));
+ }
+};
+
+
+template <typename Polygon>
+struct add_to_containment<polygon_tag, Polygon>
+{
+ template <typename ContainmentContainer, typename Map>
+ static inline void apply(ContainmentContainer& container,
+ ring_identifier const& id, Polygon const& polygon, Map const& map)
+ {
+ // Add exterior ring and interior rings
+ ring_identifier copy = id;
+
+ typedef add_to_containment
+ <
+ ring_tag,
+ typename ring_type<Polygon>::type
+ > policy;
+
+ policy::apply(container, copy, exterior_ring(polygon), map);
+ copy.ring_index = 0;
+ for (typename boost::range_iterator
+ <
+ typename interior_type<Polygon>::type const
+ >::type it = boost::begin(interior_rings(polygon));
+ it != boost::end(interior_rings(polygon));
+ ++it, ++copy.ring_index)
+ {
+ policy::apply(container, copy, *it, map);
+ }
+ }
+};
+
+
+
+template <typename TurnPoints, typename Map>
+inline void map_turns(Map& map, TurnPoints const& turn_points)
+{
+ typedef typename boost::range_value<TurnPoints>::type turn_point_type;
+ typedef typename turn_point_type::container_type container_type;
+
+ int index = 0;
+ for (typename boost::range_iterator<TurnPoints const>::type
+ it = boost::begin(turn_points);
+ it != boost::end(turn_points);
+ ++it, ++index)
+ {
+ int op_index = 0;
+ for (typename boost::range_iterator<container_type const>::type
+ op_it = boost::begin(it->operations);
+ op_it != boost::end(it->operations);
+ ++op_it, ++op_index)
+ {
+ ring_identifier ring_id
+ (
+ op_it->seg_id.source_index,
+ op_it->seg_id.multi_index,
+ op_it->seg_id.ring_index
+ );
+ map[ring_id]++;
+ }
+ }
+}
+
+
+template
+<
+ typename Container,
+ typename Geometry1,
+ typename Geometry2,
+ typename RingCollection,
+ typename Box
+>
+struct enrich_containment
+{
+
+ typedef typename boost::range_value<Container>::type item_type;
+ typedef typename item_type::parent parent_type;
+ typedef typename geometry::tag<Geometry1>::type tag1;
+ typedef typename geometry::tag<Geometry2>::type tag2;
+ typedef void tag3; // For the ring-container
+
+
+ static inline void assign(item_type& item1, item_type& item2)
+ {
+ int or1 = item1.area > 0 ? 1 : item1.area < 0 ? -1 : 0;
+ int or2 = item2.area > 0 ? 1 : item2.area < 0 ? -1 : 0;
+ if (or1 != 0 && or2 != 0)
+ {
+ if (or1 == 1 && or2 == 1)
+ {
+ item1.c = 1;
+ item2.c = -1;
+ }
+
+ if (! item1.produced)
+ {
+ // This is an original ring, used to set info about
+ // the parents of interiors
+ if (or1 == 1)
+ {
+ item2.push(parent_type(item1.c, item1.ring_id));
+ }
+ else if (or1 == -1 && ! item1.intersects)
+ {
+ item2.pop();
+ }
+ }
+ else
+ {
+ if (or1 == 1 && or2 == -1 && ! item2.intersects)
+ {
+ // Assign this produced parent as the parent
+ // to this hole
+ item2.has_parent_id = true;
+ item2.parent_id = item1.ring_id;
+ }
+ }
+ }
+ }
+
+
+ // Creates a selection of pointers within the specified box
+ template <typename Collection>
+ static inline void select_by_box(Collection& selection,
+ Collection const& collection,
+ Box const& box)
+ {
+ for (typename boost::range_iterator<Collection const>::type
+ it = boost::begin(collection);
+ it != boost::end(collection);
+ ++it)
+ {
+ if (! geometry::detail::disjoint::disjoint_box_box(box, (*it)->box))
+ {
+ selection.push_back(*it);
+ }
+ }
+ }
+
+ static inline bool contains(item_type const& item1, item_type const& item2,
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ RingCollection const& collection)
+ {
+ if (item1.ring_id.source_index == 0)
+ {
+ return geometry::within(item2.point,
+ get_ring<tag1>::apply(item1.ring_id, geometry1));
+ }
+ else if (item1.ring_id.source_index == 1)
+ {
+ return geometry::within(item2.point,
+ get_ring<tag2>::apply(item1.ring_id, geometry2));
+ }
+ else if (item1.ring_id.source_index == 2)
+ {
+ return geometry::within(item2.point,
+ get_ring<tag3>::apply(item1.ring_id, collection));
+ }
+ return false;
+ }
+
+ template <typename Selection, typename Map>
+ static inline void enrich(Selection& selection, Map& map,
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ RingCollection const& collection,
+ int direction)
+ {
+ typedef typename boost::range_iterator<Selection>::type iterator;
+
+ for (iterator it1 = boost::begin(selection);
+ it1 != boost::end(selection);
+ ++it1)
+ {
+//std::cout << ".";
+ item_type& item1 = **it1;
+ iterator it2 = it1;
+ for (it2++; it2 != boost::end(selection); ++it2)
+ {
+ std::pair<item_type*, item_type*> p
+ = std::make_pair(*it1, *it2);
+ bool processed = map[p];
+ if (! processed)
+ {
+ map[p] = true;
+
+ item_type& item2 = **it2;
+ if (geometry::within(item2.point, item1.box)
+ && std::abs(item2.area) < std::abs(item1.area)
+ && contains(item1, item2, geometry1, geometry2,
+ collection)
+ )
+ {
+ assign(item1, item2);
+ }
+ }
+ }
+ }
+ }
+
+ template <int Dimension, typename Selection, typename Map>
+ static inline void divide_and_conquer(Selection& selection, Map& map,
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ RingCollection const& collection,
+ int direction, Box const& box,
+ std::size_t iteration = 0, std::size_t previous_count = 0)
+ {
+ std::size_t n = boost::size(selection);
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+std::cout << "spatial divide n="
+<< n
+<< " previous=" << previous_count
+<< " iteration=" << iteration
+<< " box: " << geometry::dsv(box) << std::endl;
+#endif
+
+ if (iteration > 3)
+ {
+ enrich(selection, map, geometry1, geometry2, collection, direction);
+ return;
+ }
+
+ // Divide the complete box in two (alternating) halves
+ Box lower = box, upper = box;
+ typename geometry::coordinate_type<Box>::type two = 2.0;
+ typename geometry::coordinate_type<Box>::type mid
+ = (geometry::get<min_corner, Dimension>(box)
+ + geometry::get<max_corner, Dimension>(box)) / two;
+
+ geometry::set<max_corner, Dimension>(lower, mid);
+ geometry::set<min_corner, Dimension>(upper, mid);
+
+ // select
+ std::vector<item_type*> lower_sel, upper_sel;
+ select_by_box(lower_sel, selection, lower);
+ select_by_box(upper_sel, selection, upper);
+
+ divide_and_conquer<1 - Dimension>(lower_sel, map, geometry1, geometry2,
+ collection, direction, lower, iteration + 1, n);
+ divide_and_conquer<1 - Dimension>(upper_sel, map, geometry1, geometry2,
+ collection, direction, upper, iteration + 1, n);
+ }
+
+ static inline void enrich(Container& container,
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ RingCollection const& collection,
+ int direction)
+ {
+ typedef typename boost::range_iterator<Container>::type iterator;
+
+ int n = 0;
+
+ for (iterator it1 = boost::begin(container);
+ it1 != boost::end(container);
+ ++it1)
+ {
+ item_type& item1 = *it1;
+ iterator it2 = it1;
+ for (it2++; it2 != boost::end(container); ++it2)
+ {
+ item_type& item2 = *it2;
+ if (geometry::within(item2.point, item1.box)
+ && std::abs(item2.area) < std::abs(item1.area)
+ && contains(item1, item2, geometry1, geometry2, collection)
+ )
+ {
+ n++;
+ assign(item1, item2);
+ }
+ }
+ }
+ //std::cout << "Enriched: " << n << std::endl;
+ }
+
+
+
+ static inline void apply(Container& container,
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ RingCollection const& collection,
+ int direction, Box const& box)
+ {
+ if (boost::size(container) == 0)
+ {
+ return;
+ }
+ enrich(container, geometry1, geometry2, collection, direction);
+ return;
+
+ // Method using divide and conquer (does NOT work corretly!)
+
+ std::vector<item_type*> selection;
+ selection.reserve(boost::size(container));
+ for (typename boost::range_iterator<Container>::type
+ it = boost::begin(container);
+ it != boost::end(container);
+ ++it)
+ {
+ selection.push_back(&(*it));
+ }
+
+ std::map<std::pair<item_type*, item_type*>, bool> map;
+ divide_and_conquer<1>(selection, map, geometry1, geometry2, collection,
+ direction, box);
+ }
+};
+
+
+template
+<
+ typename GeometryOut,
+ typename Container,
+ typename Geometry1,
+ typename Geometry2,
+ typename RingCollection,
+ typename OutputIterator
+>
+inline OutputIterator add_all_rings(Container& container,
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ RingCollection const& collection,
+ int direction,
+ OutputIterator out)
+{
+ typedef typename boost::range_iterator<Container>::type iterator;
+ typedef typename geometry::tag<GeometryOut>::type tag_out;
+ typedef typename geometry::tag<Geometry1>::type tag1;
+ typedef typename geometry::tag<Geometry2>::type tag2;
+ typedef void tag3; // For the ring-container
+
+
+ bool result_filled = false;
+ GeometryOut result;
+ ring_identifier previous_id;
+ previous_id.source_index = -1;
+
+ for (iterator it = boost::begin(container);
+ it != boost::end(container);
+ ++it)
+ {
+ if (it->area > 0)
+ {
+ if (result_filled)
+ {
+ *out++ = result;
+ previous_id.source_index = -1;
+ result_filled = false;
+ }
+
+ // If it is an outer ring, it is included if there are no parents
+ // (union) or if there are parents (intersection)
+ if (it->included(direction))
+ {
+ geometry::clear(result);
+ previous_id = it->ring_id;
+ result_filled = true;
+ if (it->ring_id.source_index == 0)
+ {
+ convert_ring<tag_out>::apply(result,
+ get_ring<tag1>::apply(it->ring_id, geometry1));
+ }
+ else if (it->ring_id.source_index == 1)
+ {
+ convert_ring<tag_out>::apply(result,
+ get_ring<tag2>::apply(it->ring_id, geometry2));
+ }
+ else if (it->ring_id.source_index == 2)
+ {
+ convert_ring<tag_out>::apply(result,
+ get_ring<tag3>::apply(it->ring_id, collection));
+ }
+ }
+ }
+ else
+ {
+ // If it is an interior ring, it is included if
+ // it's parent-id matches the id of the outputted exterior ring
+ if (result_filled
+ && it->id() == previous_id
+ && it->included(direction))
+ {
+ if (it->ring_id.source_index == 0)
+ {
+ convert_ring<tag_out>::apply(result,
+ get_ring<tag1>::apply(it->ring_id,
+ geometry1), true);
+ }
+ else if (it->ring_id.source_index == 1)
+ {
+ convert_ring<tag_out>::apply(result,
+ get_ring<tag2>::apply(it->ring_id,
+ geometry2), true);
+ }
+ else if (it->ring_id.source_index == 2)
+ {
+ convert_ring<tag_out>::apply(result,
+ get_ring<tag3>::apply(it->ring_id,
+ collection), true);
+ }
+ }
+ }
+ }
+ if (result_filled)
+ {
+ *out++ = result;
+ }
+ return out;
+}
+
+template <typename Container>
+inline void sort_on_parent_id(Container& container, int direction)
+{
+ typedef typename boost::range_iterator<Container>::type iterator;
+ typedef typename boost::range_value<Container>::type item_type;
+
+ // For negative rings produced by traversal,
+ // find the parent of the selected operation
+ // (by popping from the stack if necessary)
+ for (iterator it = boost::begin(container);
+ it != boost::end(container);
+ ++it)
+ {
+ if (it->produced && it->area < 0)
+ {
+ while (! it->interior_included(direction)
+ && ! it->parent_stack_empty())
+ {
+ it->pop();
+ }
+ }
+ }
+
+ // Sort container on parent-id
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+std::cout << "assemble.properties sort on parent-id "
+ << boost::size(container) << std::endl;
+#endif
+ std::sort(boost::begin(container), boost::end(container),
+ sort_on_id_or_parent_id<item_type>());
+}
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename OutputIterator, typename GeometryOut,
+ int Direction,
+ typename Strategy
+>
+struct overlay_and_assemble
+{
+ typedef typename geometry::tag<Geometry1>::type tag1;
+ typedef typename geometry::tag<Geometry2>::type tag2;
+ typedef typename geometry::tag<GeometryOut>::type tag_out;
+
+ static inline OutputIterator apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2, OutputIterator out,
+ Strategy const& strategy)
+ {
+ if (geometry::num_points(geometry1) == 0
+ || geometry::num_points(geometry2) == 0)
+ {
+ return out;
+ }
+
+ typedef typename geometry::point_type<GeometryOut>::type point_type;
+
+
+ typedef detail::overlay::traversal_turn_info<point_type> turn_info;
+ typedef std::deque<turn_info> container_type;
+
+ // "Abuse" rangetype for ringtype: for polygon, it is the type of the
+ // exterior ring. For ring, it is the ring itself. That is what is
+ // wished here as well.
+ typedef typename geometry::range_type<GeometryOut>::type ring_type;
+
+ container_type turn_points;
+
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+std::cout << "get turns" << std::endl;
+#endif
+ boost::geometry::get_turns
+ <
+ detail::overlay::CalculateDistancePolicy
+ >(geometry1, geometry2, turn_points);
+
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+std::cout << "enrich" << std::endl;
+#endif
+ typename Strategy::side_strategy_type side_strategy;
+ geometry::enrich_intersection_points(turn_points, geometry1, geometry2,
+ side_strategy);
+
+ std::vector<ring_type> rings;
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+std::cout << "traverse" << std::endl;
+#endif
+ geometry::traverse<typename Strategy::side_strategy_type, ring_type>
+ (
+ geometry1,
+ geometry2,
+ Direction == -1
+ ? boost::geometry::detail::overlay::operation_intersection
+ : boost::geometry::detail::overlay::operation_union
+ ,
+ turn_points,
+ std::back_inserter(rings)
+ );
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+std::cout << "assemble" << std::endl;
+#endif
+
+
+ // Map intersection-points per ring-identifier to <count>
+ std::map<ring_identifier, int> map;
+ map_turns(map, turn_points);
+
+// TODO: translate/implement this (sorry for the dutch)
+//1. loop ook door originele ringen heen, map[ring] = 0
+//2. verander dan map.find=.end in .find -> it=0
+//3. we weten nu dat er "untouched" ringen zijn, als dat zo is,
+// dan "enrich assemble" etc.kl
+
+ typedef std::vector
+ <
+ ring_properties<point_type>
+ > ring_properties_container_type;
+ ring_properties_container_type ring_properties_container;
+
+
+ add_to_containment
+ <
+ tag1,
+ Geometry1
+ >::apply(ring_properties_container,
+ ring_identifier(0,-1,-1), geometry1, map);
+ add_to_containment
+ <
+ tag2,
+ Geometry2
+ >::apply(ring_properties_container,
+ ring_identifier(1,-1,-1), geometry2, map);
+
+
+
+ // Add all produced rings using source index 2
+ {
+ ring_identifier id(2, 0, -1);
+ for (typename std::vector<ring_type>::const_iterator
+ it = boost::begin(rings);
+ it != boost::end(rings);
+ ++it, ++id.multi_index)
+ {
+ ring_properties_container.push_back(
+ ring_properties<point_type>(id, *it, false, true));
+ }
+ }
+
+ bool only_positive = true;
+ {
+ int pos=0, neg=0;
+ for (typename ring_properties_container_type::const_iterator
+ it = boost::begin(ring_properties_container);
+ it != boost::end(ring_properties_container);
+ ++it)
+ {
+ if (it->area>0)
+ {
+ pos++;
+ }
+ else
+ {
+ neg++;
+ only_positive = false;
+ }
+ }
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+ std::cout << "assemble, pos=" << pos << " neg=" << neg << std::endl;
+#endif
+ }
+
+ //if (! only_positive)
+ {
+ typedef geometry::box<point_type> box_type;
+ box_type total = geometry::make_envelope<box_type>(geometry1);
+ geometry::combine(total,
+ geometry::make_envelope<box_type>(geometry2));
+
+
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+std::cout << "assemble.properties sort "
+ << boost::size(ring_properties_container) << std::endl;
+#endif
+ std::sort(boost::begin(ring_properties_container),
+ boost::end(ring_properties_container));
+
+
+
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+std::cout << "assemble.enrich containment" << std::endl;
+#endif
+ enrich_containment
+ <
+ ring_properties_container_type,
+ Geometry1,
+ Geometry2,
+ std::vector<ring_type>,
+ geometry::box<point_type>
+ >::apply(ring_properties_container,
+ geometry1, geometry2, rings, Direction, total);
+
+ sort_on_parent_id(ring_properties_container, Direction);
+ }
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+std::cout << "assemble.add rings" << std::endl;
+#endif
+ return add_all_rings<GeometryOut>(ring_properties_container,
+ geometry1, geometry2, rings, Direction, out);
+ }
+};
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_OVERLAY_ASSEMBLE_HPP

Added: sandbox/geometry/boost/geometry/algorithms/overlay/clip_linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/overlay/clip_linestring.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,239 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_OVERLAY_CLIP_LINESTRING_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_OVERLAY_CLIP_LINESTRING_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/append.hpp>
+#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/util/copy.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+#include <boost/geometry/geometries/segment.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace intersection {
+
+/*!
+ \brief Strategy: line clipping algorithm after Liang Barsky
+ \ingroup overlay
+ \details The Liang-Barsky line clipping algorithm clips a line with a clipping box.
+ It is slightly adapted in the sense that it returns which points are clipped
+ \tparam B input box type of clipping box
+ \tparam P input/output point-type of segments to be clipped
+ \note The algorithm is currently only implemented for 2D Cartesian points
+ \note Though it is implemented in namespace strategy, and theoretically another
+ strategy could be used, it is not (yet) updated to the general strategy concepts,
+ and not (yet) splitted into a file in folder strategies
+ \author Barend Gehrels, and the following recourses
+ - A tutorial: http://www.skytopia.com/project/articles/compsci/clipping.html
+ - a German applet (link broken): http://ls7-www.cs.uni-dortmund.de/students/projectgroups/acit/lineclip.shtml
+*/
+template<typename Box, typename Point>
+class liang_barsky
+{
+private:
+ typedef geometry::segment<Point> segment_type;
+
+ template <typename T>
+ inline bool check_edge(T const& p, T const& q, T& t1, T& t2) const
+ {
+ bool visible = true;
+
+ if(p < 0)
+ {
+ T const r = q / p;
+ if (r > t2)
+ visible = false;
+ else if (r > t1)
+ t1 = r;
+ }
+ else if(p > 0)
+ {
+ T const r = q / p;
+ if (r < t1)
+ visible = false;
+ else if (r < t2)
+ t2 = r;
+ }
+ else
+ {
+ if (q < 0)
+ visible = false;
+ }
+
+ return visible;
+ }
+
+public:
+
+ inline bool clip_segment(Box const& b, segment_type& s, bool& sp1_clipped, bool& sp2_clipped) const
+ {
+ typedef typename select_coordinate_type<Box, Point>::type coordinate_type;
+
+ coordinate_type t1 = 0;
+ coordinate_type t2 = 1;
+
+ coordinate_type const dx = get<1, 0>(s) - get<0, 0>(s);
+ coordinate_type const dy = get<1, 1>(s) - get<0, 1>(s);
+
+ coordinate_type const p1 = -dx;
+ coordinate_type const p2 = dx;
+ coordinate_type const p3 = -dy;
+ coordinate_type const p4 = dy;
+
+ coordinate_type const q1 = get<0, 0>(s) - get<min_corner, 0>(b);
+ coordinate_type const q2 = get<max_corner, 0>(b) - get<0, 0>(s);
+ coordinate_type const q3 = get<0, 1>(s) - get<min_corner, 1>(b);
+ coordinate_type const q4 = get<max_corner, 1>(b) - get<0, 1>(s);
+
+ 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;
+
+ if (sp2_clipped)
+ {
+ set<1, 0>(s, get<0, 0>(s) + t2 * dx);
+ set<1, 1>(s, get<0, 1>(s) + t2 * dy);
+ }
+
+ if(sp1_clipped)
+ {
+ set<0, 0>(s, get<0, 0>(s) + t1 * dx);
+ set<0, 1>(s, get<0, 1>(s) + t1 * dy);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ template<typename Linestring, typename OutputIterator>
+ inline void apply(Linestring& line_out, OutputIterator out) const
+ {
+ if (!boost::empty(line_out))
+ {
+ *out = line_out;
+ ++out;
+ geometry::clear(line_out);
+ }
+ }
+};
+
+
+}} // namespace strategy::intersection
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersection {
+
+/*!
+ \brief Clips a linestring with a box
+ \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.
+ \tparam OutputLinestring type of the output linestrings
+ \tparam OutputIterator an output iterator which outputs linestrings
+ \tparam Linestring linestring-type, for example a vector of points, matching the output-iterator type,
+ the points should also match the input-iterator type
+ \tparam Box box type
+ \tparam Strategy strategy, a clipping strategy which should implement the methods "clip_segment" and "apply"
+*/
+template
+<
+ typename OutputLinestring,
+ typename OutputIterator,
+ typename Linestring,
+ typename Box,
+ typename Strategy
+>
+OutputIterator clip_linestring_with_box(Box const& b, Linestring const& linestring,
+ OutputIterator out, Strategy const& strategy)
+{
+ if (boost::begin(linestring) == boost::end(linestring))
+ {
+ return out;
+ }
+
+ typedef typename point_type<OutputLinestring>::type point_type;
+
+ OutputLinestring line_out;
+
+ typedef typename boost::range_const_iterator<Linestring>::type iterator_type;
+ iterator_type vertex = boost::begin(linestring);
+ for(iterator_type previous = vertex++;
+ vertex != boost::end(linestring);
+ previous = vertex++)
+ {
+ point_type p1, p2;
+ copy_coordinates(*previous, p1);
+ copy_coordinates(*vertex, p2);
+
+ // 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 = false;
+ bool c2 = false;
+ segment<point_type> s(p1, p2);
+
+ if (!strategy.clip_segment(b, s, c1, c2))
+ {
+ strategy.apply(line_out, out);
+ }
+ else
+ {
+ // a. If necessary, finish the line and add a start a new one
+ if (c1)
+ {
+ strategy.apply(line_out, out);
+ }
+
+ // b. Add p1 only if it is the first point, then add p2
+ if (boost::empty(line_out))
+ {
+ geometry::append(line_out, p1);
+ }
+ geometry::append(line_out, p2);
+
+ // c. If c2 is clipped, finish the line
+ if (c2)
+ {
+ strategy.apply(line_out, out);
+ }
+ }
+
+ }
+
+ // Add last part
+ strategy.apply(line_out, out);
+ return out;
+}
+
+}} // namespace detail::intersection
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_OVERLAY_CLIP_LINESTRING_HPP

Added: sandbox/geometry/boost/geometry/algorithms/overlay/copy_segment_point.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/overlay/copy_segment_point.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,273 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_OVERLAY_COPY_SEGMENT_POINT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_OVERLAY_COPY_SEGMENT_POINT_HPP
+
+
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/overlay/intersection_point.hpp>
+
+#include <boost/geometry/iterators/ever_circling_iterator.hpp>
+
+#include <boost/geometry/iterators/range_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace copy_segments {
+
+
+template <typename Range, typename SegmentIdentifier, typename PointOut>
+struct copy_segment_point_range
+{
+ static inline bool apply(Range const& range,
+ SegmentIdentifier const& seg_id, bool second,
+ PointOut& point)
+ {
+ int index = seg_id.segment_index;
+ if (second)
+ {
+ index++;
+ if (index >= boost::size(range))
+ {
+ index = 0;
+ }
+ }
+
+ // Exception?
+ if (index >= boost::size(range))
+ {
+ return false;
+ }
+
+ geometry::copy_coordinates(range[index], point);
+ return true;
+ }
+};
+
+
+template <typename Polygon, typename SegmentIdentifier, typename PointOut>
+struct copy_segment_point_polygon
+{
+ static inline bool apply(Polygon const& polygon,
+ SegmentIdentifier const& seg_id, bool second,
+ PointOut& point)
+ {
+ // Call ring-version with the right ring
+ return copy_segment_point_range
+ <
+ typename geometry::ring_type<Polygon>::type,
+ SegmentIdentifier,
+ PointOut
+ >::apply
+ (
+ seg_id.ring_index < 0
+ ? geometry::exterior_ring(polygon)
+ : geometry::interior_rings(polygon)[seg_id.ring_index],
+ seg_id, second,
+ point
+ );
+ }
+};
+
+
+template <typename Box, typename SegmentIdentifier, typename PointOut>
+struct copy_segment_point_box
+{
+ static inline bool apply(Box const& box,
+ SegmentIdentifier const& seg_id, bool second,
+ PointOut& point)
+ {
+ int index = seg_id.segment_index;
+ if (second)
+ {
+ index++;
+ }
+
+ PointOut ll, lr, ul, ur;
+ assign_box_corners(box, ll, lr, ul, ur);
+ switch(index)
+ {
+ case 1 : point = ul; break;
+ case 2 : point = ur; break;
+ case 3 : point = lr; break;
+ default : // 0,4 or 'overflow'
+ point = ll; break;
+ }
+ return true;
+ }
+};
+
+
+
+
+}} // namespace detail::copy_segments
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+
+template
+<
+ typename Tag,
+ typename GeometryIn,
+ typename SegmentIdentifier,
+ typename PointOut
+>
+struct copy_segment_point
+{};
+
+
+template <typename LineString, typename SegmentIdentifier, typename PointOut>
+struct copy_segment_point<linestring_tag, LineString, SegmentIdentifier, PointOut>
+ : detail::copy_segments::copy_segment_point_range
+ <
+ LineString, SegmentIdentifier, PointOut
+ >
+{};
+
+
+template <typename Ring, typename SegmentIdentifier, typename PointOut>
+struct copy_segment_point<ring_tag, Ring, SegmentIdentifier, PointOut>
+ : detail::copy_segments::copy_segment_point_range
+ <
+ Ring, SegmentIdentifier, PointOut
+ >
+{};
+
+template <typename Polygon, typename SegmentIdentifier, typename PointOut>
+struct copy_segment_point<polygon_tag, Polygon, SegmentIdentifier, PointOut>
+ : detail::copy_segments::copy_segment_point_polygon
+ <
+ Polygon, SegmentIdentifier, PointOut
+ >
+{};
+
+
+template <typename Box, typename SegmentIdentifier, typename PointOut>
+struct copy_segment_point<box_tag, Box, SegmentIdentifier, PointOut>
+ : detail::copy_segments::copy_segment_point_box
+ <
+ Box, SegmentIdentifier, PointOut
+ >
+{};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+
+
+/*!
+ \brief Helper function, copies a point from a segment
+ \ingroup overlay
+ */
+template<typename Geometry, typename SegmentIdentifier, typename PointOut>
+inline bool copy_segment_point(Geometry const& geometry,
+ SegmentIdentifier const& seg_id, bool second,
+ PointOut& point_out)
+{
+ concept::check<const Geometry>();
+
+ return dispatch::copy_segment_point
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ SegmentIdentifier,
+ PointOut
+ >::apply(geometry, seg_id, second, point_out);
+}
+
+
+/*!
+ \brief Helper function, to avoid the same construct several times,
+ copies a point, based on a source-index and two geometries
+ \ingroup overlay
+ */
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename SegmentIdentifier,
+ typename PointOut
+>
+inline bool copy_segment_point(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ SegmentIdentifier const& seg_id, bool second,
+ PointOut& point_out)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ if (seg_id.source_index == 0)
+ {
+ return dispatch::copy_segment_point
+ <
+ typename tag<Geometry1>::type,
+ Geometry1,
+ SegmentIdentifier,
+ PointOut
+ >::apply(geometry1, seg_id, second, point_out);
+ }
+ else if (seg_id.source_index == 1)
+ {
+ return dispatch::copy_segment_point
+ <
+ typename tag<Geometry2>::type,
+ Geometry2,
+ SegmentIdentifier,
+ PointOut
+ >::apply(geometry2, seg_id, second, point_out);
+ }
+ // Exception?
+ return false;
+}
+
+
+/*!
+ \brief Helper function, to avoid the same construct several times,
+ copies a point, based on a source-index and two geometries
+ \ingroup overlay
+ */
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename SegmentIdentifier,
+ typename PointOut
+>
+inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ SegmentIdentifier const& seg_id,
+ PointOut& point1, PointOut& point2)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ return copy_segment_point(geometry1, geometry2, seg_id, false, point1)
+ && copy_segment_point(geometry1, geometry2, seg_id, true, point2);
+}
+
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_OVERLAY_COPY_SEGMENT_POINT_HPP

Added: sandbox/geometry/boost/geometry/algorithms/overlay/copy_segments.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/overlay/copy_segments.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,221 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_OVERLAY_COPY_SEGMENTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_OVERLAY_COPY_SEGMENTS_HPP
+
+#include <boost/assert.hpp>
+
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/overlay/intersection_point.hpp>
+
+#include <boost/geometry/iterators/ever_circling_iterator.hpp>
+
+#include <boost/geometry/iterators/range_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace copy_segments {
+
+
+template <typename Ring, typename SegmentIdentifier, typename RangeOut>
+struct copy_segments_ring
+{
+ static inline void apply(Ring const& ring,
+ SegmentIdentifier const& seg_id, int to_index,
+ RangeOut& current_output)
+ {
+ typedef typename boost::range_const_iterator<Ring>::type iterator;
+
+ typedef geometry::ever_circling_iterator<iterator> ec_iterator;
+
+ // The problem: sometimes we want to from "3" to "2" -> end = "3" -> end == begin
+ // This is not convenient with iterators.
+
+ // So we use the ever-circling iterator and determine when to step out
+
+ int from_index = seg_id.segment_index + 1;
+
+ // Sanity check
+ BOOST_ASSERT(from_index < boost::size(ring));
+
+ ec_iterator it(boost::begin(ring), boost::end(ring),
+ boost::begin(ring) + from_index);
+
+ // [2..4] -> 4 - 2 + 1 = 3 -> {2,3,4} -> OK
+ // [4..2],size=6 -> 6 - 4 + 2 + 1 = 5 -> {4,5,0,1,2} -> OK
+ // [1..1], travel the whole ring round
+ int count = from_index <= to_index
+ ? to_index - from_index + 1
+ : boost::size(ring) - from_index + to_index + 1;
+
+ for (int i = 0; i < count; ++i, ++it)
+ {
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ std::cout << " add: ("
+ << geometry::get<0>(*it) << ", " << geometry::get<1>(*it) << ")"
+ << std::endl;
+#endif
+ typename geometry::point_type<RangeOut>::type p;
+ geometry::copy_coordinates(*it, p);
+ //current_output.push_back(p);
+ *(std::back_inserter(current_output)++) = p;
+ }
+ }
+};
+
+
+template <typename Polygon, typename SegmentIdentifier, typename RangeOut>
+struct copy_segments_polygon
+{
+ static inline void apply(Polygon const& polygon,
+ SegmentIdentifier const& seg_id, int to_index,
+ RangeOut& current_output)
+ {
+ // Call ring-version with the right ring
+ copy_segments_ring
+ <
+ typename geometry::ring_type<Polygon>::type,
+ SegmentIdentifier,
+ RangeOut
+ >::apply
+ (
+ seg_id.ring_index < 0
+ ? geometry::exterior_ring(polygon)
+ : geometry::interior_rings(polygon)[seg_id.ring_index],
+ seg_id, to_index,
+ current_output
+ );
+ }
+};
+
+
+template <typename Box, typename SegmentIdentifier, typename RangeOut>
+struct copy_segments_box
+{
+ static inline void apply(Box const& box,
+ SegmentIdentifier const& seg_id, int to_index,
+ RangeOut& current_output)
+ {
+ // Convert again...
+ // TODO: avoid that...
+
+ typedef typename point_type<Box>::type point_type;
+
+ point_type ll, lr, ul, ur;
+ assign_box_corners(box, ll, lr, ul, ur);
+
+ std::vector<point_type> points;
+ points.push_back(ll);
+ points.push_back(ul);
+ points.push_back(ur);
+ points.push_back(lr);
+ points.push_back(ll);
+
+ copy_segments_ring
+ <
+ std::vector<point_type>,
+ SegmentIdentifier,
+ RangeOut
+ >
+ ::apply(points, seg_id, to_index, current_output);
+ }
+};
+
+
+
+
+}} // namespace detail::copy_segments
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+
+template
+<
+ typename Tag,
+ typename GeometryIn,
+ typename SegmentIdentifier,
+ typename RangeOut
+>
+struct copy_segments
+{
+};
+
+
+template <typename Ring, typename SegmentIdentifier, typename RangeOut>
+struct copy_segments<ring_tag, Ring, SegmentIdentifier, RangeOut>
+ : detail::copy_segments::copy_segments_ring
+ <
+ Ring, SegmentIdentifier, RangeOut
+ >
+{};
+
+template <typename Polygon, typename SegmentIdentifier, typename RangeOut>
+struct copy_segments<polygon_tag, Polygon, SegmentIdentifier, RangeOut>
+ : detail::copy_segments::copy_segments_polygon
+ <
+ Polygon, SegmentIdentifier, RangeOut
+ >
+{};
+
+
+template <typename Box, typename SegmentIdentifier, typename RangeOut>
+struct copy_segments<box_tag, Box, SegmentIdentifier, RangeOut>
+ : detail::copy_segments::copy_segments_box
+ <
+ Box, SegmentIdentifier, RangeOut
+ >
+{};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+
+
+/*!
+ \brief Traverses through intersection points / geometries
+ \ingroup overlay
+ */
+template<typename Geometry, typename SegmentIdentifier, typename RangeOut>
+inline void copy_segments(Geometry const& geometry,
+ SegmentIdentifier const& seg_id, int to_index,
+ RangeOut& range_out)
+{
+ concept::check<const Geometry>();
+
+ dispatch::copy_segments
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ SegmentIdentifier,
+ RangeOut
+ >::apply(geometry, seg_id, to_index, range_out);
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_OVERLAY_COPY_SEGMENTS_HPP

Added: sandbox/geometry/boost/geometry/algorithms/overlay/enrich_intersection_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/overlay/enrich_intersection_points.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,381 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2010, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICH_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICH_HPP
+
+
+#include <cstddef>
+#include <algorithm>
+#include <map>
+#include <vector>
+
+#ifdef BOOST_GEOMETRY_DEBUG_OVERLAY
+#include <iostream>
+#endif
+
+#include <boost/assert.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
+#include <boost/geometry/algorithms/overlay/copy_segment_point.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_relative_order.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+template <typename Operation>
+struct indexed_operation
+{
+ typedef Operation type;
+
+ int index;
+ int operation_index;
+ Operation subject;
+
+ inline indexed_operation(int i, int oi, Operation const& s)
+ : index(i)
+ , operation_index(oi)
+ , subject(s)
+ {}
+};
+
+
+template
+<
+ typename Indexed,
+ typename Geometry1,
+ typename Geometry2,
+ typename Strategy
+>
+struct sort_on_distance
+{
+private :
+ Geometry1 const& m_geometry1;
+ Geometry2 const& m_geometry2;
+ Strategy const& m_strategy;
+
+ typedef typename Indexed::type operation_type;
+ typedef typename point_type<Geometry1>::type point_type;
+
+
+ inline bool normal_compare_distances(operation_type const& left,
+ operation_type const& right) const
+ {
+ return left.enriched.distance < right.enriched.distance;
+ }
+
+protected :
+
+
+ // Note that left/right do NOT correspond to m_geometry1/m_geometry2
+ inline bool compare_distances(operation_type const& left,
+ operation_type const& right) const
+ {
+ // TODO: change this, it gives non-consequent behaviour resulting in
+ // an assertion within sort.
+ // SOLUTION: first sort on distance, then check if the sorted vector
+ // has distances close to zero, swap them mutually if there is a reason
+ // (reason by sides)
+ //if (fuzzy_equals(left.enriched.distance, right.enriched.distance))
+ if (false)
+ {
+
+ // Distances are the same, or quite close.
+ // We sort now using sides instead of using distance
+ // In most cases, this is possible. Else we fallback to distance
+ // (--> very rare cases, when both methods fail)
+
+#ifdef BOOST_GEOMETRY_DEBUG_OVERLAY
+ std::cout << "Equal Distance"
+ << " : " << left.seg_id << " / " << left.other_id
+ << " and " << right.seg_id << " / " << right.other_id
+ << std::endl;
+#endif
+
+ point_type pi, pj, ri, rj, si, sj;
+ if (left.seg_id == right.seg_id)
+ {
+ geometry::copy_segment_points(m_geometry1, m_geometry2,
+ left.seg_id,
+ pi, pj);
+ geometry::copy_segment_points(m_geometry1, m_geometry2,
+ left.other_id,
+ ri, rj);
+ geometry::copy_segment_points(m_geometry1, m_geometry2,
+ right.other_id,
+ si, sj);
+ }
+ else if (left.other_id == right.other_id)
+ {
+ geometry::copy_segment_points(m_geometry1, m_geometry2,
+ left.other_id,
+ pi, pj);
+ geometry::copy_segment_points(m_geometry1, m_geometry2,
+ left.seg_id,
+ ri, rj);
+ geometry::copy_segment_points(m_geometry1, m_geometry2,
+ right.seg_id,
+ si, sj);
+ }
+ else
+ {
+ return normal_compare_distances(left, right);
+ }
+
+ int const order = get_relative_order<point_type>::apply(pi, pj,
+ ri, rj, si, sj);
+ if (order != 0)
+ {
+ // If order == -1, r is the first segment along p
+ // So then return true;
+ return order == -1;
+ }
+ }
+
+ return normal_compare_distances(left, right);
+ }
+
+public :
+ sort_on_distance(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ : m_geometry1(geometry1)
+ , m_geometry2(geometry2)
+ , m_strategy(strategy)
+ {}
+
+ inline bool operator()(Indexed const& left, Indexed const& right) const
+ {
+ return compare_distances(left.subject, right.subject);
+ }
+};
+
+
+template
+<
+ typename Indexed,
+ typename Geometry1,
+ typename Geometry2,
+ typename Strategy
+>
+struct sort_on_operation
+ : public sort_on_distance
+ <
+ Indexed,
+ Geometry1, Geometry2, Strategy
+ >
+{
+ sort_on_operation(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ : sort_on_distance
+ <
+ Indexed,
+ Geometry1, Geometry2, Strategy
+ >(geometry1, geometry2, strategy)
+ {}
+
+ inline bool operator()(Indexed const& left, Indexed const& right) const
+ {
+ segment_identifier const& sl = left.subject.seg_id;
+ segment_identifier const& sr = right.subject.seg_id;
+
+ return sl == sr
+ ? compare_distances(left.subject, right.subject)
+ : sl < sr;
+ }
+};
+
+
+// Sorts IP-s of this ring on segment-identifier, and if on same segment,
+// on distance.
+// Then assigns for each IP which is the next IP on this segment,
+// plus the vertex-index to travel to, plus the next IP
+// (might be on another segment)
+template
+<
+ typename IndexType,
+ typename Container,
+ typename TurnPoints,
+ typename Geometry1,
+ typename Geometry2,
+ typename Strategy
+>
+static inline bool assign_order(Container& operation_container,
+ TurnPoints& turn_points,
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ std::sort(boost::begin(operation_container),
+ boost::end(operation_container),
+ sort_on_operation
+ <
+ IndexType,
+ Geometry1, Geometry2,
+ Strategy
+ >(geometry1, geometry2, strategy));
+
+
+
+#ifdef BOOST_GEOMETRY_DEBUG_OVERLAY
+ // Check if it is really sorted.
+ if (copy.size() > 1)
+ {
+ indexed_iterator_type it = boost::begin(copy);
+ for (indexed_iterator_type prev = it++;
+ it != boost::end(copy);
+ prev = it++)
+ {
+ if (geometry::math::equals(
+ prev->operations_of_subject.front().enriched.distance,
+ it->operations_of_subject.front().enriched.distance))
+ {
+ typedef typename turn_point_type::operation_type op;
+ op const& first = prev->operations_of_subject.front();
+ op const& second = it->operations_of_subject.front();
+
+ std::cout << "Equal Distance on " << seg_id
+ << " : " << first.seg_id << " / " << first.other_id
+ << " and " << second.seg_id << " / " << second.other_id
+ << std::endl;
+ std::cout << "\tType of intersections: "
+ << prev->subject.method
+ << " , " << it->subject.method
+ << std::endl;
+ }
+ }
+ }
+#endif
+
+ typedef typename IndexType::type operation_type;
+ typedef typename boost::range_iterator<Container const>::type iterator_type;
+
+ // Assign travel-to-vertex/ip index for each turning point.
+ // Because IP's are circular, PREV starts at the very last one,
+ // being assigned from the first one.
+ // For "next ip on same segment" it should not be considered circular.
+ bool first = true;
+ iterator_type it = boost::begin(operation_container);
+ for (iterator_type prev = it + (boost::size(operation_container) - 1);
+ it != boost::end(operation_container);
+ prev = it++)
+ {
+ operation_type& prev_op = turn_points[prev->index]
+ .operations[prev->operation_index];
+
+ prev_op.enriched.travels_to_ip_index = it->index;
+ prev_op.enriched.travels_to_vertex_index
+ = it->subject.seg_id.segment_index;
+
+ operation_type& op = turn_points[it->index]
+ .operations[it->operation_index];
+
+ if (! first && prev_op.seg_id.segment_index == op.seg_id.segment_index)
+ {
+ prev_op.enriched.next_ip_index = it->index;
+ }
+ first = false;
+ }
+
+#ifdef BOOST_GEOMETRY_DEBUG_OVERLAY
+ std::cout << "Enrichment - ordered on segment (src: "
+ << source_index << "): " << std::endl;
+ report_tp(turn_points);
+#endif
+
+ return true;
+}
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief All intersection points are enriched with successor information
+ \ingroup overlay
+ \tparam TurnPoints type of intersection container
+ (e.g. vector of "intersection_point"'s)
+ \param turn_points container containing intersectionpoints
+ */
+template
+<
+ typename TurnPoints,
+ typename Geometry1,
+ typename Geometry2,
+ typename Strategy
+>
+inline void enrich_intersection_points(TurnPoints& turn_points,
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ typedef typename boost::range_value<TurnPoints>::type turn_point_type;
+ typedef typename turn_point_type::container_type container_type;
+ typedef typename boost::range_value<container_type>::type operation_type;
+ typedef detail::overlay::indexed_operation<operation_type> indexed_type;
+ typedef std::map
+ <
+ ring_identifier,
+ std::vector<indexed_type>
+ > mapped_vector_type;
+
+ // Create a map of vectors of indexed operation-types to be able
+ // to sort per ring, later on.
+ mapped_vector_type mapped_vector;
+
+ int index = 0;
+ for (typename boost::range_iterator<TurnPoints const>::type
+ it = boost::begin(turn_points);
+ it != boost::end(turn_points);
+ ++it, ++index)
+ {
+ int op_index = 0;
+ for (typename boost::range_iterator<container_type const>::type
+ op_it = boost::begin(it->operations);
+ op_it != boost::end(it->operations);
+ ++op_it, ++op_index)
+ {
+ ring_identifier ring_id
+ (
+ op_it->seg_id.source_index,
+ op_it->seg_id.multi_index,
+ op_it->seg_id.ring_index
+ );
+ mapped_vector[ring_id].push_back
+ (
+ indexed_type(index, op_index, *op_it)
+ );
+ }
+ }
+
+#ifdef BOOST_GEOMETRY_DEBUG_OVERLAY
+ detail::overlay::report_map(map);
+#endif
+
+ // No const-operator because contents of mapped copy is changed)
+ for (typename mapped_vector_type::iterator mit
+ = mapped_vector.begin();
+ mit != mapped_vector.end();
+ ++mit)
+ {
+ detail::overlay::assign_order<indexed_type>(mit->second, turn_points,
+ geometry1, geometry2, strategy);
+ }
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICH_HPP

Added: sandbox/geometry/boost/geometry/algorithms/overlay/get_intersection_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/overlay/get_intersection_points.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,981 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_OVERLAY_GET_INTERSECTION_POINTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_OVERLAY_GET_INTERSECTION_POINTS_HPP
+
+/*!
+\defgroup overlay overlay helper operations (getting intersection points, etc)
+*/
+
+
+#include <cstddef>
+#include <map>
+
+#include <boost/mpl/if.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/is_multi.hpp>
+#include <boost/geometry/core/reverse_dispatch.hpp>
+
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/util/math.hpp>
+
+#include <boost/geometry/geometries/box.hpp>
+
+#include <boost/geometry/iterators/range_type.hpp>
+
+#include <boost/geometry/strategies/cartesian/cart_intersect.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+#include <boost/geometry/strategies/intersection_result.hpp>
+
+
+#include <boost/geometry/algorithms/overlay/intersection_point.hpp>
+
+#include <boost/geometry/algorithms/detail/disjoint.hpp>
+
+#include <boost/geometry/algorithms/combine.hpp>
+#include <boost/geometry/algorithms/distance.hpp>
+#include <boost/geometry/algorithms/sectionalize.hpp>
+#include <boost/geometry/algorithms/get_section.hpp>
+#include <boost/geometry/algorithms/within.hpp>
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+# include <sstream>
+# include <boost/geometry/util/write_dsv.hpp>
+#endif
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace get_intersection_points {
+
+
+template
+<
+ typename Segment1,
+ typename Segment2,
+ typename IntersectionPoints,
+ typename IntersectionStrategy
+>
+struct relate
+{
+private :
+ template <typename Segment, typename Point>
+ static inline void copy_point(int how, Segment const& segment, Point& point)
+ {
+ if (how == 1)
+ {
+ // Arrival
+ geometry::copy_coordinates(segment.first, point);
+ }
+ else
+ {
+ // Departure
+ geometry::copy_coordinates(segment.second, point);
+ }
+ }
+
+ template <typename Info, typename IntersectionPoint, typename Direction, typename Segment>
+ static inline void process_one(
+ Info& info,
+ IntersectionPoint const& ipoint,
+ Segment const& segment,
+ segment_identifier const& seg_id_first,
+ segment_identifier const& seg_id_second,
+ Direction const& dir, int arrival, int direction, bool reverse)
+ {
+ info.how = dir.how;
+ info.opposite = dir.opposite;
+
+ info.seg_id = seg_id_first;
+ info.other_id = seg_id_second;
+ copy_point(arrival, segment, info.other_point);
+
+ info.distance = geometry::distance(ipoint, segment.first);
+
+ info.arrival = arrival;
+ info.direction = direction;
+ info.sides = dir.sides;
+
+ // Seen from B, the first one is B, the second one is A
+ if (reverse)
+ {
+ info.sides.reverse();
+ }
+ }
+
+
+ template <typename IntersectionPoint, typename Direction>
+ static inline void process(IntersectionPoint& ipoint,
+ Direction const& dir,
+ Segment1 const& s1, Segment2 const& s2,
+ segment_identifier const& seg_id1,
+ segment_identifier const& seg_id2,
+ IntersectionPoints& out, bool& trivial)
+ {
+ typedef typename boost::range_value
+ <
+ IntersectionPoints
+ >::type intersection_point;
+
+ typename intersection_point::traversal_type info;
+
+ ipoint.info.resize(ipoint.info.size() + 1);
+ process_one(ipoint.info.back(), ipoint,
+ s1, seg_id1, seg_id2,
+ dir, dir.how_a, dir.dir_a, false);
+
+ ipoint.info.resize(ipoint.info.size() + 1);
+ process_one(ipoint.info.back(), ipoint,
+ s2, seg_id2, seg_id1,
+ dir, dir.how_b, dir.dir_b, true);
+
+
+ if (dir.how != 'i')
+ {
+ trivial = false;
+ ipoint.trivial = false;
+ }
+
+ out.push_back(ipoint);
+ }
+
+
+
+public :
+ static inline bool apply(Segment1 const& s1, Segment2 const& s2,
+ segment_identifier const& seg_id1,
+ segment_identifier const& seg_id2,
+ IntersectionPoints& out, bool& trivial)
+ {
+ typename IntersectionStrategy::return_type result
+ = IntersectionStrategy::apply(s1, s2);
+
+ for (std::size_t i = 0; i < result.get<0>().count; i++)
+ {
+ process(
+ // Process the tupled result value
+ result.get<0>().intersections[i],
+ result.get<1>(),
+ s1, s2, seg_id1, seg_id2,
+ out, trivial);
+ }
+ return result.get<0>().count > 0;
+ }
+};
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Section1, typename Section2,
+ typename IntersectionPoints,
+ typename IntersectionStrategy
+>
+class get_ips_in_sections
+{
+public :
+ static inline void apply(
+ std::size_t source_id1, Geometry1 const& geometry1,
+ Section1 const& sec1,
+ std::size_t source_id2, Geometry2 const& geometry2,
+ Section2 const& sec2,
+ bool return_if_found,
+ IntersectionPoints& intersection_points,
+ bool& trivial)
+ {
+
+ typedef typename boost::range_const_iterator
+ <
+ typename geometry::range_type<Geometry1>::type
+ >::type range1_iterator;
+ typedef typename boost::range_const_iterator
+ <
+ typename geometry::range_type<Geometry2>::type
+ >::type range2_iterator;
+
+ int const dir1 = sec1.directions[0];
+ int const dir2 = sec2.directions[0];
+ int index1 = sec1.begin_index;
+ int ndi1 = sec1.non_duplicate_index;
+
+ bool const same_source =
+ source_id1 == source_id2
+ && sec1.multi_index == sec2.multi_index
+ && sec1.ring_index == sec2.ring_index;
+
+ // Note that it is NOT possible to have section-iterators here
+ // because of the logistics of "index" (the section-iterator automatically
+ // skips to the begin-point, we loose the index or have to recalculate it)
+ // So we mimic it here
+ range1_iterator it1, end1;
+ get_section(geometry1, sec1, it1, end1);
+
+ // Mimic 1: Skip to point such that section interects other box
+ range1_iterator prev1 = it1++;
+ for(; it1 != end1 && preceding<0>(dir1, *it1, sec2.bounding_box);
+ prev1 = it1++, index1++, ndi1++)
+ {
+ }
+ // Go back one step because we want to start completely preceding
+ it1 = prev1;
+
+ // Walk through section and stop if we exceed the other box
+ for (prev1 = it1++;
+ it1 != end1 && ! exceeding<0>(dir1, *prev1, sec2.bounding_box);
+ prev1 = it1++, index1++, ndi1++)
+ {
+ segment1_type s1(*prev1, *it1);
+
+ int index2 = sec2.begin_index;
+ int ndi2 = sec2.non_duplicate_index;
+
+ range2_iterator it2, end2;
+ get_section(geometry2, sec2, it2, end2);
+
+ range2_iterator prev2 = it2++;
+
+ // Mimic 2:
+ for(; it2 != end2 && preceding<0>(dir2, *it2, sec1.bounding_box);
+ prev2 = it2++, index2++, ndi2++)
+ {
+ }
+ it2 = prev2;
+
+ for (prev2 = it2++;
+ it2 != end2 && ! exceeding<0>(dir2, *prev2, sec1.bounding_box);
+ prev2 = it2++, index2++, ndi2++)
+ {
+ bool skip = same_source;
+ if (skip)
+ {
+ // If sources are the same (possibly self-intersecting):
+ // check if it is a neighbouring sement.
+ // (including first-last segment
+ // and two segments with one or more degenerate/duplicate
+ // (zero-length) segments in between)
+
+ // Also skip if index1 < index2 to avoid getting all
+ // intersections twice (only do this on same source!)
+
+ // About n-2:
+ // (square: range_count=5, indices 0,1,2,3
+ // -> 0-3 are adjacent)
+ skip = index2 >= index1
+ || ndi1 == ndi2 + 1
+ || (index2 == 0 && index1 >= int(sec1.range_count) - 2)
+ ;
+ }
+
+ if (! skip)
+ {
+ if (relate<segment1_type, segment2_type, IntersectionPoints, IntersectionStrategy>
+ ::apply(s1, segment2_type(*prev2, *it2),
+ segment_identifier(source_id1,
+ sec1.multi_index, sec1.ring_index, index1),
+ segment_identifier(source_id2,
+ sec2.multi_index, sec2.ring_index, index2),
+ intersection_points, trivial)
+ && return_if_found)
+ {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+
+private :
+ typedef typename geometry::point_type<Geometry1>::type point1_type;
+ typedef typename geometry::point_type<Geometry2>::type point2_type;
+ typedef typename geometry::segment<const point1_type> segment1_type;
+ typedef typename geometry::segment<const point2_type> segment2_type;
+
+
+ template <size_t Dim, typename Point, typename Box>
+ static inline bool preceding(int dir, Point const& point, Box const& box)
+ {
+ return (dir == 1 && get<Dim>(point) < get<min_corner, Dim>(box))
+ || (dir == -1 && get<Dim>(point) > get<max_corner, Dim>(box));
+ }
+
+ template <size_t Dim, typename Point, typename Box>
+ static inline bool exceeding(int dir, Point const& point, Box const& box)
+ {
+ return (dir == 1 && get<Dim>(point) > get<max_corner, Dim>(box))
+ || (dir == -1 && get<Dim>(point) < get<min_corner, Dim>(box));
+ }
+
+
+};
+
+
+template
+<
+ typename Ring, typename Box,
+ typename Section1, typename Section2,
+ typename IntersectionPoints,
+ typename IntersectionStrategy
+>
+class get_ips_range_box
+{
+public :
+ static inline void apply(
+ std::size_t source_id1, Ring const& ring,
+ std::size_t source_id2, Box const& box,
+ Section1 const& sec1, Section2 const& sec2,
+ IntersectionPoints& intersection_points, bool& trivial)
+ {
+ get_ips_in_sections<Ring, Box, Section1, Section2, IntersectionPoints, IntersectionStrategy>
+ ::apply(
+ source_id1, ring, sec1,
+ source_id2, box, sec2,
+ false,
+ intersection_points, trivial);
+ }
+};
+
+template <typename Section, int Dimension, int Index>
+struct compare_section
+{
+ inline bool operator()(Section const& left, Section const& right) const
+ {
+ return
+ geometry::get<Index, Dimension>(left.bounding_box)
+ < geometry::get<Index, Dimension>(right.bounding_box);
+ }
+};
+
+
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename IntersectionPoints,
+ typename IntersectionStrategy
+>
+class get_ips_generic
+{
+ template <typename Box, typename Sections>
+ static inline void add_sections(Box& box, Sections const& sections)
+ {
+ for (typename boost::range_iterator<const Sections>::type
+ it = sections.begin();
+ it != sections.end();
+ ++it)
+ {
+ geometry::combine(box, it->bounding_box);
+ }
+ }
+
+ template <typename Sections, typename Box>
+ static inline void get_sections(Sections const& sections,
+ Box const& box, Sections& selection)
+ {
+ for (typename boost::range_iterator<const Sections>::type
+ it = sections.begin();
+ it != sections.end();
+ ++it)
+ {
+ if (! geometry::detail::disjoint::disjoint_box_box(box, it->bounding_box))
+ {
+ selection.push_back(*it);
+ }
+ }
+ }
+
+ template <typename Sections1, typename Sections2, typename Map>
+ static inline void intersect(
+ std::size_t source_id1, Geometry1 const& geometry1,
+ std::size_t source_id2, Geometry2 const& geometry2,
+ IntersectionPoints& intersection_points,
+ Sections1 const& sec1, Sections2 const& sec2,
+ Map& map,
+ bool &trivial)
+ {
+ for (typename boost::range_const_iterator<Sections1>::type
+ it1 = sec1.begin();
+ it1 != sec1.end();
+ ++it1)
+ {
+ for (typename boost::range_const_iterator<Sections2>::type
+ it2 = sec2.begin();
+ it2 != sec2.end();
+ ++it2)
+ {
+ std::pair<int, int> p = std::make_pair(it1->id, it2->id);
+ bool processed = map[p];
+ if (! processed)
+ {
+ map[p] = true;
+ if (! geometry::detail::disjoint::disjoint_box_box(
+ it1->bounding_box, it2->bounding_box))
+ {
+ get_ips_in_sections
+ <
+ Geometry1,
+ Geometry2,
+ typename boost::range_value<Sections1>::type,
+ typename boost::range_value<Sections2>::type,
+ IntersectionPoints,
+ IntersectionStrategy
+ >::apply(
+ source_id1, geometry1, *it1,
+ source_id2, geometry2, *it2,
+ false,
+ intersection_points, trivial);
+ }
+ }
+ }
+ }
+ }
+
+
+ // Divide and conquer (suggested by Luke during GGL Formal Review)
+ template
+ <
+ std::size_t Dimension,
+ typename Box,
+ typename Sections1, typename Sections2,
+ typename Map
+ >
+ static inline void divide_and_conquer(
+ std::size_t source_id1, Geometry1 const& geometry1,
+ std::size_t source_id2, Geometry2 const& geometry2,
+ IntersectionPoints& intersection_points,
+
+ Box const& box,
+ Sections1 const& sec1, Sections2 const& sec2,
+ Map& map,
+ bool &trivial,
+ std::size_t iteration = 0, std::size_t previous_count = 0)
+ {
+ // To stop the iteration, fallback to (quadratic) behaviour below certain limits,
+ // or if dividing does not give any profit.
+ std::size_t n = sec1.size() + sec2.size();
+ if (sec1.size() < 5
+ || sec2.size() < 5
+ || n == previous_count
+ || iteration > 100)
+ {
+ intersect(source_id1, geometry1, source_id2, geometry2,
+ intersection_points, sec1, sec2, map, trivial);
+ return;
+ }
+
+ // Divide the complete box in two (alternating) halves
+ Box lower = box, upper = box;
+ typename geometry::coordinate_type<Box>::type two = 2.0;
+ typename geometry::coordinate_type<Box>::type mid
+ = (geometry::get<min_corner, Dimension>(box)
+ + geometry::get<max_corner, Dimension>(box)) / two;
+
+ geometry::set<max_corner, Dimension>(lower, mid);
+ geometry::set<min_corner, Dimension>(upper, mid);
+
+ Sections1 lower1, upper1;
+ Sections2 lower2, upper2;
+ get_sections(sec1, lower, lower1);
+ get_sections(sec2, lower, lower2);
+ get_sections(sec1, upper, upper1);
+ get_sections(sec2, upper, upper2);
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION_DIVIDE_AND_CONQUER
+ std::cout
+ << "Get IP's, iteration: " << iteration
+ << " box: " << geometry::dsv(box)
+ << " n: " << n
+ << " lower: " << lower1.size() << " , " << lower2.size()
+ << " upper: " << upper1.size() << " , " << upper2.size()
+ << std::endl;
+#endif
+
+ // Recursively handle lower and upper half, dividing in other dimension
+ divide_and_conquer<1 - Dimension>(source_id1, geometry1,
+ source_id2, geometry2, intersection_points,
+ lower, lower1, lower2, map, trivial, iteration + 1, n);
+
+ divide_and_conquer<1 - Dimension>(source_id1, geometry1,
+ source_id2, geometry2, intersection_points,
+ upper, upper1, upper2, map, trivial, iteration + 1, n);
+ }
+
+public:
+ static inline bool apply(
+ std::size_t source_id1, Geometry1 const& geometry1,
+ std::size_t source_id2, Geometry2 const& geometry2,
+ IntersectionPoints& intersection_points)
+ {
+ // Create monotonic sections in ONE direction
+ // - in most cases ONE direction is faster (e.g. ~1% faster for the NLP4 testset)
+ // - the sections now have a limit (default 10) so will not be too large
+
+ // Note that the sections contain boxes, are dynamic, and therefore
+ // are specified using output/intersection-point-type
+ // (to enable input-pointer-point-types)
+ typedef typename boost::range_value<IntersectionPoints>::type ip_type;
+ typedef typename ip_type::point_type point_type;
+ typedef typename geometry::sections<geometry::box<point_type>, 1> sections1_type;
+ typedef typename geometry::sections<geometry::box<point_type>, 1> sections2_type;
+
+ sections1_type sec1;
+ sections2_type sec2;
+
+ geometry::sectionalize(geometry1, sec1);
+ geometry::sectionalize(geometry2, sec2);
+
+ // Divide and conquer
+ geometry::box<point_type> box;
+ geometry::assign_inverse(box);
+ add_sections(box, sec1);
+ add_sections(box, sec2);
+
+ // House-keeping map, to avoid section-pairs being compared twice
+ std::map<std::pair<int, int>, bool> map;
+
+ bool trivial = true;
+ divide_and_conquer<1>(source_id1, geometry1, source_id2, geometry2,
+ intersection_points, box, sec1, sec2, map, trivial);
+ return trivial;
+ }
+};
+
+
+
+template
+<
+ typename Range,
+ typename Box,
+ typename IntersectionPoints,
+ typename IntersectionStrategy
+>
+struct get_ips_cs
+{
+ static inline void apply(std::size_t source_id1, Range const& range,
+ int multi_index, int ring_index,
+ std::size_t source_id2, Box const& box,
+ IntersectionPoints& intersection_points,
+ bool& trivial)
+ {
+ if (boost::size(range) <= 1)
+ {
+ return;
+ }
+
+
+ typedef typename geometry::point_type<Box>::type box_point_type;
+ typedef typename geometry::point_type<Range>::type point_type;
+
+ typedef segment<const box_point_type> box_segment_type;
+ typedef segment<const point_type> segment_type;
+
+ point_type lower_left, upper_left, lower_right, upper_right;
+ assign_box_corners(box, lower_left, lower_right, upper_left, upper_right);
+
+ box_segment_type left(lower_left, upper_left);
+ box_segment_type top(upper_left, upper_right);
+ box_segment_type right(upper_right, lower_right);
+ box_segment_type bottom(lower_right, lower_left);
+
+
+ typedef typename boost::range_const_iterator<Range>::type iterator_type;
+ iterator_type it = boost::begin(range);
+
+ bool first = true;
+
+ char previous_side[2] = {0, 0};
+
+ int index = 0;
+
+ for (iterator_type prev = it++;
+ it != boost::end(range);
+ prev = it++, index++)
+ {
+ segment_type segment(*prev, *it);
+
+ if (first)
+ {
+ previous_side[0] = get_side<0>(box, *prev);
+ previous_side[1] = get_side<1>(box, *prev);
+ }
+
+ char current_side[2];
+ current_side[0] = get_side<0>(box, *it);
+ current_side[1] = get_side<1>(box, *it);
+
+ // There can NOT be intersections if
+ // 1) EITHER the two points are lying on one side of the box (! 0 && the same)
+ // 2) OR same in Y-direction
+ // 3) OR all points are inside the box (0)
+ /*if (! (
+ (current_side[0] != 0 && current_side[0] == previous_side[0])
+ || (current_side[1] != 0 && current_side[1] == previous_side[1])
+ || (current_side[0] == 0
+ && current_side[1] == 0
+ && previous_side[0] == 0
+ && previous_side[1] == 0)
+ )
+ )*/
+ if (true)
+ {
+ segment_identifier seg_id(source_id1,
+ multi_index, ring_index, index);
+
+ typedef relate
+ <
+ segment_type,
+ box_segment_type,
+ IntersectionPoints,
+ IntersectionStrategy
+ > relater;
+
+ // Depending on code some relations can be left out
+ relater::apply(segment, left, seg_id,
+ segment_identifier(source_id2, -1, -1, 0),
+ intersection_points, trivial);
+ relater::apply(segment, top, seg_id,
+ segment_identifier(source_id2, -1, -1, 1),
+ intersection_points, trivial);
+ relater::apply(segment, right, seg_id,
+ segment_identifier(source_id2, -1, -1, 2),
+ intersection_points, trivial);
+ relater::apply(segment, bottom, seg_id,
+ segment_identifier(source_id2, -1, -1, 3),
+ intersection_points, trivial);
+
+ }
+ }
+ }
+
+private:
+ template<std::size_t Index, typename Point>
+ static inline int get_side(Box const& box, Point const& point)
+ {
+ // Inside -> 0
+ // Outside -> -1 (left/below) or 1 (right/above)
+ // On border -> -2 (left/lower) or 2 (right/upper)
+ // The only purpose of the value is to not be the same,
+ // and to denote if it is inside (0)
+
+ typename coordinate_type<Point>::type const& c = get<Index>(point);
+ typename coordinate_type<Box>::type const& left = get<min_corner, Index>(box);
+ typename coordinate_type<Box>::type const& right = get<max_corner, Index>(box);
+
+ if (geometry::math::equals(c, left)) return -2;
+ else if (geometry::math::equals(c, right)) return 2;
+ else if (c < left) return -1;
+ else if (c > right) return 1;
+ else return 0;
+ }
+
+
+};
+
+
+}} // namespace detail::get_intersection_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2,
+ bool IsMulti1, bool IsMulti2,
+ typename Geometry1, typename Geometry2,
+ typename IntersectionPoints,
+ typename IntersectionStrategy
+>
+struct get_intersection_points
+{
+};
+
+
+template<typename Polygon, typename Box, typename IntersectionPoints, typename IntersectionStrategy>
+struct get_intersection_points
+ <
+ polygon_tag, box_tag, false, false,
+ Polygon, Box,
+ IntersectionPoints,
+ IntersectionStrategy
+ >
+{
+
+ static inline bool apply(
+ std::size_t source_id1, Polygon const& polygon,
+ std::size_t source_id2, Box const& box,
+ IntersectionPoints& intersection_points)
+ {
+ typedef typename geometry::ring_type<Polygon>::type ring_type;
+
+ typedef typename boost::range_const_iterator
+ <
+ typename interior_type<Polygon>::type
+ >::type iterator_type;
+
+
+ typedef detail::get_intersection_points::get_ips_cs
+ <
+ ring_type,
+ Box,
+ IntersectionPoints,
+ IntersectionStrategy
+ > intersector_type;
+
+ bool trivial = true;
+ intersector_type::apply(
+ source_id1, geometry::exterior_ring(polygon), -1, -1,
+ source_id2, box,
+ intersection_points, trivial);
+
+ int i = 0;
+ for (iterator_type it = boost::begin(interior_rings(polygon));
+ it != boost::end(interior_rings(polygon));
+ ++it, ++i)
+ {
+ intersector_type::apply(
+ source_id1, *it, -1, i,
+ source_id2, box, intersection_points, trivial);
+ }
+
+ return trivial;
+ }
+};
+
+
+template<typename Ring, typename Box, typename IntersectionPoints, typename IntersectionStrategy>
+struct get_intersection_points
+ <
+ ring_tag, box_tag, false, false,
+ Ring, Box,
+ IntersectionPoints, IntersectionStrategy
+ >
+{
+ static inline bool apply(
+ std::size_t source_id1, Ring const& ring,
+ std::size_t source_id2, Box const& box,
+ IntersectionPoints& intersection_points)
+ {
+ typedef typename boost::range_const_iterator
+ <
+ Ring
+ >::type iterator_type;
+
+ typedef detail::get_intersection_points::get_ips_cs
+ <Ring, Box, IntersectionPoints, IntersectionStrategy> intersector_type;
+
+ bool trivial = true;
+ intersector_type::apply(
+ source_id1, ring, -1, -1,
+ source_id2, box,
+ intersection_points, trivial);
+
+ return trivial;
+ }
+};
+
+
+template
+<
+ typename Ring1,
+ typename Ring2,
+ typename IntersectionPoints,
+ typename IntersectionStrategy
+>
+struct get_intersection_points
+ <
+ ring_tag, ring_tag, false, false,
+ Ring1, Ring2,
+ IntersectionPoints, IntersectionStrategy
+ >
+ : detail::get_intersection_points::get_ips_generic
+ <
+ Ring1,
+ Ring2,
+ IntersectionPoints,
+ IntersectionStrategy
+ >
+{};
+
+
+template
+<
+ typename Polygon1,
+ typename Polygon2,
+ typename IntersectionPoints,
+ typename IntersectionStrategy
+>
+struct get_intersection_points
+ <
+ polygon_tag, polygon_tag, false, false,
+ Polygon1, Polygon2,
+ IntersectionPoints, IntersectionStrategy
+ >
+ : detail::get_intersection_points::get_ips_generic
+ <
+ Polygon1,
+ Polygon2,
+ IntersectionPoints,
+ IntersectionStrategy
+ >
+{};
+
+template
+<
+ typename Polygon,
+ typename Ring,
+ typename IntersectionPoints,
+ typename IntersectionStrategy
+>
+struct get_intersection_points
+ <
+ polygon_tag, ring_tag, false, false,
+ Polygon, Ring,
+ IntersectionPoints, IntersectionStrategy
+ >
+ : detail::get_intersection_points::get_ips_generic
+ <
+ Polygon,
+ Ring,
+ IntersectionPoints,
+ IntersectionStrategy
+ >
+{};
+
+template
+<
+ typename LineString1,
+ typename LineString2,
+ typename IntersectionPoints,
+ typename IntersectionStrategy
+>
+struct get_intersection_points
+ <
+ linestring_tag, linestring_tag, false, false,
+ LineString1, LineString2,
+ IntersectionPoints, IntersectionStrategy
+ >
+ : detail::get_intersection_points::get_ips_generic
+ <
+ LineString1,
+ LineString2,
+ IntersectionPoints,
+ IntersectionStrategy
+ >
+{};
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2,
+ bool IsMulti1, bool IsMulti2,
+ typename Geometry1, typename Geometry2,
+ typename IntersectionPoints,
+ typename IntersectionStrategy
+>
+struct get_intersection_points_reversed
+{
+ static inline bool apply(
+ std::size_t source_id1, Geometry1 const& g1,
+ std::size_t source_id2, Geometry2 const& g2,
+ IntersectionPoints& intersection_points)
+ {
+ return get_intersection_points
+ <
+ GeometryTag2, GeometryTag1,
+ IsMulti2, IsMulti1,
+ Geometry2, Geometry1,
+ IntersectionPoints, IntersectionStrategy
+ >::apply(source_id2, g2, source_id1, g1, intersection_points);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+/*!
+ \brief Calculate intersection points of two geometries
+ \ingroup overlay
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \tparam IntersectionPoints type of intersection container (e.g. vector of "intersection_point"'s)
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \param intersection_points container which will contain intersection points
+ */
+template <typename Geometry1, typename Geometry2, typename IntersectionPoints>
+inline void get_intersection_points(Geometry1 const& geometry1,
+ Geometry2 const& geometry2, IntersectionPoints& intersection_points)
+{
+ concept::check_concepts_and_equal_dimensions<const Geometry1, const Geometry2>();
+
+ typedef typename boost::remove_const<Geometry1>::type ncg1_type;
+ typedef typename boost::remove_const<Geometry2>::type ncg2_type;
+
+ typedef typename strategy_intersection
+ <
+ typename cs_tag<Geometry1>::type,
+ Geometry1,
+ Geometry2,
+ typename boost::range_value<IntersectionPoints>::type
+ >::segment_intersection_strategy_type segment_intersection_strategy_type;
+
+ boost::mpl::if_c
+ <
+ reverse_dispatch<Geometry1, Geometry2>::type::value,
+ dispatch::get_intersection_points_reversed
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ is_multi<Geometry1>::type::value,
+ is_multi<Geometry2>::type::value,
+ ncg1_type,
+ ncg2_type,
+ IntersectionPoints,
+ segment_intersection_strategy_type
+ >,
+ dispatch::get_intersection_points
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ is_multi<Geometry1>::type::value,
+ is_multi<Geometry2>::type::value,
+ ncg1_type,
+ ncg2_type,
+ IntersectionPoints,
+ segment_intersection_strategy_type
+ >
+ >::type::apply(
+ 0, geometry1,
+ 1, geometry2,
+ intersection_points);
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_OVERLAY_GET_INTERSECTION_POINTS_HPP

Added: sandbox/geometry/boost/geometry/algorithms/overlay/get_turns.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/overlay/get_turns.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,1003 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_OVERLAY_GET_TURNS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_OVERLAY_GET_TURNS_HPP
+
+
+#include <cstddef>
+#include <map>
+
+#include <boost/mpl/if.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/is_multi.hpp>
+#include <boost/geometry/core/reverse_dispatch.hpp>
+
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/util/math.hpp>
+
+#include <boost/geometry/geometries/box.hpp>
+
+#include <boost/geometry/iterators/range_type.hpp>
+#include <boost/geometry/iterators/ever_circling_iterator.hpp>
+
+#include <boost/geometry/strategies/cartesian/cart_intersect.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+#include <boost/geometry/strategies/intersection_result.hpp>
+
+#include <boost/geometry/algorithms/detail/disjoint.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
+
+#include <boost/geometry/algorithms/detail/sections/get_full_section.hpp>
+
+
+#include <boost/geometry/algorithms/combine.hpp>
+#include <boost/geometry/algorithms/distance.hpp>
+#include <boost/geometry/algorithms/sectionalize.hpp>
+#include <boost/geometry/algorithms/get_section.hpp>
+#include <boost/geometry/algorithms/within.hpp>
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+# include <sstream>
+# include <boost/geometry/util/write_dsv.hpp>
+#endif
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace get_turns {
+
+
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Section1, typename Section2,
+ typename TurnCollection,
+ typename IntersectionStrategy,
+ typename AssignPolicy
+>
+class get_turns_in_sections
+{
+
+public :
+ static inline void apply(
+ int source_id1, Geometry1 const& geometry1,
+ Section1 const& sec1,
+ int source_id2, Geometry2 const& geometry2,
+ Section2 const& sec2,
+ bool return_if_found,
+ TurnCollection& turns,
+ bool& trivial)
+ {
+
+ typedef typename boost::range_const_iterator
+ <
+ typename geometry::range_type<Geometry1>::type
+ >::type range1_iterator;
+
+ typedef typename boost::range_const_iterator
+ <
+ typename geometry::range_type<Geometry2>::type
+ >::type range2_iterator;
+
+ int const dir1 = sec1.directions[0];
+ int const dir2 = sec2.directions[0];
+ int index1 = sec1.begin_index;
+ int ndi1 = sec1.non_duplicate_index;
+
+ bool const same_source =
+ source_id1 == source_id2
+ && sec1.multi_index == sec2.multi_index
+ && sec1.ring_index == sec2.ring_index;
+
+ range1_iterator prev1, it1, end1;
+ range1_iterator begin_range_1, end_range_1;
+
+ ever_circling_iterator<range1_iterator> next1
+ = start_at_section(sec1, prev1, it1, end1, begin_range_1, end_range_1,
+ index1, ndi1, geometry1, dir1, sec2.bounding_box);
+
+ // Walk through section and stop if we exceed the other box
+ for (prev1 = it1++, next1++;
+ it1 != end1 && ! exceeding<0>(dir1, *prev1, sec2.bounding_box);
+ prev1 = it1++, index1++, next1++, ndi1++)
+ {
+ ever_circling_iterator<range1_iterator> nd_next1(
+ begin_range_1, end_range_1, next1, true);
+ advance_to_non_duplicate_next(nd_next1, it1, sec1);
+
+ int index2 = sec2.begin_index;
+ int ndi2 = sec2.non_duplicate_index;
+
+ range2_iterator prev2, it2, end2;
+ range2_iterator begin_range_2, end_range_2;
+
+ ever_circling_iterator<range2_iterator> next2 =
+ start_at_section(sec2, prev2, it2, end2, begin_range_2, end_range_2,
+ index2, ndi2, geometry2, dir2, sec1.bounding_box);
+
+ for (prev2 = it2++, next2++;
+ it2 != end2 && ! exceeding<0>(dir2, *prev2, sec1.bounding_box);
+ prev2 = it2++, index2++, next2++, ndi2++)
+ {
+ bool skip = same_source;
+ if (skip)
+ {
+ // If sources are the same (possibly self-intersecting):
+ // skip if it is a neighbouring sement.
+ // (including first-last segment
+ // and two segments with one or more degenerate/duplicate
+ // (zero-length) segments in between)
+
+ // Also skip if index1 < index2 to avoid getting all
+ // intersections twice (only do this on same source!)
+
+ // About n-2:
+ // (square: range_count=5, indices 0,1,2,3
+ // -> 0-3 are adjacent)
+ skip = index2 >= index1
+ || ndi1 == ndi2 + 1
+ || (index2 == 0 && index1 >= int(sec1.range_count) - 2)
+ ;
+ }
+
+ if (! skip)
+ {
+ // Move to the "non duplicate next"
+ ever_circling_iterator<range2_iterator> nd_next2(
+ begin_range_2, end_range_2, next2, true);
+ advance_to_non_duplicate_next(nd_next2, it2, sec2);
+
+ typedef typename boost::range_value<TurnCollection>::type turn_info;
+ typedef typename turn_info::point_type ip;
+
+ turn_info ti;
+ ti.operations[0].seg_id = segment_identifier(source_id1,
+ sec1.multi_index, sec1.ring_index, index1),
+ ti.operations[1].seg_id = segment_identifier(source_id2,
+ sec2.multi_index, sec2.ring_index, index2),
+
+ ti.operations[0].other_id = ti.operations[1].seg_id;
+ ti.operations[1].other_id = ti.operations[0].seg_id;
+
+ detail::overlay::get_turn_info
+ <
+ point1_type,
+ point2_type,
+ turn_info,
+ AssignPolicy
+ >::apply(*prev1, *it1, *nd_next1, *prev2, *it2, *nd_next2,
+ ti, std::back_inserter(turns));
+
+ if (return_if_found
+ && boost::size(turns) > 0)
+ {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+
+private :
+ typedef typename geometry::point_type<Geometry1>::type point1_type;
+ typedef typename geometry::point_type<Geometry2>::type point2_type;
+ typedef typename geometry::segment<const point1_type> segment1_type;
+ typedef typename geometry::segment<const point2_type> segment2_type;
+
+
+ template <size_t Dim, typename Point, typename Box>
+ static inline bool preceding(int dir, Point const& point, Box const& box)
+ {
+ return (dir == 1 && get<Dim>(point) < get<min_corner, Dim>(box))
+ || (dir == -1 && get<Dim>(point) > get<max_corner, Dim>(box));
+ }
+
+ template <size_t Dim, typename Point, typename Box>
+ static inline bool exceeding(int dir, Point const& point, Box const& box)
+ {
+ return (dir == 1 && get<Dim>(point) > get<max_corner, Dim>(box))
+ || (dir == -1 && get<Dim>(point) < get<min_corner, Dim>(box));
+ }
+
+ template <typename Iterator, typename RangeIterator, typename Section>
+ static inline void advance_to_non_duplicate_next(Iterator& next,
+ RangeIterator const& it, Section const& section)
+ {
+ // To see where the next segments bend to, in case of touch/intersections
+ // on end points, we need (in case of degenerate/duplicate points) an extra
+ // iterator which moves to the REAL next point, so non duplicate.
+ // This needs an extra comparison (disjoint).
+ // (Note that within sections, non duplicate points are already asserted,
+ // by the sectionalize process).
+
+ // So advance to the "non duplicate next"
+ // (the check is defensive, to avoid endless loops)
+ std::size_t check = 0;
+ while(! detail::disjoint::disjoint_point_point(*it, *next)
+ && check++ < section.range_count)
+ {
+ next++;
+ }
+ }
+
+ // It is NOT possible to have section-iterators here
+ // because of the logistics of "index" (the section-iterator automatically
+ // skips to the begin-point, we loose the index or have to recalculate it)
+ // So we mimic it here
+ template <typename RangeIterator, typename Section, typename Geometry, typename Box>
+ static inline ever_circling_iterator<RangeIterator> start_at_section(Section & section,
+ RangeIterator& it, RangeIterator& prev, RangeIterator& end,
+ RangeIterator& begin_range_it, RangeIterator& end_range_it,
+ int& index, int& ndi,
+ Geometry const& geometry,
+ int dir, Box const& other_bounding_box)
+ {
+ get_section(geometry, section, it, end);
+
+ // Mimic section-iterator:
+ // Skip to point such that section interects other box
+ prev = it++;
+ for(; it != end && preceding<0>(dir, *it, other_bounding_box);
+ prev = it++, index++, ndi++)
+ {}
+ // Go back one step because we want to start completely preceding
+ it = prev;
+
+ get_full_section(geometry, section, begin_range_it, end_range_it);
+
+ ever_circling_iterator<RangeIterator> next(begin_range_it, end_range_it, it, true);
+ next++;
+ return next;
+ }
+};
+
+
+template
+<
+ typename Ring, typename Box,
+ typename Section1, typename Section2,
+ typename TurnCollection,
+ typename IntersectionStrategy,
+ typename AssignPolicy
+>
+class get_turns_range_box
+{
+public :
+ static inline void apply(
+ int source_id1, Ring const& ring,
+ int source_id2, Box const& box,
+ Section1 const& sec1, Section2 const& sec2,
+ TurnCollection& turns, bool& trivial)
+ {
+ get_turns_in_sections
+ <
+ Ring,
+ Box,
+ Section1,
+ Section2,
+ TurnCollection,
+ IntersectionStrategy,
+ AssignPolicy
+ >
+ ::apply(
+ source_id1, ring, sec1,
+ source_id2, box, sec2,
+ false,
+ turns, trivial);
+ }
+};
+
+template <typename Section, int Dimension, int Index>
+struct compare_section
+{
+ inline bool operator()(Section const& left, Section const& right) const
+ {
+ return
+ geometry::get<Index, Dimension>(left.bounding_box)
+ < geometry::get<Index, Dimension>(right.bounding_box);
+ }
+};
+
+
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename TurnCollection,
+ typename IntersectionStrategy,
+ typename AssignPolicy
+>
+class get_turns_generic
+{
+ template <typename Box, typename Sections>
+ static inline void add_sections(Box& box, Sections const& sections)
+ {
+ for (typename boost::range_iterator<const Sections>::type
+ it = sections.begin();
+ it != sections.end();
+ ++it)
+ {
+ geometry::combine(box, it->bounding_box);
+ }
+ }
+
+ template <typename Sections, typename Box>
+ static inline void get_sections(Sections const& sections,
+ Box const& box, Sections& selection)
+ {
+ for (typename boost::range_iterator<const Sections>::type
+ it = sections.begin();
+ it != sections.end();
+ ++it)
+ {
+ if (! geometry::detail::disjoint::disjoint_box_box(box, it->bounding_box))
+ {
+ selection.push_back(*it);
+ }
+ }
+ }
+
+ template <typename Sections1, typename Sections2, typename Map>
+ static inline void intersect(
+ int source_id1, Geometry1 const& geometry1,
+ int source_id2, Geometry2 const& geometry2,
+ TurnCollection& turns,
+ Sections1 const& sec1, Sections2 const& sec2,
+ Map& map,
+ bool &trivial)
+ {
+ for (typename boost::range_const_iterator<Sections1>::type
+ it1 = sec1.begin();
+ it1 != sec1.end();
+ ++it1)
+ {
+ for (typename boost::range_const_iterator<Sections2>::type
+ it2 = sec2.begin();
+ it2 != sec2.end();
+ ++it2)
+ {
+ std::pair<int, int> p = std::make_pair(it1->id, it2->id);
+ bool processed = map[p];
+ if (! processed)
+ {
+ map[p] = true;
+ if (! geometry::detail::disjoint::disjoint_box_box(
+ it1->bounding_box, it2->bounding_box))
+ {
+ get_turns_in_sections
+ <
+ Geometry1,
+ Geometry2,
+ typename boost::range_value<Sections1>::type,
+ typename boost::range_value<Sections2>::type,
+ TurnCollection,
+ IntersectionStrategy,
+ AssignPolicy
+ >::apply(
+ source_id1, geometry1, *it1,
+ source_id2, geometry2, *it2,
+ false,
+ turns, trivial);
+ }
+ }
+ }
+ }
+ }
+
+
+ // Divide and conquer (suggested by Luke during GGL Formal Review)
+ template
+ <
+ std::size_t Dimension,
+ typename Box,
+ typename Sections1, typename Sections2,
+ typename Map
+ >
+ static inline void divide_and_conquer(
+ int source_id1, Geometry1 const& geometry1,
+ int source_id2, Geometry2 const& geometry2,
+ TurnCollection& turns,
+
+ Box const& box,
+ Sections1 const& sec1, Sections2 const& sec2,
+ Map& map,
+ bool &trivial,
+ std::size_t iteration = 0, std::size_t previous_count = 0)
+ {
+ // To stop the iteration, fallback to (quadratic) behaviour below certain limits,
+ // or if dividing does not give any profit.
+ std::size_t n = sec1.size() + sec2.size();
+ if (sec1.size() < 5
+ || sec2.size() < 5
+ || n == previous_count
+ || iteration > 100)
+ {
+ intersect(source_id1, geometry1, source_id2, geometry2,
+ turns, sec1, sec2, map, trivial);
+ return;
+ }
+
+ // Divide the complete box in two (alternating) halves
+ Box lower = box, upper = box;
+ typename geometry::coordinate_type<Box>::type two = 2.0;
+ typename geometry::coordinate_type<Box>::type mid
+ = (geometry::get<min_corner, Dimension>(box)
+ + geometry::get<max_corner, Dimension>(box)) / two;
+
+ geometry::set<max_corner, Dimension>(lower, mid);
+ geometry::set<min_corner, Dimension>(upper, mid);
+
+ Sections1 lower1, upper1;
+ Sections2 lower2, upper2;
+ get_sections(sec1, lower, lower1);
+ get_sections(sec2, lower, lower2);
+ get_sections(sec1, upper, upper1);
+ get_sections(sec2, upper, upper2);
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION_DIVIDE_AND_CONQUER
+ std::cout
+ << "Get IP's, iteration: " << iteration
+ << " box: " << geometry::dsv(box)
+ << " n: " << n
+ << " lower: " << lower1.size() << " , " << lower2.size()
+ << " upper: " << upper1.size() << " , " << upper2.size()
+ << std::endl;
+#endif
+
+ // Recursively handle lower and upper half, dividing in other dimension
+ divide_and_conquer<1 - Dimension>(source_id1, geometry1,
+ source_id2, geometry2, turns,
+ lower, lower1, lower2, map, trivial, iteration + 1, n);
+
+ divide_and_conquer<1 - Dimension>(source_id1, geometry1,
+ source_id2, geometry2, turns,
+ upper, upper1, upper2, map, trivial, iteration + 1, n);
+ }
+
+public:
+ static inline bool apply(
+ int source_id1, Geometry1 const& geometry1,
+ int source_id2, Geometry2 const& geometry2,
+ TurnCollection& turns)
+ {
+ // Create monotonic sections in ONE direction
+ // - in most cases ONE direction is faster (e.g. ~1% faster for the NLP4 testset)
+ // - the sections now have a limit (default 10) so will not be too large
+
+ // Note that the sections contain boxes, are dynamic, and therefore
+ // are specified using output/intersection-point-type
+ // (to enable input-pointer-point-types)
+ typedef typename boost::range_value<TurnCollection>::type ip_type;
+ typedef typename ip_type::point_type point_type;
+ typedef typename geometry::sections<geometry::box<point_type>, 1> sections1_type;
+ typedef typename geometry::sections<geometry::box<point_type>, 1> sections2_type;
+
+ sections1_type sec1;
+ sections2_type sec2;
+
+ geometry::sectionalize(geometry1, sec1);
+ geometry::sectionalize(geometry2, sec2);
+
+ // Divide and conquer
+ geometry::box<point_type> box;
+ geometry::assign_inverse(box);
+ add_sections(box, sec1);
+ add_sections(box, sec2);
+
+ // House-keeping map, to avoid section-pairs being compared twice
+ std::map<std::pair<int, int>, bool> map;
+
+ bool trivial = true;
+ divide_and_conquer<1>(source_id1, geometry1, source_id2, geometry2,
+ turns, box, sec1, sec2, map, trivial);
+ return trivial;
+ }
+};
+
+
+// Get turns for something with a box, following Cohen-Sutherland (cs) approach
+template
+<
+ typename Range,
+ typename Box,
+ typename TurnCollection,
+ typename IntersectionStrategy,
+ typename AssignPolicy
+>
+struct get_turns_cs
+{
+ static inline void apply(int source_id1, Range const& range,
+ int multi_index, int ring_index,
+ int source_id2, Box const& box,
+ TurnCollection& turns,
+ bool& trivial)
+ {
+ if (boost::size(range) <= 1)
+ {
+ return;
+ }
+
+
+ typedef typename geometry::point_type<Box>::type box_point_type;
+ typedef typename geometry::point_type<Range>::type point_type;
+
+ point_type lower_left, upper_left, lower_right, upper_right;
+ assign_box_corners(box, lower_left, lower_right, upper_left, upper_right);
+
+ /*
+ box_segment_type left(lower_left, upper_left);
+ box_segment_type top(upper_left, upper_right);
+ box_segment_type right(upper_right, lower_right);
+ box_segment_type bottom(lower_right, lower_left);
+ */
+
+ typedef typename boost::range_iterator
+ <Range const>::type iterator_type;
+ iterator_type it = boost::begin(range);
+
+ ever_circling_iterator<iterator_type> next(boost::begin(range),
+ boost::end(range), it, true);
+ next++;
+ next++;
+
+ bool first = true;
+
+ char previous_side[2] = {0, 0};
+
+ int index = 0;
+
+ for (iterator_type prev = it++;
+ it != boost::end(range);
+ prev = it++, next++, index++)
+ {
+ segment_identifier seg_id(source_id1,
+ multi_index, ring_index, index);
+
+ if (first)
+ {
+ previous_side[0] = get_side<0>(box, *prev);
+ previous_side[1] = get_side<1>(box, *prev);
+ }
+
+ char current_side[2];
+ current_side[0] = get_side<0>(box, *it);
+ current_side[1] = get_side<1>(box, *it);
+
+ // There can NOT be intersections if
+ // 1) EITHER the two points are lying on one side of the box (! 0 && the same)
+ // 2) OR same in Y-direction
+ // 3) OR all points are inside the box (0)
+ /*if (! (
+ (current_side[0] != 0 && current_side[0] == previous_side[0])
+ || (current_side[1] != 0 && current_side[1] == previous_side[1])
+ || (current_side[0] == 0
+ && current_side[1] == 0
+ && previous_side[0] == 0
+ && previous_side[1] == 0)
+ )
+ )*/
+ if (true)
+ {
+ typedef typename boost::range_value<TurnCollection>::type turn_info;
+ typedef detail::overlay::get_turn_info
+ <
+ box_point_type,
+ point_type,
+ turn_info,
+ AssignPolicy
+ > relater;
+
+ // Depending on code some relations can be left out
+ turn_info ti;
+ ti.operations[0].seg_id = seg_id;
+ ti.operations[1].other_id = ti.operations[0].seg_id;
+
+ ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 0);
+ ti.operations[0].other_id = ti.operations[1].seg_id;
+ relater::apply(*prev, *it, *next,
+ lower_left, upper_left, upper_right,
+ ti, std::back_inserter(turns));
+
+ ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 1);
+ ti.operations[0].other_id = ti.operations[1].seg_id;
+ relater::apply(*prev, *it, *next,
+ upper_left, upper_right, lower_right,
+ ti, std::back_inserter(turns));
+
+ ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 2);
+ ti.operations[0].other_id = ti.operations[1].seg_id;
+ relater::apply(*prev, *it, *next,
+ upper_right, lower_right, lower_left,
+ ti, std::back_inserter(turns));
+
+ ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 3);
+ ti.operations[0].other_id = ti.operations[1].seg_id;
+ relater::apply(*prev, *it, *next,
+ lower_right, lower_left, upper_left,
+ ti, std::back_inserter(turns));
+
+ }
+ }
+ }
+
+private:
+ template<std::size_t Index, typename Point>
+ static inline int get_side(Box const& box, Point const& point)
+ {
+ // Inside -> 0
+ // Outside -> -1 (left/below) or 1 (right/above)
+ // On border -> -2 (left/lower) or 2 (right/upper)
+ // The only purpose of the value is to not be the same,
+ // and to denote if it is inside (0)
+
+ typename coordinate_type<Point>::type const& c = get<Index>(point);
+ typename coordinate_type<Box>::type const& left = get<min_corner, Index>(box);
+ typename coordinate_type<Box>::type const& right = get<max_corner, Index>(box);
+
+ if (geometry::math::equals(c, left)) return -2;
+ else if (geometry::math::equals(c, right)) return 2;
+ else if (c < left) return -1;
+ else if (c > right) return 1;
+ else return 0;
+ }
+
+
+};
+
+
+}} // namespace detail::get_turns
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2,
+ bool IsMulti1, bool IsMulti2,
+ typename Geometry1, typename Geometry2,
+ typename TurnCollection,
+ typename IntersectionStrategy,
+ typename AssignPolicy
+>
+struct get_turns
+{
+};
+
+
+template
+<
+ typename Polygon,
+ typename Box,
+ typename TurnCollection,
+ typename IntersectionStrategy,
+ typename AssignPolicy
+>
+struct get_turns
+ <
+ polygon_tag, box_tag, false, false,
+ Polygon, Box,
+ TurnCollection,
+ IntersectionStrategy,
+ AssignPolicy
+ >
+{
+
+ static inline bool apply(
+ int source_id1, Polygon const& polygon,
+ int source_id2, Box const& box,
+ TurnCollection& turns)
+ {
+ typedef typename geometry::ring_type<Polygon>::type ring_type;
+
+ typedef typename boost::range_const_iterator
+ <
+ typename interior_type<Polygon>::type
+ >::type iterator_type;
+
+
+ typedef detail::get_turns::get_turns_cs
+ <
+ ring_type,
+ Box,
+ TurnCollection,
+ IntersectionStrategy,
+ AssignPolicy
+ > intersector_type;
+
+ bool trivial = true;
+ intersector_type::apply(
+ source_id1, geometry::exterior_ring(polygon), -1, -1,
+ source_id2, box,
+ turns, trivial);
+
+ int i = 0;
+ for (iterator_type it = boost::begin(interior_rings(polygon));
+ it != boost::end(interior_rings(polygon));
+ ++it, ++i)
+ {
+ intersector_type::apply(
+ source_id1, *it, -1, i,
+ source_id2, box, turns, trivial);
+ }
+
+ return trivial;
+ }
+};
+
+
+template
+<
+ typename Ring,
+ typename Box,
+ typename TurnCollection,
+ typename IntersectionStrategy,
+ typename AssignPolicy
+>
+struct get_turns
+ <
+ ring_tag, box_tag, false, false,
+ Ring, Box,
+ TurnCollection,
+ IntersectionStrategy,
+ AssignPolicy
+ >
+{
+ static inline bool apply(
+ int source_id1, Ring const& ring,
+ int source_id2, Box const& box,
+ TurnCollection& turns)
+ {
+ typedef typename boost::range_const_iterator
+ <
+ Ring
+ >::type iterator_type;
+
+ typedef detail::get_turns::get_turns_cs
+ <
+ Ring,
+ Box,
+ TurnCollection,
+ IntersectionStrategy,
+ AssignPolicy
+ > intersector_type;
+
+ bool trivial = true;
+ intersector_type::apply(
+ source_id1, ring, -1, -1,
+ source_id2, box,
+ turns, trivial);
+
+ return trivial;
+ }
+};
+
+
+template
+<
+ typename Ring1,
+ typename Ring2,
+ typename TurnCollection,
+ typename IntersectionStrategy,
+ typename AssignPolicy
+>
+struct get_turns
+ <
+ ring_tag, ring_tag, false, false,
+ Ring1, Ring2,
+ TurnCollection, IntersectionStrategy,
+ AssignPolicy
+ >
+ : detail::get_turns::get_turns_generic
+ <
+ Ring1,
+ Ring2,
+ TurnCollection,
+ IntersectionStrategy,
+ AssignPolicy
+ >
+{};
+
+
+template
+<
+ typename Polygon1,
+ typename Polygon2,
+ typename TurnCollection,
+ typename IntersectionStrategy,
+ typename AssignPolicy
+>
+struct get_turns
+ <
+ polygon_tag, polygon_tag, false, false,
+ Polygon1, Polygon2,
+ TurnCollection, IntersectionStrategy,
+ AssignPolicy
+ >
+ : detail::get_turns::get_turns_generic
+ <
+ Polygon1,
+ Polygon2,
+ TurnCollection,
+ IntersectionStrategy,
+ AssignPolicy
+ >
+{};
+
+template
+<
+ typename Polygon,
+ typename Ring,
+ typename TurnCollection,
+ typename IntersectionStrategy,
+ typename AssignPolicy
+>
+struct get_turns
+ <
+ polygon_tag, ring_tag, false, false,
+ Polygon, Ring,
+ TurnCollection, IntersectionStrategy,
+ AssignPolicy
+ >
+ : detail::get_turns::get_turns_generic
+ <
+ Polygon,
+ Ring,
+ TurnCollection,
+ IntersectionStrategy,
+ AssignPolicy
+ >
+{};
+
+template
+<
+ typename LineString1,
+ typename LineString2,
+ typename TurnCollection,
+ typename IntersectionStrategy,
+ typename AssignPolicy
+>
+struct get_turns
+ <
+ linestring_tag, linestring_tag, false, false,
+ LineString1, LineString2,
+ TurnCollection, IntersectionStrategy,
+ AssignPolicy
+ >
+ : detail::get_turns::get_turns_generic
+ <
+ LineString1,
+ LineString2,
+ TurnCollection,
+ IntersectionStrategy,
+ AssignPolicy
+ >
+{};
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2,
+ bool IsMulti1, bool IsMulti2,
+ typename Geometry1, typename Geometry2,
+ typename TurnCollection,
+ typename IntersectionStrategy,
+ typename AssignPolicy
+>
+struct get_turns_reversed
+{
+ static inline bool apply(
+ int source_id1, Geometry1 const& g1,
+ int source_id2, Geometry2 const& g2,
+ TurnCollection& turns)
+ {
+ return get_turns
+ <
+ GeometryTag2, GeometryTag1,
+ IsMulti2, IsMulti1,
+ Geometry2, Geometry1,
+ TurnCollection, IntersectionStrategy,
+ AssignPolicy
+ >::apply(source_id2, g2, source_id1, g1, turns);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+/*!
+ \brief Calculate intersection points of two geometries
+ \ingroup overlay
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \tparam TurnCollection type of turn-container (e.g. vector of "intersection/turn point"'s)
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \param turns container which will contain intersection points
+ */
+template
+<
+ typename AssignPolicy,
+ typename Geometry1,
+ typename Geometry2,
+ typename TurnCollection
+>
+inline void get_turns(Geometry1 const& geometry1,
+ Geometry2 const& geometry2, TurnCollection& turns)
+{
+ concept::check_concepts_and_equal_dimensions<const Geometry1, const Geometry2>();
+
+ typedef typename boost::remove_const<Geometry1>::type ncg1_type;
+ typedef typename boost::remove_const<Geometry2>::type ncg2_type;
+
+ typedef typename strategy_intersection
+ <
+ typename cs_tag<Geometry1>::type,
+ Geometry1,
+ Geometry2,
+ typename boost::range_value<TurnCollection>::type
+ >::segment_intersection_strategy_type segment_intersection_strategy_type;
+
+ boost::mpl::if_c
+ <
+ reverse_dispatch<Geometry1, Geometry2>::type::value,
+ dispatch::get_turns_reversed
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ is_multi<Geometry1>::type::value,
+ is_multi<Geometry2>::type::value,
+ ncg1_type,
+ ncg2_type,
+ TurnCollection,
+ segment_intersection_strategy_type,
+ AssignPolicy
+ >,
+ dispatch::get_turns
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ is_multi<Geometry1>::type::value,
+ is_multi<Geometry2>::type::value,
+ ncg1_type,
+ ncg2_type,
+ TurnCollection,
+ segment_intersection_strategy_type,
+ AssignPolicy
+ >
+ >::type::apply(
+ 0, geometry1,
+ 1, geometry2,
+ turns);
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_OVERLAY_GET_TURNS_HPP

Added: sandbox/geometry/boost/geometry/algorithms/overlay/intersection_point.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/overlay/intersection_point.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,359 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_INTERSECTION_POINT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_INTERSECTION_POINT_HPP
+
+
+#include <vector>
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/distance_result.hpp>
+
+#include <boost/geometry/algorithms/overlay/segment_identifier.hpp>
+
+
+#ifdef BOOST_GEOMETRY_USE_MSM
+# include <boost/geometry/algorithms/overlay/msm_state.hpp>
+#endif
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersection {
+
+
+#if ! defined(BOOST_GEOMETRY_USE_MSM)
+
+class visit_info
+{
+private :
+ static const int NONE = 0;
+ static const int STARTED = 1;
+ static const int VISITED = 2;
+ static const int FINISHED = 3;
+ //static const int WITHIN = 4;
+
+ int visit_code;
+
+public:
+ inline visit_info()
+ : visit_code(0)
+ {}
+
+ void set_visited() { visit_code = VISITED; }
+ void set_started() { visit_code = STARTED; }
+ void set_finished() { visit_code = FINISHED; }
+
+ bool none() const { return visit_code == NONE; }
+ bool visited() const { return visit_code == VISITED; }
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ friend std::ostream& operator<<(std::ostream &os, visit_info const& v)
+ {
+ if (v.visit_code != 0)
+ {
+ os << " VIS: " << int(v.visit_code);
+ }
+ return os;
+ }
+#endif
+
+};
+
+#else
+
+class visit_info
+{
+private :
+#ifndef USE_MSM_MINI
+ mutable
+#endif
+ traverse_state state;
+
+public :
+ inline visit_info()
+ {
+ state.start();
+ }
+
+ void set_visited() { state.process_event(visit()); }
+ void set_started() { state.process_event(starting()); }
+ void set_finished() { state.process_event(finish()); }
+
+#ifdef USE_MSM_MINI
+ bool none() const { return state.flag_none(); }
+ bool visited() const { return state.flag_visited(); }
+#else
+ bool none() const { return state.is_flag_active<is_init>(); }
+ bool visited() const { return state.is_flag_active<is_visited>(); }
+#endif
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ friend std::ostream& operator<<(std::ostream &os, visit_info const& v)
+ {
+ return os;
+ }
+#endif
+};
+#endif
+
+
+
+template<typename P>
+struct intersection_info
+{
+ typedef P point_type;
+ typedef typename distance_result<P, P>::type distance_type;
+
+ inline intersection_info()
+ : travels_to_vertex_index(-1)
+ , travels_to_ip_index(-1)
+ , next_ip_index(-1)
+ , distance(geometry::make_distance_result<distance_type>(0))
+ , direction(0)
+ , how('?')
+ , arrival(0)
+ , opposite(false)
+ , flagged(false)
+ {}
+
+ // Point to which the segment from IP is directing (TO-point)
+ // If they intersect on their "arrival" points, it is the FROM-point.
+ P other_point;
+
+ // Identifier of this segment (source,segment,ring,multi)
+ segment_identifier seg_id;
+
+ // Identify the segment where it was intersected with to form this IP
+ segment_identifier other_id;
+
+
+ // vertex to which is free travel after this IP,
+ // so from "segment_index+1" to "travels_to_vertex_index", without IP-s,
+ // can be -1
+ int travels_to_vertex_index;
+
+ // same but now IP index, so "next IP index" but not on THIS segment
+ int travels_to_ip_index;
+
+ // index of next IP on this segment, -1 if there is no one
+ int next_ip_index;
+
+ distance_type distance; // distance-measurement from segment.first to IP
+
+ // 1: left, -1: right, 0: collinear
+ int direction;
+
+ // Information about how intersection is done
+ char how;
+
+ // 1: arrived at IP, -1: departs from IP, 0: crosses IP
+ int arrival;
+
+ bool opposite;
+
+ visit_info visit_state;
+ side_info sides;
+
+ bool flagged; // flagged for deletion
+
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+
+ static inline std::string dir(int d)
+ {
+ return d == 0 ? "-" : (d == 1 ? "L" : d == -1 ? "R" : "#");
+ }
+ static inline std::string how_str(int h)
+ {
+ return h == 0 ? "-" : (h == 1 ? "A" : "D");
+ }
+
+ friend std::ostream& operator<<(std::ostream &os, intersection_info<P> const& info)
+ {
+ typename geometry::coordinate_type<P>::type d = info.distance;
+ os << "\t"
+ << " src " << info.seg_id.source_index
+ << " seg " << info.seg_id.segment_index
+ << " (// " << info.other_id.source_index
+ << "." << info.other_id.segment_index << ")"
+ << " how " << info.how
+ << "[" << how_str(info.arrival)
+ << " " << dir(info.direction)
+ << (info.opposite ? " o" : "")
+ << "]"
+ << " sd "
+ << dir(info.sides.get<0,0>())
+ << dir(info.sides.get<0,1>())
+ << dir(info.sides.get<1,0>())
+ << dir(info.sides.get<1,1>())
+ << " nxt seg " << info.travels_to_vertex_index
+ << " , ip " << info.travels_to_ip_index
+ << " , or " << info.next_ip_index
+ << " dst " << double(d)
+ << info.visit_state;
+ if (info.flagged)
+ {
+ os << " FLAGGED";
+ }
+ return os;
+ }
+#endif
+};
+
+
+template<typename P>
+struct intersection_point
+{
+ public :
+ inline intersection_point()
+ : trivial(true)
+ , shared(false)
+ , flagged(false)
+ {
+ }
+
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ friend std::ostream& operator<<(std::ostream &os, intersection_point<P> const& p)
+ {
+ // Convert them to double to make them comparable in DEBUG-files
+ typedef double casted;
+
+ os
+ << std::setprecision(6)
+ << "IP (" << casted(geometry::get<0>(p.point))
+ << "," << casted(geometry::get<1>(p.point)) << ")"
+ << p.visit_state
+ << (p.shared ? " SHARED" : "")
+ << (p.flagged ? " FLAGGED" : "")
+ << std::endl;
+
+ for (unsigned int i = 0; i < p.info.size(); i++)
+ {
+ os << p.info[i] << std::endl;
+ }
+ if (! p.report.empty())
+ {
+ os << p.report << std::endl;
+ }
+ return os;
+ }
+ std::string report;
+#endif
+ typedef intersection_info<P> traversal_type;
+ typedef std::vector<traversal_type> traversal_vector;
+
+ typedef P point_type;
+
+ P point;
+
+ visit_info visit_state;
+
+ bool trivial; // FALSE if there is an collinearity, touch or so.
+ bool shared; // shared with more IP's
+ bool flagged; // flagged for deletion afterwards
+
+ // info about the two intersecting segments
+ // usually two, but often more if IP's are merged
+ traversal_vector info;
+
+ inline void clone_except_info(intersection_point& other) const
+ {
+ other.point = point;
+ other.trivial = trivial;
+ other.shared = shared;
+ other.flagged = flagged;
+ // Probably not necessary:
+ other.visit_state = visit_state;
+ }
+};
+
+
+
+
+}} // namespace detail::intersection
+#endif //DOXYGEN_NO_DETAIL
+
+
+// Register the intersection point as being a point fulfilling the Point Concept
+namespace traits
+{
+
+ template <typename P>
+ struct coordinate_type<geometry::detail::intersection::intersection_point<P> >
+ {
+ typedef typename geometry::coordinate_type<P>::type type;
+ };
+
+ template <typename P>
+ struct coordinate_system<geometry::detail::intersection::intersection_point<P> >
+ {
+ typedef typename geometry::coordinate_system<P>::type type;
+ };
+
+ template <typename P>
+ struct dimension<geometry::detail::intersection::intersection_point<P> >
+ : geometry::dimension<P>
+ {};
+
+ template <typename P>
+ struct tag<geometry::detail::intersection::intersection_point<P> >
+ {
+ typedef point_tag type;
+ };
+
+ template <typename P, std::size_t Dimension>
+ struct access<geometry::detail::intersection::intersection_point<P>, Dimension>
+ {
+ static inline typename coordinate_type<P>::type get(
+ geometry::detail::intersection::intersection_point<P> const& p)
+ {
+ return geometry::get<Dimension>(p.point);
+ }
+
+ static inline void set(geometry::detail::intersection::intersection_point<P>& p,
+ typename coordinate_type<P>::type const& value)
+ {
+ geometry::set<Dimension>(p.point, value);
+ }
+ };
+
+}
+
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+
+template <typename V>
+inline void report_ip(V const& intersection_points)
+{
+ typedef typename V::const_iterator iterator_type;
+
+ for (iterator_type it = intersection_points.begin();
+ it != intersection_points.end();
+ ++it)
+ {
+ if (! it->flagged)
+ {
+ std::cout << *it;
+ }
+ }
+}
+#endif // BOOST_GEOMETRY_DEBUG_INTERSECTION
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_INTERSECTION_POINT_HPP

Added: sandbox/geometry/boost/geometry/algorithms/overlay/msm_state.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/overlay/msm_state.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,178 @@
+#ifndef BOOST_GEOMETRY_ALGORITHMS_OVERLAY_MSM_STATE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_OVERLAY_MSM_STATE_HPP
+
+
+
+#ifdef USE_MSM_MINI
+
+# include <boost/msm/back/mini_state_machine.hpp>
+# include <boost/fusion/include/vector.hpp>
+
+#else
+
+# include <boost/msm/back/state_machine.hpp>
+# include <boost/msm/front/state_machine_def.hpp>
+
+#endif
+
+
+
+// Events
+struct starting {};
+struct visit {};
+struct finish {};
+
+
+// Flags
+struct is_init {};
+struct is_visited {};
+
+enum StatesEnum
+{
+ STATE_NONE=0,
+ STATE_IS_INIT=1,
+ STATE_IS_VISITED=2
+};
+
+
+
+#ifndef USE_MSM_MINI
+
+// front-end: define the FSM structure
+struct traverse_state_ : public boost::msm::front::state_machine_def<traverse_state_>
+{
+ traverse_state_():m_state(STATE_IS_INIT){}
+ // The list of FSM states
+ struct Init : public boost::msm::front::state<>
+ {
+ typedef boost::mpl::vector1<is_init> flag_list;
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& fsm) {fsm.m_state=STATE_IS_INIT;}
+ };
+
+ struct Started : public boost::msm::front::state<>
+ {
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& fsm) {fsm.m_state=STATE_NONE;}
+ };
+
+ struct Visited : public boost::msm::front::state<>
+ {
+ typedef boost::mpl::vector1<is_visited> flag_list;
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& fsm) {fsm.m_state=STATE_IS_VISITED;}
+ };
+
+ struct Finished : public boost::msm::front::state<>
+ {
+ typedef boost::mpl::vector1<is_visited> flag_list;
+ //template <class Event,class FSM>
+ //void on_entry(Event const&,FSM& fsm) {fsm.m_state=STATE_IS_VISITED;}
+ };
+
+
+ // the initial state of the player SM. Must be defined
+ typedef Init initial_state;
+
+ // transition actions
+ void start_traverse(starting const&) {m_state=STATE_NONE;}
+ void finish_after_visit(finish const&) {m_state=STATE_IS_VISITED;}
+ void do_finish(finish const&) {m_state=STATE_IS_VISITED;}
+ void do_visit(visit const&) {m_state=STATE_IS_VISITED;}
+ void do_visit2(visit const&) {m_state=STATE_IS_VISITED;}
+ void do_nothing(finish const&) {m_state=STATE_IS_VISITED;}
+
+
+ typedef traverse_state_ p; // makes transition table cleaner
+
+ // Transition table for player
+ struct transition_table : mpl::vector
+ <
+ // Start Event Next Action Guard
+ // +---------+-------------+---------+---------------------+----------------------+
+ a_row < Init , starting , Started , &p::start_traverse >,
+ a_row < Init , visit , Visited , &p::do_visit >,
+ a_row < Init , finish , Finished , &p::do_nothing >,
+ a_row < Started , finish , Finished , &p::do_finish >,
+ a_row < Started , visit , Visited , &p::do_visit2 >,
+ // +---------+-------------+---------+---------------------+----------------------+
+ a_row < Visited , finish , Finished , &p::finish_after_visit >
+ // +---------+-------------+---------+---------------------+----------------------+
+ > {};
+
+ // Replaces the default no-transition response.
+ template <class Machine, class Event>
+ void no_transition(Event const& e, Machine&, int state)
+ {
+ //std::cout << "no transition from state " << state << " on event " << typeid(e).name() << std::endl;
+ }
+
+ typedef int no_exception_thrown;
+ typedef int no_message_queue;
+ StatesEnum m_state;
+
+};
+
+
+typedef boost::msm::back::state_machine<traverse_state_> traverse_state;
+
+#else
+
+// mini-back-end
+
+
+struct traverse_state : public boost::msm::back::mini::state_machine<traverse_state>
+{
+ traverse_state():m_state(STATE_IS_INIT){}
+
+ // The list of FSM states
+ enum states
+ {
+ Init, Started, Visited, Finished
+ , initial_state = Init
+ };
+
+ friend class boost::msm::back::mini::state_machine<traverse_state>;
+ typedef traverse_state p; // makes transition table cleaner
+
+ // transition actions
+ void start_traverse(starting const&) {m_state=STATE_NONE;}
+ void finish_after_visit(finish const&) {m_state=STATE_IS_VISITED;}
+ void do_finish(finish const&) {m_state=STATE_IS_VISITED;}
+ void do_visit(visit const&) {m_state=STATE_IS_VISITED;}
+ void do_visit2(visit const&) {m_state=STATE_IS_VISITED;}
+ void do_nothing(finish const&) {m_state=STATE_IS_VISITED;}
+
+ bool flag_none() const { return m_state == STATE_IS_INIT; }
+ bool flag_visited() const { return m_state == STATE_IS_VISITED; }
+
+
+ // Transition table
+ struct transition_table : mpl::vector6<
+ // Start Event Next Action
+ // +---------+-------------+---------+---------------------+
+ row < Init , starting , Started , &p::start_traverse >,
+ row < Init , visit , Visited , &p::do_visit >,
+ row < Init , finish , Finished, &p::do_nothing >,
+ row < Started , finish , Finished, &p::do_finish >,
+ row < Started , visit , Visited , &p::do_visit2 >,
+ row < Visited , finish , Finished, &p::finish_after_visit>
+ // +---------+-------------+---------+---------------------+
+ > {};
+
+ // Replaces the default no-transition response.
+ template <class Event>
+ int no_transition(int state, Event const& e)
+ {
+ std::cout << "no transition from state " << state
+ << " on event " << typeid(e).name() << std::endl;
+ return state;
+ }
+ StatesEnum m_state;
+
+};
+
+#endif
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_OVERLAY_MSM_STATE_HPP

Added: sandbox/geometry/boost/geometry/algorithms/overlay/segment_identifier.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/overlay/segment_identifier.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,92 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_OVERLAY_SEGMENT_IDENTIFIER_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_OVERLAY_SEGMENT_IDENTIFIER_HPP
+
+
+#if defined(BOOST_GEOMETRY_DEBUG_OVERLAY)
+# define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER
+#endif
+
+
+#include <vector>
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+
+#include <boost/geometry/strategies/distance_result.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+// Internal struct to uniquely identify a segment
+// on a linestring,ring
+// or polygon (needs ring_index)
+// or multi-geometry (needs multi_index)
+struct segment_identifier
+{
+ inline segment_identifier()
+ : source_index(-1)
+ , multi_index(-1)
+ , ring_index(-1)
+ , segment_index(-1)
+ {}
+
+ inline segment_identifier(int src, int mul, int rin, int seg)
+ : source_index(src)
+ , multi_index(mul)
+ , ring_index(rin)
+ , segment_index(seg)
+ {}
+
+ inline bool operator<(segment_identifier const& other) const
+ {
+ return source_index != other.source_index ? source_index < other.source_index
+ : multi_index !=other.multi_index ? multi_index < other.multi_index
+ : ring_index != other.ring_index ? ring_index < other.ring_index
+ : segment_index < other.segment_index
+ ;
+ }
+
+ inline bool operator==(segment_identifier const& other) const
+ {
+ return source_index == other.source_index
+ && segment_index == other.segment_index
+ && ring_index == other.ring_index
+ && multi_index == other.multi_index
+ ;
+ }
+
+#if defined(BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER)
+ friend std::ostream& operator<<(std::ostream &os, segment_identifier const& seg_id)
+ {
+ std::cout
+ << "s:" << seg_id.source_index
+ << ", v:" << seg_id.segment_index // ~vertex
+ ;
+ if (seg_id.ring_index >= 0) std::cout << ", r:" << seg_id.ring_index;
+ if (seg_id.multi_index >= 0) std::cout << ", m:" << seg_id.multi_index;
+ return os;
+ }
+#endif
+
+ int source_index;
+ int multi_index;
+ int ring_index;
+ int segment_index;
+};
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_OVERLAY_SEGMENT_IDENTIFIER_HPP

Added: sandbox/geometry/boost/geometry/algorithms/overlay/self_intersection_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/overlay/self_intersection_points.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,185 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_OVERLAY_SELF_INTERSECTION_POINTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_OVERLAY_SELF_INTERSECTION_POINTS_HPP
+
+#include <cstddef>
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/is_multi.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/detail/disjoint.hpp>
+#include <boost/geometry/algorithms/overlay/get_intersection_points.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace self_intersection_points {
+
+template
+<
+ typename Geometry,
+ typename IntersectionPoints,
+ typename IntersectionStrategy
+>
+struct check_ips
+{
+ static inline bool apply(
+ Geometry const& geometry,
+ bool return_if_found,
+ IntersectionPoints& intersection_points)
+ {
+ typedef typename geometry::sections
+ <
+ geometry::box < typename geometry::point_type<Geometry>::type >, 1
+ > sections_type;
+
+ sections_type sec;
+ geometry::sectionalize(geometry, sec);
+
+ bool trivial = true;
+ for (typename boost::range_const_iterator<sections_type>::type
+ it1 = sec.begin();
+ it1 != sec.end();
+ ++it1)
+ {
+ for (typename boost::range_const_iterator<sections_type>::type
+ it2 = sec.begin();
+ it2 != sec.end();
+ ++it2)
+ {
+ if (! geometry::detail::disjoint::disjoint_box_box(
+ it1->bounding_box, it2->bounding_box)
+ && ! it1->duplicate
+ && ! it2->duplicate
+ )
+ {
+ geometry::detail::get_intersection_points::get_ips_in_sections
+ <
+ Geometry, Geometry,
+ typename boost::range_value<sections_type>::type,
+ typename boost::range_value<sections_type>::type,
+ IntersectionPoints, IntersectionStrategy
+ >::apply(
+ 0, geometry, *it1,
+ 0, geometry, *it2,
+ return_if_found,
+ intersection_points, trivial);
+ }
+ }
+ }
+ return trivial;
+ }
+};
+
+
+}} // namespace detail::self_intersection_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename GeometryTag,
+ bool IsMulti,
+ typename Geometry,
+ typename IntersectionPoints,
+ typename IntersectionStrategy
+>
+struct self_intersection_points
+{
+};
+
+
+template<typename Ring, typename IntersectionPoints, typename IntersectionStrategy>
+struct self_intersection_points
+ <
+ ring_tag, false, Ring,
+ IntersectionPoints,
+ IntersectionStrategy
+ >
+ : detail::self_intersection_points::check_ips
+ <
+ Ring,
+ IntersectionPoints,
+ IntersectionStrategy
+ >
+{};
+
+
+template<typename Polygon, typename IntersectionPoints, typename IntersectionStrategy>
+struct self_intersection_points
+ <
+ polygon_tag, false, Polygon,
+ IntersectionPoints, IntersectionStrategy
+ >
+ : detail::self_intersection_points::check_ips
+ <
+ Polygon,
+ IntersectionPoints,
+ IntersectionStrategy
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Calculate self intersections of a geometry
+ \ingroup overlay
+ \tparam Geometry geometry type
+ \tparam IntersectionPoints type of intersection container (e.g. vector of "intersection_point"'s)
+ \param geometry geometry
+ \param intersection_points container which will contain intersection points
+ \return TRUE if it is trivial, else FALSE
+ */
+template <typename Geometry, typename IntersectionPoints>
+inline bool get_intersection_points(Geometry const& geometry,
+ IntersectionPoints& intersection_points)
+{
+ concept::check<Geometry>();
+
+ typedef typename strategy_intersection
+ <
+ typename cs_tag<Geometry>::type,
+ Geometry,
+ Geometry,
+ typename boost::range_value<IntersectionPoints>::type
+ >::segment_intersection_strategy_type segment_intersection_strategy_type;
+
+ typedef typename boost::remove_const<Geometry>::type ncg_type;
+
+ return dispatch::self_intersection_points
+ <
+ typename tag<ncg_type>::type,
+ is_multi<ncg_type>::type::value,
+ ncg_type,
+ IntersectionPoints, segment_intersection_strategy_type
+ >::apply(geometry, false, intersection_points);
+}
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_OVERLAY_SELF_INTERSECTION_POINTS_HPP

Added: sandbox/geometry/boost/geometry/algorithms/overlay/self_turn_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/overlay/self_turn_points.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,210 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2010, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_OVERLAY_SELF_TURN_POINTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_OVERLAY_SELF_TURN_POINTS_HPP
+
+#include <cstddef>
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/is_multi.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/detail/disjoint.hpp>
+#include <boost/geometry/algorithms/overlay/get_turns.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace self_get_turn_points {
+
+template
+<
+ typename Geometry,
+ typename IntersectionPoints,
+ typename IntersectionStrategy,
+ typename AssignPolicy
+>
+struct get_turns
+{
+ static inline bool apply(
+ Geometry const& geometry,
+ bool return_if_found,
+ IntersectionPoints& intersection_points)
+ {
+ typedef typename geometry::sections
+ <
+ geometry::box <typename geometry::point_type<Geometry>::type>,
+ 1
+ > sections_type;
+
+ sections_type sec;
+ geometry::sectionalize(geometry, sec);
+
+ bool trivial = true;
+ for (typename boost::range_const_iterator<sections_type>::type
+ it1 = sec.begin();
+ it1 != sec.end();
+ ++it1)
+ {
+ for (typename boost::range_const_iterator<sections_type>::type
+ it2 = sec.begin();
+ it2 != sec.end();
+ ++it2)
+ {
+ if (! geometry::detail::disjoint::disjoint_box_box(
+ it1->bounding_box, it2->bounding_box)
+ && ! it1->duplicate
+ && ! it2->duplicate
+ )
+ {
+ geometry::detail::get_turns::get_turns_in_sections
+ <
+ Geometry, Geometry,
+ typename boost::range_value<sections_type>::type,
+ typename boost::range_value<sections_type>::type,
+ IntersectionPoints, IntersectionStrategy,
+ AssignPolicy
+ >::apply(
+#ifdef BG_SELF_NEGATIVE
+ -2, geometry, *it1,
+ -1, geometry, *it2,
+#else
+ 0, geometry, *it1,
+ 0, geometry, *it2,
+#endif
+ return_if_found,
+ intersection_points, trivial);
+ }
+ }
+ }
+ return trivial;
+ }
+};
+
+
+}} // namespace detail::self_get_turn_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename GeometryTag,
+ bool IsMulti,
+ typename Geometry,
+ typename IntersectionPoints,
+ typename IntersectionStrategy,
+ typename AssignPolicy
+>
+struct self_get_turn_points
+{
+};
+
+
+template
+<
+ typename Ring,
+ typename IntersectionPoints,
+ typename IntersectionStrategy,
+ typename AssignPolicy
+>
+struct self_get_turn_points
+ <
+ ring_tag, false, Ring,
+ IntersectionPoints,
+ IntersectionStrategy,
+ AssignPolicy
+ >
+ : detail::self_get_turn_points::get_turns
+ <
+ Ring,
+ IntersectionPoints,
+ IntersectionStrategy,
+ AssignPolicy
+ >
+{};
+
+
+template
+<
+ typename Polygon,
+ typename IntersectionPoints,
+ typename IntersectionStrategy,
+ typename AssignPolicy
+>
+struct self_get_turn_points
+ <
+ polygon_tag, false, Polygon,
+ IntersectionPoints, IntersectionStrategy,
+ AssignPolicy
+ >
+ : detail::self_get_turn_points::get_turns
+ <
+ Polygon,
+ IntersectionPoints,
+ IntersectionStrategy,
+ AssignPolicy
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Calculate self intersections of a geometry
+ \ingroup overlay
+ \tparam Geometry geometry type
+ \tparam IntersectionPoints type of intersection container
+ (e.g. vector of "intersection_point"'s)
+ \param geometry geometry
+ \param intersection_points container which will contain intersection points
+ */
+template <typename AssignPolicy, typename Geometry, typename IntersectionPoints>
+inline void get_turns(Geometry const& geometry,
+ IntersectionPoints& intersection_points)
+{
+ concept::check<Geometry>();
+
+ typedef typename strategy_intersection
+ <
+ typename cs_tag<Geometry>::type,
+ Geometry,
+ Geometry,
+ typename boost::range_value<IntersectionPoints>::type
+ >::segment_intersection_strategy_type strategy_type;
+
+ typedef typename boost::remove_const<Geometry>::type ncg_type;
+
+ dispatch::self_get_turn_points
+ <
+ typename tag<ncg_type>::type,
+ is_multi<ncg_type>::type::value,
+ ncg_type,
+ IntersectionPoints, strategy_type,
+ AssignPolicy
+ >::apply(geometry, false, intersection_points);
+}
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_OVERLAY_SELF_TURN_POINTS_HPP

Added: sandbox/geometry/boost/geometry/algorithms/overlay/traverse.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/overlay/traverse.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,346 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_OVERLAY_TRAVERSE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_OVERLAY_TRAVERSE_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+
+#include <boost/geometry/algorithms/overlay/copy_segments.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+#include <boost/geometry/extensions/gis/io/wkt/write_wkt.hpp>
+#endif
+
+
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+
+
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay {
+
+
+template <typename Info, typename Turn>
+inline void set_visited_for_contine(Info& info, Turn const& turn)
+{
+ // On "continue", set "visited" for ALL directions
+
+ if (turn.operation == detail::overlay::operation_continue)
+ {
+ for (typename boost::range_iterator
+ <
+ typename Info::container_type
+ >::type it = boost::begin(info.operations);
+ it != boost::end(info.operations);
+ ++it)
+ {
+ if (it->visited.none())
+ {
+ it->visited.set_visited();
+ }
+ }
+ }
+}
+
+
+template
+<
+ typename GeometryOut,
+ typename G1,
+ typename G2,
+ typename TurnPoints,
+ typename IntersectionInfo
+>
+inline void assign_next_ip(G1 const& g1, G2 const& g2,
+ TurnPoints& turn_points,
+ typename boost::range_iterator<TurnPoints>::type & ip,
+ GeometryOut& current_output,
+ IntersectionInfo & info,
+ segment_identifier& seg_id)
+{
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ //std::cout << "traverse: take: " << info << std::endl;
+#endif
+ info.visited.set_visited();
+ set_visited_for_contine(*ip, info);
+
+ // If there is no next IP on this segment
+ if (info.enriched.next_ip_index < 0)
+ {
+ if (info.seg_id.source_index == 0)
+ {
+ geometry::copy_segments(g1, info.seg_id,
+ info.enriched.travels_to_vertex_index,
+ current_output);
+ }
+ else
+ {
+ geometry::copy_segments(g2, info.seg_id,
+ info.enriched.travels_to_vertex_index,
+ current_output);
+ }
+ ip = boost::begin(turn_points) + info.enriched.travels_to_ip_index;
+ seg_id = info.seg_id;
+ }
+ else
+ {
+ ip = boost::begin(turn_points) + info.enriched.next_ip_index;
+ seg_id = info.seg_id;
+ }
+ *(std::back_inserter(current_output)++) = ip->point;
+}
+
+
+inline bool select_source(operation_type operation, int source1, int source2)
+{
+ return
+ (operation == operation_intersection && source1 != source2)
+ || (operation == operation_union && source1 == source2);
+}
+
+
+template
+<
+ typename Turn,
+ typename Iterator
+>
+inline bool select_next_ip(operation_type operation,
+ Turn& turn,
+ segment_identifier const& seg_id,
+ Iterator const& start,
+ Iterator& selected)
+{
+ bool has_tp = false;
+ selected = boost::end(turn.operations);
+ for (Iterator it = boost::begin(turn.operations);
+ it != boost::end(turn.operations);
+ ++it)
+ {
+ // In some cases there are two alternatives.
+ // For "ii", take the other one (alternate)
+ // For "uu", take the same one
+ // For "cc", take either one, but if there is a starting one,
+ // take that one.
+ if ( (it->operation == operation_continue
+ && (! has_tp
+ || it->visited.started()
+ )
+ )
+ || (it->operation == operation
+ && (! has_tp
+ || select_source(operation,
+ it->seg_id.source_index, seg_id.source_index)
+ )
+ )
+ )
+ {
+ selected = it;
+ has_tp = true;
+ }
+
+ if (it->visited.started())
+ {
+ selected = it;
+ has_tp = true;
+ return true;
+ }
+
+ }
+
+ return has_tp;
+}
+
+
+template <typename Container>
+inline void stop_gracefully(Container& container, bool& stop,
+ std::string const& reason)
+{
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ std::cout << "STOPPING: " << reason << std::endl;
+#endif
+
+ stop = true;
+ if (container.size() > 0)
+ {
+ // Two-step adding first value, without assignment
+ // and without (erroneous) push_back of reference
+ typename boost::range_value<Container>::type p;
+ geometry::copy_coordinates(container.front(), p);
+ *(std::back_inserter(container)++) = p;
+
+ }
+}
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief Traverses through intersection points / geometries
+ \ingroup overlay
+ */
+template
+<
+ typename SideStrategy,
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename TurnPoints,
+ typename OutputIterator
+>
+inline void traverse(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ detail::overlay::operation_type operation,
+ TurnPoints& turn_points,
+ OutputIterator out)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ typedef typename boost::range_iterator<TurnPoints>::type turn_iterator;
+ typedef typename boost::range_value<TurnPoints>::type turn_type;
+ typedef typename boost::range_iterator
+ <
+ typename turn_type::container_type
+ >::type turn_operation_iterator_type;
+
+
+ // Iterate through all unvisited points
+ for (turn_iterator it = boost::begin(turn_points);
+ it != boost::end(turn_points);
+ ++it)
+ {
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ //std::cout << "traversal: try: " << *it;
+#endif
+
+ for (turn_operation_iterator_type iit = boost::begin(it->operations);
+ iit != boost::end(it->operations);
+ ++iit)
+ {
+ if (iit->visited.none()
+ && (iit->operation == operation
+ || iit->operation == detail::overlay::operation_continue)
+ )
+ {
+ set_visited_for_contine(*it, *iit);
+
+ GeometryOut current_output;
+ *(std::back_inserter(current_output)++) = it->point;
+
+ turn_iterator current = it;
+ turn_operation_iterator_type current_iit = iit;
+ segment_identifier current_seg_id;
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ //std::cout << "traversal: start: " << *current;
+#endif
+
+ detail::overlay::assign_next_ip(geometry1, geometry2,
+ turn_points,
+ current, current_output,
+ *iit, current_seg_id);
+ detail::overlay::select_next_ip(
+ operation,
+ *current,
+ current_seg_id,
+ boost::end(it->operations),
+ current_iit);
+
+ iit->visited.set_started();
+
+
+ unsigned int i = 0;
+ bool stop = false;
+
+ while (current_iit != iit && ! stop)
+ {
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ //std::cout << "traverse: " << *current;
+#endif
+
+ if (current_iit->visited.visited())
+ {
+ // It visits a visited node again, without passing the start node.
+ // This makes it suspicious for endless loops
+ // Check if it is really same node
+ detail::overlay::stop_gracefully(
+ current_output, stop, "Visit again");
+ }
+
+
+ // We assume clockwise polygons only, non self-intersecting, closed.
+ // However, the input might be different, and checking validity
+ // is up to the library user.
+
+ // Therefore we make here some sanity checks. If the input
+ // violates the assumptions, the output polygon will not be correct
+ // but the routine will stop and output the current polygon, and
+ // will continue with the next one.
+
+ // Below three reasons to stop.
+ assign_next_ip(geometry1, geometry2,
+ turn_points, current, current_output,
+ *current_iit, current_seg_id);
+
+ if (! detail::overlay::select_next_ip(
+ operation,
+ *current,
+ current_seg_id,
+ iit,
+ current_iit))
+ {
+ // Should not occur in valid (non-self-intersecting) polygons
+ // Should not occur in self-intersecting polygons without spikes
+ // Might occur in polygons with spikes
+ detail::overlay::stop_gracefully(
+ current_output, stop, "Dead end");
+ }
+
+ if (i++ > turn_points.size())
+ {
+ // Sanity check: there may be never more loops
+ // than intersection points.
+ detail::overlay::stop_gracefully(
+ current_output, stop, "Endless loop");
+ }
+ }
+
+ iit->visited.set_finished();
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ //std::cout << "traversal: finish: " << *current;
+ std::cout << geometry::wkt(current_output) << std::endl;
+#endif
+
+ *out++ = current_output;
+ }
+ }
+ }
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ std::cout << "traversal: all IP's handled" << std::endl;
+#endif
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_OVERLAY_TRAVERSE_HPP

Added: sandbox/geometry/boost/geometry/algorithms/parse.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/parse.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,122 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_PARSE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_PARSE_HPP
+
+#include <string>
+
+
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/strategies/parse.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+// TODO: remove used EXTENSION here (result should be part of parsing strategy)
+#include <boost/geometry/extensions/gis/geographic/strategies/dms_parser.hpp>
+
+/*!
+\defgroup parse parse and assign string values
+*/
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+template <typename Tag, typename G>
+struct parsing
+{
+};
+
+template <typename Point>
+struct parsing<point_tag, Point>
+{
+ template <typename S>
+ static inline void parse(Point& point, std::string const& c1, std::string const& c2, S const& strategy)
+ {
+ assert_dimension<Point, 2>();
+ dms_result r1 = strategy(c1.c_str());
+ dms_result r2 = strategy(c2.c_str());
+
+ if (0 == r1.axis())
+ set<0>(point, r1);
+ else
+ set<1>(point, r1);
+
+ if (0 == r2.axis())
+ set<0>(point, r2);
+ else
+ set<1>(point, r2);
+ }
+
+ static inline void parse(Point& point, std::string const& c1, std::string const& c2)
+ {
+ // strategy-parser corresponding to degree/radian
+ typename strategy_parse
+ <
+ typename cs_tag<Point>::type,
+ typename coordinate_system<Point>::type
+ >::type strategy;
+
+ parse(point, c1, c2, strategy);
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief parse two strings to a spherical/geographic point, using W/E/N/S
+ \ingroup parse
+ */
+template <typename Geometry>
+inline void parse(Geometry& geometry, std::string const& c1, std::string const& c2)
+{
+ concept::check<Geometry>();
+ dispatch::parsing<typename tag<Geometry>::type, Geometry>::parse(geometry, c1, c2);
+}
+
+/*!
+ \brief parse two strings to a spherical/geographic point, using a specified strategy
+ \details user can use N/E/S/O or N/O/Z/W or other formats
+ \ingroup parse
+ */
+template <typename Geometry, typename S>
+inline void parse(Geometry& geometry, std::string const& c1,
+ std::string const& c2, S const& strategy)
+{
+ concept::check<Geometry>();
+ dispatch::parsing<typename tag<Geometry>::type, Geometry>::parse(geometry, c1, c2, strategy);
+}
+
+// There will be a parsing function with three arguments (ANGLE,ANGLE,RADIUS)
+
+template <typename Geometry>
+inline Geometry parse(std::string const& c1, std::string const& c2)
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ dispatch::parsing<typename tag<Geometry>::type, Geometry>::parse(geometry, c1, c2);
+ return geometry;
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_PARSE_HPP

Added: sandbox/geometry/boost/geometry/algorithms/perimeter.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/perimeter.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,137 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_PERIMETER_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_PERIMETER_HPP
+
+
+#include <boost/geometry/core/cs.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/strategies/length_result.hpp>
+
+#include <boost/geometry/algorithms/length.hpp>
+#include <boost/geometry/algorithms/detail/calculate_null.hpp>
+#include <boost/geometry/algorithms/detail/calculate_sum.hpp>
+
+
+/*!
+\defgroup perimeter perimeter: calculate perimeter of a geometry
+\par Geometries:
+- \b polygon
+- \b box
+- \b linear_ring
+- \b multi_polygon
+*/
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// Default perimeter is 0.0, specializations implement calculated values
+template <typename Tag, typename Geometry, typename Strategy>
+struct perimeter : detail::calculate_null
+ <
+ typename length_result<Geometry>::type,
+ Geometry,
+ Strategy
+ >
+{};
+
+template <typename Geometry, typename Strategy>
+struct perimeter<ring_tag, Geometry, Strategy>
+ : detail::length::range_length<Geometry, Strategy>
+{};
+
+template <typename Polygon, typename Strategy>
+struct perimeter<polygon_tag, Polygon, Strategy>
+ : detail::calculate_polygon_sum
+ <
+ typename length_result<Polygon>::type,
+ Polygon,
+ Strategy,
+ detail::length::range_length
+ <
+ typename ring_type<Polygon>::type,
+ Strategy
+ >
+ >
+{};
+
+
+// box,n-sphere: to be implemented
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Calculate perimeter of a geometry
+ \ingroup perimeter
+ \details The function perimeter returns the perimeter of a geometry,
+ using the default distance-calculation-strategy
+ \param geometry the geometry, be it a geometry::ring, vector, iterator pair,
+ or any other boost compatible range
+ \return the perimeter
+ */
+template<typename Geometry>
+inline typename length_result<Geometry>::type perimeter(
+ Geometry const& geometry)
+{
+ concept::check<const Geometry>();
+
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename cs_tag<point_type>::type cs_tag;
+ typedef typename strategy_distance
+ <
+ cs_tag,
+ cs_tag,
+ point_type,
+ point_type
+ >::type strategy_type;
+
+ return dispatch::perimeter
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ strategy_type
+ >::apply(geometry, strategy_type());
+}
+
+/*!
+ \brief Calculate perimeter of a geometry
+ \ingroup perimeter
+ \details The function perimeter returns the perimeter of a geometry,
+ using specified strategy
+ \param geometry the geometry, be it a geometry::ring, vector, iterator pair,
+ or any other boost compatible range
+ \param strategy strategy to be used for distance calculations.
+ \return the perimeter
+ */
+template<typename Geometry, typename Strategy>
+inline typename length_result<Geometry>::type perimeter(
+ Geometry const& geometry, Strategy const& strategy)
+{
+ concept::check<const Geometry>();
+
+ return dispatch::perimeter
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Strategy
+ >::apply(geometry, strategy);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_PERIMETER_HPP
+

Added: sandbox/geometry/boost/geometry/algorithms/sectionalize.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/sectionalize.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,590 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_SECTIONALIZE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_SECTIONALIZE_HPP
+
+#include <cstddef>
+#include <vector>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/combine.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/geometries/segment.hpp>
+
+
+/*!
+\defgroup sectionalize sectionalize: split a geometry (polygon, linestring, etc)
+ into monotonic sections
+
+\par Geometries:
+- LINESTRING:
+- RING:
+- POLYGON:
+- BOX
+*/
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Structure containing section information
+ \details Section information consists of a bounding box, direction
+ information (if it is increasing or decreasing, per dimension),
+ index information (begin-end, ring, multi) and the number of
+ segments in this section
+
+ \tparam Box box-type
+ \tparam DimensionCount number of dimensions for this section
+ \ingroup sectionalize
+ */
+template <typename Box, std::size_t DimensionCount>
+struct section
+{
+ typedef Box box_type;
+
+ int id;
+ int directions[DimensionCount];
+ int ring_index;
+ int multi_index;
+ Box bounding_box;
+
+ int begin_index;
+ int end_index;
+ std::size_t count;
+ std::size_t range_count;
+ bool duplicate;
+ int non_duplicate_index;
+
+
+ inline section()
+ : id(-1)
+ , ring_index(-99)
+ , multi_index(-99)
+ , begin_index(-1)
+ , end_index(-1)
+ , count(0)
+ , range_count(0)
+ , duplicate(false)
+ , non_duplicate_index(-1)
+ {
+ assign_inverse(bounding_box);
+ for (register std::size_t i = 0; i < DimensionCount; i++)
+ {
+ directions[i] = 0;
+ }
+ }
+};
+
+
+/*!
+ \brief Structure containing a collection of sections
+ \note Derived from a vector, proves to be faster than of deque
+ \note vector might be templated in the future
+ \ingroup sectionalize
+ */
+template <typename Box, std::size_t DimensionCount>
+struct sections : std::vector<section<Box, DimensionCount> >
+{
+ typedef Box box_type;
+ static const std::size_t value = DimensionCount;
+};
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace sectionalize {
+
+template <typename Segment, std::size_t Dimension, std::size_t DimensionCount>
+struct get_direction_loop
+{
+ typedef typename coordinate_type<Segment>::type coordinate_type;
+
+ static inline void apply(Segment const& seg,
+ int directions[DimensionCount])
+ {
+ coordinate_type const diff =
+ geometry::get<1, Dimension>(seg) - geometry::get<0, Dimension>(seg);
+
+ directions[Dimension] = diff > 0 ? 1 : (diff < 0 ? -1 : 0);
+
+ get_direction_loop
+ <
+ Segment, Dimension + 1, DimensionCount
+ >::apply(seg, directions);
+ }
+};
+
+template <typename Segment, std::size_t DimensionCount>
+struct get_direction_loop<Segment, DimensionCount, DimensionCount>
+{
+ static inline void apply(Segment const& seg,
+ int directions[DimensionCount])
+ {
+ boost::ignore_unused_variable_warning(seg);
+ boost::ignore_unused_variable_warning(directions);
+ }
+};
+
+template <typename T, std::size_t Dimension, std::size_t DimensionCount>
+struct copy_loop
+{
+ static inline void apply(const T source[DimensionCount],
+ T target[DimensionCount])
+ {
+ target[Dimension] = source[Dimension];
+ copy_loop<T, Dimension + 1, DimensionCount>::apply(source, target);
+ }
+};
+
+template <typename T, std::size_t DimensionCount>
+struct copy_loop<T, DimensionCount, DimensionCount>
+{
+ static inline void apply(const T source[DimensionCount],
+ T target[DimensionCount])
+ {
+ boost::ignore_unused_variable_warning(source);
+ boost::ignore_unused_variable_warning(target);
+ }
+};
+
+template <typename T, std::size_t Dimension, std::size_t DimensionCount>
+struct compare_loop
+{
+ static inline bool apply(const T source[DimensionCount],
+ const T target[DimensionCount])
+ {
+ bool const not_equal = target[Dimension] != source[Dimension];
+
+ return not_equal
+ ? false
+ : compare_loop
+ <
+ T, Dimension + 1, DimensionCount
+ >::apply(source, target);
+ }
+};
+
+template <typename T, std::size_t DimensionCount>
+struct compare_loop<T, DimensionCount, DimensionCount>
+{
+ static inline bool apply(const T source[DimensionCount],
+ const T target[DimensionCount])
+ {
+ boost::ignore_unused_variable_warning(source);
+ boost::ignore_unused_variable_warning(target);
+
+ return true;
+ }
+};
+
+
+template <typename Segment, std::size_t Dimension, std::size_t DimensionCount>
+struct check_duplicate_loop
+{
+ typedef typename coordinate_type<Segment>::type coordinate_type;
+
+ static inline bool apply(Segment const& seg)
+ {
+ coordinate_type const diff =
+ geometry::get<1, Dimension>(seg) - geometry::get<0, Dimension>(seg);
+
+ if (! geometry::math::equals(diff, 0))
+ {
+ return false;
+ }
+
+ return check_duplicate_loop
+ <
+ Segment, Dimension + 1, DimensionCount
+ >::apply(seg);
+ }
+};
+
+template <typename Segment, std::size_t DimensionCount>
+struct check_duplicate_loop<Segment, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Segment const&)
+ {
+ return true;
+ }
+};
+
+template <typename T, std::size_t Dimension, std::size_t DimensionCount>
+struct assign_loop
+{
+ static inline void apply(T dims[DimensionCount], int const value)
+ {
+ dims[Dimension] = value;
+ assign_loop<T, Dimension + 1, DimensionCount>::apply(dims, value);
+ }
+};
+
+template <typename T, std::size_t DimensionCount>
+struct assign_loop<T, DimensionCount, DimensionCount>
+{
+ static inline void apply(T dims[DimensionCount], int const)
+ {
+ boost::ignore_unused_variable_warning(dims);
+ }
+};
+
+
+template
+<
+ typename Range,
+ typename Point,
+ typename Sections,
+ std::size_t DimensionCount,
+ std::size_t MaxCount
+>
+struct sectionalize_range
+{
+ static inline void apply(Range const& range, Sections& sections,
+ int ring_index = -1, int multi_index = -1)
+ {
+ typedef segment<const Point> segment_type;
+
+ std::size_t const n = boost::size(range);
+ if (n == 0)
+ {
+ // Zero points, no section
+ return;
+ }
+
+ if (n == 1)
+ {
+ // Line with one point ==> no sections
+ return;
+ }
+
+ int i = 0;
+ int ndi = 0; // non duplicate index
+
+ typedef typename boost::range_value<Sections>::type sections_range_type;
+ sections_range_type section;
+
+ typedef typename boost::range_const_iterator<Range>::type iterator_type;
+ iterator_type it = boost::begin(range);
+
+ for(iterator_type previous = it++;
+ it != boost::end(range);
+ previous = it++, i++)
+ {
+ segment_type s(*previous, *it);
+
+ int direction_classes[DimensionCount] = {0};
+ get_direction_loop
+ <
+ segment_type, 0, DimensionCount
+ >::apply(s, direction_classes);
+
+ // if "dir" == 0 for all point-dimensions, it is duplicate.
+ // Those sections might be omitted, if wished, lateron
+ bool check_duplicate = true; //?
+ bool duplicate = false;
+
+ if (check_duplicate && direction_classes[0] == 0)
+ {
+ // Recheck because all dimensions should be checked,
+ // not only first one,
+ // Note that DimensionCount might be < dimension<P>::value
+ if (check_duplicate_loop
+ <
+ segment_type, 0, geometry::dimension<Point>::type::value
+ >::apply(s)
+ )
+ {
+ duplicate = true;
+
+ // Change direction-info to force new section
+ // Note that wo consecutive duplicate segments will generate
+ // only one duplicate-section.
+ // Actual value is not important as long as it is not -1,0,1
+ assign_loop
+ <
+ int, 0, DimensionCount
+ >::apply(direction_classes, -99);
+ }
+ }
+
+ if (section.count > 0
+ && (!compare_loop
+ <
+ int, 0, DimensionCount
+ >::apply(direction_classes, section.directions)
+ || section.count > MaxCount
+ )
+ )
+ {
+ sections.push_back(section);
+ section = sections_range_type();
+ }
+
+ if (section.count == 0)
+ {
+ section.begin_index = i;
+ section.ring_index = ring_index;
+ section.multi_index = multi_index;
+ section.duplicate = duplicate;
+ section.non_duplicate_index = ndi;
+ section.range_count = boost::size(range);
+
+ copy_loop
+ <
+ int, 0, DimensionCount
+ >::apply(direction_classes, section.directions);
+ geometry::combine(section.bounding_box, *previous);
+ }
+
+ geometry::combine(section.bounding_box, *it);
+ section.end_index = i + 1;
+ section.count++;
+ if (! duplicate)
+ {
+ ndi++;
+ }
+ }
+
+ if (section.count > 0)
+ {
+ sections.push_back(section);
+ }
+ }
+};
+
+template
+<
+ typename Polygon,
+ typename Sections,
+ std::size_t DimensionCount,
+ std::size_t MaxCount
+>
+struct sectionalize_polygon
+{
+ static inline void apply(Polygon const& poly, Sections& sections,
+ int multi_index = -1)
+ {
+ typedef typename point_type<Polygon>::type point_type;
+ typedef typename ring_type<Polygon>::type ring_type;
+ typedef sectionalize_range
+ <
+ ring_type, point_type, Sections, DimensionCount, MaxCount
+ > sectionalizer_type;
+
+ typedef typename boost::range_const_iterator
+ <
+ typename interior_type<Polygon>::type
+ >::type iterator_type;
+
+ sectionalizer_type::apply(exterior_ring(poly), sections, -1, multi_index);
+
+ int i = 0;
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly));
+ ++it, ++i)
+ {
+ sectionalizer_type::apply(*it, sections, i, multi_index);
+ }
+ }
+};
+
+template
+<
+ typename Box,
+ typename Sections,
+ std::size_t DimensionCount,
+ std::size_t MaxCount
+>
+struct sectionalize_box
+{
+ static inline void apply(Box const& box, Sections& sections)
+ {
+ typedef typename point_type<Box>::type point_type;
+
+ assert_dimension<Box, 2>();
+
+ // Add all four sides of the 2D-box as separate section.
+ // Easiest is to convert it to a polygon.
+ // However, we don't have the polygon type
+ // (or polygon would be a helper-type).
+ // Therefore we mimic a linestring/std::vector of 5 points
+
+ point_type ll, lr, ul, ur;
+ assign_box_corners(box, ll, lr, ul, ur);
+
+ std::vector<point_type> points;
+ points.push_back(ll);
+ points.push_back(ul);
+ points.push_back(ur);
+ points.push_back(lr);
+ points.push_back(ll);
+
+ sectionalize_range
+ <
+ std::vector<point_type>,
+ point_type,
+ Sections,
+ DimensionCount,
+ MaxCount
+ >::apply(points, sections);
+ }
+};
+
+}} // namespace detail::sectionalize
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag,
+ typename Geometry,
+ typename Sections,
+ std::size_t DimensionCount,
+ std::size_t MaxCount
+>
+struct sectionalize
+{};
+
+template
+<
+ typename Box,
+ typename Sections,
+ std::size_t DimensionCount,
+ std::size_t MaxCount
+>
+struct sectionalize<box_tag, Box, Sections, DimensionCount, MaxCount>
+ : detail::sectionalize::sectionalize_box
+ <
+ Box,
+ Sections,
+ DimensionCount,
+ MaxCount
+ >
+{};
+
+template
+<
+ typename LineString, typename
+ Sections,
+ std::size_t DimensionCount,
+ std::size_t MaxCount
+>
+struct sectionalize
+ <
+ linestring_tag,
+ LineString,
+ Sections,
+ DimensionCount,
+ MaxCount
+ >
+ : detail::sectionalize::sectionalize_range
+ <
+ LineString,
+ typename point_type<LineString>::type,
+ Sections,
+ DimensionCount,
+ MaxCount
+ >
+{};
+
+template
+<
+ typename Range,
+ typename Sections,
+ std::size_t DimensionCount,
+ std::size_t MaxCount
+>
+struct sectionalize<ring_tag, Range, Sections, DimensionCount, MaxCount>
+ : detail::sectionalize::sectionalize_range
+ <
+ Range,
+ typename point_type<Range>::type,
+ Sections,
+ DimensionCount,
+ MaxCount
+ >
+{};
+
+template
+<
+ typename Polygon,
+ typename Sections,
+ std::size_t DimensionCount,
+ std::size_t MaxCount
+>
+struct sectionalize<polygon_tag, Polygon, Sections, DimensionCount, MaxCount>
+ : detail::sectionalize::sectionalize_polygon
+ <
+ Polygon, Sections, DimensionCount, MaxCount
+ >
+{};
+
+} // namespace dispatch
+#endif
+
+
+/*!
+ \brief Split a geometry into monotonic sections
+ \ingroup sectionalize
+ \tparam Geometry type of geometry to check
+ \tparam Sections type of sections to create
+ \param geometry geometry to create sections from
+ \param sections structure with sections
+
+ */
+template<typename Geometry, typename Sections>
+inline void sectionalize(Geometry const& geometry, Sections& sections)
+{
+ concept::check<const Geometry>();
+
+ // A maximum of 10 segments per section seems to give the fastest results
+ static const std::size_t max_segments_per_section = 10;
+ typedef dispatch::sectionalize
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Sections,
+ Sections::value,
+ max_segments_per_section
+ > sectionalizer_type;
+
+ sections.clear();
+ sectionalizer_type::apply(geometry, sections);
+ int index = 0;
+ for (typename boost::range_iterator<Sections>::type it = boost::begin(sections);
+ it != boost::end(sections);
+ ++it)
+ {
+ it->id = index++;
+ }
+}
+
+
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_SECTIONALIZE_HPP

Added: sandbox/geometry/boost/geometry/algorithms/simplify.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/simplify.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,409 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_SIMPLIFY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_SIMPLIFY_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp>
+#include <boost/geometry/strategies/concepts/simplify_concept.hpp>
+
+#include <boost/geometry/algorithms/clear.hpp>
+
+
+
+/*!
+\defgroup simplify simplify: remove points from a geometry, keeping shape (simplification or generalization)
+\par Source description:
+- Wikipedia: given a 'curve' composed of line segments to find a curve
+ not too dissimilar but that has fewer points
+
+\see http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
+
+\par Performance
+- Performance is measured on simplification of a collection of rings,
+ such that 10% of the points is kept.
+- 2776 counties of US are simplified in 0.7 seconds
+(http://trac.osgeo.org/ggl/wiki/Performance#Simplify1)
+
+\par Geometries
+- \b linestring:
+\image html svg_simplify_road.png
+This US Road originally contained 34 points, the simplified version contains 7 points
+
+- \b polygon:
+\image html svg_simplify_country.png
+This country (Belgium) originally contained 55 points, the simplified version contains 24 points
+
+\note 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.
+Efficient simplification of a ring/polygon is still an "Open Problem"
+(http://maven.smith.edu/~orourke/TOPP/P24.html#Problem.24)
+
+- \b multi_linestring
+- \b multi_polygon
+
+
+*/
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace simplify {
+
+template<typename Range, typename Strategy>
+struct simplify_range_inserter
+{
+ template <typename OutputIterator>
+ static inline void apply(Range const& range, OutputIterator out,
+ double max_distance, Strategy const& strategy)
+ {
+ if (boost::size(range) <= 2 || max_distance < 0)
+ {
+ std::copy(boost::begin(range), boost::end(range), out);
+ }
+ else
+ {
+ strategy.apply(range, out, max_distance);
+ }
+ }
+};
+
+
+template<typename Range, typename Strategy>
+struct simplify_copy
+{
+ static inline void apply(Range const& range, Range& out,
+ double max_distance, Strategy const& strategy)
+ {
+ std::copy
+ (
+ boost::begin(range), boost::end(range), std::back_inserter(out)
+ );
+ }
+};
+
+
+template<typename Range, typename Strategy, std::size_t Minimum>
+struct simplify_range
+{
+ static inline void apply(Range const& range, Range& out,
+ double max_distance, Strategy const& strategy)
+ {
+ // Call do_container for a linestring / ring
+
+ /* For a RING:
+ 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 (boost::size(range) <= int(Minimum) || max_distance < 0.0)
+ {
+ simplify_copy<Range, Strategy>::apply
+ (
+ range, out, max_distance, strategy
+ );
+ }
+ else
+ {
+ simplify_range_inserter<Range, Strategy>::apply
+ (
+ range, std::back_inserter(out), max_distance, strategy
+ );
+ }
+ }
+};
+
+template<typename Polygon, typename Strategy>
+struct simplify_polygon
+{
+ static inline void apply(Polygon const& poly_in, Polygon& poly_out,
+ double max_distance, Strategy const& strategy)
+ {
+ typedef typename ring_type<Polygon>::type ring_type;
+
+ typedef typename boost::range_iterator
+ <typename interior_type<Polygon>::type>::type iterator_type;
+ typedef typename boost::range_const_iterator
+ <typename interior_type<Polygon>::type>::type const_iterator_type;
+
+ // 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_range<ring_type, Strategy, 4>::apply(exterior_ring(poly_in),
+ exterior_ring(poly_out),
+ max_distance, strategy);
+
+ // Note: here a resizeable container is assumed.
+ // Maybe we should make this part of the concept.
+ interior_rings(poly_out).resize(num_interior_rings(poly_in));
+
+ iterator_type it_out = boost::begin(interior_rings(poly_out));
+
+ for (const_iterator_type it_in = boost::begin(interior_rings(poly_in));
+ it_in != boost::end(interior_rings(poly_in));
+ ++it_in, ++it_out)
+ {
+ simplify_range<ring_type, Strategy, 4>::apply(*it_in,
+ *it_out, max_distance, strategy);
+ }
+ }
+};
+
+
+}} // namespace detail::simplify
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, typename Geometry, typename Strategy>
+struct simplify
+{
+};
+
+template <typename Point, typename Strategy>
+struct simplify<point_tag, Point, Strategy>
+{
+ static inline void apply(Point const& point, Point& out,
+ double max_distance, Strategy const& strategy)
+ {
+ copy_coordinates(point, out);
+ }
+};
+
+
+template <typename Linestring, typename Strategy>
+struct simplify<linestring_tag, Linestring, Strategy>
+ : detail::simplify::simplify_range
+ <
+ Linestring,
+ Strategy,
+ 2
+ >
+{};
+
+template <typename Ring, typename Strategy>
+struct simplify<ring_tag, Ring, Strategy>
+ : detail::simplify::simplify_range
+ <
+ Ring,
+ Strategy,
+ 4
+ >
+{};
+
+template <typename Polygon, typename Strategy>
+struct simplify<polygon_tag, Polygon, Strategy>
+ : detail::simplify::simplify_polygon
+ <
+ Polygon,
+ Strategy
+ >
+{};
+
+
+template <typename Tag, typename Geometry, typename Strategy>
+struct simplify_inserter
+{
+};
+
+
+template <typename Linestring, typename Strategy>
+struct simplify_inserter<linestring_tag, Linestring, Strategy>
+ : detail::simplify::simplify_range_inserter
+ <
+ Linestring,
+ Strategy
+ >
+{};
+
+template <typename Ring, typename Strategy>
+struct simplify_inserter<ring_tag, Ring, Strategy>
+ : detail::simplify::simplify_range_inserter
+ <
+ Ring,
+ Strategy
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Simplify a geometry using a specified strategy
+ \ingroup simplify
+ \param geometry input geometry, to be simplified
+ \param out output geometry, simplified version of the input geometry
+ \param max_distance distance (in units of input coordinates) of a vertex
+ to other segments to be removed
+ \param strategy simplify strategy to be used for simplification, might
+ include point-distance strategy
+ */
+template<typename Geometry, typename Strategy>
+inline void simplify(Geometry const& geometry, Geometry& out,
+ double max_distance, Strategy const& strategy)
+{
+ concept::check<Geometry>();
+
+ BOOST_CONCEPT_ASSERT( (geometry::concept::SimplifyStrategy<Strategy>) );
+
+ geometry::clear(out);
+
+ dispatch::simplify
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Strategy
+ >::apply(geometry, out, max_distance, strategy);
+}
+
+
+
+
+/*!
+ \brief Simplify a geometry
+ \ingroup simplify
+ \note This version of simplify simplifies a geometry using the default
+ strategy (Douglas Peucker),
+ \param geometry input geometry, to be simplified
+ \param out output geometry, simplified version of the input geometry
+ \param max_distance distance (in units of input coordinates) of a vertex
+ to other segments to be removed
+ \par Example:
+ The simplify algorithm can be used as following:
+ \dontinclude doxygen_1.cpp
+ \skip example_simplify_linestring1
+ \line {
+ \until }
+ */
+template<typename Geometry>
+inline void simplify(Geometry const& geometry, Geometry& out,
+ double max_distance)
+{
+ concept::check<Geometry>();
+
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename cs_tag<point_type>::type cs_tag;
+ typedef typename strategy_distance_segment
+ <
+ cs_tag,
+ cs_tag,
+ point_type,
+ point_type
+ >::type ds_strategy_type;
+
+ typedef strategy::simplify::douglas_peucker
+ <
+ point_type, ds_strategy_type
+ > strategy_type;
+
+ simplify(geometry, out, max_distance, strategy_type());
+}
+
+
+/*!
+ \brief Simplify a geometry, using an output iterator
+ and a specified strategy
+ \ingroup simplify
+ \param geometry input geometry, to be simplified
+ \param out output iterator, outputs all simplified points
+ \param max_distance distance (in units of input coordinates) of a vertex
+ to other segments to be removed
+ \param strategy simplify strategy to be used for simplification,
+ might include point-distance strategy
+ \par Example:
+ simplify_inserter with strategy is used as following:
+ \dontinclude doxygen_1.cpp
+ \skip example_simplify_linestring2
+ \line {
+ \until }
+ */
+template<typename Geometry, typename OutputIterator, typename Strategy>
+inline void simplify_inserter(Geometry const& geometry, OutputIterator out,
+ double max_distance, Strategy const& strategy)
+{
+ concept::check<const Geometry>();
+ BOOST_CONCEPT_ASSERT( (geometry::concept::SimplifyStrategy<Strategy>) );
+
+ dispatch::simplify_inserter
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Strategy
+ >::apply(geometry, out, max_distance, strategy);
+}
+
+/*!
+ \brief Simplify a geometry, using an output iterator
+ \ingroup simplify
+ \param geometry input geometry, to be simplified
+ \param out output iterator, outputs all simplified points
+ \param max_distance distance (in units of input coordinates) of a vertex
+ to other segments to be removed
+ */
+template<typename Geometry, typename OutputIterator>
+inline void simplify_inserter(Geometry const& geometry, OutputIterator out,
+ double max_distance)
+{
+ typedef typename point_type<Geometry>::type point_type;
+
+ // Concept: output point type = point type of input geometry
+ concept::check<const Geometry>();
+ concept::check<point_type>();
+
+ typedef typename cs_tag<point_type>::type cs_tag;
+ typedef typename strategy_distance_segment
+ <
+ cs_tag,
+ cs_tag,
+ point_type,
+ point_type
+ >::type ds_strategy_type;
+
+ typedef strategy::simplify::douglas_peucker
+ <
+ point_type, ds_strategy_type
+ > strategy_type;
+
+ dispatch::simplify_inserter
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ strategy_type
+ >::apply(geometry, out, max_distance, strategy_type());
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_SIMPLIFY_HPP

Added: sandbox/geometry/boost/geometry/algorithms/transform.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/transform.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,335 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP
+
+#include <cmath>
+#include <iterator>
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/assign.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/strategies/transform.hpp>
+
+
+/*!
+\defgroup transform transform: apply transformations on geometries
+\brief Transforms from one geometry to another geometry, optionally using a strategy
+\details The transform algorithm automatically transforms from one coordinate system to another coordinate system.
+If the coordinate system of both geometries are the same, the geometry is copied. All point(s of the geometry)
+are transformed.
+
+There is a version without a strategy, transforming automatically, and there is a version with a strategy.
+
+This function has a lot of appliances, for example
+- transform from spherical coordinates to cartesian coordinates, and back
+- transform from geographic coordinates to cartesian coordinates (projections) and back
+- transform from degree to radian, and back
+- transform from and to cartesian coordinates (mapping, translations, etc)
+
+The automatic transformations look to the coordinate system family, and dimensions, of the point type and by this
+apply the strategy (internally bounded by traits classes).
+
+\par Examples:
+The example below shows automatic transformations to go from one coordinate system to another one:
+\dontinclude doxygen_2.cpp
+\skip example_for_transform()
+\skipline XYZ
+\until endl;
+
+The next example takes another approach and transforms from Cartesian to Cartesian:
+\skipline XY
+\until endl;
+
+\note Not every possibility is yet worked out, e.g. polar coordinate system is ignored until now
+\note This "transform" is broader then geodetic datum transformations, those are currently not worked out
+
+*/
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace transform {
+
+template <typename Point1, typename Point2, typename Strategy>
+struct transform_point
+{
+ static inline bool apply(Point1 const& p1, Point2& p2,
+ Strategy const& strategy)
+ {
+ return strategy.apply(p1, p2);
+ }
+};
+
+template <typename Box1, typename Box2, typename Strategy>
+struct transform_box
+{
+ static inline bool apply(Box1 const& b1, Box2& b2,
+ Strategy const& strategy)
+ {
+ typedef typename point_type<Box1>::type point_type1;
+ typedef typename point_type<Box2>::type point_type2;
+
+ point_type1 lower_left, upper_right;
+ detail::assign::assign_box_2d_corner<min_corner, min_corner>(
+ b1, lower_left);
+ detail::assign::assign_box_2d_corner<max_corner, max_corner>(
+ b1, upper_right);
+
+ point_type2 p1, p2;
+ if (strategy.apply(lower_left, p1) && strategy.apply(upper_right, p2))
+ {
+ // Create a valid box and therefore swap if necessary
+ typedef typename coordinate_type<point_type2>::type coordinate_type;
+ coordinate_type x1 = geometry::get<0>(p1)
+ , y1 = geometry::get<1>(p1)
+ , x2 = geometry::get<0>(p2)
+ , y2 = geometry::get<1>(p2);
+
+ if (x1 > x2) { std::swap(x1, x2); }
+ if (y1 > y2) { std::swap(y1, y2); }
+
+ set<min_corner, 0>(b2, x1);
+ set<min_corner, 1>(b2, y1);
+ set<max_corner, 0>(b2, x2);
+ set<max_corner, 1>(b2, y2);
+
+ return true;
+ }
+ return false;
+ }
+};
+
+template
+<
+ typename PointOut,
+ typename OutputIterator,
+ typename Range,
+ typename Strategy
+>
+inline bool transform_range_out(Range const& range,
+ OutputIterator out, Strategy const& strategy)
+{
+ PointOut point_out;
+ for(typename boost::range_const_iterator<Range>::type
+ it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ if (! transform_point
+ <
+ typename point_type<Range>::type,
+ PointOut,
+ Strategy
+ >::apply(*it, point_out, strategy))
+ {
+ return false;
+ }
+ *out = point_out;
+ ++out;
+ }
+ return true;
+}
+
+template <typename Polygon1, typename Polygon2, typename Strategy>
+struct transform_polygon
+{
+ static inline bool apply(const Polygon1& poly1, Polygon2& poly2,
+ Strategy const& strategy)
+ {
+ typedef typename interior_type<Polygon1>::type interior1_type;
+ typedef typename interior_type<Polygon2>::type interior2_type;
+ typedef typename ring_type<Polygon1>::type ring1_type;
+ typedef typename ring_type<Polygon2>::type ring2_type;
+ typedef typename point_type<Polygon2>::type point2_type;
+
+ geometry::clear(poly2);
+
+ if (!transform_range_out<point2_type>(exterior_ring(poly1),
+ std::back_inserter(exterior_ring(poly2)), strategy))
+ {
+ return false;
+ }
+
+ interior_rings(poly2).resize(num_interior_rings(poly1));
+
+ typedef typename boost::range_const_iterator
+ <
+ interior1_type
+ >::type iterator1_type;
+ typedef typename boost::range_iterator
+ <
+ interior2_type
+ >::type iterator2_type;
+
+ iterator1_type it1 = boost::begin(interior_rings(poly1));
+ iterator2_type it2 = boost::begin(interior_rings(poly2));
+ for ( ; it1 != boost::end(interior_rings(poly1));
+ ++it1, ++it2)
+ {
+ if (!transform_range_out<point2_type>(*it1,
+ std::back_inserter(*it2), strategy))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+};
+
+
+template <typename Point1, typename Point2>
+struct select_strategy
+{
+ typedef typename strategy_transform
+ <
+ typename cs_tag<Point1>::type,
+ typename cs_tag<Point2>::type,
+ typename coordinate_system<Point1>::type,
+ typename coordinate_system<Point2>::type,
+ dimension<Point1>::type::value,
+ dimension<Point2>::type::value,
+ typename point_type<Point1>::type,
+ typename point_type<Point2>::type
+ >::type type;
+};
+
+template <typename Range1, typename Range2, typename Strategy>
+struct transform_range
+{
+ static inline bool apply(Range1 const& range1,
+ Range2& range2, Strategy const& strategy)
+ {
+ typedef typename point_type<Range2>::type point_type;
+
+ geometry::clear(range2);
+ return transform_range_out<point_type>(range1,
+ std::back_inserter(range2), strategy);
+ }
+};
+
+}} // namespace detail::transform
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag1, typename Tag2,
+ typename Geometry1, typename Geometry2,
+ typename Strategy
+>
+struct transform {};
+
+template <typename Point1, typename Point2, typename Strategy>
+struct transform<point_tag, point_tag, Point1, Point2, Strategy>
+ : detail::transform::transform_point<Point1, Point2, Strategy>
+{
+};
+
+
+template <typename Linestring1, typename Linestring2, typename Strategy>
+struct transform
+ <
+ linestring_tag, linestring_tag,
+ Linestring1, Linestring2, Strategy
+ >
+ : detail::transform::transform_range<Linestring1, Linestring2, Strategy>
+{
+};
+
+template <typename Range1, typename Range2, typename Strategy>
+struct transform<ring_tag, ring_tag, Range1, Range2, Strategy>
+ : detail::transform::transform_range<Range1, Range2, Strategy>
+{
+};
+
+template <typename Polygon1, typename Polygon2, typename Strategy>
+struct transform<polygon_tag, polygon_tag, Polygon1, Polygon2, Strategy>
+ : detail::transform::transform_polygon<Polygon1, Polygon2, Strategy>
+{
+};
+
+template <typename Box1, typename Box2, typename Strategy>
+struct transform<box_tag, box_tag, Box1, Box2, Strategy>
+ : detail::transform::transform_box<Box1, Box2, Strategy>
+{
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Transforms from one geometry to another geometry using a strategy
+ \ingroup transform
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \tparam Strategy strategy
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \param strategy the strategy to be used for transformation
+ */
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2,
+ Strategy const& strategy)
+{
+ concept::check<const Geometry1>();
+ concept::check<Geometry2>();
+
+ typedef dispatch::transform
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ Geometry1,
+ Geometry2,
+ Strategy
+ > transform_type;
+
+ return transform_type::apply(geometry1, geometry2, strategy);
+}
+
+/*!
+ \brief Transforms from one geometry to another geometry using a strategy
+ \ingroup transform
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \return true if the transformation could be done
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2)
+{
+ concept::check<const Geometry1>();
+ concept::check<Geometry2>();
+
+ typename detail::transform::select_strategy<Geometry1, Geometry2>::type strategy;
+ return transform(geometry1, geometry2, strategy);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP

Added: sandbox/geometry/boost/geometry/algorithms/union.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/union.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,197 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_UNION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_UNION_HPP
+
+
+#include <boost/mpl/if.hpp>
+
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/reverse_dispatch.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/overlay/assemble.hpp>
+#include <boost/geometry/algorithms/within.hpp>
+
+
+
+/*!
+\defgroup union union: calculate new geometry containing geometries A or B
+\details The union of two geometries A and B is the geometry containing
+ all points belong to either of A or B, but no other elements.
+\par Source description:
+- OGC: Returns a geometric object that represents the Point set union of
+ this geometric object with another Geometry.
+\see http://en.wikipedia.org/wiki/Union_(set_theory)
+\note A union of two rings can result in a polygon having a hole
+
+\par Geometries:
+- \b polygon + \b box -> \b polygon(s)
+\image html svg_union_polygon_box.png
+- \b ring + \b box -> \b polygon(s)
+\image html svg_union_ring_box.png
+- \b ring + \b ring -> \b polygon(s)
+\image html svg_union_ring_ring.png
+- \b polygon + \b ring -> \b polygon(s)
+\image html svg_union_polygon_ring.png
+- combinations above -> \b ring(s).
+ <i>If the output is an ouput iterator of rings, holes are omitted</i>
+
+*/
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag1, typename Tag2, typename Tag3,
+ typename G1, typename G2,
+ typename OutputIterator,
+ typename GeometryOut,
+ typename Strategy
+>
+struct union_inserter
+ : detail::overlay::overlay_and_assemble
+ <G1, G2, OutputIterator, GeometryOut, 1, Strategy>
+{
+};
+
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2, typename GeometryTag3,
+ typename Geometry1, typename Geometry2,
+ typename OutputIterator, typename GeometryOut,
+ typename Strategy
+>
+struct union_inserter_reversed
+{
+ static inline OutputIterator apply(Geometry1 const& g1,
+ Geometry2 const& g2, OutputIterator out,
+ Strategy const& strategy)
+ {
+ return union_inserter
+ <
+ GeometryTag2, GeometryTag1, GeometryTag3,
+ Geometry2, Geometry1,
+ OutputIterator, GeometryOut,
+ Strategy
+ >::apply(g2, g1, out, strategy);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Combines two geometries which each other
+ \ingroup union
+ \tparam GeometryOut output geometry type, must be specified
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \tparam OutputIterator output iterator
+ \tparam Strategy compound strategy for intersection
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \param out the output iterator, outputting polygons
+ \param strategy the strategy
+ \return the output iterator
+*/
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename OutputIterator,
+ typename Strategy
+>
+inline OutputIterator union_inserter(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ OutputIterator out,
+ Strategy const& strategy)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ return boost::mpl::if_c
+ <
+ reverse_dispatch<Geometry1, Geometry2>::type::value,
+ dispatch::union_inserter_reversed
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ typename tag<GeometryOut>::type,
+ Geometry1,
+ Geometry2,
+ OutputIterator, GeometryOut,
+ Strategy
+ >,
+ dispatch::union_inserter
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ typename tag<GeometryOut>::type,
+ Geometry1,
+ Geometry2,
+ OutputIterator, GeometryOut,
+ Strategy
+ >
+ >::type::apply(geometry1, geometry2, out, strategy);
+}
+
+/*!
+ \brief Combines two geometries which each other
+ \ingroup union
+ \tparam GeometryOut output geometry type, must be specified
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \tparam OutputIterator output iterator
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \param out the output iterator, outputting polygons
+ \return the output iterator
+*/
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename OutputIterator
+>
+inline OutputIterator union_inserter(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ OutputIterator out)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ typedef typename geometry::point_type<GeometryOut>::type point_type;
+ typedef detail::intersection::intersection_point<point_type> ip_type;
+
+ typedef strategy_intersection
+ <
+ typename cs_tag<point_type>::type,
+ Geometry1,
+ Geometry2,
+ ip_type
+ > strategy;
+
+ return union_inserter<GeometryOut>(geometry1, geometry2, out, strategy());
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif //GGL_ALGORITHMS_UNION_HPP

Added: sandbox/geometry/boost/geometry/algorithms/unique.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/unique.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,155 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_UNIQUE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_UNIQUE_HPP
+
+#include <algorithm>
+
+#include <boost/range.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/policies/compare.hpp>
+
+
+/*!
+\defgroup unique unique: make a geometry unique w.r.t. points,
+ so no duplicate consecutive points
+
+*/
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace unique
+{
+
+
+template <typename Range, typename ComparePolicy>
+struct range_unique
+{
+ static inline void apply(Range& range, ComparePolicy const& policy)
+ {
+ typename boost::range_iterator<Range>::type it
+ = std::unique
+ (
+ boost::begin(range),
+ boost::end(range),
+ policy
+ );
+
+ // Note: this assumes "resize".
+ // TODO: look at RangeEx solution
+ range.resize(it - boost::begin(range));
+ }
+};
+
+
+template <typename Polygon, typename ComparePolicy>
+struct polygon_unique
+{
+ static inline void apply(Polygon& polygon, ComparePolicy const& policy)
+ {
+ typedef typename geometry::ring_type<Polygon>::type ring_type;
+
+ typedef range_unique<ring_type, ComparePolicy> per_range;
+ per_range::apply(exterior_ring(polygon), policy);
+
+ for (typename boost::range_iterator
+ <
+ typename interior_type<Polygon>::type
+ >::type it = boost::begin(interior_rings(polygon));
+ it != boost::end(interior_rings(polygon));
+ ++it)
+ {
+ per_range::apply(*it, policy);
+ }
+ }
+};
+
+
+
+}} // namespace detail::unique
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Tag,
+ typename Geometry,
+ typename ComparePolicy
+>
+struct unique
+{
+ static inline void apply(Geometry&, ComparePolicy const& )
+ {}
+};
+
+
+template <typename Ring, typename ComparePolicy>
+struct unique<ring_tag, Ring, ComparePolicy>
+ : detail::unique::range_unique<Ring, ComparePolicy>
+{};
+
+
+template <typename LineString, typename ComparePolicy>
+struct unique<linestring_tag, LineString, ComparePolicy>
+ : detail::unique::range_unique<LineString, ComparePolicy>
+{};
+
+
+template <typename Polygon, typename ComparePolicy>
+struct unique<polygon_tag, Polygon, ComparePolicy>
+ : detail::unique::polygon_unique<Polygon, ComparePolicy>
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+/*!
+ \ingroup unique
+ \tparam Geometry geometry type
+ \param geometry the geometry to make unique
+*/
+template <typename Geometry>
+inline void unique(Geometry& geometry)
+{
+ concept::check<Geometry>();
+
+ // Default strategy is the default point-comparison policy
+ typedef geometry::equal_to
+ <
+ typename geometry::point_type<Geometry>::type
+ > policy;
+
+
+ dispatch::unique
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ policy
+ >::apply(geometry, policy());
+}
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_UNIQUE_HPP

Added: sandbox/geometry/boost/geometry/algorithms/within.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/algorithms/within.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,373 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP
+
+/*!
+\defgroup within within: detect if a geometry is inside another geometry, a.o. point-in-polygon
+
+\par Source descriptions:
+- OGC: Returns 1 (TRUE) if this geometric object is "spatially within"
+ another Geometry.
+
+\par Performance
+- 2776 within determinations using bounding box and polygon are done
+ in 0.05 seconds (http://trac.osgeo.org/ggl/wiki/Performance#Within1)
+- note that using another strategy the performance can be increased:
+ - winding : 0.093 s
+ - franklin : 0.062 s
+ - Crossings-multiply : 0.047 s
+- but note also that the last two do not detect point-on-border cases
+
+\par Geometries:
+- \b point + \b polygon: The well-known point-in-polygon, returning true if
+ a point falls within a polygon (and not
+within one of its holes) \image html within_polygon.png
+- \b point + \b ring: returns true if point is completely within
+ a ring \image html within_ring.png
+- \b point + \b box
+- \b box + \b box
+
+\par Example:
+The within algorithm is used as following:
+\dontinclude doxygen_1.cpp
+\skip example_within
+\line {
+\until }
+
+*/
+
+
+#include <cstddef>
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/distance.hpp>
+#include <boost/geometry/algorithms/make.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/cs.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/strategies/point_in_poly.hpp>
+#include <boost/geometry/strategies/concepts/within_concept.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace within {
+
+
+/*!
+ \brief Implementation for boxes
+ \ingroup boolean_relations
+ \note Should have strategy for e.g. Wrangel
+ */
+template
+<
+ typename Point,
+ typename Box,
+ typename Strategy,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct point_in_box
+{
+ static inline bool apply(Point const& p, Box const& b, Strategy const& s)
+ {
+ assert_dimension_equal<Point, Box>();
+
+ if (get<Dimension>(p) <= get<min_corner, Dimension>(b)
+ || get<Dimension>(p) >= get<max_corner, Dimension>(b))
+ {
+ return false;
+ }
+
+ return point_in_box
+ <
+ Point,
+ Box,
+ Strategy,
+ Dimension + 1,
+ DimensionCount
+ >::apply(p, b, s);
+ }
+};
+
+template
+<
+ typename Point,
+ typename Box,
+ typename Strategy,
+ std::size_t DimensionCount
+>
+struct point_in_box<Point, Box, Strategy, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Point const& , Box const& , Strategy const& )
+ {
+ return true;
+ }
+};
+
+
+template
+<
+ typename Box1,
+ typename Box2,
+ typename Strategy,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct box_in_box
+{
+ static inline bool apply(Box1 const& b1, Box2 const& b2, Strategy const& s)
+ {
+ assert_dimension_equal<Box1, Box2>();
+
+ if (get<min_corner, Dimension>(b1) <= get<min_corner, Dimension>(b2)
+ || get<max_corner, Dimension>(b1) >= get<max_corner, Dimension>(b2))
+ {
+ return false;
+ }
+
+ return box_in_box
+ <
+ Box1,
+ Box2,
+ Strategy,
+ Dimension + 1,
+ DimensionCount
+ >::apply(b1, b2, s);
+ }
+};
+
+template
+<
+ typename Box1,
+ typename Box2,
+ typename Strategy,
+ std::size_t DimensionCount
+>
+struct box_in_box<Box1, Box2, Strategy, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Box1 const& , Box2 const& , Strategy const&)
+ {
+ return true;
+ }
+};
+
+
+template<typename Point, typename Ring, typename Strategy>
+struct point_in_ring
+{
+ BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategy<Strategy>) );
+
+ static inline bool apply(Point const& point, Ring const& ring,
+ Strategy const& strategy)
+ {
+ if (boost::size(ring) < 4)
+ {
+ return false;
+ }
+
+ typedef typename boost::range_const_iterator<Ring>::type iterator_type;
+
+ typename Strategy::state_type state;
+
+ iterator_type it = boost::begin(ring);
+ for (iterator_type previous = it++;
+ it != boost::end(ring);
+ previous = it++)
+ {
+ if (! strategy.apply(point, *previous, *it, state))
+ {
+ return false;
+ }
+ }
+ return strategy.result(state);
+ }
+};
+
+// Polygon: in exterior ring, and if so, not within interior ring(s)
+template<typename Point, typename Polygon, typename Strategy>
+struct point_in_polygon
+{
+ BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategy<Strategy>) );
+
+ static inline bool apply(Point const& point, Polygon const& poly,
+ Strategy const& strategy)
+ {
+
+ typedef point_in_ring
+ <
+ Point,
+ typename ring_type<Polygon>::type,
+ Strategy
+ > per_ring;
+
+ if (per_ring::apply(point, exterior_ring(poly), strategy))
+ {
+
+ for (typename boost::range_const_iterator
+ <
+ typename interior_type<Polygon>::type
+ >::type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly));
+ ++it)
+ {
+ if (per_ring::apply(point, *it, strategy))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+};
+
+}} // namespace detail::within
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag1,
+ typename Tag2,
+ typename Geometry1,
+ typename Geometry2,
+ typename Strategy
+>
+struct within
+{};
+
+
+template <typename Point, typename Box, typename Strategy>
+struct within<point_tag, box_tag, Point, Box, Strategy>
+ : detail::within::point_in_box
+ <
+ Point,
+ Box,
+ Strategy,
+ 0,
+ dimension<Point>::type::value
+ >
+{};
+
+template <typename Box1, typename Box2, typename Strategy>
+struct within<box_tag, box_tag, Box1, Box2, Strategy>
+ : detail::within::box_in_box
+ <
+ Box1,
+ Box2,
+ Strategy,
+ 0,
+ dimension<Box1>::type::value
+ >
+{};
+
+
+
+template <typename Point, typename Ring, typename Strategy>
+struct within<point_tag, ring_tag, Point, Ring, Strategy>
+ : detail::within::point_in_ring
+ <Point, Ring, Strategy>
+{};
+
+template <typename Point, typename Polygon, typename Strategy>
+struct within<point_tag, polygon_tag, Point, Polygon, Strategy>
+ : detail::within::point_in_polygon
+ <Point, Polygon, Strategy>
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Within, examine if a geometry is within another geometry
+ \ingroup within
+ \param geometry1 geometry which might be within the second geometry
+ \param geometry2 geometry which might contain the first geometry
+ \return true if geometry1 is completely contained within geometry2,
+ else false
+ \note The default strategy is used for within detection
+
+ */
+template<typename Geometry1, typename Geometry2>
+inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ typedef typename point_type<Geometry1>::type point_type1;
+ typedef typename point_type<Geometry2>::type point_type2;
+
+ typedef typename strategy_within
+ <
+ typename cs_tag<point_type1>::type,
+ typename cs_tag<point_type2>::type,
+ point_type1,
+ point_type2
+ >::type strategy_type;
+
+ return dispatch::within
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ Geometry1,
+ Geometry2,
+ strategy_type
+ >::apply(geometry1, geometry2, strategy_type());
+}
+
+/*!
+ \brief Within, examine if a geometry is within another geometry,
+ using a specified strategy
+ \ingroup within
+ \param geometry1 geometry which might be within the second geometry
+ \param geometry2 geometry which might contain the first geometry
+ \param strategy strategy to be used
+ \return true if geometry1 is completely contained within geometry2,
+ else false
+ */
+template<typename Geometry1, typename Geometry2, typename Strategy>
+inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ // Always assume a point-in-polygon strategy here.
+ // Because for point-in-box, it makes no sense to specify one.
+ BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategy<Strategy>) );
+
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ return dispatch::within
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ Geometry1,
+ Geometry2,
+ Strategy
+ >::apply(geometry1, geometry2, strategy);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP

Added: sandbox/geometry/boost/geometry/arithmetic/arithmetic.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/arithmetic/arithmetic.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,209 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ARITHMETIC_ARITHMETIC_HPP
+#define BOOST_GEOMETRY_ARITHMETIC_ARITHMETIC_HPP
+
+#include <functional>
+
+#include <boost/call_traits.hpp>
+#include <boost/concept/requires.hpp>
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/util/for_each_coordinate.hpp>
+
+/*!
+\defgroup arithmetic arithmetic: arithmetic operations on points
+*/
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename P>
+struct param
+{
+ typedef typename boost::call_traits
+ <
+ typename coordinate_type<P>::type
+ >::param_type type;
+};
+
+template <typename C, template <typename> class Function>
+struct value_operation
+{
+ C m_value;
+
+ inline value_operation(C const &value)
+ : m_value(value)
+ {}
+
+ template <typename P, int I>
+ inline void apply(P& point) const
+ {
+ set<I>(point, Function<C>()(get<I>(point), m_value));
+ }
+};
+
+template <typename PointSrc, template <typename> class Function>
+struct point_operation
+{
+ typedef typename coordinate_type<PointSrc>::type coordinate_type;
+ PointSrc const& m_source_point;
+
+ inline point_operation(PointSrc const& point)
+ : m_source_point(point)
+ {}
+
+ template <typename PointDst, int I>
+ inline void apply(PointDst& dest_point) const
+ {
+ set<I>(dest_point,
+ Function<coordinate_type>()(get<I>(dest_point), get<I>(m_source_point)));
+ }
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+/*!
+ \brief Adds a value to each coordinate of a point
+ \ingroup arithmetic
+ \details
+ \param p point
+ \param value value to add
+ */
+template <typename Point>
+inline void add_value(Point& p, typename detail::param<Point>::type value)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+ for_each_coordinate(p, detail::value_operation<typename coordinate_type<Point>::type, std::plus>(value));
+}
+
+/*!
+ \brief Adds a point to another
+ \ingroup arithmetic
+ \details The coordinates of the second point will be added to those of the first point.
+ The second point is not modified.
+ \param p1 first point
+ \param p2 second point
+ */
+template <typename Point1, typename Point2>
+inline void add_point(Point1& p1, Point2 const& p2)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point2>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
+
+ for_each_coordinate(p1, detail::point_operation<Point2, std::plus>(p2));
+}
+
+/*!
+ \brief Subtracts a value to each coordinate of a point
+ \ingroup arithmetic
+ \details
+ \param p point
+ \param value value to subtract
+ */
+template <typename Point>
+inline void subtract_value(Point& p, typename detail::param<Point>::type value)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+ for_each_coordinate(p, detail::value_operation<typename coordinate_type<Point>::type, std::minus>(value));
+}
+
+/*!
+ \brief Subtracts a point to another
+ \ingroup arithmetic
+ \details The coordinates of the second point will be subtracted to those of the first point.
+ The second point is not modified.
+ \param p1 first point
+ \param p2 second point
+ */
+template <typename Point1, typename Point2>
+inline void subtract_point(Point1& p1, Point2 const& p2)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point2>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
+
+ for_each_coordinate(p1, detail::point_operation<Point2, std::minus>(p2));
+}
+
+/*!
+ \brief Multiplies each coordinate of a point by a value
+ \ingroup arithmetic
+ \details
+ \param p point
+ \param value value to multiply by
+ */
+template <typename Point>
+inline void multiply_value(Point& p, typename detail::param<Point>::type value)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+ for_each_coordinate(p, detail::value_operation<typename coordinate_type<Point>::type, std::multiplies>(value));
+}
+
+/*!
+ \brief Multiplies a point by another
+ \ingroup arithmetic
+ \details The coordinates of the second point will be multiplied by those of the first point.
+ The second point is not modified.
+ \param p1 first point
+ \param p2 second point
+ \note This is *not* a dot, cross or wedge product. It is a mere field-by-field multiplication.
+ */
+template <typename Point1, typename Point2>
+inline void multiply_point(Point1& p1, Point2 const& p2)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point2>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
+
+ for_each_coordinate(p1, detail::point_operation<Point2, std::multiplies>(p2));
+}
+
+/*!
+ \brief Divides each coordinate of a point by a value
+ \ingroup arithmetic
+ \details
+ \param p point
+ \param value value to divide by
+ */
+template <typename Point>
+inline void divide_value(Point& p, typename detail::param<Point>::type value)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+ for_each_coordinate(p, detail::value_operation<typename coordinate_type<Point>::type, std::divides>(value));
+}
+
+/*!
+ \brief Divides a point by another
+ \ingroup arithmetic
+ \details The coordinates of the second point will be divided by those of the first point.
+ The second point is not modified.
+ \param p1 first point
+ \param p2 second point
+ */
+template <typename Point1, typename Point2>
+inline void divide_point(Point1& p1, Point2 const& p2)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point2>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
+
+ for_each_coordinate(p1, detail::point_operation<Point2, std::divides>(p2));
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ARITHMETIC_ARITHMETIC_HPP

Added: sandbox/geometry/boost/geometry/arithmetic/cross_product.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/arithmetic/cross_product.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,105 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright (c) 2009 Mateusz Loskot, (mateusz_at_[hidden])
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ARITHMETIC_CROSS_PRODUCT_HPP
+#define BOOST_GEOMETRY_ARITHMETIC_CROSS_PRODUCT_HPP
+
+#include <boost/concept/requires.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename P1, typename P2, std::size_t Dimension>
+struct cross_product
+{
+ // We define cross product only for 2d (see Wolfram) and 3d.
+ // In Math, it is also well-defined for 7-dimension.
+ // Generalisation of cross product to n-dimension is defined as
+ // wedge product but it is not direct analogue to binary cross product.
+};
+
+template <typename P1, typename P2>
+struct cross_product<P1, P2, 2>
+{
+ typedef P1 return_type;
+
+ static inline return_type apply(P1 const& p1, P2 const& p2)
+ {
+ assert_dimension<P1, 2>();
+ assert_dimension<P2, 2>();
+
+ // For 2-dimensions, analog of the cross product U(x,y) and V(x,y) is
+ // Ux * Vy - Uy * Vx
+ // which is returned as 0-component (or X) of 2d vector, 1-component is undefined.
+ return_type v;
+ set<0>(v, get<0>(p1) * get<1>(p2) - get<1>(p1) * get<0>(p2));
+ return v;
+ }
+};
+
+template <typename P1, typename P2>
+struct cross_product<P1, P2, 3>
+{
+ typedef P1 return_type;
+
+ static inline return_type apply(P1 const& p1, P2 const& p2)
+ {
+ assert_dimension<P1, 3>();
+ assert_dimension<P2, 3>();
+
+ return_type v;
+ set<0>(v, get<1>(p1) * get<2>(p2) - get<2>(p1) * get<1>(p2));
+ set<1>(v, get<2>(p1) * get<0>(p2) - get<0>(p1) * get<2>(p2));
+ set<2>(v, get<0>(p1) * get<1>(p2) - get<1>(p1) * get<0>(p2));
+ return v;
+ }
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+// TODO: This is a simple draft. If relevant, it can be extended to:
+// - accept vectors of different coordinate_type, but common coordinate_system
+// - if vectors are of mixed 2d and 3d, lower dimension is used
+// - define result_type that will generate type of vector based on:
+// -- select_coordinate_type
+// -- selection of lower dimension
+
+/*!
+ \brief Computes the cross product of two vector.
+ \details Both vectors shall be of the same type.
+ This type also determines type of result vector.
+ \ingroup arithmetic
+ \param p1 first vector
+ \param p2 second vector
+ \return the cross product vector
+ */
+template <typename P1, typename P2>
+inline P1 cross_product(P1 const& p1, P2 const& p2)
+{
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<P1>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<P2>) );
+
+ return detail::cross_product
+ <
+ P1, P2,
+ dimension<P1>::type::value
+ >::apply(p1, p2);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ARITHMETIC_CROSS_PRODUCT_HPP

Added: sandbox/geometry/boost/geometry/arithmetic/dot_product.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/arithmetic/dot_product.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,74 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ARITHMETIC_DOT_PRODUCT_HPP
+#define BOOST_GEOMETRY_ARITHMETIC_DOT_PRODUCT_HPP
+
+#include <boost/concept/requires.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename P1, typename P2, std::size_t Dimension, std::size_t DimensionCount>
+struct dot_product_maker
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+
+ static inline coordinate_type apply(P1 const& p1, P2 const& p2)
+ {
+ return get<Dimension>(p1) * get<Dimension>(p2)
+ + dot_product_maker<P1, P2, Dimension+1, DimensionCount>::apply(p1, p2);
+ }
+};
+
+template <typename P1, typename P2, std::size_t DimensionCount>
+struct dot_product_maker<P1, P2, DimensionCount, DimensionCount>
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+
+ static inline coordinate_type apply(P1 const& p1, P2 const& p2)
+ {
+ return get<DimensionCount>(p1) * get<DimensionCount>(p2);
+ }
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief Computes the dot product (or scalar product) of 2 vectors (points).
+ \ingroup arithmetic
+ \param p1 first point
+ \param p2 second point
+ \return the dot product
+ */
+template <typename P1, typename P2>
+inline typename select_coordinate_type<P1, P2>::type dot_product(
+ P1 const& p1, P2 const& p2)
+{
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<P1>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<P2>) );
+
+ return detail::dot_product_maker
+ <
+ P1, P2,
+ 0, dimension<P1>::type::value - 1
+ >::apply(p1, p2);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ARITHMETIC_DOT_PRODUCT_HPP

Added: sandbox/geometry/boost/geometry/core/access.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/access.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,381 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_ACCESS_HPP
+#define BOOST_GEOMETRY_CORE_ACCESS_HPP
+
+
+
+/*!
+\defgroup access access: get/set coordinate values, make objects, clear geometries, append point(s)
+\details There are many ways to edit geometries. It is possible to:
+- use the geometries themselves, so access point.x(). This is not done inside the library because it is agnostic
+ to geometry type. However, library users can use this as it is intuitive.
+- use the standard library, so use .push_back(point) or use inserters. This is also avoided inside the library.
+However, library users can use it if they are used to the standard library
+- use the functionality provided in this geometry library. These are the functions in this module.
+
+The library provides the following functions to edit geometries:
+- set to set one coordinate value
+- assign to set two or more coordinate values
+- make to construct and return geometries with specified coordinates.
+- append to append one or more points to a geometry
+- clear to remove all points from a geometry
+
+For getting coordinates it is similar:
+- get to get a coordinate value
+- or use the standard library
+- or use the geometries themselves
+
+*/
+
+#include <cstddef>
+
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/concept_check.hpp>
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+const int min_corner = 0;
+const int max_corner = 1;
+
+namespace traits
+{
+
+/*!
+\brief Traits class which gives access (get,set) to points
+\ingroup traits
+\par Geometries:
+ - point
+\par Specializations should provide, per Dimension
+ - static inline T get(const G&)
+ - static inline void set(G&, T const&)
+\tparam Geometry geometry-type
+\tparam Dimension dimension to access
+*/
+template <typename Geometry, std::size_t Dimension>
+struct access {};
+
+
+/*!
+\brief Traits class defining "get" and "set" to get
+ and set point coordinate values
+\tparam Geometry geometry (box, segment)
+\tparam Index index (min_corner/max_corner for box, 0/1 for segment)
+\tparam Dimension dimension
+\par Geometries:
+ - box
+ - segment
+\par Specializations should provide:
+ - static inline T get(const G&)
+ - static inline void set(G&, T const&)
+\ingroup traits
+*/
+template <typename Geometry, std::size_t Index, std::size_t Dimension>
+struct indexed_access {};
+
+
+/*!
+\brief Traits class, optional, indicating that the std-library should be used
+\details The default geometry (linestring, ring, multi*) follow std:: for
+ its modifying operations (push_back, clear, size, resize, reserve, etc)
+ If they NOT follow the std:: library they should specialize this traits
+ class
+\ingroup traits
+\par Geometries:
+ - linestring
+ - linear_ring
+\par Specializations should provide:
+ - value (defaults to true)
+ */
+template <typename Geometry>
+struct use_std
+{
+ static const bool value = true;
+};
+
+
+/*!
+\brief Traits class, optional, might be implemented to clear a geometry
+\details If a geometry type should not use the std ".clear()"
+ then it can specialize the "use_std" traits class to false,
+ it should then implement (a.o.) clear
+\ingroup traits
+\par Geometries:
+ - linestring
+ - linear_ring
+\par Specializations should provide:
+ - apply
+ */
+template <typename Geometry>
+struct clear
+{};
+
+
+/*!
+\brief Traits class, optional, might be implemented to append a point
+\details If a geometry type should not use the std "push_back"
+ then it can specialize the "use_std" traits class to false,
+ it should then implement (a.o.) append_point
+\ingroup traits
+\par Geometries:
+ - linestring
+ - linear_ring
+\par Specializations should provide:
+ - apply
+ */
+template <typename Geometry, typename Point>
+struct append_point
+{};
+
+
+} // namespace traits
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template
+<
+ typename Tag,
+ typename Geometry,
+ typename
+ CoordinateType, std::size_t Dimension
+>
+struct access
+{
+ //static inline T get(const G& ) {}
+ //static inline void set(G& g, T const& value) {}
+};
+
+template
+<
+ typename Tag,
+ typename Geometry,
+ typename CoordinateType,
+ std::size_t Index,
+ std::size_t Dimension
+>
+struct indexed_access
+{
+ //static inline T get(const G& ) {}
+ //static inline void set(G& g, T const& value) {}
+};
+
+template <typename Point, typename CoordinateType, std::size_t Dimension>
+struct access<point_tag, Point, CoordinateType, Dimension>
+{
+ static inline CoordinateType get(Point const& point)
+ {
+ return traits::access<Point, Dimension>::get(point);
+ }
+ static inline void set(Point& p, CoordinateType const& value)
+ {
+ traits::access<Point, Dimension>::set(p, value);
+ }
+};
+
+template
+<
+ typename Box,
+ typename CoordinateType,
+ std::size_t Index,
+ std::size_t Dimension
+>
+struct indexed_access<box_tag, Box, CoordinateType, Index, Dimension>
+{
+ static inline CoordinateType get(Box const& box)
+ {
+ return traits::indexed_access<Box, Index, Dimension>::get(box);
+ }
+ static inline void set(Box& b, CoordinateType const& value)
+ {
+ traits::indexed_access<Box, Index, Dimension>::set(b, value);
+ }
+};
+
+template
+<
+ typename Segment,
+ typename CoordinateType,
+ std::size_t Index,
+ std::size_t Dimension
+>
+struct indexed_access<segment_tag, Segment, CoordinateType, Index, Dimension>
+{
+ static inline CoordinateType get(Segment const& segment)
+ {
+ return traits::indexed_access<Segment, Index, Dimension>::get(segment);
+ }
+ static inline void set(Segment& segment, CoordinateType const& value)
+ {
+ traits::indexed_access<Segment, Index, Dimension>::set(segment, value);
+ }
+};
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+// Two dummy tags to distinguish get/set variants below.
+// They don't have to be specified by the user. The functions are distinguished
+// by template signature also, but for e.g. GCC this is not enough. So give them
+// a different signature.
+struct signature_getset_dimension {};
+struct signature_getset_index_dimension {};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+// Note the comments below tell Doxygen to create one function with doc for both
+
+/*!
+\brief
+- get coordinate value of a Point ( / Sphere)
+\ingroup access
+\return coordinate value
+\tparam Index index
+- for Point: don't specify
+- for Box: min_corner or max_corner
+- for Segment: 0 / 1
+\tparam Dimension dimension
+\tparam Geometry geometry
+\param geometry geometry to get coordinate value from
+*/
+template <std::size_t Dimension, typename Geometry>
+inline typename coordinate_type<Geometry>::type get(Geometry const& geometry
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ , detail::signature_getset_dimension* dummy = 0
+#endif
+ )
+{
+ boost::ignore_unused_variable_warning(dummy);
+
+ typedef typename boost::remove_const<Geometry>::type ncg_type;
+
+ typedef core_dispatch::access
+ <
+ typename tag<Geometry>::type,
+ ncg_type,
+ typename coordinate_type<ncg_type>::type,
+ Dimension
+ > coord_access_type;
+
+ return coord_access_type::get(geometry);
+}
+
+
+/*!
+\brief
+- set coordinate value of a Point ( / Sphere)
+\ingroup access
+\tparam Index index
+- for Point: don't specify
+- for Box: min_corner or max_corner
+- for Segment: 0 / 1
+\tparam Dimension dimension
+\tparam Geometry geometry
+\param geometry geometry to assign coordinate to
+\param value coordinate value to assign
+*/
+template <std::size_t Dimension, typename Geometry>
+inline void set(Geometry& geometry
+ , typename coordinate_type<Geometry>::type const& value
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ , detail::signature_getset_dimension* dummy = 0
+#endif
+ )
+{
+ boost::ignore_unused_variable_warning(dummy);
+
+ typedef typename boost::remove_const<Geometry>::type ncg_type;
+
+ typedef core_dispatch::access
+ <
+ typename tag<Geometry>::type,
+ ncg_type,
+ typename coordinate_type<ncg_type>::type,
+ Dimension
+ > coord_access_type;
+
+ coord_access_type::set(geometry, value);
+}
+
+// Note: doxygen needs a construct to distinguish get/set (like the gcc compiler)
+
+/*!
+\brief
+- get coordinate value of a Box / Segment
+\ingroup access
+*/
+template <std::size_t Index, std::size_t Dimension, typename Geometry>
+inline typename coordinate_type<Geometry>::type get(Geometry const& geometry
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ , detail::signature_getset_index_dimension* dummy = 0
+#endif
+ )
+{
+ boost::ignore_unused_variable_warning(dummy);
+
+ typedef typename boost::remove_const<Geometry>::type ncg_type;
+
+ typedef core_dispatch::indexed_access
+ <
+ typename tag<Geometry>::type,
+ ncg_type,
+ typename coordinate_type<ncg_type>::type,
+ Index,
+ Dimension
+ > coord_access_type;
+
+ return coord_access_type::get(geometry);
+}
+
+/*!
+\brief
+- set coordinate value of a Box / Segment
+\ingroup access
+*/
+template <std::size_t Index, std::size_t Dimension, typename Geometry>
+inline void set(Geometry& geometry
+ , typename coordinate_type<Geometry>::type const& value
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ , detail::signature_getset_index_dimension* dummy = 0
+#endif
+ )
+{
+ boost::ignore_unused_variable_warning(dummy);
+
+ typedef typename boost::remove_const<Geometry>::type ncg_type;
+
+ typedef core_dispatch::indexed_access
+ <
+ typename tag<Geometry>::type, ncg_type,
+ typename coordinate_type<ncg_type>::type,
+ Index,
+ Dimension
+ > coord_access_type;
+
+ coord_access_type::set(geometry, value);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_ACCESS_HPP

Added: sandbox/geometry/boost/geometry/core/coordinate_dimension.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/coordinate_dimension.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,111 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_COORDINATE_DIMENSION_HPP
+#define BOOST_GEOMETRY_CORE_COORDINATE_DIMENSION_HPP
+
+#include <cstddef>
+
+#include <boost/mpl/equal_to.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+/*!
+ \brief Traits class indicating the number of dimensions of a point
+ \par Geometries:
+ - point
+ \par Specializations should provide:
+ - value (should be derived from boost::mpl::int_<D>
+ \ingroup traits
+*/
+template <typename P>
+struct dimension {};
+
+} // namespace traits
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+// Base class derive from its own specialization of point-tag
+template <typename T, typename G>
+struct dimension : dimension<point_tag, typename point_type<T, G>::type> {};
+
+template <typename P>
+struct dimension<point_tag, P> : traits::dimension<P> {};
+
+} // namespace core_dispatch
+#endif
+
+/*!
+ \brief Meta-function which defines coordinate dimensions, i.e. the number of axes of any geometry
+ \ingroup core
+*/
+template <typename G>
+struct dimension
+ : core_dispatch::dimension
+ <
+ typename tag<G>::type,
+ typename boost::remove_const<G>::type
+ >
+{};
+
+/*!
+ \brief assert_dimension, enables compile-time checking if coordinate dimensions are as expected
+ \ingroup utility
+*/
+template <typename G, int D>
+inline void assert_dimension()
+{
+ BOOST_STATIC_ASSERT((
+ boost::mpl::equal_to
+ <
+ geometry::dimension<G>,
+ boost::mpl::int_<D>
+ >::type::value
+ ));
+}
+
+/*!
+ \brief assert_dimension, enables compile-time checking if coordinate dimensions are as expected
+ \ingroup utility
+*/
+template <typename G, int D>
+inline void assert_dimension_less_equal()
+{
+ BOOST_STATIC_ASSERT(( dimension<G>::type::value <= D ));
+}
+
+template <typename G, int D>
+inline void assert_dimension_greater_equal()
+{
+ BOOST_STATIC_ASSERT(( dimension<G>::type::value >= D ));
+}
+
+/*!
+ \brief assert_dimension_equal, enables compile-time checking if coordinate dimensions of two geometries are equal
+ \ingroup utility
+*/
+template <typename G1, typename G2>
+inline void assert_dimension_equal()
+{
+ BOOST_STATIC_ASSERT(( dimension<G1>::type::value == dimension<G2>::type::value ));
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_COORDINATE_DIMENSION_HPP

Added: sandbox/geometry/boost/geometry/core/coordinate_system.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/coordinate_system.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,81 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_COORDINATE_SYSTEM_HPP
+#define BOOST_GEOMETRY_CORE_COORDINATE_SYSTEM_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+ /*!
+ \brief Traits class defining the coordinate system of a point, important for strategy selection
+ \ingroup traits
+ \par Geometries:
+ - point
+ \par Specializations should provide:
+ - typedef CS type; (cs::cartesian, cs::spherical, etc)
+ */
+ template <typename P>
+ struct coordinate_system {};
+
+} // namespace traits
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+ template <typename GeometryTag, typename G>
+ struct coordinate_system
+ {
+ typedef typename point_type<GeometryTag, G>::type P;
+
+ // Call its own specialization on point-tag
+ typedef typename coordinate_system<point_tag, P>::type type;
+ };
+
+
+ template <typename P>
+ struct coordinate_system<point_tag, P>
+ {
+ typedef typename traits::coordinate_system<P>::type type;
+ };
+
+
+} // namespace core_dispatch
+#endif
+
+
+/*!
+ \brief Meta-function which defines coordinate system for any geometry
+ \ingroup core
+*/
+template <typename G>
+struct coordinate_system
+{
+ typedef typename boost::remove_const<G>::type ncg;
+ typedef typename core_dispatch::coordinate_system
+ <
+ typename tag<G>::type,
+ ncg
+ >::type type;
+};
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_COORDINATE_SYSTEM_HPP

Added: sandbox/geometry/boost/geometry/core/coordinate_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/coordinate_type.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,72 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_COORDINATE_TYPE_HPP
+#define BOOST_GEOMETRY_CORE_COORDINATE_TYPE_HPP
+
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+
+namespace boost { namespace geometry {
+
+namespace traits {
+
+/*!
+ \brief Traits class which indicate the coordinate type (double,float,...) of a point
+ \ingroup traits
+ \par Geometries:
+ - point
+ \par Specializations should provide:
+ - typedef T type; (double,float,int,etc)
+*/
+template <typename P>
+struct coordinate_type {};
+
+} // namespace traits
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename GeometryTag, typename G>
+struct coordinate_type
+{
+ typedef typename point_type<GeometryTag, G>::type point_type;
+
+ // Call its own specialization on point-tag
+ typedef typename coordinate_type<point_tag, point_type>::type type;
+};
+
+template <typename P>
+struct coordinate_type<point_tag, P>
+{
+ typedef typename traits::coordinate_type<P>::type type;
+};
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+/*!
+ \brief Meta-function which defines coordinate type (int, float, double, etc) of any geometry
+ \ingroup core
+*/
+template <typename G>
+struct coordinate_type
+{
+ typedef typename boost::remove_const<G>::type ncg;
+ typedef typename core_dispatch::coordinate_type
+ <
+ typename tag<G>::type,
+ ncg
+ >::type type;
+};
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_COORDINATE_TYPE_HPP

Added: sandbox/geometry/boost/geometry/core/cs.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/cs.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,186 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_CS_HPP
+#define BOOST_GEOMETRY_CORE_CS_HPP
+
+#include <cstddef>
+
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+/*!
+\defgroup cs coordinate systems
+\brief Defines coordinate systems
+\details Coordinate systems are essential for any point in the Generic Geometry Library. Many
+algorithms such as distance or transform use coordinate systems to select the strategy to use.
+*/
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief Unit of plane angle: Degrees
+ \ingroup cs
+*/
+class degree {};
+
+
+/*!
+ \brief Unit of plane angle: Radians
+ \ingroup cs
+*/
+class radian {};
+
+
+namespace cs
+{
+
+/*!
+ \brief Cartesian coordinate system
+ \details Defines the Cartesian or rectangular coordinate system
+ where points are defined in 2 or 3 (or more)
+ dimensions and usually (but not always) known as x,y,z
+ \see http://en.wikipedia.org/wiki/Cartesian_coordinate_system
+ \ingroup cs
+*/
+struct cartesian {};
+
+
+
+
+/*!
+ \brief Geographic coordinate system, in degree or in radian
+ \details Defines the geographic coordinate system where points
+ are defined in two angles and usually
+ known as lat,long or lo,la or phi,lambda
+ \see http://en.wikipedia.org/wiki/Geographic_coordinate_system
+ \ingroup cs
+ \note might be moved to extensions/gis/geographic
+*/
+template<typename DegreeOrRadian>
+struct geographic
+{
+ typedef DegreeOrRadian units;
+};
+
+
+
+/*!
+ \brief Spherical coordinate system, in degree or in radian
+ \details Defines the spherical coordinate system where points are
+ defined in two angles
+ and an optional radius usually known as r, theta, phi
+ \par Coordinates:
+ - coordinate 0:
+ 0 <= phi < 2pi is the angle between the positive x-axis and the
+ line from the origin to the P projected onto the xy-plane.
+ - coordinate 1:
+ 0 <= theta <= pi is the angle between the positive z-axis and the
+ line formed between the origin and P.
+ - coordinate 2 (if specified):
+ r >= 0 is the distance from the origin to a given point P.
+
+ \see http://en.wikipedia.org/wiki/Spherical_coordinates
+ \ingroup cs
+*/
+template<typename DegreeOrRadian>
+struct spherical
+{
+ typedef DegreeOrRadian units;
+};
+
+/*!
+ \brief Polar coordinate system
+ \details Defines the polar coordinate system "in which each point
+ on a plane is determined by an angle and a distance"
+ \see http://en.wikipedia.org/wiki/Polar_coordinates
+ \ingroup cs
+*/
+template<typename DegreeOrRadian>
+struct polar
+{
+ typedef DegreeOrRadian units;
+};
+
+
+} // namespace cs
+
+namespace traits
+{
+/*!
+ \brief Traits class defining coordinate system tag, bound to coordinate system
+ \ingroup traits
+ \tparam CoordinateSystem coordinate system
+*/
+template <typename CoordinateSystem>
+struct cs_tag
+{
+};
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+template<typename DegreeOrRadian>
+struct cs_tag<cs::geographic<DegreeOrRadian> >
+{
+ typedef geographic_tag type;
+};
+
+template<typename DegreeOrRadian>
+struct cs_tag<cs::spherical<DegreeOrRadian> >
+{
+ typedef spherical_tag type;
+};
+
+template<>
+struct cs_tag<cs::cartesian>
+{
+ typedef cartesian_tag type;
+};
+
+
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+} // namespace traits
+
+/*!
+ \brief Meta-function returning coordinate system tag (cs family) of any geometry
+ \ingroup core
+*/
+template <typename G>
+struct cs_tag
+{
+ typedef typename traits::cs_tag
+ <
+ typename geometry::coordinate_system<G>::type
+ >::type type;
+};
+
+
+/*!
+ \brief Meta-function to verify if a coordinate system is radian
+ \ingroup core
+*/
+template <typename CoordinateSystem>
+struct is_radian : boost::true_type {};
+
+
+#ifndef DOXYGEN_NO_SPECIALIZATIONS
+
+// Specialization for any degree coordinate systems
+template <template<typename> class CoordinateSystem>
+struct is_radian< CoordinateSystem<degree> > : boost::false_type
+{
+};
+
+#endif // DOXYGEN_NO_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_CS_HPP

Added: sandbox/geometry/boost/geometry/core/exception.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/exception.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,26 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_EXCEPTION_HPP
+#define BOOST_GEOMETRY_CORE_EXCEPTION_HPP
+
+#include <exception>
+
+namespace boost { namespace geometry {
+
+/*!
+\brief Base exception class for GGL
+\ingroup core
+*/
+struct exception : public std::exception
+{
+};
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_EXCEPTION_HPP

Added: sandbox/geometry/boost/geometry/core/exterior_ring.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/exterior_ring.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,128 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_EXTERIOR_RING_HPP
+#define BOOST_GEOMETRY_CORE_EXTERIOR_RING_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+
+
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/add_const_if_c.hpp>
+
+
+namespace boost { namespace geometry {
+
+namespace traits {
+
+
+/*!
+ \brief Traits class defining access to exterior_ring of a polygon
+ \details Should define const and non const access
+ \ingroup traits
+ \tparam Polygon the polygon type
+ \par Geometries:
+ - polygon
+ \par Specializations should provide:
+ - static inline RING& get(POLY& )
+ - static inline const RING& get(const POLY& )
+*/
+template <typename Polygon>
+struct exterior_ring
+{};
+
+
+} // namespace traits
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+
+template <typename Tag, typename Geometry, bool IsConst>
+struct exterior_ring {};
+
+
+template <typename Polygon, bool IsConst>
+struct exterior_ring<polygon_tag, Polygon, IsConst>
+{
+ static inline typename add_const_if_c
+ <
+ IsConst,
+ typename geometry::ring_type
+ <
+ Polygon
+ >::type
+ >::type& apply(typename add_const_if_c
+ <
+ IsConst,
+ Polygon
+ >::type& polygon)
+ {
+ return traits::exterior_ring
+ <
+ typename boost::remove_const<Polygon>::type
+ >::get(polygon);
+ }
+};
+
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Function to get the exterior_ring ring of a polygon
+ \ingroup access
+ \note OGC compliance: instead of ExteriorRing
+ \tparam P polygon type
+ \param polygon the polygon to get the exterior ring from
+ \return a reference to the exterior ring
+*/
+template <typename Polygon>
+inline typename ring_type<Polygon>::type& exterior_ring(Polygon& polygon)
+{
+ return core_dispatch::exterior_ring
+ <
+ typename tag<Polygon>::type,
+ Polygon,
+ false
+ >::apply(polygon);
+}
+
+
+/*!
+ \brief Function to get the exterior ring of a polygon (const version)
+ \ingroup access
+ \note OGC compliance: instead of ExteriorRing
+ \tparam Polygon polygon type
+ \param polygon the polygon to get the exterior ring from
+ \return a const reference to the exterior ring
+*/
+template <typename Polygon>
+inline const typename ring_type<Polygon>::type& exterior_ring(
+ Polygon const& polygon)
+{
+ return core_dispatch::exterior_ring
+ <
+ typename tag<Polygon>::type,
+ Polygon,
+ true
+ >::apply(polygon);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_EXTERIOR_RING_HPP

Added: sandbox/geometry/boost/geometry/core/geometry_id.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/geometry_id.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,76 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_GEOMETRY_ID_HPP
+#define BOOST_GEOMETRY_CORE_GEOMETRY_ID_HPP
+
+
+#include <boost/mpl/int.hpp>
+#include <boost/type_traits.hpp>
+
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename GeometryTag>
+struct geometry_id {};
+
+
+template <>
+struct geometry_id<point_tag> : boost::mpl::int_<1> {};
+
+
+template <>
+struct geometry_id<linestring_tag> : boost::mpl::int_<2> {};
+
+
+template <>
+struct geometry_id<polygon_tag> : boost::mpl::int_<3> {};
+
+
+template <>
+struct geometry_id<segment_tag> : boost::mpl::int_<92> {};
+
+
+template <>
+struct geometry_id<ring_tag> : boost::mpl::int_<93> {};
+
+
+template <>
+struct geometry_id<box_tag> : boost::mpl::int_<94> {};
+
+
+
+} // namespace core_dispatch
+#endif
+
+
+
+/*!
+ \brief Meta-function the id for a geometry type
+ \note Used for e.g. reverse meta-function
+ \ingroup core
+*/
+template <typename Geometry>
+struct geometry_id : core_dispatch::geometry_id<typename tag<Geometry>::type>
+{};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_GEOMETRY_ID_HPP

Added: sandbox/geometry/boost/geometry/core/interior_rings.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/interior_rings.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,235 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_INTERIOR_RINGS_HPP
+#define BOOST_GEOMETRY_CORE_INTERIOR_RINGS_HPP
+
+#include <cstddef>
+
+#include <boost/range/functions.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/add_const_if_c.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+/*!
+ \brief Traits class indicating interior container type of a polygon
+ \details defines inner container type, so the container containing
+ the interior rings
+ \ingroup traits
+ \par Geometries:
+ - polygon
+ \par Specializations should provide:
+ - typedef X type ( e.g. std::vector&lt;myring&lt;P&gt;&gt; )
+ \tparam Geometry geometry
+*/
+template <typename Geometry>
+struct interior_type
+{};
+
+
+/*!
+ \brief Traits class defining access to interior_rings of a polygon
+ \details defines access (const and non const) to interior ring
+ \ingroup traits
+ \par Geometries:
+ - polygon
+ \par Specializations should provide:
+ - static inline INTERIOR& get(POLY&)
+ - static inline const INTERIOR& get(const POLY&)
+ \tparam Geometry geometry
+*/
+template <typename Geometry>
+struct interior_rings
+{};
+
+
+} // namespace traits
+
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+
+template <typename GeometryTag, typename Geometry>
+struct interior_type
+{};
+
+
+template <typename Polygon>
+struct interior_type<polygon_tag, Polygon>
+{
+ typedef typename traits::interior_type
+ <
+ typename boost::remove_const<Polygon>::type
+ >::type type;
+};
+
+
+template
+<
+ typename GeometryTag,
+ typename Geometry,
+ bool IsConst
+>
+struct interior_rings {};
+
+
+template <typename Polygon, bool IsConst>
+struct interior_rings<polygon_tag, Polygon, IsConst>
+{
+ static inline typename add_const_if_c
+ <
+ IsConst,
+ typename interior_type
+ <
+ polygon_tag,
+ Polygon
+ >::type
+ >::type& apply(typename add_const_if_c
+ <
+ IsConst,
+ Polygon
+ >::type& polygon)
+ {
+ return traits::interior_rings
+ <
+ typename boost::remove_const<Polygon>::type
+ >::get(polygon);
+ }
+};
+
+
+template <typename Tag, typename Geometry>
+struct num_interior_rings
+{
+ static inline std::size_t apply(Geometry const&)
+ {
+ return 0;
+ }
+
+};
+
+
+template <typename Polygon>
+struct num_interior_rings<polygon_tag, Polygon>
+{
+ static inline std::size_t apply(Polygon const& polygon)
+ {
+ return boost::size(interior_rings
+ <
+ polygon_tag, Polygon, true
+ >::apply(polygon));
+ }
+
+};
+
+
+} // namespace core_dispatch
+#endif
+
+
+/*!
+ \brief Meta-function defining container type
+ of inner rings of (multi)polygon geometriy
+ \details the interior rings should be organized as a container
+ (std::vector, std::deque, boost::array) with
+ boost range support. This meta function defines the type
+ of that container.
+ \ingroup core
+*/
+template <typename Geometry>
+struct interior_type
+{
+ typedef typename core_dispatch::interior_type
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::type type;
+};
+
+
+/*!
+ \brief Function to get the interior rings of a polygon (non const version)
+ \ingroup access
+ \note OGC compliance: instead of InteriorRingN
+ \tparam P polygon type
+ \param polygon the polygon to get the interior rings from
+ \return a reference to the interior rings
+*/
+template <typename Polygon>
+inline typename interior_type<Polygon>::type& interior_rings(Polygon& polygon)
+{
+ return core_dispatch::interior_rings
+ <
+ typename tag<Polygon>::type,
+ Polygon,
+ false
+ >::apply(polygon);
+}
+
+
+/*!
+ \brief Function to get the interior rings of a polygon (const version)
+ \ingroup access
+ \note OGC compliance: instead of InteriorRingN
+ \tparam P polygon type
+ \param polygon the polygon to get the interior rings from
+ \return a const reference to the interior rings
+*/
+template <typename Polygon>
+inline const typename interior_type<Polygon>::type& interior_rings(
+ Polygon const& polygon)
+{
+ return core_dispatch::interior_rings
+ <
+ typename tag<Polygon>::type,
+ Polygon,
+ true
+ >::apply(polygon);
+}
+
+
+
+/*!
+ \brief Function to get the number of interior rings of a polygon
+ \ingroup access
+ \note Defined by OGC as "numInteriorRing". To be consistent with "numPoints"
+ letter "s" is appended
+ \note Can be used for any geometry, returning 0 for geometries not having
+ interior rings
+ \tparam Geometry geometry type
+ \param geometry the polygon or other geometry
+ \return the number of interior rings of the geometry
+*/
+template <typename Geometry>
+inline std::size_t num_interior_rings(Geometry const& geometry)
+{
+ return core_dispatch::num_interior_rings
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::apply(geometry);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_INTERIOR_RINGS_HPP

Added: sandbox/geometry/boost/geometry/core/is_linear.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/is_linear.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,59 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_IS_LINEAR_HPP
+#define BOOST_GEOMETRY_CORE_IS_LINEAR_HPP
+
+
+#include <boost/type_traits.hpp>
+
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename GeometryTag>
+struct is_linear : boost::false_type {};
+
+
+template <>
+struct is_linear<linestring_tag> : boost::true_type {};
+
+
+template <>
+struct is_linear<ring_tag> : boost::true_type {};
+
+
+} // namespace core_dispatch
+#endif
+
+
+
+/*!
+ \brief Meta-function defining "true" for linear types (linestring,ring),
+ "false" for non-linear typse
+ \note Used for tag dispatching and meta-function finetuning
+ \ingroup core
+*/
+template <typename Geometry>
+struct is_linear : core_dispatch::is_linear<typename tag<Geometry>::type>
+{};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_IS_LINEAR_HPP

Added: sandbox/geometry/boost/geometry/core/is_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/is_multi.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,49 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_IS_MULTI_HPP
+#define BOOST_GEOMETRY_CORE_IS_MULTI_HPP
+
+
+#include <boost/type_traits.hpp>
+
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename GeometryTag>
+struct is_multi : boost::false_type {};
+
+
+} // namespace core_dispatch
+#endif
+
+
+
+
+/*!
+ \brief Meta-function defining "true" for multi geometries (multi_point, etc)
+ \ingroup core
+*/
+template <typename Geometry>
+struct is_multi : core_dispatch::is_multi<typename tag<Geometry>::type>
+{};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_IS_MULTI_HPP

Added: sandbox/geometry/boost/geometry/core/point_order.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/point_order.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,98 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_POINT_ORDER_HPP
+#define BOOST_GEOMETRY_CORE_POINT_ORDER_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+namespace boost { namespace geometry {
+
+
+enum order_selector { clockwise = 1, counterclockwise = 2, order_undetermined = 0 };
+
+namespace traits {
+
+/*!
+ \brief Traits class indicating the order of contained points within a
+ ring or (multi)polygon, clockwise, counter clockwise or not known.
+ \ingroup traits
+ \par Geometries:
+ - ring
+ - polygon
+ - multi polygon
+ \par Specializations should provide:
+ - typedef P type (where P should fulfil the Point concept)
+ \tparam G geometry
+*/
+template <typename G>
+struct point_order
+{
+ static const order_selector value = clockwise;
+};
+
+
+} // namespace traits
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename Tag, typename Geometry>
+struct point_order
+{
+ static const order_selector value = clockwise;
+};
+
+
+
+template <typename Ring>
+struct point_order<ring_tag, Ring>
+{
+ static const order_selector value = geometry::traits::point_order<Ring>::value;
+};
+
+// Specialization for polygon: the order is the order of its rings
+template <typename Polygon>
+struct point_order<polygon_tag, Polygon>
+{
+ static const order_selector value = core_dispatch::point_order
+ <
+ ring_tag,
+ typename ring_type<polygon_tag, Polygon>::type
+ >::value ;
+};
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Meta-function which defines point type of any geometry
+ \ingroup core
+*/
+template <typename Geometry>
+struct point_order
+{
+ typedef typename boost::remove_const<Geometry>::type ncg;
+ static const order_selector value = core_dispatch::point_order
+ <
+ typename tag<Geometry>::type,
+ ncg
+ >::value;
+};
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_POINT_ORDER_HPP

Added: sandbox/geometry/boost/geometry/core/point_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/point_type.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,109 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_POINT_TYPE_HPP
+#define BOOST_GEOMETRY_CORE_POINT_TYPE_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+namespace boost { namespace geometry {
+
+namespace traits {
+
+/*!
+ \brief Traits class indicating the type of contained points
+ \ingroup traits
+ \par Geometries:
+ - all geometries except point
+ \par Specializations should provide:
+ - typedef P type (where P should fulfil the Point concept)
+ \tparam G geometry
+*/
+template <typename G>
+struct point_type
+{};
+
+
+} // namespace traits
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename Tag, typename Geometry>
+struct point_type
+{
+ // Default: call traits to get point type
+ typedef typename boost::remove_const
+ <
+ typename traits::point_type<Geometry>::type
+ >::type type;
+};
+
+
+// Specialization for point: the point itself
+template <typename Point>
+struct point_type<point_tag, Point>
+{
+ typedef Point type;
+};
+
+// Specializations for linestring/linear ring, via boost::range
+template <typename Linestring>
+struct point_type<linestring_tag, Linestring>
+{
+ typedef typename boost::range_value<Linestring>::type type;
+};
+
+template <typename Ring>
+struct point_type<ring_tag, Ring>
+{
+ typedef typename boost::range_value<Ring>::type type;
+};
+
+// Specialization for polygon: the point-type is the point-type of its rings
+template <typename Polygon>
+struct point_type<polygon_tag, Polygon>
+{
+ typedef typename point_type
+ <
+ ring_tag,
+ typename ring_type<polygon_tag, Polygon>::type
+ >::type type;
+};
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Meta-function which defines point type of any geometry
+ \ingroup core
+*/
+template <typename Geometry>
+struct point_type
+{
+ typedef typename boost::remove_const<Geometry>::type ncg;
+ typedef typename core_dispatch::point_type<
+ typename tag<Geometry>::type, ncg>::type type;
+
+
+
+
+};
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_POINT_TYPE_HPP

Added: sandbox/geometry/boost/geometry/core/radian_access.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/radian_access.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,143 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_RADIAN_ACCESS_HPP
+#define BOOST_GEOMETRY_CORE_RADIAN_ACCESS_HPP
+
+
+#include <cstddef>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/cs.hpp>
+
+
+#include <boost/geometry/util/math.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail {
+
+template<std::size_t Dimension, typename Geometry>
+struct degree_radian_converter
+{
+ typedef typename coordinate_type<Geometry>::type coordinate_type;
+
+ static inline coordinate_type get(Geometry const& geometry)
+ {
+ return boost::numeric_cast
+ <
+ coordinate_type
+ >(geometry::get<Dimension>(geometry) * geometry::math::d2r);
+ }
+
+ static inline void set(Geometry& geometry, coordinate_type const& radians)
+ {
+ geometry::set<Dimension>(geometry, boost::numeric_cast
+ <
+ coordinate_type
+ >(radians * geometry::math::r2d));
+ }
+
+};
+
+
+// Default, radian (or any other coordinate system) just works like "get"
+template <std::size_t Dimension, typename Geometry, typename DegreeOrRadian>
+struct radian_access
+{
+ typedef typename coordinate_type<Geometry>::type coordinate_type;
+
+ static inline coordinate_type get(Geometry const& geometry)
+ {
+ return geometry::get<Dimension>(geometry);
+ }
+
+ static inline void set(Geometry& geometry, coordinate_type const& radians)
+ {
+ geometry::set<Dimension>(geometry, radians);
+ }
+};
+
+// Specialize, any "degree" coordinate system will convert to radian
+// but only for dimension 0,1 (so: dimension 2 and heigher are untouched)
+
+template
+<
+ typename Geometry,
+ template<typename> class CoordinateSystem
+>
+struct radian_access<0, Geometry, CoordinateSystem<degree> >
+ : degree_radian_converter<0, Geometry>
+{};
+
+
+template
+<
+ typename Geometry,
+ template<typename> class CoordinateSystem
+>
+struct radian_access<1, Geometry, CoordinateSystem<degree> >
+ : degree_radian_converter<1, Geometry>
+{};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief get coordinate value of a point, result is in Radian
+ \details Result is in Radian, even if source coordinate system
+ is in Degrees
+ \return coordinate value
+ \ingroup access
+ \tparam Dimension dimension
+ \tparam Geometry geometry
+ \param geometry geometry to get coordinate value from
+ \note Only applicable to coordinate systems templatized by units,
+ e.g. spherical or geographic coordinate systems
+*/
+template <std::size_t Dimension, typename Geometry>
+inline typename coordinate_type<Geometry>::type get_as_radian(const Geometry& geometry)
+{
+ return detail::radian_access<Dimension, Geometry,
+ typename coordinate_system<Geometry>::type>::get(geometry);
+}
+
+
+/*!
+ \brief set coordinate value (in radian) to a point
+ \details Coordinate value will be set correctly, if coordinate system of
+ point is in Degree, Radian value will be converted to Degree
+ \ingroup access
+ \tparam Dimension dimension
+ \tparam Geometry geometry
+ \param geometry geometry to assign coordinate to
+ \param radians coordinate value to assign
+ \note Only applicable to coordinate systems templatized by units,
+ e.g. spherical or geographic coordinate systems
+*/
+template <std::size_t Dimension, typename Geometry>
+inline void set_from_radian(Geometry& geometry,
+ const typename coordinate_type<Geometry>::type& radians)
+{
+ detail::radian_access<Dimension, Geometry,
+ typename coordinate_system<Geometry>::type>::set(geometry, radians);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_RADIAN_ACCESS_HPP

Added: sandbox/geometry/boost/geometry/core/replace_point_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/replace_point_type.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,92 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_REPLACE_POINT_TYPE_HPP
+#define BOOST_GEOMETRY_CORE_REPLACE_POINT_TYPE_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+
+// For now: use ggl-provided geometries
+// TODO: figure out how to get the class and replace the type
+// TODO: take "const" into account
+#include <boost/geometry/geometries/point.hpp>
+#include <boost/geometry/geometries/linestring.hpp>
+#include <boost/geometry/geometries/linear_ring.hpp>
+#include <boost/geometry/geometries/polygon.hpp>
+#include <boost/geometry/geometries/segment.hpp>
+#include <boost/geometry/geometries/box.hpp>
+
+
+namespace boost { namespace geometry {
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+template <typename GeometryTag, typename Geometry, typename NewPointType>
+struct replace_point_type {};
+
+template <typename Geometry, typename NewPointType>
+struct replace_point_type<point_tag, Geometry, NewPointType>
+{
+ typedef NewPointType type;
+};
+
+template <typename Geometry, typename NewPointType>
+struct replace_point_type<linestring_tag, Geometry, NewPointType>
+{
+ typedef linestring<NewPointType> type;
+};
+
+template <typename Geometry, typename NewPointType>
+struct replace_point_type<segment_tag, Geometry, NewPointType>
+{
+ typedef segment<NewPointType> type;
+};
+
+template <typename Geometry, typename NewPointType>
+struct replace_point_type<ring_tag, Geometry, NewPointType>
+{
+ typedef linear_ring<NewPointType> type;
+};
+
+template <typename Geometry, typename NewPointType>
+struct replace_point_type<box_tag, Geometry, NewPointType>
+{
+ typedef box<NewPointType> type;
+};
+
+template <typename Geometry, typename NewPointType>
+struct replace_point_type<polygon_tag, Geometry, NewPointType>
+{
+ typedef polygon<NewPointType> type;
+};
+
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+template <typename Geometry, typename NewPointType>
+struct replace_point_type : core_dispatch::replace_point_type
+ <
+ typename tag<Geometry>::type,
+ typename boost::remove_const<Geometry>::type,
+ NewPointType
+ >
+{};
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_REPLACE_POINT_TYPE_HPP

Added: sandbox/geometry/boost/geometry/core/reverse_dispatch.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/reverse_dispatch.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,59 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_REVERSE_DISPATCH_HPP
+#define BOOST_GEOMETRY_CORE_REVERSE_DISPATCH_HPP
+
+
+#include <boost/type_traits.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/greater.hpp>
+
+#include <boost/geometry/core/geometry_id.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+// Different geometries: reverse_dispatch if second ID < first ID
+template <std::size_t GeometryId1, std::size_t GeometryId2>
+struct reverse_dispatch : boost::mpl::if_c
+ <
+ (GeometryId1 > GeometryId2),
+ boost::true_type,
+ boost::false_type
+ >
+{};
+
+
+// Same geometry: never reverse_dispatch
+template <std::size_t GeometryId>
+struct reverse_dispatch<GeometryId, GeometryId> : boost::false_type {};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+template <typename Geometry1, typename Geometry2>
+struct reverse_dispatch : detail::reverse_dispatch
+ <
+ geometry_id<Geometry1>::type::value,
+ geometry_id<Geometry2>::type::value
+ >
+{};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_REVERSE_DISPATCH_HPP

Added: sandbox/geometry/boost/geometry/core/ring_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/ring_type.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,95 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_RING_TYPE_HPP
+#define BOOST_GEOMETRY_CORE_RING_TYPE_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+
+/*!
+ \brief Traits class to indicate ring-type of a polygon's exterior ring/interior rings
+ \ingroup traits
+ \par Geometries:
+ - polygon
+ \par Specializations should provide:
+ - typedef XXX type ( e.g. linear_ring<P> )
+ \tparam Geometry geometry
+*/
+template <typename Geometry>
+struct ring_type
+{
+ // should define type
+};
+
+
+} // namespace traits
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+
+template <typename GeometryTag, typename Geometry>
+struct ring_type
+{};
+
+
+template <typename Polygon>
+struct ring_type<polygon_tag, Polygon>
+{
+ typedef typename traits::ring_type
+ <
+ typename boost::remove_const<Polygon>::type
+ >::type type;
+
+};
+
+
+} // namespace core_dispatch
+#endif
+
+
+/*!
+ \brief Meta-function which defines ring type of (multi)polygon geometry
+ \details a polygon contains one exterior ring
+ and zero or more interior rings (holes).
+ This meta function retrieves the type of the rings
+ \note Exterior ring and interior rings must have the same ring-type.
+ \ingroup core
+*/
+template <typename Geometry>
+struct ring_type
+{
+ typedef typename core_dispatch::ring_type
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_RING_TYPE_HPP

Added: sandbox/geometry/boost/geometry/core/tag.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/tag.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,65 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_TAG_HPP
+#define BOOST_GEOMETRY_CORE_TAG_HPP
+
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/tags.hpp>
+
+/*!
+\defgroup core core: meta-functions for geometry types
+*/
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+/*!
+ \brief Traits class to attach a tag to a geometry
+ \details All geometries should implement a traits::tag<G>::type metafunction to indicate their
+ own geometry type.
+ \ingroup traits
+ \par Geometries:
+ - all geometries
+ \par Specializations should provide:
+ - typedef XXX_tag type; (point_tag, box_tag, ...)
+ \tparam Geometry geometry
+*/
+template <typename Geometry>
+struct tag
+{
+ typedef geometry_not_recognized_tag type;
+};
+
+} // namespace traits
+
+
+/*!
+ \brief Meta-function to get the tag of any geometry type
+ \details All geometries tell their geometry type (point, linestring, polygon, etc) by implementing
+ a tag traits class. This meta-function uses that traits class to retrieve the tag.
+ If the input type is not a geometry at all, a geometry_not_recognized_tag will be returned.
+ \tparam Geometry geometry
+ \ingroup core
+*/
+template <typename Geometry>
+struct tag
+{
+ typedef typename traits::tag
+ <
+ typename boost::remove_const<Geometry>::type
+ >::type type;
+};
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_TAG_HPP

Added: sandbox/geometry/boost/geometry/core/tags.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/tags.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,61 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_TAGS_HPP
+#define BOOST_GEOMETRY_CORE_TAGS_HPP
+
+
+/*!
+\defgroup traits traits: adapt geometries
+\brief Traits classes are small classes or structs to adapt geometries
+such that they are recognized by the Generic Geometry Library
+*/
+
+namespace boost { namespace geometry
+{
+
+// Tags defining strategies linked to coordinate systems
+
+
+/// Tag indicating Cartesian coordinate system family (cartesian,epsg)
+struct cartesian_tag {};
+
+/// Tag indicating Geographic coordinate system family (geographic)
+struct geographic_tag {};
+
+/// Tag indicating Spherical coordinate system family (spherical,celestial,...)
+struct spherical_tag {};
+
+
+// Tags defining geometry types
+
+
+/// "default" tag
+struct geometry_not_recognized_tag {};
+
+/// OGC Point identifying tag
+struct point_tag {};
+
+/// OGC Linestring identifying tag
+struct linestring_tag {};
+
+/// OGC Polygon identifying tag
+struct polygon_tag {};
+
+/// Convenience (linear) ring identifying tag
+struct ring_tag {};
+
+/// Convenience 2D or 3D box (mbr) identifying tag
+struct box_tag {};
+
+/// Convenience segment (2-points) identifying tag
+struct segment_tag {};
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_TAGS_HPP

Added: sandbox/geometry/boost/geometry/core/topological_dimension.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/core/topological_dimension.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,82 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_TOPOLOGICAL_DIMENSION_HPP
+#define BOOST_GEOMETRY_CORE_TOPOLOGICAL_DIMENSION_HPP
+
+
+#include <boost/mpl/int.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch {
+
+
+template <typename GeometryTag>
+struct top_dim {};
+
+
+template <>
+struct top_dim<point_tag> : boost::mpl::int_<0> {};
+
+
+template <>
+struct top_dim<linestring_tag> : boost::mpl::int_<1> {};
+
+
+template <>
+struct top_dim<segment_tag> : boost::mpl::int_<1> {};
+
+
+// ring: topological dimension of two, but some people say: 1 !!
+template <>
+struct top_dim<ring_tag> : boost::mpl::int_<2> {};
+
+
+template <>
+struct top_dim<box_tag> : boost::mpl::int_<2> {};
+
+
+template <>
+struct top_dim<polygon_tag> : boost::mpl::int_<2> {};
+
+
+
+} // namespace core_dispatch
+#endif
+
+
+
+
+
+/*!
+ \brief Meta-function returning the topological dimension of a geometry
+ \details The topological dimension defines a point as 0-dimensional,
+ a linestring as 1-dimensional,
+ and a ring or polygon as 2-dimensional.
+ \see http://www.math.okstate.edu/mathdept/dynamics/lecnotes/node36.html
+ \ingroup core
+*/
+template <typename Geometry>
+struct topological_dimension
+ : core_dispatch::top_dim<typename tag<Geometry>::type> {};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_TOPOLOGICAL_DIMENSION_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/geographic/detail/ellipsoid.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/geographic/detail/ellipsoid.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,58 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_EXTENSIONS_GIS_GEOGRAPHIC_DETAIL_ELLIPSOID_HPP
+#define BOOST_GEOMETRY_EXTENSIONS_GIS_GEOGRAPHIC_DETAIL_ELLIPSOID_HPP
+
+
+namespace boost { namespace geometry { namespace detail {
+
+
+/*!
+ \brief Defines ellipsoid values for use in distance calculations
+ \details They have a constructor with the earth radius
+ \note Will be moved / merged with projections
+ \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
+};
+
+
+
+
+}}} // namespace boost::geometry::detail
+
+
+#endif // BOOST_GEOMETRY_EXTENSIONS_GIS_GEOGRAPHIC_DETAIL_ELLIPSOID_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/andoyer.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/andoyer.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,142 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_EXTENSIONS_GIS_GEOGRAPHIC_STRATEGIES_ANDOYER_HPP
+#define BOOST_GEOMETRY_EXTENSIONS_GIS_GEOGRAPHIC_STRATEGIES_ANDOYER_HPP
+
+
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+
+#include <boost/geometry/extensions/gis/geographic/detail/ellipsoid.hpp>
+
+
+namespace boost { namespace geometry
+{
+namespace strategy
+{
+
+ namespace distance
+ {
+
+
+ /*!
+ \brief Point-point distance approximation taking flattening into account
+ \ingroup distance
+ \tparam P1 first point type
+ \tparam P2 optional second point type
+ \author After Andoyer, 19xx, republished 1950, republished by Meeus, 1999
+ \note Although not so well-known, the approximation is very good: in all cases the results
+ are about the same as Vincenty. In my (Barend's) testcases the results didn't differ more than 6 m
+ \see http://nacc.upc.es/tierra/node16.html
+ \see http://sci.tech-archive.net/Archive/sci.geo.satellite-nav/2004-12/2724.html
+ \see http://home.att.net/~srschmitt/great_circle_route.html (implementation)
+ \see http://www.codeguru.com/Cpp/Cpp/algorithms/article.php/c5115 (implementation)
+ \see http://futureboy.homeip.net/frinksamp/navigation.frink (implementation)
+ \see http://www.voidware.com/earthdist.htm (implementation)
+ */
+ template <typename P1, typename P2 = P1>
+ class andoyer
+ {
+ public :
+ //typedef spherical_distance return_type;
+ typedef P1 first_point_type;
+ typedef P2 second_point_type;
+ typedef double return_type;
+
+ andoyer()
+ : m_ellipsoid()
+ {}
+ andoyer(double f)
+ : m_ellipsoid(f)
+ {}
+
+ inline return_type apply(const P1& p1, const P2& p2) const
+ {
+ return calc(get_as_radian<0>(p1), get_as_radian<1>(p1),
+ get_as_radian<0>(p2), get_as_radian<1>(p2));
+ }
+
+
+ private :
+ typedef typename coordinate_type<P1>::type T1;
+ typedef typename coordinate_type<P2>::type T2;
+ geometry::detail::ellipsoid m_ellipsoid;
+
+ inline return_type calc(const T1& lon1, const T1& lat1, const T2& lon2, const T2& lat2) const
+ {
+ typedef double calculation_type;
+ calculation_type G = (lat1 - lat2) / 2.0;
+ calculation_type lambda = (lon1 - lon2) / 2.0;
+
+ if (geometry::math::equals(lambda, 0.0)
+ && geometry::math::equals(G, 0.0))
+ {
+ return 0.0;
+ }
+
+ calculation_type F = (lat1 + lat2) / 2.0;
+
+ calculation_type sinG2 = math::sqr(sin(G));
+ calculation_type cosG2 = math::sqr(cos(G));
+ calculation_type sinF2 = math::sqr(sin(F));
+ calculation_type cosF2 = math::sqr(cos(F));
+ calculation_type sinL2 = math::sqr(sin(lambda));
+ calculation_type cosL2 = math::sqr(cos(lambda));
+
+ calculation_type S = sinG2 * cosL2 + cosF2 * sinL2;
+ calculation_type C = cosG2 * cosL2 + sinF2 * sinL2;
+
+ if (geometry::math::equals(S, 0.0) || geometry::math::equals(C, 0.0))
+ {
+ return 0.0;
+ }
+
+ calculation_type omega = atan(sqrt(S / C));
+ calculation_type r = sqrt(S * C) / omega; // not sure if this is r or greek nu
+
+ calculation_type D = 2.0 * omega * m_ellipsoid.a();
+ calculation_type H1 = (3 * r - 1.0) / (2.0 * C);
+ calculation_type H2 = (3 * r + 1.0) / (2.0 * S);
+
+ return return_type(D
+ * (1.0 + m_ellipsoid.f() * H1 * sinF2 * cosG2
+ - m_ellipsoid.f() * H2 * cosF2 * sinG2));
+ }
+ };
+
+
+
+ } // namespace distance
+
+
+} // namespace strategy
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename P1, typename P2>
+struct strategy_distance<geographic_tag, geographic_tag, P1, P2>
+{
+ typedef strategy::distance::andoyer<P1, P2> type;
+};
+
+
+template <typename P1, typename P2>
+struct strategy_tag<strategy::distance::andoyer<P1, P2> >
+{
+ typedef strategy_tag_distance_point_point type;
+};
+
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_EXTENSIONS_GIS_GEOGRAPHIC_STRATEGIES_ANDOYER_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/area_huiller_earth.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/area_huiller_earth.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,60 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_EXTENSIONS_GIS_GEOGRAPHIC_STRATEGIES_AREA_HUILLER_EARTH_HPP
+#define BOOST_GEOMETRY_EXTENSIONS_GIS_GEOGRAPHIC_STRATEGIES_AREA_HUILLER_EARTH_HPP
+
+
+
+#include <boost/geometry/strategies/spherical/area_huiller.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace area {
+
+
+
+template
+<
+ typename PointOfSegment,
+ typename CalculationType = void
+>
+class huiller_earth
+ : public huiller<PointOfSegment, CalculationType>
+{
+public :
+ // By default the average earth radius.
+ // Uses can specify another radius.
+ // Note that the earth is still spherical
+ inline huiller_earth(double radius = 6372795.0)
+ : huiller<PointOfSegment, CalculationType>(radius)
+ {}
+};
+
+
+
+}} // namespace strategy::area
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+template <typename Point>
+struct strategy_area<geographic_tag, Point>
+{
+ typedef strategy::area::huiller_earth<Point> type;
+};
+
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_EXTENSIONS_GIS_GEOGRAPHIC_STRATEGIES_AREA_HUILLER_EARTH_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/dms_parser.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/dms_parser.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,267 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_EXTENSIONS_GIS_GEOGRAPHIC_STRATEGIES_DMS_PARSER_HPP
+#define BOOST_GEOMETRY_EXTENSIONS_GIS_GEOGRAPHIC_STRATEGIES_DMS_PARSER_HPP
+
+// This file is totally revised from PROJ4 dmstor.c
+
+// PROJ4 is originally written by Gerald Evenden (then of the USGS)
+// PROJ4 is maintained by Frank Warmerdam
+// PROJ4 is converted to Geometry Library by Barend Gehrels (Geodan, Amsterdam)
+
+// Original copyright notice:
+
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+
+// 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 AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#include <string>
+
+#include <boost/static_assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/strategies/parse.hpp>
+
+#include <boost/geometry/util/math.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+struct dms_result
+{
+ enum axis_selector {axis_lat = 1, axis_lon = 0};
+
+ private :
+ typedef double T;
+ T m_angle;
+ axis_selector m_axis;
+
+ public :
+
+ explicit dms_result(const T& v, axis_selector ax)
+ : m_angle(v)
+ , m_axis(ax)
+ {}
+
+ inline axis_selector axis() const { return m_axis; }
+
+ inline operator double() const { return m_angle; }
+
+ template <typename CH, typename TR>
+ inline friend std::basic_ostream<CH, TR>& operator<<(std::basic_ostream<CH, TR>& os,
+ const dms_result& d)
+ {
+ os << d.m_angle;
+ return os;
+ }
+
+};
+
+
+namespace strategy
+{
+
+ template <bool as_radian = true
+ , char N = 'N', char E = 'E', char S = 'S', char W = 'W' // translatable
+ , char MIN = '\'', char SEC = '"' // other char's possible
+ , char D = 'D', char R = 'R' // degree sign might be small o
+ >
+ struct dms_parser
+ {
+
+
+ // Question from Barend: can we compile-time select that it is case-sensitive/case-insensitive?
+ // We have to change the switch then -> specializations
+
+ // For now: make it (compile-time) case sensitive
+ static const int diff = 'a' - 'A';
+#ifndef __GNUC__
+ BOOST_STATIC_ASSERT((diff > 0)); // make sure we've the right assumption. GCC does not accept this here.
+#endif
+ static const char n_alter = N <= 'Z' ? N + diff : N - diff;
+ static const char e_alter = E <= 'Z' ? E + diff : E - diff;
+ static const char s_alter = S <= 'Z' ? S + diff : S - diff;
+ static const char w_alter = W <= 'Z' ? W + diff : W - diff;
+
+ static const char r_alter = R <= 'Z' ? R + diff : R - diff;
+
+ // degree is normally D (proj4) but might be superscript o
+ // Note d_alter is not correct then, so map it to NULL now, guarded by the while
+ static const char d_alter =
+ ((D >= 'A' && D <= 'Z') || (D >= 'a' && D <= 'z')) ? (D <= 'Z' ? D + diff : D - diff) : '\0';
+
+
+ struct dms_value
+ {
+ double dms[3];
+ bool has_dms[3];
+
+ dms_value()
+ {
+ memset(this, 0, sizeof(dms_value));
+ }
+ };
+
+
+ template <size_t I>
+ static inline void assign_dms(dms_value& dms, std::string& value, bool& has_value)
+ {
+ dms.dms[I] = boost::lexical_cast<double>(value.c_str());
+ dms.has_dms[I] = true;
+ has_value = false;
+ value.clear();
+ }
+
+ static inline void process(dms_value& dms, std::string& value, bool& has_value)
+ {
+ if (has_value)
+ {
+ // Assign last one, sequentially
+ if (! dms.has_dms[0]) assign_dms<0>(dms, value, has_value);
+ else if (! dms.has_dms[1]) assign_dms<1>(dms, value, has_value);
+ else if (! dms.has_dms[2]) assign_dms<2>(dms, value, has_value);
+ }
+ }
+
+
+ dms_result operator()(const char* is) const
+ {
+ dms_value dms;
+ bool has_value = false;
+ std::string value;
+
+ double factor = 1.0; // + denotes N/E values, -1 denotes S/W values
+ dms_result::axis_selector axis = dms_result::axis_lon; // true denotes N/S values
+ bool in_radian = false; // true denotes values as "0.1R"
+
+ while(*is)
+ {
+ switch(*is)
+ {
+ case '-' :
+ if (! has_value && ! dms.has_dms[0])
+ {
+ factor = -factor;
+ }
+ break;
+ case N :
+ case n_alter :
+ axis = dms_result::axis_lat;
+ break;
+ case S :
+ case s_alter :
+ axis = dms_result::axis_lat;
+ factor = -factor;
+ break;
+ case E :
+ case e_alter :
+ axis = dms_result::axis_lon;
+ break;
+ case W :
+ case w_alter :
+ axis = dms_result::axis_lon;
+ factor = -factor;
+ break;
+ case D :
+ case d_alter :
+ if (! dms.has_dms[0] && has_value)
+ {
+ assign_dms<0>(dms, value, has_value);
+ }
+ break;
+ case R :
+ case r_alter :
+ if (! dms.has_dms[0] && has_value)
+ {
+ // specified value is in radian!
+ in_radian = true;
+ assign_dms<0>(dms, value, has_value);
+ }
+ break;
+ case MIN:
+ if (! dms.has_dms[1] && has_value)
+ {
+ assign_dms<1>(dms, value, has_value);
+ }
+ break;
+ case SEC :
+ if (! dms.has_dms[2] && has_value)
+ {
+ assign_dms<2>(dms, value, has_value);
+ }
+ break;
+ case ' ' :
+ case '\t' :
+ case '\n' :
+ process(dms, value, has_value);
+ break;
+ default :
+ value += *is;
+ has_value = true;
+ break;
+ }
+ is++;
+ }
+
+ // Assign last one, if any
+ process(dms, value, has_value);
+
+ return dms_result(factor *
+ (in_radian && as_radian
+ ? dms.dms[0]
+ : in_radian && ! as_radian
+ ? dms.dms[0] * math::r2d
+ : ! in_radian && as_radian
+ ? dms.dms[0] * math::d2r + dms.dms[1] * math::d2r / 60.0 + dms.dms[2] * math::d2r / 3600.0
+ : dms.dms[0] + dms.dms[1] / 60.0 + dms.dms[2] / 3600.0)
+ , axis);
+ }
+ };
+
+}
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+template <template<typename> class CS>
+struct strategy_parse<geographic_tag, CS<degree> >
+{
+ typedef strategy::dms_parser<false> type;
+};
+
+
+template <template<typename> class CS>
+struct strategy_parse<geographic_tag, CS<radian> >
+{
+ typedef strategy::dms_parser<true> type;
+};
+
+#endif
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_EXTENSIONS_GIS_GEOGRAPHIC_STRATEGIES_DMS_PARSER_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/vincenty.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/vincenty.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,151 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_EXTENSIONS_GIS_GEOGRAPHIC_STRATEGIES_VINCENTY_HPP
+#define BOOST_GEOMETRY_EXTENSIONS_GIS_GEOGRAPHIC_STRATEGIES_VINCENTY_HPP
+
+
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+
+#include <boost/geometry/extensions/gis/geographic/detail/ellipsoid.hpp>
+
+
+namespace boost { namespace geometry
+{
+namespace strategy
+{
+
+ namespace distance
+ {
+
+ /*!
+ \brief Distance calculation formulae on latlong coordinates, after Vincenty, 1975
+ \ingroup distance
+ \tparam P1 first point type
+ \tparam P2 optional second point type
+ \author See http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
+ \author Adapted from various implementations to get it close to the original document
+ - http://www.movable-type.co.uk/scripts/LatLongVincenty.html
+ - http://exogen.case.edu/projects/geopy/source/geopy.distance.html
+ - http://futureboy.homeip.net/fsp/colorize.fsp?fileName=navigation.frink
+
+ */
+ template <typename P1, typename P2 = P1>
+ class vincenty
+ {
+ public :
+ //typedef spherical_distance return_type;
+ typedef P1 first_point_type;
+ typedef P2 second_point_type;
+ typedef double return_type;
+
+ inline return_type apply(P1 const& p1, P2 const& p2) const
+ {
+ return calculate(get_as_radian<0>(p1), get_as_radian<1>(p1),
+ get_as_radian<0>(p2), get_as_radian<1>(p2));
+ }
+
+ private :
+ typedef typename coordinate_type<P1>::type T1;
+ typedef typename coordinate_type<P2>::type T2;
+ geometry::detail::ellipsoid m_ellipsoid;
+
+ inline return_type calculate(T1 const& lon1, T1 const& lat1, T2 const& lon2, T2 const& lat2) const
+ {
+ // lambda: difference in longitude on an auxiliary sphere
+ double L = lon2 - lon1;
+ double lambda = L;
+
+ if (L < -math::pi) L += math::two_pi;
+ if (L > math::pi) L -= math::two_pi;
+
+ if (lat1 == lat2 && lon1 == lon2)
+ {
+ return return_type(0);
+ }
+
+ // U: reduced latitude, defined by tan U = (1-f) tan phi
+ double U1 = atan((1-m_ellipsoid.f()) * tan(lat1)); // above (1)
+ double U2 = atan((1-m_ellipsoid.f()) * tan(lat2)); // above (1)
+
+ double cos_U1 = cos(U1);
+ double cos_U2 = cos(U2);
+ double sin_U1 = sin(U1);
+ double sin_U2 = sin(U2);
+
+ // alpha: azimuth of the geodesic at the equator
+ double cos2_alpha;
+ double sin_alpha;
+
+ // sigma: angular distance p1,p2 on the sphere
+ // sigma1: angular distance on the sphere from the equator to p1
+ // sigma_m: angular distance on the sphere from the equator to the midpoint of the line
+ double sigma;
+ double sin_sigma;
+ double cos2_sigma_m;
+
+ double previous_lambda;
+
+ do
+ {
+ previous_lambda = lambda; // (13)
+ double sin_lambda = sin(lambda);
+ double cos_lambda = cos(lambda);
+ sin_sigma = sqrt(math::sqr(cos_U2 * sin_lambda) + math::sqr(cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda)); // (14)
+ double cos_sigma = sin_U1 * sin_U2 + cos_U1 * cos_U2 * cos_lambda; // (15)
+ sin_alpha = cos_U1 * cos_U2 * sin_lambda / sin_sigma; // (17)
+ cos2_alpha = 1.0 - math::sqr(sin_alpha);
+ cos2_sigma_m = cos2_alpha == 0 ? 0 : cos_sigma - 2.0 * sin_U1 * sin_U2 / cos2_alpha; // (18)
+
+ double C = m_ellipsoid.f()/16.0 * cos2_alpha * (4.0 + m_ellipsoid.f() * (4.0 - 3.0 * cos2_alpha)); // (10)
+ sigma = atan2(sin_sigma, cos_sigma); // (16)
+ lambda = L + (1.0 - C) * m_ellipsoid.f() * sin_alpha *
+ (sigma + C * sin_sigma * ( cos2_sigma_m + C * cos_sigma * (-1.0 + 2.0 * math::sqr(cos2_sigma_m)))); // (11)
+
+ } while (fabs(previous_lambda - lambda) > 1e-12 && fabs(lambda) < math::pi);
+
+ double sqr_u = cos2_alpha * (math::sqr(m_ellipsoid.a()) - math::sqr(m_ellipsoid.b())) / math::sqr(m_ellipsoid.b()); // above (1)
+
+ double A = 1.0 + sqr_u/16384.0 * (4096 + sqr_u * (-768.0 + sqr_u * (320.0 - 175.0 * sqr_u))); // (3)
+ double B = sqr_u/1024.0 * (256.0 + sqr_u * ( -128.0 + sqr_u * (74.0 - 47.0 * sqr_u))); // (4)
+ double delta_sigma = B * sin_sigma * ( cos2_sigma_m + (B/4.0) * (cos(sigma)* (-1.0 + 2.0 * cos2_sigma_m)
+ - (B/6.0) * cos2_sigma_m * (-3.0 + 4.0 * math::sqr(sin_sigma)) * (-3.0 + 4.0 * cos2_sigma_m))); // (6)
+
+ double dist = m_ellipsoid.b() * A * (sigma - delta_sigma); // (19)
+
+ return return_type(dist);
+ }
+ };
+
+
+ // We might add a vincenty-like strategy also for point-segment distance, but to calculate the projected point is not trivial
+
+ } // namespace distance
+
+
+} // namespace strategy
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+template <typename P1, typename P2>
+struct strategy_tag<strategy::distance::vincenty<P1, P2> >
+{
+ typedef strategy_tag_distance_point_point type;
+};
+
+
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_EXTENSIONS_GIS_GEOGRAPHIC_STRATEGIES_VINCENTY_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/io/wkb/detail/endian.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/io/wkb/detail/endian.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,259 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Mateusz Loskot <mateusz_at_[hidden]> 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// Load/Store values from/to stream of bytes across different endianness.
+//
+// Original design of unrolled_byte_loops templates based on
+// endian utility library from Boost C++ Libraries,
+// source: boost/spirit/home/support/detail/integer/endian.hpp
+// Copyright Darin Adler 2000
+// Copyright Beman Dawes 2006, 2009
+// Distributed under the Boost Software License, Version 1.0.
+
+#ifndef BOOST_GEOMETRY_DETAIL_ENDIAN_HPP
+#define BOOST_GEOMETRY_DETAIL_ENDIAN_HPP
+
+#include <cassert>
+#include <climits>
+#include <cstring>
+#include <cstddef>
+
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/detail/endian.hpp>
+#include <boost/type_traits/is_signed.hpp>
+
+#if CHAR_BIT != 8
+#error Platforms with CHAR_BIT != 8 are not supported
+#endif
+
+// TODO: mloskot - add static asserts to validate compile-time pre-conditions
+
+namespace boost { namespace geometry
+
+{ namespace detail { namespace endian {
+
+// Endianness tag used to indicate load/store directoin
+
+struct big_endian_tag {};
+struct little_endian_tag {};
+
+#ifdef BOOST_BIG_ENDIAN
+typedef big_endian_tag native_endian_tag;
+#else
+typedef little_endian_tag native_endian_tag;
+#endif
+
+// Unrolled loops for loading and storing streams of bytes.
+
+template <typename T, std::size_t N, bool Sign = boost::is_signed<T>::value>
+struct unrolled_byte_loops
+{
+ typedef unrolled_byte_loops<T, N - 1, Sign> next;
+
+ template <typename Iterator>
+ static T load_forward(Iterator& bytes)
+ {
+ T const value = *bytes;
+ ++bytes;
+ return value | (next::load_forward(bytes) << 8);
+ }
+
+ template <typename Iterator>
+ static T load_backward(Iterator& bytes)
+ {
+ T const value = *(bytes - 1);
+ --bytes;
+ return value | (next::load_backward(bytes) << 8);
+ }
+
+ template <typename Iterator>
+ static void store_forward(Iterator& bytes, T value)
+ {
+ *bytes = static_cast<char>(value);
+ next::store_forward(++bytes, value >> 8);
+ }
+
+ template <typename Iterator>
+ static void store_backward(Iterator& bytes, T value)
+ {
+ *(bytes - 1) = static_cast<char>(value);
+ next::store_backward(--bytes, value >> 8);
+ }
+};
+
+template <typename T>
+struct unrolled_byte_loops<T, 1, false>
+{
+ template <typename Iterator>
+ static T load_forward(Iterator& bytes)
+ {
+ return *bytes;
+ }
+
+ template <typename Iterator>
+ static T load_backward(Iterator& bytes)
+ {
+ return *(bytes - 1);
+ }
+
+ template <typename Iterator>
+ static void store_forward(Iterator& bytes, T value)
+ {
+ // typename Iterator::value_type
+ *bytes = static_cast<char>(value);
+ }
+
+ template <typename Iterator>
+ static void store_backward(Iterator& bytes, T value)
+ {
+ *(bytes - 1) = static_cast<char>(value);
+ }
+};
+
+template <typename T>
+struct unrolled_byte_loops<T, 1, true>
+{
+ template <typename Iterator>
+ static T load_forward(Iterator& bytes)
+ {
+ return *reinterpret_cast<const signed char*>(&*bytes);
+ }
+
+ template <typename Iterator>
+ static T load_backward(Iterator& bytes)
+ {
+ return *reinterpret_cast<const signed char*>(&*(bytes - 1));
+ }
+
+ template <typename Iterator>
+ static void store_forward(Iterator& bytes, T value)
+ {
+ BOOST_STATIC_ASSERT((boost::is_signed<typename Iterator::value_type>::value));
+
+ *bytes = static_cast<typename Iterator::value_type>(value);
+ }
+
+ template <typename Iterator>
+ static void store_backward(Iterator& bytes, T value)
+ {
+ BOOST_STATIC_ASSERT((boost::is_signed<typename Iterator::value_type>::value));
+
+ *(bytes - 1) = static_cast<typename Iterator::value_type>(value);
+ }
+};
+
+// load/store operation dispatch
+// E, E - source and target endianness is the same
+// E1, E2 - source and target endianness is different (big-endian <-> little-endian)
+
+template <typename T, std::size_t N, typename Iterator, typename E>
+T load_dispatch(Iterator& bytes, E, E)
+{
+ return unrolled_byte_loops<T, N>::load_forward(bytes);
+}
+
+template <typename T, std::size_t N, typename Iterator, typename E1, typename E2>
+T load_dispatch(Iterator& bytes, E1, E2)
+{
+ std::advance(bytes, N);
+ return unrolled_byte_loops<T, N>::load_backward(bytes);
+}
+
+template <typename T, std::size_t N, typename Iterator, typename E>
+void store_dispatch(Iterator& bytes, T value, E, E)
+{
+ return unrolled_byte_loops<T, N>::store_forward(bytes, value);
+}
+
+template <typename T, std::size_t N, typename Iterator, typename E1, typename E2>
+void store_dispatch(Iterator& bytes, T value, E1, E2)
+{
+ std::advance(bytes, N);
+ return unrolled_byte_loops<T, N>::store_backward(bytes, value);
+}
+
+// numeric value holder for load/store operation
+
+template <typename T>
+struct endian_value_base
+{
+ typedef T value_type;
+ typedef native_endian_tag endian_type;
+
+ endian_value_base() : value(T()) {}
+ explicit endian_value_base(T value) : value(value) {}
+
+ operator T() const
+ {
+ return value;
+ }
+
+protected:
+ T value;
+};
+
+template <typename T, std::size_t N = sizeof(T)>
+struct endian_value : public endian_value_base<T>
+{
+ typedef endian_value_base<T> base;
+
+ endian_value() {}
+ explicit endian_value(T value) : base(value) {}
+
+ template <typename E, typename Iterator>
+ void load(Iterator bytes)
+ {
+ base::value = load_dispatch<T, N>(bytes, typename base::endian_type(), E());
+ }
+
+ template <typename E, typename Iterator>
+ void store(Iterator bytes)
+ {
+ store_dispatch<T, N>(bytes, base::value, typename base::endian_type(), E());
+ }
+};
+
+template <>
+struct endian_value<double, 8> : public endian_value_base<double>
+{
+ typedef endian_value_base<double> base;
+
+ endian_value() {}
+ explicit endian_value(double value) : base(value) {}
+
+ template <typename E, typename Iterator>
+ void load(Iterator bytes)
+ {
+ endian_value<boost::uint64_t, 8> raw;
+ raw.load<E>(bytes);
+
+ double& target_value = base::value;
+ std::memcpy(&target_value, &raw, sizeof(double));
+ }
+
+ template <typename E, typename Iterator>
+ void store(Iterator bytes)
+ {
+ boost::uint64_t raw;
+ double const& source_value = base::value;
+ std::memcpy(&raw, &source_value, sizeof(boost::uint64_t));
+
+ store_dispatch
+ <
+ boost::uint64_t,
+ sizeof(boost::uint64_t)
+ >(bytes, raw, typename base::endian_type(), E());
+ }
+};
+
+}} // namespace detail::endian
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_DETAIL_ENDIAN_HPP
+

Added: sandbox/geometry/boost/geometry/extensions/gis/io/wkb/detail/ogc.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/io/wkb/detail/ogc.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,84 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Mateusz Loskot <mateusz_at_[hidden]> 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_WKB_DETAIL_OGC_HPP
+#define BOOST_GEOMETRY_IO_WKB_DETAIL_OGC_HPP
+
+#include <boost/cstdint.hpp>
+
+namespace boost { namespace geometry
+{
+
+// The well-known binary representation for OGC geometry (WKBGeometry),
+// provides a portable representation of a geometry value as a contiguous
+// stream of bytes. It permits geometry values to be exchanged between
+// a client application and an SQL database in binary form.
+//
+// Basic Type definitions
+// byte : 1 byte
+// uint32 : 32 bit unsigned integer (4 bytes)
+// double : double precision number (8 bytes)
+//
+// enum wkbByteOrder
+// {
+// wkbXDR = 0, // Big Endian
+// wkbNDR = 1 // Little Endian
+// };
+//
+// enum wkbGeometryType
+// {
+// wkbPoint = 1,
+// wkbLineString = 2,
+// wkbPolygon = 3,
+// wkbMultiPoint = 4,
+// wkbMultiLineString = 5,
+// wkbMultiPolygon = 6,
+// wkbGeometryCollection = 7
+// };
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace wkb {
+
+// TODO: Replace 'struct' with scoped enum from <boost/detail/scoped_enum_emulation.hpp>
+// For older Boost, copy
+// <boost/spirit/home/support/detail/scoped_enum_emulation.hpp>
+// to
+// <boost/geometry/detail/scoped_enum_emulation.hpp>
+// and use it.
+
+struct byte_order_type
+{
+ enum enum_t
+ {
+ xdr = 0, // wkbXDR, bit-endian
+ ndr = 1, // wkbNDR, little-endian
+ unknown = 2 // not defined by OGC
+ };
+};
+
+struct geometry_type
+{
+ enum enum_t
+ {
+ point = 1,
+ linestring = 2,
+ polygon = 3
+
+ // TODO: Not implemented
+ //multipoint = 4,
+ //multilinestring = 5,
+ //multipolygon = 6,
+ //collection = 7
+ };
+};
+
+}} // namespace detail::endian
+#endif // DOXYGEN_NO_IMPL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_IO_WKB_DETAIL_OGC_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/io/wkb/detail/parser.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/io/wkb/detail/parser.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,308 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Mateusz Loskot <mateusz_at_[hidden]> 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_WKB_DETAIL_PARSER_HPP
+#define BOOST_GEOMETRY_IO_WKB_DETAIL_PARSER_HPP
+
+#include <cassert>
+#include <cstddef>
+#include <algorithm>
+#include <iterator>
+#include <limits>
+
+#include <boost/cstdint.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/extensions/gis/io/wkb/detail/endian.hpp>
+#include <boost/geometry/extensions/gis/io/wkb/detail/ogc.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace wkb {
+
+template <typename T>
+struct value_parser
+{
+ typedef T value_type;
+
+ template <typename Iterator>
+ static bool parse(Iterator& it, Iterator end, T& value, byte_order_type::enum_t order)
+ {
+ // Very basic pre-conditions check on stream of bytes passed in
+ BOOST_STATIC_ASSERT((
+ boost::is_integral<typename std::iterator_traits<Iterator>::value_type>::value
+ ));
+ BOOST_STATIC_ASSERT((sizeof(boost::uint8_t) ==
+ sizeof(typename std::iterator_traits<Iterator>::value_type)
+ ));
+
+ typedef typename std::iterator_traits<Iterator>::difference_type diff_type;
+ diff_type const required_size = sizeof(T);
+ if (it != end && std::distance(it, end) >= required_size)
+ {
+ typedef endian::endian_value<T> parsed_value_type;
+ parsed_value_type parsed_value;
+
+ // Decide on direcion of endianness translation, detault to native
+ if (byte_order_type::xdr == order)
+ {
+ parsed_value.template load<endian::big_endian_tag>(it);
+ }
+ else if (byte_order_type::ndr == order)
+ {
+ parsed_value.template load<endian::little_endian_tag>(it);
+ }
+ else
+ {
+ parsed_value.template load<endian::native_endian_tag>(it);
+ }
+
+ value = parsed_value;
+ std::advance(it, required_size);
+ return true;
+ }
+
+ return false;
+ }
+};
+
+struct byte_order_parser
+{
+ template <typename Iterator>
+ static bool parse(Iterator& it, Iterator end, byte_order_type::enum_t& order)
+ {
+ boost::uint8_t value;
+ if (value_parser<boost::uint8_t>::parse(it, end, value, byte_order_type::unknown))
+ {
+ if (byte_order_type::unknown > value)
+ {
+ order = byte_order_type::enum_t(value);
+ }
+ return true;
+ }
+ return false;
+ }
+};
+
+struct geometry_type_parser
+{
+ template <typename Iterator>
+ static bool parse(Iterator& it, Iterator end, geometry_type::enum_t& type,
+ byte_order_type::enum_t order)
+ {
+ boost::uint32_t value;
+ if (value_parser<boost::uint32_t>::parse(it, end, value, order))
+ {
+ // TODO: Refine the test when multi* geometries are supported
+
+ boost::uint32_t id = value & 0xff;
+ if (geometry_type::polygon >= id)
+ {
+ type = geometry_type::enum_t(id);
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+template <typename P, int I, int N>
+struct parsing_assigner
+{
+ template <typename Iterator>
+ static void run(Iterator& it, Iterator end, P& point, byte_order_type::enum_t order)
+ {
+ typedef typename coordinate_type<P>::type coordinate_type;
+
+ // coordinate type in WKB is always double
+ double value(0);
+ if (value_parser<double>::parse(it, end, value, order))
+ {
+ // actual coordinate type of point may be different
+ set<I>(point, static_cast<coordinate_type>(value));
+ }
+ else
+ {
+ // TODO: mloskot - Report premature termination at coordinate level
+ //throw failed to read coordinate value
+
+ // default initialized value as fallback
+ set<I>(point, coordinate_type());
+ }
+ parsing_assigner<P, I+1, N>::run(it, end, point, order);
+ }
+};
+
+template <typename P, int N>
+struct parsing_assigner<P, N, N>
+{
+ template <typename Iterator>
+ static void run(Iterator& it, Iterator end, P& point, byte_order_type::enum_t order)
+ {
+ // terminate
+ }
+};
+
+template <typename P>
+struct point_parser
+{
+ template <typename Iterator>
+ static bool parse(Iterator& it, Iterator end, P& point, byte_order_type::enum_t order)
+ {
+ // TODO: mloskot - Add assert on point dimension, 2d only
+
+ geometry_type::enum_t type;
+ if (geometry_type_parser::parse(it, end, type, order))
+ {
+ if (geometry_type::point == type && it != end)
+ {
+ parsing_assigner<P, 0, dimension<P>::value>::run(it, end, point, order);
+ }
+ return true;
+ }
+ return false;
+ }
+};
+
+template <typename C>
+struct point_container_parser
+{
+ template <typename Iterator>
+ static bool parse(Iterator& it, Iterator end, C& container, byte_order_type::enum_t order)
+ {
+ typedef typename point_type<C>::type point_type;
+
+ boost::uint32_t num_points(0);
+ if (!value_parser<boost::uint32_t>::parse(it, end, num_points, order))
+ {
+ return false;
+ }
+
+ typedef typename std::iterator_traits<Iterator>::difference_type size_type;
+ assert(num_points <= boost::uint32_t( (std::numeric_limits<size_type>::max)() ) );
+
+ size_type const container_size = static_cast<size_type>(num_points);
+ size_type const point_size = dimension<point_type>::value * sizeof(double);
+
+ if (std::distance(it, end) >= (container_size * point_size))
+ {
+ point_type point_buffer;
+ std::back_insert_iterator<C> output(std::back_inserter(container));
+
+ // Read coordinates into point and append point to line (ring)
+ size_type points_parsed = 0;
+ while (points_parsed < container_size && it != end)
+ {
+ parsing_assigner<point_type, 0, dimension<point_type>::value>::run(it, end, point_buffer, order);
+ output = point_buffer;
+ ++output;
+ ++points_parsed;
+ }
+
+ if (container_size != points_parsed)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+};
+
+template <typename L>
+struct linestring_parser
+{
+ template <typename Iterator>
+ static bool parse(Iterator& it, Iterator end, L& linestring, byte_order_type::enum_t order)
+ {
+ typedef typename point_type<L>::type point_type;
+
+ geometry_type::enum_t type;
+ if (!geometry_type_parser::parse(it, end, type, order))
+ {
+ return false;
+ }
+
+ if (geometry_type::linestring != type)
+ {
+ return false;
+ }
+
+ assert(it != end);
+ return point_container_parser<L>::parse(it, end, linestring, order);
+ }
+};
+
+template <typename Polygon>
+struct polygon_parser
+{
+ template <typename Iterator>
+ static bool parse(Iterator& it, Iterator end, Polygon& polygon, byte_order_type::enum_t order)
+ {
+ geometry_type::enum_t type;
+ if (!geometry_type_parser::parse(it, end, type, order))
+ {
+ return false;
+ }
+
+ boost::uint32_t num_rings(0);
+ if (geometry_type::polygon != type ||
+ !value_parser<boost::uint32_t>::parse(it, end, num_rings, order))
+ {
+ return false;
+ }
+
+ typedef typename ring_type<Polygon>::type ring_type;
+
+ std::size_t rings_parsed = 0;
+ while (rings_parsed < num_rings && it != end) //while (rings_parsed < num_rings && it != end)
+ {
+ if (0 == rings_parsed)
+ {
+ ring_type& ring0 = exterior_ring(polygon);
+ if (!point_container_parser<ring_type>::parse(it, end, ring0, order))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ interior_rings(polygon).resize(rings_parsed);
+ ring_type& ringN = interior_rings(polygon).back();
+ if (!point_container_parser<ring_type>::parse(it, end, ringN, order))
+ {
+ return false;
+ }
+ }
+ ++rings_parsed;
+ }
+
+ if (num_rings != rings_parsed)
+ {
+ return false;
+ }
+
+ return true;
+ }
+};
+
+}} // namespace detail::wkb
+#endif // DOXYGEN_NO_IMPL
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_IO_WKB_DETAIL_PARSER_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/io/wkb/read_wkb.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/io/wkb/read_wkb.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,107 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Mateusz Loskot <mateusz_at_[hidden]> 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_WKB_READ_WKB_HPP
+#define BOOST_GEOMETRY_IO_WKB_READ_WKB_HPP
+
+#include <iterator>
+
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/extensions/gis/io/wkb/detail/parser.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, typename G>
+struct read_wkb {};
+
+template <typename G>
+struct read_wkb<point_tag, G>
+{
+ template <typename Iterator>
+ static inline bool parse(Iterator& it, Iterator end, G& geometry,
+ detail::wkb::byte_order_type::enum_t order)
+ {
+ return detail::wkb::point_parser<G>::parse(it, end, geometry, order);
+ }
+};
+
+template <typename G>
+struct read_wkb<linestring_tag, G>
+{
+ template <typename Iterator>
+ static inline bool parse(Iterator& it, Iterator end, G& geometry,
+ detail::wkb::byte_order_type::enum_t order)
+ {
+ geometry::clear(geometry);
+ return detail::wkb::linestring_parser<G>::parse(it, end, geometry, order);
+ }
+};
+
+template <typename G>
+struct read_wkb<polygon_tag, G>
+{
+ template <typename Iterator>
+ static inline bool parse(Iterator& it, Iterator end, G& geometry,
+ detail::wkb::byte_order_type::enum_t order)
+ {
+ geometry::clear(geometry);
+ return detail::wkb::polygon_parser<G>::parse(it, end, geometry, order);
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+template <typename Iterator, typename G>
+inline bool read_wkb(Iterator begin, Iterator end, G& geometry)
+{
+ // Stream of bytes can only be parsed using random access iterator.
+ BOOST_STATIC_ASSERT((
+ boost::is_convertible
+ <
+ typename std::iterator_traits<Iterator>::iterator_category,
+ const std::random_access_iterator_tag&
+ >::value));
+
+ detail::wkb::byte_order_type::enum_t byte_order;
+ if (detail::wkb::byte_order_parser::parse(begin, end, byte_order))
+ {
+ return dispatch::read_wkb
+ <
+ typename tag<G>::type,
+ G
+ >::parse(begin, end, geometry, byte_order);
+ }
+
+ return false;
+}
+
+template <typename ByteType, typename G>
+inline bool read_wkb(ByteType const* bytes, std::size_t length, G& geometry)
+{
+ BOOST_STATIC_ASSERT((boost::is_integral<ByteType>::value));
+ BOOST_STATIC_ASSERT((sizeof(boost::uint8_t) == sizeof(ByteType)));
+
+ ByteType const* begin = bytes;
+ ByteType const* const end = bytes + length;
+
+ return read_wkb(begin, end, geometry);
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_IO_WKB_READ_WKB_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/io/wkb/utility.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/io/wkb/utility.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,89 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Mateusz Loskot <mateusz_at_[hidden]> 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_WKB_UTILITY_HPP
+#define BOOST_GEOMETRY_IO_WKB_UTILITY_HPP
+
+#include <iomanip>
+#include <iterator>
+#include <sstream>
+#include <string>
+
+#include <boost/cstdint.hpp>
+
+namespace boost { namespace geometry {
+
+// TODO: Waiting for errors handling design, eventually return bool
+// may be replaced to throw exception.
+
+template <typename OutputIterator>
+bool hex2wkb(std::string const& hex, OutputIterator bytes)
+{
+ // Bytes can be only written to output iterator.
+ BOOST_STATIC_ASSERT((boost::is_convertible<
+ typename std::iterator_traits<OutputIterator>::iterator_category,
+ const std::output_iterator_tag&>::value));
+
+ std::string::size_type const byte_size = 2;
+ if (0 != hex.size() % byte_size)
+ {
+ return false;
+ }
+
+ std::string::size_type const size = hex.size() / byte_size;
+ for (std::string::size_type i = 0; i < size; ++i)
+ {
+ // TODO: This is confirmed performance killer - to be replaced with static char-to-byte map --mloskot
+ std::istringstream iss(hex.substr(i * byte_size, byte_size));
+ unsigned int byte(0);
+ if (!(iss >> std::hex >> byte))
+ {
+ return false;
+ }
+ *bytes = static_cast<boost::uint8_t>(byte);
+ ++bytes;
+ }
+
+ return true;
+}
+
+template <typename Iterator>
+bool wkb2hex(Iterator begin, Iterator end, std::string& hex)
+{
+ // Stream of bytes can only be passed using random access iterator.
+ BOOST_STATIC_ASSERT((boost::is_convertible<
+ typename std::iterator_traits<Iterator>::iterator_category,
+ const std::random_access_iterator_tag&>::value));
+
+ const char hexalpha[] = "0123456789ABCDEF";
+ char hexbyte[3] = { 0 };
+ std::ostringstream oss;
+
+ Iterator it = begin;
+ while (it != end)
+ {
+ boost::uint8_t byte = static_cast<boost::uint8_t>(*it);
+ hexbyte[0] = hexalpha[(byte >> 4) & 0xf];
+ hexbyte[1] = hexalpha[byte & 0xf];
+ hexbyte[2] = '\0';
+ oss << std::setw(2) << hexbyte;
+ ++it;
+ }
+
+ // TODO: Binary streams can be big.
+ // Does it make sense to request stream buffer of proper (large) size or
+ // use incremental appends within while-loop?
+ hex = oss.str();
+
+ // Poor-man validation, no performance penalty expected
+ // because begin/end always are random access iterators.
+ return hex.size() == (2 * std::distance(begin, end));
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_IO_WKB_UTILITY_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/io/wkt/detail/wkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/io/wkt/detail/wkt.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,43 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2008-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_WKT_DETAIL_WKT_HPP
+#define BOOST_GEOMETRY_IO_WKT_DETAIL_WKT_HPP
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace wkt {
+
+
+struct prefix_point
+{
+ static inline const char* apply() { return "POINT"; }
+};
+
+struct prefix_polygon
+{
+ static inline const char* apply() { return "POLYGON"; }
+};
+
+struct prefix_linestring
+{
+ static inline const char* apply() { return "LINESTRING"; }
+};
+
+
+
+}} // namespace wkt::impl
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_IO_WKT_DETAIL_WKT_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/io/wkt/detail/wkt_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/io/wkt/detail/wkt_multi.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,50 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2008-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_WKT_HPP
+#define BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_WKT_HPP
+
+
+#include <boost/geometry/extensions/gis/io/wkt/write_wkt.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace wkt {
+
+struct prefix_null
+{
+ static inline const char* apply() { return ""; }
+};
+
+struct prefix_multipoint
+{
+ static inline const char* apply() { return "MULTIPOINT"; }
+};
+
+struct prefix_multilinestring
+{
+ static inline const char* apply() { return "MULTILINESTRING"; }
+};
+
+struct prefix_multipolygon
+{
+ static inline const char* apply() { return "MULTIPOLYGON"; }
+};
+
+
+
+}} // namespace wkt::impl
+#endif
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_WKT_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/io/wkt/read_wkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/io/wkt/read_wkt.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,681 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2008-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_READ_WKT_HPP
+#define BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_READ_WKT_HPP
+
+#include <string>
+
+#include <boost/lexical_cast.hpp>
+#include <boost/tokenizer.hpp>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/type_traits.hpp>
+
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/clear.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/exception.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+
+#include <boost/geometry/extensions/gis/io/wkt/detail/wkt.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+
+/*!
+\brief Exception showing things wrong with WKT parsing
+\ingroup wkt
+*/
+struct read_wkt_exception : public geometry::exception
+{
+ template <typename Iterator>
+ read_wkt_exception(std::string const& msg,
+ Iterator const& it, Iterator const& end, std::string const& wkt)
+ : message(msg)
+ , wkt(wkt)
+ {
+ if (it != end)
+ {
+ source = " at '";
+ source += it->c_str();
+ source += "'";
+ }
+ complete = message + source + " in '" + wkt.substr(0, 100) + "'";
+ }
+
+ read_wkt_exception(std::string const& msg, std::string const& wkt)
+ : message(msg)
+ , wkt(wkt)
+ {
+ complete = message + "' in (" + wkt.substr(0, 100) + ")";
+ }
+
+ virtual ~read_wkt_exception() throw() {}
+
+ virtual const char* what() const throw()
+ {
+ return complete.c_str();
+ }
+private :
+ std::string source;
+ std::string message;
+ std::string wkt;
+ std::string complete;
+};
+
+
+
+#ifndef DOXYGEN_NO_DETAIL
+// (wkt: Well Known Text, defined by OGC for all geometries and implemented by e.g. databases (MySQL, PostGIS))
+namespace detail { namespace wkt {
+
+typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+
+template <typename Point, std::size_t Dimension, std::size_t DimensionCount>
+struct parsing_assigner
+{
+ static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
+ Point& point, std::string const& wkt)
+ {
+ typedef typename coordinate_type<Point>::type coordinate_type;
+ typedef typename boost::mpl::if_c
+ <
+ boost::is_fundamental<coordinate_type>::type::value,
+ coordinate_type,
+ double
+ >::type type;
+
+
+
+ // Stop at end of tokens, or at "," ot ")"
+ bool finished = (it == end || *it == "," || *it == ")");
+
+ try
+ {
+ // Initialize missing coordinates to default constructor (zero)
+ // OR
+ // 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
+ set<Dimension>(point, (finished ? type() : boost::lexical_cast<type>(it->c_str())));
+ }
+ catch(boost::bad_lexical_cast const& blc)
+ {
+ throw read_wkt_exception(blc.what(), it, end, wkt);
+ }
+ catch(std::exception const& e)
+ {
+ throw read_wkt_exception(e.what(), it, end, wkt);
+ }
+ catch(...)
+ {
+ throw read_wkt_exception("", it, end, wkt);
+ }
+
+ parsing_assigner<Point, Dimension + 1, DimensionCount>::apply(
+ (finished ? it : ++it), end, point, wkt);
+ }
+};
+
+template <typename Point, std::size_t DimensionCount>
+struct parsing_assigner<Point, DimensionCount, DimensionCount>
+{
+ static inline void apply(tokenizer::iterator&, tokenizer::iterator, Point&,
+ std::string const&)
+ {
+ }
+};
+
+
+
+template <typename Iterator>
+inline void handle_open_parenthesis(Iterator& it,
+ Iterator const& end, std::string const& wkt)
+{
+ if (it == end || *it != "(")
+ {
+ throw read_wkt_exception("Expected '('", it, end, wkt);
+ }
+ ++it;
+}
+
+
+template <typename Iterator>
+inline void handle_close_parenthesis(Iterator& it,
+ Iterator const& end, std::string const& wkt)
+{
+ if (it != end && *it == ")")
+ {
+ ++it;
+ }
+ else
+ {
+ throw read_wkt_exception("Expected ')'", it, end, wkt);
+ }
+}
+
+template <typename Iterator>
+inline void check_end(Iterator& it,
+ Iterator const& end, std::string const& wkt)
+{
+ if (it != end)
+ {
+ throw read_wkt_exception("Too much tokens", it, end, wkt);
+ }
+}
+
+/*!
+\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
+*/
+template <typename Point>
+struct container_inserter
+{
+ // Version with output iterator
+ template <typename OutputIterator>
+ static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
+ std::string const& wkt, OutputIterator out)
+ {
+ handle_open_parenthesis(it, end, wkt);
+
+ Point point;
+
+ // Parse points until closing parenthesis
+
+ while (it != end && *it != ")")
+ {
+ parsing_assigner
+ <
+ Point,
+ 0,
+ dimension<Point>::value
+ >::apply(it, end, point, wkt);
+ out = point;
+ ++out;
+ if (it != end && *it == ",")
+ {
+ ++it;
+ }
+ }
+
+ handle_close_parenthesis(it, end, wkt);
+ }
+};
+
+/*!
+\brief Internal, parses a point from a string like this "(x y)"
+\note used for parsing points and multi-points
+*/
+template <typename P>
+struct point_parser
+{
+ static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
+ std::string const& wkt, P& point)
+ {
+ handle_open_parenthesis(it, end, wkt);
+ parsing_assigner<P, 0, dimension<P>::value>::apply(it, end, point, wkt);
+ handle_close_parenthesis(it, end, wkt);
+ }
+};
+
+
+template <typename Geometry>
+struct linestring_parser
+{
+ static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
+ std::string const& wkt, Geometry& geometry)
+ {
+ container_inserter
+ <
+ typename point_type<Geometry>::type
+ >::apply(it, end, wkt, std::back_inserter(geometry));
+ }
+};
+
+
+template <typename Ring>
+struct ring_parser
+{
+ static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
+ std::string const& wkt, Ring& ring)
+ {
+ // A ring should look like polygon((x y,x y,x y...))
+ // So handle the extra opening/closing parentheses
+ // and in between parse using the container-inserter
+ handle_open_parenthesis(it, end, wkt);
+ container_inserter
+ <
+ typename point_type<Ring>::type
+ >::apply(it, end, wkt, std::back_inserter(ring));
+ handle_close_parenthesis(it, end, wkt);
+ }
+};
+
+
+
+
+/*!
+\brief Internal, parses a polygon from a string like this "((x y,x y),(x y,x y))"
+\note used for parsing polygons and multi-polygons
+*/
+template <typename Polygon>
+struct polygon_parser
+{
+ static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
+ std::string const& wkt, Polygon& poly)
+ {
+ typedef container_inserter
+ <
+ typename point_type<Polygon>::type
+ > container_inserter;
+
+ handle_open_parenthesis(it, end, wkt);
+
+ int n = -1;
+
+ // Stop at ")"
+ while (it != end && *it != ")")
+ {
+ // Parse ring
+ if (++n == 0)
+ {
+ container_inserter::apply(it, end, wkt,
+ std::back_inserter(exterior_ring(poly)));
+ }
+ else
+ {
+ interior_rings(poly).resize(n);
+ container_inserter::apply(it, end, wkt,
+ std::back_inserter(interior_rings(poly).back()));
+ }
+
+ if (it != end && *it == ",")
+ {
+ // Skip "," after ring is parsed
+ ++it;
+ }
+ }
+
+ handle_close_parenthesis(it, end, wkt);
+ }
+};
+
+inline bool one_of(tokenizer::iterator const& it, std::string const& value,
+ bool& is_present)
+{
+ if (boost::iequals(*it, value))
+ {
+ is_present = true;
+ return true;
+ }
+ return false;
+}
+
+inline bool one_of(tokenizer::iterator const& it, std::string const& value,
+ bool& present1, bool& present2)
+{
+ if (boost::iequals(*it, value))
+ {
+ present1 = true;
+ present2 = true;
+ return true;
+ }
+ return false;
+}
+
+
+inline void handle_empty_z_m(tokenizer::iterator& it, tokenizer::iterator end,
+ bool& has_empty, bool& has_z, bool& has_m)
+{
+ has_empty = false;
+ has_z = false;
+ has_m = false;
+
+ // WKT can optionally have Z and M (measured) values as in
+ // POINT ZM (1 1 5 60), POINT M (1 1 80), POINT Z (1 1 5)
+ // GGL supports any of them as coordinate values, but is not aware
+ // of any Measured value.
+ while (it != end
+ && (one_of(it, "M", has_m)
+ || one_of(it, "Z", has_z)
+ || one_of(it, "EMPTY", has_empty)
+ || one_of(it, "MZ", has_m, has_z)
+ || one_of(it, "ZM", has_z, has_m)
+ )
+ )
+ {
+ ++it;
+ }
+}
+
+/*!
+\brief Internal, starts parsing
+\param tokens boost tokens, parsed with separator " " and keeping separator "()"
+\param geometry string to compare with first token
+*/
+template <typename Geometry>
+inline bool initialize(tokenizer const& tokens,
+ std::string const& geometry_name, std::string const& wkt,
+ tokenizer::iterator& it)
+{
+ it = tokens.begin();
+ if (it != tokens.end() && boost::iequals(*it++, geometry_name))
+ {
+ bool has_empty, has_z, has_m;
+
+ handle_empty_z_m(it, tokens.end(), has_empty, has_z, has_m);
+
+ if (has_z && dimension<Geometry>::type::value < 3)
+ {
+ throw read_wkt_exception("Z only allowed for 3 or more dimensions", wkt);
+ }
+ if (has_empty)
+ {
+ check_end(it, tokens.end(), wkt);
+ return false;
+ }
+ // M is ignored at all.
+
+ return true;
+ }
+ throw read_wkt_exception(std::string("Should start with '") + geometry_name + "'", wkt);
+}
+
+
+template <typename Geometry, template<typename> class Parser, typename PrefixPolicy>
+struct geometry_parser
+{
+ static inline void apply(std::string const& wkt, Geometry& geometry)
+ {
+ geometry::clear(geometry);
+
+ tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
+ tokenizer::iterator it;
+ if (initialize<Geometry>(tokens, PrefixPolicy::apply(), wkt, it))
+ {
+ Parser<Geometry>::apply(it, tokens.end(), wkt, geometry);
+ check_end(it, tokens.end(), wkt);
+ }
+ }
+};
+
+
+
+
+
+/*!
+\brief Supports box parsing
+\note OGC does not define the box geometry, and WKT does not support boxes.
+ However, to be generic GGL supports reading and writing from and to boxes.
+ Boxes are outputted as a standard POLYGON. GGL can read boxes from
+ a standard POLYGON, from a POLYGON with 2 points of from a BOX
+\tparam Box the box
+*/
+template <typename Box>
+struct box_parser
+{
+ static inline void apply(std::string const& wkt, Box& box)
+ {
+ bool should_close = false;
+ tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
+ tokenizer::iterator it = tokens.begin();
+ tokenizer::iterator end = tokens.end();
+ if (it != end && boost::iequals(*it, "POLYGON"))
+ {
+ ++it;
+ bool has_empty, has_z, has_m;
+ handle_empty_z_m(it, end, has_empty, has_z, has_m);
+ if (has_empty)
+ {
+ assign_zero(box);
+ return;
+ }
+ handle_open_parenthesis(it, end, wkt);
+ should_close = true;
+ }
+ else if (it != end && boost::iequals(*it, "BOX"))
+ {
+ ++it;
+ }
+ else
+ {
+ throw read_wkt_exception("Should start with 'POLYGON' or 'BOX'", wkt);
+ }
+
+ typedef typename point_type<Box>::type point_type;
+ std::vector<point_type> points;
+ container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points));
+
+ if (should_close)
+ {
+ handle_close_parenthesis(it, end, wkt);
+ }
+ check_end(it, end, wkt);
+
+ int index = 0;
+ int n = boost::size(points);
+ if (n == 2)
+ {
+ index = 1;
+ }
+ else if (n == 4 || n == 5)
+ {
+ // In case of 4 or 5 points, we do not check the other ones, just
+ // take the opposite corner which is always 2
+ index = 2;
+ }
+ else
+ {
+ throw read_wkt_exception("Box should have 2,4 or 5 points", wkt);
+ }
+
+ assign_point_to_index<min_corner>(points.front(), box);
+ assign_point_to_index<max_corner>(points[index], box);
+ }
+};
+
+
+/*!
+\brief Supports segment parsing
+\note OGC does not define the segment, and WKT does not support segmentes.
+ However, it is useful to implement it, also for testing purposes
+\tparam Segment the segment
+*/
+template <typename Segment>
+struct segment_parser
+{
+ static inline void apply(std::string const& wkt, Segment& segment)
+ {
+ tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
+ tokenizer::iterator it = tokens.begin();
+ tokenizer::iterator end = tokens.end();
+ if (it != end &&
+ (boost::iequals(*it, "SEGMENT")
+ || boost::iequals(*it, "LINESTRING") ))
+ {
+ ++it;
+ }
+ else
+ {
+ throw read_wkt_exception("Should start with 'LINESTRING' or 'SEGMENT'", wkt);
+ }
+
+ typedef typename point_type<Segment>::type point_type;
+ std::vector<point_type> points;
+ container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points));
+
+ check_end(it, end, wkt);
+
+ if (boost::size(points) == 2)
+ {
+ assign_point_to_index<0>(points.front(), segment);
+ assign_point_to_index<1>(points.back(), segment);
+ }
+ else
+ {
+ throw read_wkt_exception("Segment should have 2 points", wkt);
+ }
+
+ }
+};
+
+
+
+}} // namespace detail::wkt
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, typename Geometry>
+struct read_wkt {};
+
+
+template <typename Point>
+struct read_wkt<point_tag, Point>
+ : detail::wkt::geometry_parser
+ <
+ Point,
+ detail::wkt::point_parser,
+ detail::wkt::prefix_point
+ >
+{};
+
+
+template <typename L>
+struct read_wkt<linestring_tag, L>
+ : detail::wkt::geometry_parser
+ <
+ L,
+ detail::wkt::linestring_parser,
+ detail::wkt::prefix_linestring
+ >
+{};
+
+template <typename Ring>
+struct read_wkt<ring_tag, Ring>
+ : detail::wkt::geometry_parser
+ <
+ Ring,
+ detail::wkt::ring_parser,
+ detail::wkt::prefix_polygon
+ >
+{};
+
+template <typename Geometry>
+struct read_wkt<polygon_tag, Geometry>
+ : detail::wkt::geometry_parser
+ <
+ Geometry,
+ detail::wkt::polygon_parser,
+ detail::wkt::prefix_polygon
+ >
+{};
+
+
+// Box (Non-OGC)
+template <typename Box>
+struct read_wkt<box_tag, Box>
+ : detail::wkt::box_parser<Box>
+{};
+
+// Segment (Non-OGC)
+template <typename Segment>
+struct read_wkt<segment_tag, Segment>
+ : detail::wkt::segment_parser<Segment>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Parses OGC Well-Known Text (\ref WKT) into a geometry (any geometry)
+\ingroup wkt
+\param wkt string containing \ref WKT
+\param geometry output geometry
+\par Example:
+\note It is case insensitive and can have the WKT forms "point", "point m", "point z", "point zm", "point mz"
+\note Empty sequences can have forms as "LINESTRING ()" or "POLYGON(())"
+Small example showing how to use read_wkt to build a point
+\dontinclude doxygen_1.cpp
+\skip example_from_wkt_point
+\line {
+\until }
+\par Example:
+Small example showing how to use read_wkt to build a linestring
+\dontinclude doxygen_1.cpp
+\skip example_from_wkt_linestring
+\line {
+\until }
+\par Example:
+Small example showing how to use read_wkt to build a polygon
+\dontinclude doxygen_1.cpp
+\skip example_from_wkt_polygon
+\line {
+\until }
+*/
+template <typename Geometry>
+inline void read_wkt(std::string const& wkt, Geometry& geometry)
+{
+ geometry::concept::check<Geometry>();
+ dispatch::read_wkt<typename tag<Geometry>::type, Geometry>::apply(wkt, geometry);
+}
+
+/*!
+\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
+\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 read_wkt with an output iterator
+\dontinclude doxygen_1.cpp
+\skip example_from_wkt_output_iterator
+\line {
+\until }
+*/
+template <typename Point, typename Out>
+inline void read_wkt(std::string const& wkt, Out out)
+{
+ geometry::concept::check<Point>();
+
+ // Todo: maybe take this from the string, or do not call initialize, such that
+ // any coordinate string is parsed and outputted
+ std::string const& tag = "linestring";
+
+ detail::wkt::tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
+ detail::wkt::tokenizer::iterator it;
+ if (detail::wkt::initialize<Point>(tokens, tag, wkt, it))
+ {
+ detail::wkt::container_inserter<Point>::apply(it, tokens.end(), wkt, out);
+ }
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_READ_WKT_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/io/wkt/read_wkt_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/io/wkt/read_wkt_multi.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,105 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2008-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_READ_WKT_MULTI_HPP
+#define BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_READ_WKT_MULTI_HPP
+
+#include <string>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/core/point_type.hpp>
+
+#include <boost/geometry/extensions/gis/io/wkt/read_wkt.hpp>
+#include <boost/geometry/extensions/gis/io/wkt/detail/wkt_multi.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace detail { namespace wkt {
+
+template <typename MultiGeometry, template<typename> class Parser, typename PrefixPolicy>
+struct multi_parser
+{
+ static inline void apply(std::string const& wkt, MultiGeometry& geometry)
+ {
+ geometry.clear();
+
+ tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
+ tokenizer::iterator it;
+ if (initialize<MultiGeometry>(tokens, PrefixPolicy::apply(), wkt, it))
+ {
+ handle_open_parenthesis(it, tokens.end(), wkt);
+
+ // Parse sub-geometries
+ while(it != tokens.end() && *it != ")")
+ {
+ geometry.resize(geometry.size() + 1);
+ Parser
+ <
+ typename boost::range_value<MultiGeometry>::type
+ >::apply(it, tokens.end(), wkt, geometry.back());
+ if (it != tokens.end() && *it == ",")
+ {
+ // Skip "," after multi-element is parsed
+ ++it;
+ }
+ }
+
+ handle_close_parenthesis(it, tokens.end(), wkt);
+ }
+ }
+};
+
+
+
+
+}} // namespace detail::wkt
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename MultiGeometry>
+struct read_wkt<multi_point_tag, MultiGeometry>
+ : detail::wkt::multi_parser
+ <
+ MultiGeometry,
+ detail::wkt::point_parser,
+ detail::wkt::prefix_multipoint
+ >
+{};
+
+
+template <typename MultiGeometry>
+struct read_wkt<multi_linestring_tag, MultiGeometry>
+ : detail::wkt::multi_parser
+ <
+ MultiGeometry,
+ detail::wkt::linestring_parser,
+ detail::wkt::prefix_multilinestring
+ >
+{};
+
+
+template <typename MultiGeometry>
+struct read_wkt<multi_polygon_tag, MultiGeometry>
+ : detail::wkt::multi_parser
+ <
+ MultiGeometry,
+ detail::wkt::polygon_parser,
+ detail::wkt::prefix_multipolygon
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_READ_WKT_MULTI_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/io/wkt/stream_wkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/io/wkt/stream_wkt.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,40 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2008-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_STREAM_WKT_HPP
+#define BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_STREAM_WKT_HPP
+
+#include <boost/geometry/extensions/gis/io/wkt/write_wkt.hpp>
+
+// This short file contains only one manipulator, streaming as WKT
+// Don't move contents to as_wkt, developers must be able to choose how to stream
+
+// Don't use namespace boost::geometry, to enable the library to stream custom geometries which
+// are living outside the namespace boost { namespace geometry
+
+//namespace boost { namespace geometry
+//{
+
+
+/*!
+\brief Streams a geometry as Well-Known Text
+\ingroup wkt
+*/
+template<typename Char, typename Traits, typename Geometry>
+inline std::basic_ostream<Char,Traits>& operator<<
+ (
+ std::basic_ostream<Char,Traits> &os,
+ Geometry const& geom
+ )
+{
+ os << boost::geometry::wkt(geom);
+ return os;
+}
+
+//}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_STREAM_WKT_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/io/wkt/wkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/io/wkt/wkt.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,19 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2008-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_WKT_HPP
+#define BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_WKT_HPP
+
+
+#include <boost/geometry/extensions/gis/io/wkt/read_wkt.hpp>
+#include <boost/geometry/extensions/gis/io/wkt/write_wkt.hpp>
+
+#include <boost/geometry/extensions/gis/io/wkt/read_wkt_multi.hpp>
+#include <boost/geometry/extensions/gis/io/wkt/write_wkt_multi.hpp>
+
+
+#endif // BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_WKT_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/io/wkt/write_wkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/io/wkt/write_wkt.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,360 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2008-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_WRITE_WKT_HPP
+#define BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_WRITE_WKT_HPP
+
+#include <ostream>
+#include <string>
+
+#include <boost/concept/assert.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/geometries/linear_ring.hpp>
+
+#include <boost/geometry/extensions/gis/io/wkt/detail/wkt.hpp>
+
+/*!
+\defgroup wkt wkt: parse and stream WKT (Well-Known Text)
+The wkt classes stream the specified geometry as \ref OGC Well Known Text (\ref WKT). It is defined for OGC geometries.
+It is therefore not defined for all geometries (e.g. not for 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 boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace wkt {
+
+template <typename P, int I, int Count>
+struct stream_coordinate
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os, P const& p)
+ {
+ os << (I > 0 ? " " : "") << get<I>(p);
+ stream_coordinate<P, I + 1, Count>::apply(os, p);
+ }
+};
+
+template <typename P, int Count>
+struct stream_coordinate<P, Count, Count>
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>&, P const&)
+ {}
+};
+
+struct prefix_linestring_par
+{
+ static inline const char* apply() { return "LINESTRING("; }
+};
+
+struct prefix_ring_par_par
+{
+ // Note, double parentheses are intentional, indicating WKT ring begin/end
+ static inline const char* apply() { return "POLYGON(("; }
+};
+
+struct opening_parenthesis
+{
+ static inline const char* apply() { return "("; }
+};
+
+struct closing_parenthesis
+{
+ static inline const char* apply() { return ")"; }
+};
+
+struct double_closing_parenthesis
+{
+ static inline const char* apply() { return "))"; }
+};
+
+
+
+
+/*!
+\brief Stream points as \ref WKT
+*/
+template <typename Point, typename Policy>
+struct wkt_point
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os, Point const& p)
+ {
+ os << Policy::apply() << "(";
+ stream_coordinate<Point, 0, dimension<Point>::type::value>::apply(os, p);
+ os << ")";
+ }
+};
+
+/*!
+\brief Stream ranges as WKT
+\note policy is used to stream prefix/postfix, enabling derived classes to override this
+*/
+template <typename Range, typename PrefixPolicy, typename SuffixPolicy>
+struct wkt_range
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Range const& range)
+ {
+ typedef typename boost::range_const_iterator<Range>::type iterator_type;
+
+ bool first = true;
+
+ os << PrefixPolicy::apply();
+
+ // TODO: check EMPTY here
+
+ for (iterator_type it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ os << (first ? "" : ",");
+ stream_coordinate
+ <
+ point_type, 0, dimension<point_type>::type::value
+ >::apply(os, *it);
+ first = false;
+ }
+
+ os << SuffixPolicy::apply();
+ }
+
+private:
+ typedef typename boost::range_value<Range>::type point_type;
+};
+
+/*!
+\brief Stream sequence of points as WKT-part, e.g. (1 2),(3 4)
+\note Used in polygon, all multi-geometries
+*/
+
+
+
+template <typename Range>
+struct wkt_sequence
+ : wkt_range
+ <
+ Range,
+ opening_parenthesis,
+ closing_parenthesis
+ >
+{};
+
+
+template <typename Polygon, typename PrefixPolicy>
+struct wkt_poly
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Polygon const& poly)
+ {
+ typedef typename ring_type<Polygon>::type ring;
+ typedef typename boost::range_const_iterator<
+ typename interior_type<Polygon>::type>::type iterator;
+
+ os << PrefixPolicy::apply();
+ // TODO: check EMPTY here
+ os << "(";
+ wkt_sequence<ring>::apply(os, exterior_ring(poly));
+ for (iterator it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly));
+ ++it)
+ {
+ os << ",";
+ wkt_sequence<ring>::apply(os, *it);
+ }
+ os << ")";
+ }
+};
+
+
+template <typename Box>
+struct wkt_box
+{
+ typedef typename point_type<Box>::type point_type;
+
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Box const& box)
+ {
+ // Convert to linear ring, then stream
+ typedef linear_ring<point_type> ring_type;
+ ring_type ring;
+ geometry::convert(box, ring);
+ os << "POLYGON(";
+ wkt_sequence<ring_type>::apply(os, ring);
+ os << ")";
+ }
+
+ private:
+
+ inline wkt_box()
+ {
+ // Only streaming of boxes with two dimensions is support, otherwise it is a polyhedron!
+ //assert_dimension<B, 2>();
+ }
+};
+
+}} // namespace detail::wkt
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+template <typename Tag, typename Geometry>
+struct wkt {};
+
+
+template <typename Point>
+struct wkt<point_tag, Point>
+ : detail::wkt::wkt_point
+ <
+ Point,
+ detail::wkt::prefix_point
+ >
+{};
+
+
+template <typename Linestring>
+struct wkt<linestring_tag, Linestring>
+ : detail::wkt::wkt_range
+ <
+ Linestring,
+ detail::wkt::prefix_linestring_par,
+ detail::wkt::closing_parenthesis
+ >
+{};
+
+
+/*!
+\brief Specialization to stream a box as WKT
+\details A "box" does not exist in WKT.
+It is therefore streamed as a polygon
+*/
+template <typename Box>
+struct wkt<box_tag, Box>
+ : detail::wkt::wkt_box<Box>
+{};
+
+
+/*!
+\brief Specialization to stream a ring as WKT
+\details A "linear_ring" does not exist in WKT.
+A linear ring is equivalent to a polygon without inner rings
+It is therefore streamed as a polygon
+*/
+template <typename Ring>
+struct wkt<ring_tag, Ring>
+ : detail::wkt::wkt_range
+ <
+ Ring,
+ detail::wkt::prefix_ring_par_par,
+ detail::wkt::double_closing_parenthesis
+ >
+{};
+
+
+/*!
+\brief Specialization to stream polygon as WKT
+*/
+template <typename Polygon>
+struct wkt<polygon_tag, Polygon>
+ : detail::wkt::wkt_poly
+ <
+ Polygon,
+ detail::wkt::prefix_polygon
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\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 wkt class
+\dontinclude doxygen_1.cpp
+\skip example_as_wkt_point
+\line {
+\until }
+*/
+template <typename Geometry>
+class wkt_manipulator
+{
+public:
+
+ inline wkt_manipulator(Geometry const& g)
+ : m_geometry(g)
+ {}
+
+ template <typename Char, typename Traits>
+ inline friend std::basic_ostream<Char, Traits>& operator<<(
+ std::basic_ostream<Char, Traits>& os,
+ wkt_manipulator const& m)
+ {
+ dispatch::wkt
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::apply(os, m.m_geometry);
+ os.flush();
+ return os;
+ }
+
+private:
+ Geometry const& m_geometry;
+};
+
+/*!
+\brief Main WKT-streaming function
+\ingroup wkt
+\par Example:
+Small example showing how to use the wkt helper function
+\dontinclude doxygen_1.cpp
+\skip example_as_wkt_vector
+\line {
+\until }
+*/
+template <typename Geometry>
+inline wkt_manipulator<Geometry> wkt(Geometry const& geometry)
+{
+ concept::check<const Geometry>();
+
+ return wkt_manipulator<Geometry>(geometry);
+}
+
+
+// Backward compatibility
+template <typename Geometry>
+inline wkt_manipulator<Geometry> make_wkt(Geometry const& geometry)
+{
+ concept::check<const Geometry>();
+
+ return wkt_manipulator<Geometry>(geometry);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_WRITE_WKT_HPP

Added: sandbox/geometry/boost/geometry/extensions/gis/io/wkt/write_wkt_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/gis/io/wkt/write_wkt_multi.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,109 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2008-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_WRITE_WKT_MULTI_HPP
+#define BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_WRITE_WKT_MULTI_HPP
+
+
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+#include <boost/geometry/extensions/gis/io/wkt/write_wkt.hpp>
+#include <boost/geometry/extensions/gis/io/wkt/detail/wkt_multi.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace wkt {
+
+
+template <typename Multi, typename StreamPolicy, typename PrefixPolicy>
+struct wkt_multi
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Multi const& geometry)
+ {
+ os << PrefixPolicy::apply();
+ // TODO: check EMPTY here
+ os << "(";
+
+ for (typename boost::range_const_iterator<Multi>::type
+ it = boost::begin(geometry);
+ it != boost::end(geometry);
+ ++it)
+ {
+ if (it != boost::begin(geometry))
+ {
+ os << ",";
+ }
+ StreamPolicy::apply(os, *it);
+ }
+
+ os << ")";
+ }
+};
+
+}} // namespace wkt::impl
+#endif
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+
+template <typename Multi>
+struct wkt<multi_point_tag, Multi>
+ : detail::wkt::wkt_multi
+ <
+ Multi,
+ detail::wkt::wkt_point
+ <
+ typename boost::range_value<Multi>::type,
+ detail::wkt::prefix_null
+ >,
+ detail::wkt::prefix_multipoint
+ >
+{};
+
+
+template <typename Multi>
+struct wkt<multi_linestring_tag, Multi>
+ : detail::wkt::wkt_multi
+ <
+ Multi,
+ detail::wkt::wkt_sequence
+ <
+ typename boost::range_value<Multi>::type
+ >,
+ detail::wkt::prefix_multilinestring
+ >
+{};
+
+
+template <typename Multi>
+struct wkt<multi_polygon_tag, Multi>
+ : detail::wkt::wkt_multi
+ <
+ Multi,
+ detail::wkt::wkt_poly
+ <
+ typename boost::range_value<Multi>::type,
+ detail::wkt::prefix_null
+ >,
+ detail::wkt::prefix_multipolygon
+ >
+{};
+
+} // namespace dispatch
+#endif
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_EXTENSIONS_GIS_IO_WKT_WRITE_WKT_MULTI_HPP

Added: sandbox/geometry/boost/geometry/extensions/io/svg/write_svg.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/io/svg/write_svg.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,251 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP
+#define BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP
+
+#include <ostream>
+#include <string>
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+/*!
+\defgroup svg x Extension svg: Stream SVG (Scalable Vector Graphics)
+*/
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace svg {
+
+
+template <typename Point>
+struct svg_point
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Point const& p, std::string const& style, int size)
+ {
+ os << "<circle cx=\"" << p.x()
+ << "\" cy=\"" << p.y()
+ << "\" r=\"" << (size < 0 ? 5 : size)
+ << "\" style=\"" << style << "\"/>";
+ }
+};
+
+
+template <typename Box>
+struct svg_box
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Box const& box, std::string const& style, int size)
+ {
+ typedef typename coordinate_type<Box>::type coord_type;
+ coord_type x = geometry::get<geometry::min_corner, 0>(box);
+ coord_type y = geometry::get<geometry::min_corner, 1>(box);
+ coord_type width = std::abs(geometry::get<geometry::max_corner, 0>(box) - x);
+ coord_type height = std::abs(geometry::get<geometry::max_corner, 1>(box) - y);
+
+ os << "<rect x=\"" << static_cast<int>(x)
+ << "\" y=\"" << static_cast<int>(y)
+ << "\" width=\"" << static_cast<int>(width)
+ << "\" height=\"" << static_cast<int>(height)
+ << "\" style=\"" << style << "\"/>";
+ }
+};
+
+
+/*!
+\brief Stream ranges as SVG
+\note policy is used to select type (polyline/polygon)
+*/
+template <typename Range, typename Policy>
+struct svg_range
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Range const& range, std::string const& style, int size)
+ {
+ typedef typename boost::range_const_iterator<Range>::type iterator;
+
+ bool first = true;
+
+ os << "<" << Policy::prefix() << " points=\"";
+
+ for (iterator it = boost::begin(range);
+ it != boost::end(range);
+ ++it, first = false)
+ {
+ os << (first ? "" : " " ) << it->x() << "," << it->y();
+ }
+ os << "\" style=\"" << style << Policy::style() << "\"/>";
+ }
+};
+
+
+
+template <typename Polygon>
+struct svg_poly
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Polygon const& polygon, std::string const& style, int size)
+ {
+ typedef typename geometry::ring_type<Polygon>::type ring_type;
+ typedef typename boost::range_const_iterator<ring_type>::type iterator_type;
+
+ bool first = true;
+ os << "<g fill-rule=\"evenodd\"><path d=\"";
+
+ ring_type const& ring = geometry::exterior_ring(polygon);
+ for (iterator_type it = boost::begin(ring);
+ it != boost::end(ring);
+ ++it, first = false)
+ {
+ os << (first ? "M" : " L") << " " << it->x() << "," << it->y();
+ }
+
+ // Inner rings:
+ {
+ typedef typename boost::range_const_iterator
+ <
+ typename geometry::interior_type<Polygon>::type
+ >::type ring_iterator_type;
+ for (ring_iterator_type rit = boost::begin(interior_rings(polygon));
+ rit != boost::end(interior_rings(polygon));
+ ++rit)
+ {
+ first = true;
+ for (iterator_type it = boost::begin(*rit);
+ it != boost::end(*rit);
+ ++it, first = false)
+ {
+ os << (first ? "M" : " L") << " " << it->x() << "," << it->y();
+ }
+ }
+ }
+ os << " z \" style=\"" << style << "\"/></g>";
+
+ }
+};
+
+
+
+struct prefix_linestring
+{
+ static inline const char* prefix() { return "polyline"; }
+ static inline const char* style() { return ";fill:none"; }
+};
+
+
+struct prefix_ring
+{
+ static inline const char* prefix() { return "polygon"; }
+ static inline const char* style() { return ""; }
+};
+
+
+
+}} // namespace detail::svg
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+/*!
+\brief Dispatching base struct for SVG streaming, specialized below per geometry type
+\details Specializations should implement a static method "stream" to stream a geometry
+The static method should have the signature:
+
+template <typename Char, typename Traits>
+static inline void apply(std::basic_ostream<Char, Traits>& os, const G& geometry)
+*/
+template <typename GeometryTag, typename Geometry>
+struct svg {};
+
+template <typename Point>
+struct svg<point_tag, Point> : detail::svg::svg_point<Point> {};
+
+template <typename Box>
+struct svg<box_tag, Box> : detail::svg::svg_box<Box> {};
+
+template <typename Linestring>
+struct svg<linestring_tag, Linestring>
+ : detail::svg::svg_range<Linestring, detail::svg::prefix_linestring> {};
+
+template <typename Ring>
+struct svg<ring_tag, Ring>
+ : detail::svg::svg_range<Ring, detail::svg::prefix_ring> {};
+
+template <typename Polygon>
+struct svg<polygon_tag, Polygon>
+ : detail::svg::svg_poly<Polygon> {};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Generic geometry template manipulator class, takes corresponding output class from traits class
+\ingroup svg
+\details Stream manipulator, streams geometry classes as Virtual Earth shape
+*/
+template <typename G>
+class svg_manipulator
+{
+public:
+
+ inline svg_manipulator(G const& g, std::string const& style, int size)
+ : m_geometry(g)
+ , m_style(style)
+ , m_size(size)
+ {}
+
+ template <typename Char, typename Traits>
+ inline friend std::basic_ostream<Char, Traits>& operator<<(
+ std::basic_ostream<Char, Traits>& os, svg_manipulator const& m)
+ {
+ dispatch::svg
+ <
+ typename tag<G>::type, G
+ >::apply(os, m.m_geometry, m.m_style, m.m_size);
+ os.flush();
+ return os;
+ }
+
+private:
+ G const& m_geometry;
+ std::string const& m_style;
+ int m_size;
+};
+
+/*!
+\brief Main svg function to stream geometries as SVG
+\ingroup svg
+*/
+template <typename Geometry>
+inline svg_manipulator<Geometry> svg(Geometry const& t, std::string const& style, int size = -1)
+{
+ concept::check<const Geometry>();
+
+ return svg_manipulator<Geometry>(t, style, size);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP

Added: sandbox/geometry/boost/geometry/extensions/io/svg/write_svg_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/extensions/io/svg/write_svg_multi.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,73 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_SVG_WRITE_SVG_MULTI_HPP
+#define BOOST_GEOMETRY_IO_SVG_WRITE_SVG_MULTI_HPP
+
+
+#include <boost/geometry/extensions/io/svg/write_svg.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace svg {
+
+
+template <typename MultiGeometry, typename Policy>
+struct svg_multi
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ MultiGeometry const& multi, std::string const& style, int size)
+ {
+ for (typename boost::range_const_iterator<MultiGeometry>::type
+ it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ Policy::apply(os, *it, style, size);
+ }
+
+ }
+
+};
+
+
+
+}} // namespace detail::svg
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+
+template <typename MultiPolygon>
+struct svg<multi_polygon_tag, MultiPolygon>
+ : detail::svg::svg_multi
+ <
+ MultiPolygon,
+ detail::svg::svg_poly
+ <
+ typename boost::range_value<MultiPolygon>::type
+ >
+
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_IO_SVG_WRITE_SVG_MULTI_HPP

Added: sandbox/geometry/boost/geometry/geometries/adapted/boost_array_as_linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/adapted/boost_array_as_linestring.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,50 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_ARRAY_AS_LINESTRING_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_ARRAY_AS_LINESTRING_HPP
+
+
+#ifdef BOOST_GEOMETRY_ADAPTED_BOOST_ARRAY_AS_POINT_COLLECTION_TAG_DEFINED
+#error Include either "boost_array_as_linestring" or "boost_array_as_ring" \
+ or "boost_array_as_multi_point" to adapt a boost_array
+#endif
+
+#define BOOST_GEOMETRY_ADAPTED_BOOST_ARRAY_AS_POINT_COLLECTION_TAG_DEFINED
+
+
+#include <cstddef>
+
+#include <boost/array.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+ template <typename PointType, std::size_t DimensionCount>
+ struct tag< boost::array<PointType, DimensionCount> >
+ {
+ typedef linestring_tag type;
+ };
+
+}
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_ARRAY_AS_LINESTRING_HPP

Added: sandbox/geometry/boost/geometry/geometries/adapted/boost_array_as_ring.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/adapted/boost_array_as_ring.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,50 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_ARRAY_AS_RING_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_ARRAY_AS_RING_HPP
+
+
+#ifdef BOOST_GEOMETRY_ADAPTED_BOOST_ARRAY_AS_POINT_COLLECTION_TAG_DEFINED
+#error Include either "boost_array_as_linestring" or "boost_array_as_ring" \
+ or "boost_array_as_multi_point" to adapt a boost_array
+#endif
+
+#define BOOST_GEOMETRY_ADAPTED_BOOST_ARRAY_AS_POINT_COLLECTION_TAG_DEFINED
+
+
+#include <cstddef>
+
+#include <boost/array.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+ template <typename PointType, std::size_t DimensionCount>
+ struct tag< boost::array<PointType, DimensionCount> >
+ {
+ typedef ring_tag type;
+ };
+
+}
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_ARRAY_AS_RING_HPP

Added: sandbox/geometry/boost/geometry/geometries/adapted/c_array.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/adapted/c_array.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,98 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_HPP
+
+#include <cstddef>
+
+#include <boost/type_traits/is_arithmetic.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+// Create class and specialization to indicate the tag
+// for normal cases and the case that the type of the c-array is arithmetic
+template <bool>
+struct c_array_tag
+{
+ typedef geometry_not_recognized_tag type;
+};
+
+
+template <>
+struct c_array_tag<true>
+{
+ typedef point_tag type;
+};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+// Assign the point-tag, preventing arrays of points getting a point-tag
+template <typename CoordinateType, std::size_t DimensionCount>
+struct tag<CoordinateType[DimensionCount]>
+ : detail::c_array_tag<boost::is_arithmetic<CoordinateType>::value> {};
+
+
+template <typename CoordinateType, std::size_t DimensionCount>
+struct coordinate_type<CoordinateType[DimensionCount]>
+{
+ typedef CoordinateType type;
+};
+
+
+template <typename CoordinateType, std::size_t DimensionCount>
+struct dimension<CoordinateType[DimensionCount]>: boost::mpl::int_<DimensionCount> {};
+
+
+template <typename CoordinateType, std::size_t DimensionCount, std::size_t Dimension>
+struct access<CoordinateType[DimensionCount], Dimension>
+{
+ static inline CoordinateType get(const CoordinateType p[DimensionCount])
+ {
+ return p[Dimension];
+ }
+
+ static inline void set(CoordinateType p[DimensionCount],
+ CoordinateType const& value)
+ {
+ p[Dimension] = value;
+ }
+};
+
+// The library user has
+// 1) either to specify the coordinate system
+// 2) or include <boost/geometry/geometries/adapted/c_array__at_.hpp> where @=cartesian,geographic,...
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_HPP

Added: sandbox/geometry/boost/geometry/geometries/adapted/c_array_as_linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/adapted/c_array_as_linestring.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,45 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_AS_LINESTRING_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_AS_LINESTRING_HPP
+
+
+#ifdef BOOST_GEOMETRY_ADAPTED_C_ARRAY_AS_POINT_COLLECTION_TAG_DEFINED
+#error Include either "c_array_as_linestring" or "c_array_as_ring" \
+ or "c_array_as_multi_point" to adapt a c array
+#endif
+
+#define BOOST_GEOMETRY_ADAPTED_C_ARRAY_AS_POINT_COLLECTION_TAG_DEFINED
+
+
+#include <cstddef>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+ template <typename T, std::size_t PointCount, std::size_t DimensionCount>
+ struct tag< T[PointCount][DimensionCount] >
+ {
+ typedef linestring_tag type;
+ };
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_AS_LINESTRING_HPP

Added: sandbox/geometry/boost/geometry/geometries/adapted/c_array_as_ring.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/adapted/c_array_as_ring.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,45 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_AS_RING_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_AS_RING_HPP
+
+
+#ifdef BOOST_GEOMETRY_ADAPTED_C_ARRAY_AS_POINT_COLLECTION_TAG_DEFINED
+#error Include either "c_array_as_linestring" or "c_array_as_ring" \
+ or "c_array_as_multi_point" to adapt a c array
+#endif
+
+#define BOOST_GEOMETRY_ADAPTED_C_ARRAY_AS_POINT_COLLECTION_TAG_DEFINED
+
+
+#include <cstddef>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+ template <typename T, std::size_t PointCount, std::size_t DimensionCount>
+ struct tag< T[PointCount][DimensionCount] >
+ {
+ typedef ring_tag type;
+ };
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_AS_RING_HPP

Added: sandbox/geometry/boost/geometry/geometries/adapted/c_array_cartesian.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/adapted/c_array_cartesian.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,40 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_CARTESIAN_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_CARTESIAN_HPP
+
+#ifdef BOOST_GEOMETRY_ADAPTED_C_ARRAY_COORDINATE_SYSTEM_DEFINED
+#error Include only one headerfile to register coordinate coordinate_system for adapted c array
+#endif
+
+#define BOOST_GEOMETRY_ADAPTED_C_ARRAY_COORDINATE_SYSTEM_DEFINED
+
+
+#include <boost/geometry/geometries/adapted/c_array.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+ template <typename T, int N>
+ struct coordinate_system<T[N]>
+ { typedef cs::cartesian type; };
+
+}
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_CARTESIAN_HPP

Added: sandbox/geometry/boost/geometry/geometries/adapted/std_as_linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/adapted/std_as_linestring.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,70 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_AS_LINESTRING_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_AS_LINESTRING_HPP
+
+
+#ifdef BOOST_GEOMETRY_ADAPTED_STD_AS_POINT_COLLECTION_TAG_DEFINED
+#error Include either "std_as_linestring" or "std_as_ring" \
+ or "std_as_multi_point" to adapt the std:: containers
+#endif
+
+#define BOOST_GEOMETRY_ADAPTED_STD_AS_POINT_COLLECTION_TAG_DEFINED
+
+
+#include <vector>
+#include <deque>
+#include <list>
+#include <utility>
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace util
+{
+ struct std_as_linestring
+ {
+ typedef linestring_tag type;
+ };
+
+}
+#endif
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+ // specialization for an iterator pair (read only)
+ template <typename P> struct tag< std::pair<P, P> > : util::std_as_linestring {};
+
+ // Indicate that std::library is not used to add things to std::pair.
+ // Don't implement anything else -> adding points or clearing not possible
+ template <typename P> struct use_std< std::pair<P, P> > : boost::mpl::false_ {};
+
+ // specializations for the std:: containers: vector, deque, list
+ template <typename P> struct tag< std::vector<P> > : util::std_as_linestring {};
+ template <typename P> struct tag< std::deque<P> > : util::std_as_linestring {};
+ template <typename P> struct tag< std::list<P> > : util::std_as_linestring {};
+
+}
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_AS_LINESTRING_HPP

Added: sandbox/geometry/boost/geometry/geometries/adapted/std_as_ring.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/adapted/std_as_ring.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,47 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_AS_RING_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_AS_RING_HPP
+
+
+#ifdef BOOST_GEOMETRY_ADAPTED_STD_AS_POINT_COLLECTION_TAG_DEFINED
+#error Include either "std_as_linestring" or "std_as_ring" \
+ or "std_as_multi_point" to adapt the std:: containers
+#endif
+
+#define BOOST_GEOMETRY_ADAPTED_STD_AS_POINT_COLLECTION_TAG_DEFINED
+
+
+#include <vector>
+#include <deque>
+#include <list>
+#include <utility>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+ // specialization for an iterator pair
+ template <typename T> struct tag< std::pair<T, T> > { typedef ring_tag type; };
+
+ // specialization for the std:: containers: vector, deque, list
+ template <typename T> struct tag< std::vector<T> > { typedef ring_tag type; };
+ template <typename T> struct tag< std::deque<T> > { typedef ring_tag type; };
+ template <typename T> struct tag< std::list<T> > { typedef ring_tag type; };
+}
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_AS_RING_HPP

Added: sandbox/geometry/boost/geometry/geometries/adapted/std_pair_as_segment.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/adapted/std_pair_as_segment.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,90 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_PAIR_AS_SEGMENT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_PAIR_AS_SEGMENT_HPP
+
+// Only possible if the std::pair is not used for iterator/pair
+// (maybe it is possible to avoid that by detecting in the other file
+// if an iterator was used in the pair)
+
+#ifdef BOOST_GEOMETRY_ADAPTED_STD_RANGE_TAG_DEFINED
+#error Include only one headerfile to register tag for adapted std:: containers or iterator pair
+#endif
+
+#define BOOST_GEOMETRY_ADAPTED_STD_RANGE_TAG_DEFINED
+
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+
+template <typename Point>
+struct tag<std::pair<Point, Point> >
+{
+ typedef segment_tag type;
+};
+
+template <typename Point>
+struct point_type<std::pair<Point, Point> >
+{
+ typedef Point type;
+};
+
+template <typename Point, std::size_t Dimension>
+struct indexed_access<std::pair<Point, Point>, 0, Dimension>
+{
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+
+ static inline coordinate_type get(std::pair<Point, Point> const& s)
+ {
+ return geometry::get<Dimension>(s.first);
+ }
+
+ static inline void set(std::pair<Point, Point>& s, coordinate_type const& value)
+ {
+ geometry::set<Dimension>(s.first, value);
+ }
+};
+
+
+template <typename Point, std::size_t Dimension>
+struct indexed_access<std::pair<Point, Point>, 1, Dimension>
+{
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+
+ static inline coordinate_type get(std::pair<Point, Point> const& s)
+ {
+ return geometry::get<Dimension>(s.second);
+ }
+
+ static inline void set(std::pair<Point, Point>& s, coordinate_type const& value)
+ {
+ geometry::set<Dimension>(s.second, value);
+ }
+};
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_PAIR_AS_SEGMENT_HPP

Added: sandbox/geometry/boost/geometry/geometries/adapted/tuple.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/adapted/tuple.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,128 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_TUPLE_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_TUPLE_HPP
+
+#include <boost/tuple/tuple.hpp>
+
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+// boost::tuple, 2D
+template <typename CoordinateType>
+struct coordinate_type<boost::tuple<CoordinateType, CoordinateType> >
+{
+ typedef CoordinateType type;
+};
+
+
+template <typename CoordinateType>
+struct dimension<boost::tuple<CoordinateType, CoordinateType> >
+ : boost::mpl::int_<2>
+{};
+
+
+template <typename CoordinateType, std::size_t Dimension>
+struct access
+ <
+ boost::tuple<CoordinateType, CoordinateType>,
+ Dimension
+ >
+{
+ static inline CoordinateType get(
+ boost::tuple<CoordinateType, CoordinateType> const& point)
+ {
+ return point.template get<Dimension>();
+ }
+
+ static inline void set(boost::tuple<CoordinateType, CoordinateType>& point,
+ CoordinateType const& value)
+ {
+ point.template get<Dimension>() = value;
+ }
+};
+
+
+template <typename CoordinateType>
+struct tag<boost::tuple<CoordinateType, CoordinateType> >
+{
+ typedef point_tag type;
+};
+
+
+// boost::tuple, 3D
+template <typename CoordinateType>
+struct coordinate_type
+ <
+ boost::tuple<CoordinateType, CoordinateType, CoordinateType>
+ >
+{
+ typedef CoordinateType type;
+};
+
+template <typename CoordinateType>
+struct dimension<boost::tuple<CoordinateType, CoordinateType, CoordinateType> >
+ : boost::mpl::int_<3>
+{};
+
+
+template <typename CoordinateType, std::size_t Dimension>
+struct access
+ <
+ boost::tuple<CoordinateType, CoordinateType, CoordinateType>,
+ Dimension
+ >
+{
+ static inline CoordinateType get(
+ boost::tuple
+ <
+ CoordinateType, CoordinateType, CoordinateType
+ > const& point)
+ {
+ return point.template get<Dimension>();
+ }
+
+ static inline void set(
+ boost::tuple<CoordinateType, CoordinateType, CoordinateType>& point,
+ CoordinateType const& value)
+ {
+ point.template get<Dimension>() = value;
+ }
+};
+
+
+template <typename CoordinateType>
+struct tag<boost::tuple<CoordinateType, CoordinateType, CoordinateType> >
+{
+ typedef point_tag type;
+};
+
+// The library user has
+// 1) either to specify the coordinate system using a traits class
+// 2) or include <boost/geometry/geometries/adapted/tuple__at_.hpp>
+// where @=cartesian,geographic,...
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_TUPLE_HPP
+

Added: sandbox/geometry/boost/geometry/geometries/adapted/tuple_cartesian.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/adapted/tuple_cartesian.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,44 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_TUPLE_CARTESIAN_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_TUPLE_CARTESIAN_HPP
+
+#ifdef BOOST_GEOMETRY_ADAPTED_TUPLE_COORDINATE_SYSTEM_DEFINED
+#error Include only one headerfile to register coordinate coordinate_system for adapted tuple
+#endif
+
+#define BOOST_GEOMETRY_ADAPTED_TUPLE_COORDINATE_SYSTEM_DEFINED
+
+
+#include <boost/geometry/geometries/adapted/tuple.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+ template <typename T>
+ struct coordinate_system<boost::tuple<T, T> >
+ { typedef cs::cartesian type; };
+
+ template <typename T>
+ struct coordinate_system<boost::tuple<T, T, T> >
+ { typedef cs::cartesian type; };
+
+}
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_TUPLE_CARTESIAN_HPP

Added: sandbox/geometry/boost/geometry/geometries/box.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/box.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,121 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_BOX_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_BOX_HPP
+
+#include <cstddef>
+
+#include <boost/concept/assert.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+#include <boost/geometry/util/copy.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief Class box: defines a box made of two describing points
+ \ingroup geometries
+ \details Box is always described by a min_corner() and a max_corner() point. If another
+ rectangle is used, use linear_ring or polygon.
+ \note Boxes are for selections and for calculating the envelope of geometries. Not all algorithms
+ are implemented for box. Boxes are also used in Spatial Indexes.
+ \tparam Point point type. The box takes a point type as template parameter.
+ The point type can be any point type.
+ It can be 2D but can also be 3D or more dimensional.
+ The box can also take a latlong point type as template parameter.
+ */
+
+template<typename Point>
+class box
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+public:
+
+ inline box() {}
+
+ /*!
+ \brief Constructor taking the minimum corner point and the maximum corner point
+ */
+ inline box(Point const& min_corner, Point const& max_corner)
+ {
+ copy_coordinates(min_corner, m_min_corner);
+ copy_coordinates(max_corner, m_max_corner);
+ }
+
+ inline Point const& min_corner() const { return m_min_corner; }
+ inline Point const& max_corner() const { return m_max_corner; }
+
+ inline Point& min_corner() { return m_min_corner; }
+ inline Point& max_corner() { return m_max_corner; }
+
+private:
+
+ Point m_min_corner;
+ Point m_max_corner;
+};
+
+
+// Traits specializations for box above
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename Point>
+struct tag<box<Point> >
+{
+ typedef box_tag type;
+};
+
+template <typename Point>
+struct point_type<box<Point> >
+{
+ typedef Point type;
+};
+
+template <typename Point, std::size_t Dimension>
+struct indexed_access<box<Point>, min_corner, Dimension>
+{
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+
+ static inline coordinate_type get(box<Point> const& b)
+ {
+ return geometry::get<Dimension>(b.min_corner());
+ }
+
+ static inline void set(box<Point>& b, coordinate_type const& value)
+ {
+ geometry::set<Dimension>(b.min_corner(), value);
+ }
+};
+
+template <typename Point, std::size_t Dimension>
+struct indexed_access<box<Point>, max_corner, Dimension>
+{
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+
+ static inline coordinate_type get(box<Point> const& b)
+ {
+ return geometry::get<Dimension>(b.max_corner());
+ }
+
+ static inline void set(box<Point>& b, coordinate_type const& value)
+ {
+ geometry::set<Dimension>(b.max_corner(), value);
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_BOX_HPP

Added: sandbox/geometry/boost/geometry/geometries/cartesian2d.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/cartesian2d.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,28 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CARTESIAN2D_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CARTESIAN2D_HPP
+
+// Predeclare common Cartesian 2D points for convenience
+
+#include <boost/geometry/geometries/geometries.hpp>
+
+namespace boost { namespace geometry
+{
+
+typedef point_xy<double, cs::cartesian> point_2d;
+typedef linestring<point_2d> linestring_2d;
+typedef linear_ring<point_2d> ring_2d;
+typedef polygon<point_2d> polygon_2d;
+typedef box<point_2d> box_2d;
+typedef segment<point_2d> segment_2d;
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CARTESIAN2D_HPP

Added: sandbox/geometry/boost/geometry/geometries/cartesian3d.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/cartesian3d.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,27 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CARTESIAN3D_HPP
+#define BOOST_GEOMETRY_CARTESIAN3D_HPP
+
+// Predeclare common Cartesian 3D points for convenience
+
+#include <boost/geometry/geometries/geometries.hpp>
+
+namespace boost { namespace geometry
+{
+typedef point<double, 3, cs::cartesian> point_3d;
+typedef linestring<point_3d> linestring_3d;
+typedef linear_ring<point_3d> ring_3d;
+typedef polygon<point_3d> polygon_3d;
+typedef box<point_3d> box_3d;
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CARTESIAN3D_HPP

Added: sandbox/geometry/boost/geometry/geometries/concepts/box_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/concepts/box_concept.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,131 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_BOX_CONCEPT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_BOX_CONCEPT_HPP
+
+
+#include <cstddef>
+
+#include <boost/concept_check.hpp>
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+
+
+namespace boost { namespace geometry { namespace concept {
+
+
+/*!
+\brief Box concept
+\ingroup concepts
+\par Formal definition:
+The box concept is defined as following:
+- there must be a specialization of traits::tag defining box_tag as type
+- there must be a specialization of traits::point_type to define the
+ underlying point type (even if it does not consist of points, it should define
+ this type, to indicate the points it can work with)
+- there must be a specialization of traits::indexed_access, per index
+ (min_corner, max_corner) and per dimension, with two functions:
+ - get to get a coordinate value
+ - set to set a coordinate value (this one is not checked for ConstBox)
+*/
+template <typename Geometry>
+class Box
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+
+
+ template
+ <
+ std::size_t Index,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+ >
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ Geometry* b;
+ geometry::set<Index, Dimension>(*b, geometry::get<Index, Dimension>(*b));
+ dimension_checker<Index, Dimension + 1, DimensionCount>::apply();
+ }
+ };
+
+ template <std::size_t Index, std::size_t DimensionCount>
+ struct dimension_checker<Index, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public :
+ BOOST_CONCEPT_USAGE(Box)
+ {
+ static const std::size_t n = dimension<Geometry>::type::value;
+ dimension_checker<min_corner, 0, n>::apply();
+ dimension_checker<max_corner, 0, n>::apply();
+ }
+#endif
+};
+
+
+/*!
+\brief Box concept (const version)
+\ingroup const_concepts
+\details The ConstBox concept apply the same as the Box concept,
+but does not apply write access.
+*/
+template <typename Geometry>
+class ConstBox
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename coordinate_type<Geometry>::type coordinate_type;
+
+ template
+ <
+ std::size_t Index,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+ >
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ const Geometry* b = 0;
+ coordinate_type coord(geometry::get<Index, Dimension>(*b));
+ boost::ignore_unused_variable_warning(coord);
+ dimension_checker<Index, Dimension + 1, DimensionCount>::apply();
+ }
+ };
+
+ template <std::size_t Index, std::size_t DimensionCount>
+ struct dimension_checker<Index, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public :
+ BOOST_CONCEPT_USAGE(ConstBox)
+ {
+ static const std::size_t n = dimension<Geometry>::type::value;
+ dimension_checker<min_corner, 0, n>::apply();
+ dimension_checker<max_corner, 0, n>::apply();
+ }
+#endif
+};
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_BOX_CONCEPT_HPP

Added: sandbox/geometry/boost/geometry/geometries/concepts/check.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/concepts/check.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,208 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_CHECK_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_CHECK_HPP
+
+/*!
+\defgroup concepts geometry concepts: defines and checks concepts for geometries
+
+All GGL algorithms use concepts for their geometries. This means that all
+algorithms work on the GGL-provided geometries (point, linestring, etc) but
+also on custom geometries.
+
+By declaring registration macro's or by specializating traits classes it is
+possible to adapt custom or legacy geometries to fulfil the GGL geometry
+concepts.
+
+GGL algorithms check the concepts of the input geometries.
+Concept checking is done using BCCL (Boost Concept Check Library).
+
+This means that geometries provided by library users, or legacy geometries, or
+plain arrays, or boost tuples, all can be handled by the Generic Geometry
+Library. Also std::vector of points, or tuples can be handled either as a
+linestring or as a linear ring (polygon without holes).
+
+There are concepts for
+- points
+- segment
+- box
+- linestring
+- (linear) ring
+- polygon
+- multi point
+- multi linestring
+- multi polygon
+
+The Generic Geometry Library uses the Boost Range Library to iterate through
+standard containers, boost arrays, c-arrays.
+So:
+- linestring
+- (linear) ring
+
+are all just ranges. So a std::vector, std::deque, boost::array,
+iterator pair or c-array will be accepted as such.
+
+Also the multi geometries:
+- multi point
+- multi linestring
+- multi polygon
+are considered as ranges of respectively points, linestrings and polygons.
+
+*/
+
+
+#include <boost/concept_check.hpp>
+#include <boost/concept/requires.hpp>
+
+#include <boost/type_traits/is_const.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+
+#include <boost/geometry/geometries/concepts/box_concept.hpp>
+#include <boost/geometry/geometries/concepts/linestring_concept.hpp>
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/geometries/concepts/polygon_concept.hpp>
+#include <boost/geometry/geometries/concepts/ring_concept.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace concept_check {
+
+template <typename Concept>
+class check
+{
+ BOOST_CONCEPT_ASSERT((Concept ));
+};
+
+}} // namespace detail::check
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename GeometryTag, typename Geometry, bool IsConst>
+struct check
+{};
+
+
+template <typename Geometry>
+struct check<point_tag, Geometry, true>
+ : detail::concept_check::check<concept::ConstPoint<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<point_tag, Geometry, false>
+ : detail::concept_check::check<concept::Point<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<linestring_tag, Geometry, true>
+ : detail::concept_check::check<concept::ConstLinestring<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<linestring_tag, Geometry, false>
+ : detail::concept_check::check<concept::Linestring<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<polygon_tag, Geometry, true>
+ : detail::concept_check::check<concept::ConstPolygon<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<polygon_tag, Geometry, false>
+ : detail::concept_check::check<concept::Polygon<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<box_tag, Geometry, true>
+ : detail::concept_check::check<concept::ConstBox<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<box_tag, Geometry, false>
+ : detail::concept_check::check<concept::Box<Geometry> >
+{};
+
+
+
+} // namespace dispatch
+#endif
+
+
+
+
+namespace concept {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail {
+
+
+template <typename Geometry, bool IsConst>
+struct checker : dispatch::check
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ IsConst
+ >
+{};
+
+
+}
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief Checks, in compile-time, the concept of any geometry
+ \ingroup concepts
+*/
+template <typename Geometry>
+inline void check()
+{
+ detail::checker<Geometry, boost::is_const<Geometry>::type::value> c;
+ boost::ignore_unused_variable_warning(c);
+}
+
+
+/*!
+ \brief Checks, in compile-time, the concept of two geometries, and if they
+ have equal dimensions
+ \ingroup concepts
+*/
+template <typename Geometry1, typename Geometry2>
+inline void check_concepts_and_equal_dimensions()
+{
+ check<Geometry1>();
+ check<Geometry2>();
+ assert_dimension_equal<Geometry1, Geometry2>();
+}
+
+
+} // namespace concept
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_CHECK_HPP

Added: sandbox/geometry/boost/geometry/geometries/concepts/detail/check_append.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/concepts/detail/check_append.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,58 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_DETAIL_CHECK_APPEND_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_DETAIL_CHECK_APPEND_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/access.hpp>
+
+
+namespace boost { namespace geometry { namespace concept {
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+ template <typename Geometry, typename Point, bool UseStd>
+ struct check_append
+ {};
+
+ template <typename Geometry, typename Point>
+ struct check_append<Geometry, Point, true>
+ {
+ static void apply(Geometry& geometry, Point const& p)
+ {
+ geometry.push_back(p);
+ }
+ };
+
+
+ template <typename Geometry, typename Point>
+ struct check_append<Geometry, Point, false>
+ {
+ static void apply(Geometry& geometry, Point const& p)
+ {
+ geometry::traits::append_point
+ <
+ typename boost::remove_const<Geometry>::type,
+ Point
+ >::apply(geometry, p, -1, -1);
+ }
+ };
+}
+#endif // DOXYGEN_NO_DETAIL
+
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_DETAIL_CHECK_APPEND_HPP

Added: sandbox/geometry/boost/geometry/geometries/concepts/detail/check_clear.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/concepts/detail/check_clear.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,59 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_DETAIL_CHECK_CLEAR_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_DETAIL_CHECK_CLEAR_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/access.hpp>
+
+
+namespace boost { namespace geometry { namespace concept {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+ template <typename Geometry, bool UseStd>
+ struct check_clear
+ {};
+
+ template <typename Geometry>
+ struct check_clear<Geometry, true>
+ {
+ static void apply(Geometry& geometry)
+ {
+ geometry.clear();
+ }
+ };
+
+
+ template <typename Geometry>
+ struct check_clear<Geometry, false>
+ {
+ static void apply(Geometry& geometry)
+ {
+ geometry::traits::clear
+ <
+ typename boost::remove_const<Geometry>::type
+ >::apply(geometry);
+ }
+ };
+
+}
+#endif // DOXYGEN_NO_DETAIL
+
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_DETAIL_CHECK_CLEAR_HPP

Added: sandbox/geometry/boost/geometry/geometries/concepts/linestring_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/concepts/linestring_concept.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,130 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_LINESTRING_CONCEPT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_LINESTRING_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+#include <boost/geometry/geometries/concepts/detail/check_clear.hpp>
+#include <boost/geometry/geometries/concepts/detail/check_append.hpp>
+
+
+namespace boost { namespace geometry { namespace concept {
+
+
+/*!
+\brief Linestring concept
+\ingroup concepts
+\par Formal definition:
+The linestring concept is defined as following:
+- there must be a specialization of traits::tag defining linestring_tag as type
+- it must behave like a Boost.Range
+- either it can behave like the std library, having push_back and clear
+- or it can implement a mechanism for clearing and adding points:
+ - there can be a specialization of traits::use_std class indicating
+ that it does not use the standard library (for modifications)
+ - there should then be a specialization of traits::clear
+ to make a linestring empty
+ - there should then be a specialization of traits::append_point
+ to add a point to a linestring
+
+\note to fulfil the concepts, no traits class has to be specialized to
+define the point type. The point type is taken using boost::range_value<X>::type
+
+\par Example:
+
+A custom linestring, defining the necessary specializations to fulfil to the concept.
+
+Suppose that the following linestring is defined:
+\dontinclude doxygen_5.cpp
+\skip custom_linestring1
+\until };
+
+It can then be adapted to the concept as following:
+\dontinclude doxygen_5.cpp
+\skip adapt custom_linestring1
+\until }}
+
+\note
+- There is also the registration macro BOOST_GEOMETRY_REGISTER_LINESTRING
+- For registration of std::vector<P> (and deque, and list) it is enough to
+include the header-file geometries/adapted/std_as_linestring.hpp. That registers
+a vector as a linestring (so it cannot be registered as a linear ring then,
+in the same source code).
+
+
+*/
+
+template <typename Geometry>
+class Linestring
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Point<point_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(Linestring)
+ {
+ // Check if it can be modified
+ static const bool use_std = traits::use_std
+ <
+ typename boost::remove_const<Geometry>::type
+ >::value;
+
+ Geometry* ls;
+ detail::check_clear<Geometry, use_std>::apply(*ls);
+
+ point_type* p;
+ detail::check_append<Geometry, point_type, use_std>::apply(*ls, *p);
+ }
+#endif
+};
+
+
+/*!
+\brief Linestring concept (const version)
+\ingroup const_concepts
+\details The ConstLinestring concept check the same as the Linestring concept,
+but does not check write access.
+*/
+template <typename Geometry>
+class ConstLinestring
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstLinestring)
+ {
+ }
+#endif
+};
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_LINESTRING_CONCEPT_HPP

Added: sandbox/geometry/boost/geometry/geometries/concepts/point_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/concepts/point_concept.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,167 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library) Point concept
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POINT_CONCEPT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POINT_CONCEPT_HPP
+
+#include <cstddef>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+
+
+
+
+namespace boost { namespace geometry { namespace concept {
+
+/*!
+\brief Point concept
+\ingroup concepts
+
+\par Formal definition:
+The point concept is defined as following:
+- there must be a specialization of traits::tag defining point_tag as type
+- there must be a specialization of traits::coordinate_type defining the type
+ of its coordinates
+- there must be a specialization of traits::coordinate_system defining its
+ coordinate system (cartesian, spherical, etc)
+- there must be a specialization of traits::dimension defining its number
+ of dimensions (2, 3, ...) (derive it conveniently
+ from boost::mpl::int_&lt;X&gt; for X-D)
+- there must be a specialization of traits::access, per dimension,
+ with two functions:
+ - \b get to get a coordinate value
+ - \b set to set a coordinate value (this one is not checked for ConstPoint)
+
+\par Example:
+
+A legacy point, defining the necessary specializations to fulfil to the concept.
+
+Suppose that the following point is defined:
+\dontinclude doxygen_5.cpp
+\skip legacy_point1
+\until };
+
+It can then be adapted to the concept as following:
+\dontinclude doxygen_5.cpp
+\skip adapt legacy_point1
+\until }}
+
+Note that it is done like above to show the system. Users will normally use the registration macro.
+
+\par Example:
+
+A read-only legacy point, using a macro to fulfil to the ConstPoint concept.
+It cannot be modified by the library but can be used in all algorithms where
+points are not modified.
+
+The point looks like the following:
+
+\dontinclude doxygen_5.cpp
+\skip legacy_point2
+\until };
+
+It uses the macro as following:
+\dontinclude doxygen_5.cpp
+\skip adapt legacy_point2
+\until end adaptation
+
+*/
+
+template <typename Geometry>
+class Point
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ typedef typename coordinate_type<Geometry>::type ctype;
+ typedef typename coordinate_system<Geometry>::type csystem;
+
+ enum { ccount = dimension<Geometry>::value };
+
+
+ template <typename P, std::size_t Dimension, std::size_t DimensionCount>
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ P* p;
+ geometry::set<Dimension>(*p, geometry::get<Dimension>(*p));
+ dimension_checker<P, Dimension+1, DimensionCount>::apply();
+ }
+ };
+
+
+ template <typename P, std::size_t DimensionCount>
+ struct dimension_checker<P, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public:
+
+ /// BCCL macro to apply the Point concept
+ BOOST_CONCEPT_USAGE(Point)
+ {
+ dimension_checker<Geometry, 0, ccount>::apply();
+ }
+#endif
+};
+
+
+/*!
+\brief point concept (const version)
+\ingroup const_concepts
+\details The ConstPoint concept apply the same as the Point concept,
+but does not apply write access.
+*/
+template <typename Geometry>
+class ConstPoint
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ typedef typename coordinate_type<Geometry>::type ctype;
+ typedef typename coordinate_system<Geometry>::type csystem;
+
+ enum { ccount = dimension<Geometry>::value };
+
+
+ template <typename P, std::size_t Dimension, std::size_t DimensionCount>
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ const P* p = 0;
+ ctype coord(geometry::get<Dimension>(*p));
+ boost::ignore_unused_variable_warning(coord);
+ dimension_checker<P, Dimension+1, DimensionCount>::apply();
+ }
+ };
+
+
+ template <typename P, std::size_t DimensionCount>
+ struct dimension_checker<P, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public:
+
+ /// BCCL macro to apply the ConstPoint concept
+ BOOST_CONCEPT_USAGE(ConstPoint)
+ {
+ dimension_checker<Geometry, 0, ccount>::apply();
+ }
+#endif
+};
+
+}}} // namespace boost::geometry::concept
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POINT_CONCEPT_HPP

Added: sandbox/geometry/boost/geometry/geometries/concepts/polygon_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/concepts/polygon_concept.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,145 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POLYGON_CONCEPT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POLYGON_CONCEPT_HPP
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/geometries/concepts/ring_concept.hpp>
+
+namespace boost { namespace geometry { namespace concept {
+
+
+/*!
+\brief Polygon concept
+\ingroup concepts
+\par Formal definition:
+The polygon concept is defined as following:
+- there must be a specialization of traits::tag defining polygon_tag as type
+- there must be a specialization of traits::ring_type defining the type of its
+exterior ring and interior rings as type
+- there must be a specialization of traits::interior_type defining the type of
+the collection of its interior rings as type
+- there must be a specialization of traits::exterior_ring
+ with two functions named "get",
+ returning the exterior ring, a const version and a mutable version
+- there must be a specialization of traits::interior_rings
+ with two functions named "get", returning the interior rings,
+ a const version and a mutable version
+
+\note to fulfil the concepts, no traits class has to be specialized to
+define the point type. The point type is automatically defined as
+typename range_value<typename ring_type<P>::type>::type
+*/
+template <typename Geometry>
+class Polygon
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename ring_type<Geometry>::type ring_type;
+ typedef typename interior_type<Geometry>::type interior_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Point<point_type>) );
+ BOOST_CONCEPT_ASSERT( (concept::Ring<ring_type>) );
+
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<interior_type>) );
+
+ struct checker
+ {
+ static inline void apply()
+ {
+ Geometry* poly;
+ ring_type& e = exterior_ring(*poly);
+ ring_type const& ce = exterior_ring(*poly);
+
+ interior_type& i = interior_rings(*poly);
+ interior_type const& ci = interior_rings(*poly);
+
+ boost::ignore_unused_variable_warning(e);
+ boost::ignore_unused_variable_warning(ce);
+ boost::ignore_unused_variable_warning(i);
+ boost::ignore_unused_variable_warning(ci);
+ boost::ignore_unused_variable_warning(poly);
+ }
+
+ };
+
+public:
+
+
+ BOOST_CONCEPT_USAGE(Polygon)
+ {
+ // Check if it can be modified
+ // TODO
+
+ //Geometry* poly;
+ //clear(*poly);
+ //append(*poly, point_type());
+
+ checker::apply();
+ }
+#endif
+};
+
+
+/*!
+\brief Polygon concept (const version)
+\ingroup const_concepts
+\details The ConstPolygon concept check the same as the Polygon concept,
+but does not check write access.
+*/
+template <typename Geometry>
+class ConstPolygon
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename ring_type<Geometry>::type ring_type;
+ typedef typename interior_type<Geometry>::type interior_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point_type>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstRing<ring_type>) );
+
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<interior_type>) );
+
+ struct checker
+ {
+ static inline void apply()
+ {
+ Geometry* poly;
+ ring_type const& ce = exterior_ring(*poly);
+ interior_type const& ci = interior_rings(*poly);
+
+ boost::ignore_unused_variable_warning(ce);
+ boost::ignore_unused_variable_warning(ci);
+ boost::ignore_unused_variable_warning(poly);
+ }
+ };
+
+
+public:
+
+ BOOST_CONCEPT_USAGE(ConstPolygon)
+ {
+ checker::apply();
+ }
+#endif
+};
+
+}}} // namespace boost::geometry::concept
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POLYGON_CONCEPT_HPP

Added: sandbox/geometry/boost/geometry/geometries/concepts/ring_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/concepts/ring_concept.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,103 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_RING_CONCEPT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_RING_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+#include <boost/geometry/geometries/concepts/detail/check_clear.hpp>
+#include <boost/geometry/geometries/concepts/detail/check_append.hpp>
+
+
+namespace boost { namespace geometry { namespace concept {
+
+
+/*!
+\brief ring concept
+\ingroup concepts
+\par Formal definition:
+The ring concept is defined as following:
+- there must be a specialization of traits::tag defining ring_tag as type
+- it must behave like a Boost.Range
+- there can optionally be a specialization of traits::point_order defining the
+ order or orientation of its points, clockwise or counterclockwise.
+- either it can behave like the std library, having pushback
+- or it can implement a mechanism for clearing and adding points.
+ This is the same as the for the concept Linestring, and described there.
+
+\note to fulfil the concepts, no traits class has to be specialized to
+define the point type. The point type is taken using boost::range_value<X>::type
+*/
+template <typename Geometry>
+class Ring
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Point<point_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(Ring)
+ {
+ // Check if it can be modified
+ static const bool use_std = traits::use_std
+ <
+ typename boost::remove_const<Geometry>::type
+ >::value;
+
+ Geometry* ring;
+ detail::check_clear<Geometry, use_std>::apply(*ring);
+
+ point_type* p;
+ detail::check_append<Geometry, point_type, use_std>::apply(*ring, *p);
+ }
+#endif
+};
+
+
+/*!
+\brief (linear) ring concept (const version)
+\ingroup const_concepts
+\details The ConstLinearRing concept check the same as the Geometry concept,
+but does not check write access.
+*/
+template <typename Geometry>
+class ConstRing
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstRing)
+ {
+ }
+#endif
+};
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_RING_CONCEPT_HPP

Added: sandbox/geometry/boost/geometry/geometries/concepts/segment_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/concepts/segment_concept.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,133 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_SEGMENT_CONCEPT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_SEGMENT_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+
+
+namespace boost { namespace geometry { namespace concept {
+
+
+/*!
+\brief segment concept
+\ingroup concepts
+\par Formal definition:
+The segment concept is defined as following:
+- there must be a specialization of traits::tag defining segment_tag as type
+- there must be a specialization of traits::point_type to define the
+ underlying point type (even if it does not consist of points, it should define
+ this type, to indicate the points it can work with)
+- there must be a specialization of traits::indexed_access, per index
+ and per dimension, with two functions:
+ - get to get a coordinate value
+ - set to set a coordinate value (this one is not checked for ConstSegment)
+
+\note The segment concept is similar to the box concept, defining another tag.
+However, the box concept assumes the index as min_corner, max_corner, while
+for the segment concept there is no assumption.
+*/
+template <typename Geometry>
+class Segment
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Point<point_type>) );
+
+
+ template <size_t Index, size_t Dimension, size_t DimensionCount>
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ Geometry* s;
+ geometry::set<Index, Dimension>(*s, geometry::get<Index, Dimension>(*s));
+ dimension_checker<Index, Dimension + 1, DimensionCount>::apply();
+ }
+ };
+
+ template <size_t Index, size_t DimensionCount>
+ struct dimension_checker<Index, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public :
+
+ BOOST_CONCEPT_USAGE(Segment)
+ {
+ static const size_t n = dimension<point_type>::type::value;
+ dimension_checker<0, 0, n>::apply();
+ dimension_checker<1, 0, n>::apply();
+ }
+#endif
+};
+
+
+/*!
+\brief Segment concept (const version)
+\ingroup const_concepts
+\details The ConstSegment concept verifies the same as the Segment concept,
+but does not verify write access.
+*/
+template <typename Geometry>
+class ConstSegment
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename coordinate_type<Geometry>::type coordinate_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point_type>) );
+
+
+ template <size_t Index, size_t Dimension, size_t DimensionCount>
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ const Geometry* s = 0;
+ coordinate_type coord(geometry::get<Index, Dimension>(*s));
+ boost::ignore_unused_variable_warning(coord);
+ dimension_checker<Index, Dimension + 1, DimensionCount>::apply();
+ }
+ };
+
+ template <size_t Index, size_t DimensionCount>
+ struct dimension_checker<Index, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstSegment)
+ {
+ static const size_t n = dimension<point_type>::type::value;
+ dimension_checker<0, 0, n>::apply();
+ dimension_checker<1, 0, n>::apply();
+ }
+#endif
+};
+
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_SEGMENT_CONCEPT_HPP

Added: sandbox/geometry/boost/geometry/geometries/geometries.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/geometries.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,35 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_HPP
+
+
+/*!
+\defgroup geometries geometries: geometries provided by default
+\details The GGL can be used with the geometry classes provided by the library,
+and with custom geometries registered by traits classes or registration
+macros.
+
+This documentation page refers to the geometry classes provided by the library.
+
+*/
+
+#include <boost/geometry/geometries/adapted/c_array.hpp>
+#include <boost/geometry/geometries/adapted/tuple.hpp>
+
+#include <boost/geometry/geometries/point.hpp>
+#include <boost/geometry/geometries/point_xy.hpp>
+#include <boost/geometry/geometries/linear_ring.hpp>
+#include <boost/geometry/geometries/linestring.hpp>
+#include <boost/geometry/geometries/polygon.hpp>
+
+#include <boost/geometry/geometries/box.hpp>
+#include <boost/geometry/geometries/segment.hpp>
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_HPP

Added: sandbox/geometry/boost/geometry/geometries/linear_ring.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/linear_ring.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,94 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_LINEAR_RING_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_LINEAR_RING_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/assert.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/point_order.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief A linear_ring (linear linear_ring) is a closed line which should not be selfintersecting
+ \ingroup geometries
+ \tparam P point type
+ \tparam V optional container type, for example std::vector, std::list, std::deque
+ \tparam A optional container-allocator-type
+*/
+template
+<
+ typename P,
+ template<typename, typename> class V = std::vector,
+ bool ClockWise = true,
+ template<typename> class A = std::allocator
+>
+class linear_ring : public V<P, A<P> >
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<P>) );
+};
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename P,
+ template<typename, typename> class V,
+ bool ClockWise,
+ template<typename> class A
+>
+struct tag< linear_ring<P, V, ClockWise, A> >
+{
+ typedef ring_tag type;
+};
+
+
+template
+<
+ typename P,
+ template<typename, typename> class V,
+ template<typename> class A
+>
+struct point_order< linear_ring<P, V, false, A> >
+{
+ static const order_selector value = counterclockwise;
+};
+
+
+template
+<
+ typename P,
+ template<typename, typename> class V,
+ template<typename> class A
+>
+struct point_order< linear_ring<P, V, true, A> >
+{
+ static const order_selector value = clockwise;
+};
+
+
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_LINEAR_RING_HPP

Added: sandbox/geometry/boost/geometry/geometries/linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/linestring.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,69 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_LINESTRING_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_LINESTRING_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/assert.hpp>
+#include <boost/range/functions.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief A linestring (named so by OGC) is a collection (default a vector) of points.
+ \ingroup geometries
+ \tparam P point type
+ \tparam V optional container type, for example std::vector, std::list, std::deque
+ \tparam A optional container-allocator-type
+ (see http://accu.org/index.php/journals/427#ftn.d0e249 )
+ \par Concepts:
+ All algorithms work on ranges, based on a container with point types fulfilling
+ the point concepts. They will take linestring, but also vector, std::pair, or other containers.
+*/
+template
+<
+ typename P,
+ template<typename,typename> class V = std::vector,
+ template<typename> class A = std::allocator
+>
+class linestring : public V<P, A<P> >
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<P>) );
+};
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename P,
+ template<typename,typename> class V,
+ template<typename> class A
+>
+struct tag<linestring<P, V, A> >
+{
+ typedef linestring_tag type;
+};
+} // namespace traits
+
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_LINESTRING_HPP

Added: sandbox/geometry/boost/geometry/geometries/point.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/point.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,154 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_POINT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_POINT_HPP
+
+#include <cstddef>
+
+#include <boost/mpl/int.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/util/math.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief Basic point class, having coordinates defined in a neutral way
+ \ingroup geometries
+ \tparam T numeric type, for example double, float, int
+ \tparam D coordinate dimension as number of coordinates, for example 2
+ \tparam C coordinate system, for example cs::cartesian
+*/
+template<typename T, std::size_t D, typename C>
+class point
+{
+public:
+
+ // Concept typedefs and members
+ typedef T coordinate_type;
+ typedef C coordinate_system;
+
+ static const std::size_t coordinate_count = D;
+
+ /// Default constructor, no initialization at all
+ inline point()
+ {}
+
+ /// Constructs with one, or optionally two or three values
+ inline point(T const& v0, T const& v1 = 0, T const& v2 = 0)
+ {
+ if (D >= 1) m_values[0] = v0;
+ if (D >= 2) m_values[1] = v1;
+ if (D >= 3) m_values[2] = v2;
+ }
+
+
+ /// Compile time access to coordinate values
+ template <std::size_t K>
+ inline T const& get() const
+ {
+ BOOST_STATIC_ASSERT(K < D);
+ return m_values[K];
+ }
+
+ template <std::size_t K>
+ inline void set(T value)
+ {
+ BOOST_STATIC_ASSERT(K < D);
+ m_values[K] = value;
+ }
+
+
+private:
+
+ T m_values[D];
+};
+
+
+// Adapt the point to the concept
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+template
+<
+ typename CoordinateType,
+ std::size_t DimensionCount,
+ typename CoordinateSystem
+>
+struct tag<point<CoordinateType, DimensionCount, CoordinateSystem> >
+{
+ typedef point_tag type;
+};
+
+template
+<
+ typename CoordinateType,
+ std::size_t DimensionCount,
+ typename CoordinateSystem
+>
+struct coordinate_type<point<CoordinateType, DimensionCount, CoordinateSystem> >
+{
+ typedef CoordinateType type;
+};
+
+template
+<
+ typename CoordinateType,
+ std::size_t DimensionCount,
+ typename CoordinateSystem
+>
+struct coordinate_system<point<CoordinateType, DimensionCount, CoordinateSystem> >
+{
+ typedef CoordinateSystem type;
+};
+
+template
+<
+ typename CoordinateType,
+ std::size_t DimensionCount,
+ typename CoordinateSystem
+>
+struct dimension<point<CoordinateType, DimensionCount, CoordinateSystem> >
+ : boost::mpl::int_<DimensionCount>
+{};
+
+template
+<
+ typename CoordinateType,
+ std::size_t DimensionCount,
+ typename CoordinateSystem,
+ std::size_t Dimension
+>
+struct access<point<CoordinateType, DimensionCount, CoordinateSystem>, Dimension>
+{
+ static inline CoordinateType get(
+ point<CoordinateType, DimensionCount, CoordinateSystem> const& p)
+ {
+ return p.template get<Dimension>();
+ }
+
+ static inline void set(
+ point<CoordinateType, DimensionCount, CoordinateSystem>& p,
+ CoordinateType const& value)
+ {
+ p.template set<Dimension>(value);
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_POINT_HPP

Added: sandbox/geometry/boost/geometry/geometries/point_xy.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/point_xy.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,104 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_POINT_XY_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_POINT_XY_HPP
+
+#include <cstddef>
+
+#include <boost/mpl/int.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/geometries/point.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief 2D point in Cartesian coordinate system
+ \ingroup geometries
+ \tparam T numeric type, arguments can be, for example, double, float, int
+*/
+template<typename T, typename C = cs::cartesian>
+class point_xy : public point<T, 2, C>
+{
+public:
+
+ /// Default constructor, does not initialize anything
+ inline point_xy() : point<T, 2, C>() {}
+
+ /// Constructor with x/y values
+ inline point_xy(T const& x, T const& y) : point<T, 2, C>(x, y) {}
+
+ /// Get x-value
+ inline T const& x() const
+ { return this->template get<0>(); }
+
+ /// Get y-value
+ inline T const& y() const
+ { return this->template get<1>(); }
+
+ /// Set x-value
+ inline void x(T const& v)
+ { this->template set<0>(v); }
+
+ /// Set y-value
+ inline void y(T const& v)
+ { this->template set<1>(v); }
+};
+
+// Adapt the point_xy to the concept
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename CoordinateType, typename CoordinateSystem>
+struct tag<point_xy<CoordinateType, CoordinateSystem> >
+{
+ typedef point_tag type;
+};
+
+template<typename CoordinateType, typename CoordinateSystem>
+struct coordinate_type<point_xy<CoordinateType, CoordinateSystem> >
+{
+ typedef CoordinateType type;
+};
+
+template<typename CoordinateType, typename CoordinateSystem>
+struct coordinate_system<point_xy<CoordinateType, CoordinateSystem> >
+{
+ typedef CoordinateSystem type;
+};
+
+template<typename CoordinateType, typename CoordinateSystem>
+struct dimension<point_xy<CoordinateType, CoordinateSystem> >
+ : boost::mpl::int_<2>
+{};
+
+template<typename CoordinateType, typename CoordinateSystem, std::size_t Dimension>
+struct access<point_xy<CoordinateType, CoordinateSystem>, Dimension >
+{
+ static inline CoordinateType get(
+ point_xy<CoordinateType, CoordinateSystem> const& p)
+ {
+ return p.template get<Dimension>();
+ }
+
+ static inline void set(point_xy<CoordinateType, CoordinateSystem>& p,
+ CoordinateType const& value)
+ {
+ p.template set<Dimension>(value);
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_POINT_XY_HPP

Added: sandbox/geometry/boost/geometry/geometries/polygon.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/polygon.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,189 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_POLYGON_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_POLYGON_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/assert.hpp>
+
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/geometries/linear_ring.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief The \b polygon contains an outer ring and zero or more inner rings.
+ \ingroup geometries
+ \tparam P point type
+ \tparam PointList optional container type for points,
+ for example std::vector, std::list, std::deque
+ \tparam RingList optional container type for inner rings,
+ for example std::vector, std::list, std::deque
+ \tparam ClockWise optional parameter, true for clockwise direction,
+ false for CounterClockWise direction
+ \tparam PointAlloc container-allocator-type
+ \tparam RingAlloc 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 Point,
+ template<typename, typename> class PointList = std::vector,
+ template<typename, typename> class RingList = std::vector,
+ bool ClockWise = true,
+ template<typename> class PointAlloc = std::allocator,
+ template<typename> class RingAlloc = std::allocator
+>
+class polygon
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+public:
+
+ // Member types
+ typedef Point point_type;
+ typedef linear_ring<Point, PointList, ClockWise, PointAlloc> ring_type;
+ typedef RingList<ring_type , RingAlloc<ring_type > > inner_container_type;
+
+ inline ring_type const& outer() const { return m_outer; }
+ inline inner_container_type const& 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;
+};
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename Point,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ bool ClockWise,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct tag<polygon<Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc> >
+{
+ typedef polygon_tag type;
+};
+
+template
+<
+ typename Point,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ bool ClockWise,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct ring_type<polygon<Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc> >
+{
+ typedef typename polygon
+ <
+ Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc
+ >::ring_type type;
+};
+
+template
+<
+ typename Point,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ bool ClockWise,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct interior_type< polygon<Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc> >
+{
+ typedef typename polygon
+ <
+ Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc
+ >::inner_container_type type;
+};
+
+template
+<
+ typename Point,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ bool ClockWise,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct exterior_ring< polygon<Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc> >
+{
+ typedef polygon<Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc> polygon_type;
+
+ static inline typename polygon_type::ring_type& get(polygon_type& p)
+ {
+ return p.outer();
+ }
+
+ static inline typename polygon_type::ring_type const & get(polygon_type const& p)
+ {
+ return p.outer();
+ }
+};
+
+template
+<
+ typename Point,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ bool ClockWise,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct interior_rings< polygon<Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc> >
+{
+ typedef polygon<Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc> polygon_type;
+
+ static inline typename polygon_type::inner_container_type& get(
+ polygon_type& p)
+ {
+ return p.inners();
+ }
+
+ static inline typename polygon_type::inner_container_type const& get(
+ polygon_type const& p)
+ {
+ return p.inners();
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_POLYGON_HPP

Added: sandbox/geometry/boost/geometry/geometries/register/box.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/register/box.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,124 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_BOX_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_BOX_HPP
+
+
+#ifndef DOXYGEN_NO_SPECIALIZATIONS
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS(Box, Point, MinCorner, MaxCorner) \
+template <size_t D> \
+struct indexed_access<Box, min_corner, D> \
+{ \
+ typedef typename coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) \
+ { return geometry::get<D>(b. MinCorner); } \
+ static inline void set(Box& b, ct const& value) \
+ { geometry::set<D>(b. MinCorner, value); } \
+}; \
+template <size_t D> \
+struct indexed_access<Box, max_corner, D> \
+{ \
+ typedef typename coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) \
+ { return geometry::get<D>(b. MaxCorner); } \
+ static inline void set(Box& b, ct const& value) \
+ { geometry::set<D>(b. MaxCorner, value); } \
+};
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_TEMPLATIZED(Box, MinCorner, MaxCorner) \
+template <typename P, size_t D> \
+struct indexed_access<Box<P>, min_corner, D> \
+{ \
+ typedef typename coordinate_type<P>::type ct; \
+ static inline ct get(Box<P> const& b) \
+ { return geometry::get<D>(b. MinCorner); } \
+ static inline void set(Box<P>& b, ct const& value) \
+ { geometry::set<D>(b. MinCorner, value); } \
+}; \
+template <typename P, size_t D> \
+struct indexed_access<Box<P>, max_corner, D> \
+{ \
+ typedef typename coordinate_type<P>::type ct; \
+ static inline ct get(Box<P> const& b) \
+ { return geometry::get<D>(b. MaxCorner); } \
+ static inline void set(Box<P>& b, ct const& value) \
+ { geometry::set<D>(b. MaxCorner, value); } \
+};
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_4VALUES(Box, Point, Left, Bottom, Right, Top) \
+template <> struct indexed_access<Box, min_corner, 0> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) { return b. Left; } \
+ static inline void set(Box& b, ct const& value) { b. Left = value; } \
+}; \
+template <> struct indexed_access<Box, min_corner, 1> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) { return b. Bottom; } \
+ static inline void set(Box& b, ct const& value) { b. Bottom = value; } \
+}; \
+template <> struct indexed_access<Box, max_corner, 0> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) { return b. Right; } \
+ static inline void set(Box& b, ct const& value) { b. Right = value; } \
+}; \
+template <> struct indexed_access<Box, max_corner, 1> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) { return b. Top; } \
+ static inline void set(Box& b, ct const& value) { b. Top = value; } \
+};
+
+
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS(Box, PointType) \
+ template<> struct tag<Box > { typedef box_tag type; }; \
+ template<> struct point_type<Box > { typedef PointType type; };
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS_TEMPLATIZED(Box) \
+ template<typename P> struct tag<Box<P> > { typedef box_tag type; }; \
+ template<typename P> struct point_type<Box<P> > { typedef P type; };
+
+#endif // DOXYGEN_NO_SPECIALIZATIONS
+
+
+
+#define BOOST_GEOMETRY_REGISTER_BOX(Box, PointType, MinCorner, MaxCorner) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS(Box, PointType) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS(Box, PointType, MinCorner, MaxCorner) \
+}}}
+
+
+#define BOOST_GEOMETRY_REGISTER_BOX_TEMPLATIZED(Box, MinCorner, MaxCorner) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS_TEMPLATIZED(Box) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_TEMPLATIZED(Box, MinCorner, MaxCorner) \
+}}}
+
+#define BOOST_GEOMETRY_REGISTER_BOX_2D_4VALUES(Box, PointType, Left, Bottom, Right, Top) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS(Box, PointType) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_4VALUES(Box, PointType, Left, Bottom, Right, Top) \
+}}}
+
+
+
+// CONST versions are for boxes probably not that common. Postponed.
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_BOX_HPP

Added: sandbox/geometry/boost/geometry/geometries/register/linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/register/linestring.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,25 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_LINESTRING_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_LINESTRING_HPP
+
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+#define BOOST_GEOMETRY_REGISTER_LINESTRING(Linestring) \
+namespace boost { namespace geometry { namespace traits { \
+ template<> struct tag<Linestring> { typedef linestring_tag type; }; \
+}}}
+
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_LINESTRING_HPP

Added: sandbox/geometry/boost/geometry/geometries/register/point.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/register/point.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,158 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_POINT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_POINT_HPP
+
+
+
+// This file implements a "macro party",
+// for registration of custom geometry types
+
+#ifndef DOXYGEN_NO_SPECIALIZATIONS
+
+// Starting point, specialize basic traits necessary to register a point
+// (the 'accessor' is technically not specialization but definition, specialized in another macro)
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, Dim, CoordinateType, CoordinateSystem) \
+ template<> struct tag<Point> { typedef point_tag type; }; \
+ template<> struct dimension<Point> : boost::mpl::int_<Dim> {}; \
+ template<> struct coordinate_type<Point> { typedef CoordinateType type; }; \
+ template<> struct coordinate_system<Point> { typedef CoordinateSystem type; }; \
+ template<std::size_t Dimension> struct Point##accessor {};
+
+
+// Non Const version
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, CoordinateType) \
+ template<std::size_t Dimension> struct access<Point, Dimension> { \
+ static inline CoordinateType get(Point const& p) \
+ { return Point##accessor<Dimension>::get(p); } \
+ static inline void set(Point& p, CoordinateType const& value) \
+ { Point##accessor<Dimension>::set(p, value); } \
+ };
+
+// Const version
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, CoordinateType) \
+ template<std::size_t Dimension> struct access<Point, Dimension> { \
+ static inline CoordinateType get(Point const& p) \
+ { return Point##accessor<Dimension>::get(p); } \
+ };
+
+
+
+
+// Specialize the point-specific-accessor class, declared below, per dimension
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR(Point, Dim, CoordinateType, Get, Set) \
+ template<> struct Point##accessor< Dim > \
+ { \
+ static inline CoordinateType get(Point const& p) { return p. Get; } \
+ static inline void set(Point& p, CoordinateType const& value) { p. Set = value; } \
+ };
+
+
+// Const version
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_CONST(Point, Dim, CoordinateType, Get) \
+ template<> struct Point##accessor< Dim > \
+ { \
+ static inline CoordinateType get(Point const& p) \
+ { return p. Get; } \
+ };
+
+
+// Get/set version
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_GET_SET(Point, Dim, CoordinateType, Get, Set) \
+ template<> struct Point##accessor< Dim > \
+ { \
+ static inline CoordinateType get(Point const& p) \
+ { return p. Get (); } \
+ static inline void set(Point& p, CoordinateType const& value) \
+ { p. Set ( value ); } \
+ };
+
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_2D(Point, CoordinateType, Get0, Get1, Set0, Set1) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR(Point, 0, CoordinateType, Get0, Set0) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR(Point, 1, CoordinateType, Get1, Set1)
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_3D(Point, CoordinateType, Get0, Get1, Get2, Set0, Set1, Set2) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR(Point, 0, CoordinateType, Get0, Set0) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR(Point, 1, CoordinateType, Get1, Set1) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR(Point, 2, CoordinateType, Get2, Set2)
+
+// Const versions
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST_2D(Point, CoordinateType, Get0, Get1) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_CONST(Point, 0, CoordinateType, Get0) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_CONST(Point, 1, CoordinateType, Get1)
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST_3D(Point, CoordinateType, Get0, Get1, Get2) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_CONST(Point, 0, CoordinateType, Get0) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_CONST(Point, 1, CoordinateType, Get1) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_CONST(Point, 2, CoordinateType, Get2)
+
+#endif // DOXYGEN_NO_SPECIALIZATIONS
+
+
+
+// Library user macro to register a custom 2D point
+#define BOOST_GEOMETRY_REGISTER_POINT_2D(Point, CoordinateType, CoordinateSystem, Field0, Field1) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 2, CoordinateType, CoordinateSystem) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, CoordinateType) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_2D(Point, CoordinateType, Field0, Field1, Field0, Field1) \
+}}}
+
+// Library user macro to register a custom 3D point
+#define BOOST_GEOMETRY_REGISTER_POINT_3D(Point, CoordinateType, CoordinateSystem, Field0, Field1, Field2) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 3, CoordinateType, CoordinateSystem) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, CoordinateType) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_3D(Point, CoordinateType, Field0, Field1, Field2, Field0, Field1, Field2) \
+}}}
+
+
+
+// Library user macro to register a custom 2D point (CONST version)
+#define BOOST_GEOMETRY_REGISTER_POINT_2D_CONST(Point, CoordinateType, CoordinateSystem, Field0, Field1) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 2, CoordinateType, CoordinateSystem) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, CoordinateType) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST_2D(Point, CoordinateType, Field0, Field1) \
+}}}
+
+// Library user macro to register a custom 3D point (CONST version)
+#define BOOST_GEOMETRY_REGISTER_POINT_3D_CONST(Point, CoordinateType, CoordinateSystem, Field0, Field1, Field2) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 3, CoordinateType, CoordinateSystem) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, CoordinateType) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST_3D(Point, CoordinateType, Field0, Field1, Field2) \
+}}}
+
+
+// Library user macro to register a custom 2D point (having separate get/set methods)
+#define BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET(Point, CoordinateType, CoordinateSystem, Get0, Get1, Set0, Set1) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 2, CoordinateType, CoordinateSystem) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, CoordinateType) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_GET_SET(Point, 0, CoordinateType, Get0, Set0) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_GET_SET(Point, 1, CoordinateType, Get1, Set1) \
+}}}
+
+
+// Library user macro to register a custom 3D point (having separate get/set methods)
+#define BOOST_GEOMETRY_REGISTER_POINT_3D_GET_SET(Point, CoordinateType, CoordinateSystem, Get0, Get1, Get2, Set0, Set1, Set2) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 3, CoordinateType, CoordinateSystem) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, CoordinateType) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_GET_SET(Point, 0, CoordinateType, Get0, Set0) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_GET_SET(Point, 1, CoordinateType, Get1, Set1) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_GET_SET(Point, 2, CoordinateType, Get2, Set2) \
+}}}
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_POINT_HPP

Added: sandbox/geometry/boost/geometry/geometries/register/ring.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/register/ring.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,28 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_RING_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_RING_HPP
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#define BOOST_GEOMETRY_REGISTER_RING(Ring) \
+namespace boost { namespace geometry { namespace traits { \
+ template<> struct tag<Ring> { typedef ring_tag type; }; \
+}}}
+
+
+#define BOOST_GEOMETRY_REGISTER_RING_TEMPLATIZED(Ring) \
+namespace boost { namespace geometry { namespace traits { \
+ template<typename P> struct tag< Ring<P> > { typedef ring_tag type; }; \
+}}}
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_RING_HPP

Added: sandbox/geometry/boost/geometry/geometries/register/segment.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/register/segment.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,124 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_SEGMENT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_SEGMENT_HPP
+
+
+#ifndef DOXYGEN_NO_SPECIALIZATIONS
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS(Segment, Point, Index0, Index1) \
+template <size_t D> \
+struct indexed_access<Segment, min_corner, D> \
+{ \
+ typedef typename coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) \
+ { return geometry::get<D>(b. Index0); } \
+ static inline void set(Segment& b, ct const& value) \
+ { geometry::set<D>(b. Index0, value); } \
+}; \
+template <size_t D> \
+struct indexed_access<Segment, max_corner, D> \
+{ \
+ typedef typename coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) \
+ { return geometry::get<D>(b. Index1); } \
+ static inline void set(Segment& b, ct const& value) \
+ { geometry::set<D>(b. Index1, value); } \
+};
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS_TEMPLATIZED(Segment, Index0, Index1) \
+template <typename P, size_t D> \
+struct indexed_access<Segment<P>, min_corner, D> \
+{ \
+ typedef typename coordinate_type<P>::type ct; \
+ static inline ct get(Segment<P> const& b) \
+ { return geometry::get<D>(b. Index0); } \
+ static inline void set(Segment<P>& b, ct const& value) \
+ { geometry::set<D>(b. Index0, value); } \
+}; \
+template <typename P, size_t D> \
+struct indexed_access<Segment<P>, max_corner, D> \
+{ \
+ typedef typename coordinate_type<P>::type ct; \
+ static inline ct get(Segment<P> const& b) \
+ { return geometry::get<D>(b. Index1); } \
+ static inline void set(Segment<P>& b, ct const& value) \
+ { geometry::set<D>(b. Index1, value); } \
+};
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS_4VALUES(Segment, Point, Left, Bottom, Right, Top) \
+template <> struct indexed_access<Segment, min_corner, 0> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) { return b. Left; } \
+ static inline void set(Segment& b, ct const& value) { b. Left = value; } \
+}; \
+template <> struct indexed_access<Segment, min_corner, 1> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) { return b. Bottom; } \
+ static inline void set(Segment& b, ct const& value) { b. Bottom = value; } \
+}; \
+template <> struct indexed_access<Segment, max_corner, 0> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) { return b. Right; } \
+ static inline void set(Segment& b, ct const& value) { b. Right = value; } \
+}; \
+template <> struct indexed_access<Segment, max_corner, 1> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) { return b. Top; } \
+ static inline void set(Segment& b, ct const& value) { b. Top = value; } \
+};
+
+
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS(Segment, PointType) \
+ template<> struct tag<Segment > { typedef segment_tag type; }; \
+ template<> struct point_type<Segment > { typedef PointType type; };
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS_TEMPLATIZED(Segment) \
+ template<typename P> struct tag<Segment<P> > { typedef segment_tag type; }; \
+ template<typename P> struct point_type<Segment<P> > { typedef P type; };
+
+#endif // DOXYGEN_NO_SPECIALIZATIONS
+
+
+
+#define BOOST_GEOMETRY_REGISTER_SEGMENT(Segment, PointType, Index0, Index1) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS(Segment, PointType) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS(Segment, PointType, Index0, Index1) \
+}}}
+
+
+#define BOOST_GEOMETRY_REGISTER_SEGMENT_TEMPLATIZED(Segment, Index0, Index1) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS_TEMPLATIZED(Segment) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS_TEMPLATIZED(Segment, Index0, Index1) \
+}}}
+
+#define BOOST_GEOMETRY_REGISTER_SEGMENT_2D_4VALUES(Segment, PointType, Left, Bottom, Right, Top) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS(Segment, PointType) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS_4VALUES(Segment, PointType, Left, Bottom, Right, Top) \
+}}}
+
+
+
+// CONST versions are for segments probably not that common. Postponed.
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_SEGMENT_HPP

Added: sandbox/geometry/boost/geometry/geometries/segment.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometries/segment.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,118 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_SEGMENT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_SEGMENT_HPP
+
+#include <cstddef>
+
+#include <boost/concept/assert.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_const.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+\brief Class segment: small class containing two (templatized) point references
+\ingroup geometries
+\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.
+Difference is that it refers to points, does not have points.
+\note Like std::pair, points are public available.
+\note type is const or non const, so geometry::segment<P> or geometry::segment<const P>
+\note We cannot derive from std::pair<P&, P&> because of
+reference assignments.
+\tparam ConstOrNonConstPoint point type of the segment, maybe a point or a const point
+*/
+template<typename ConstOrNonConstPoint>
+class segment
+{
+ BOOST_CONCEPT_ASSERT( (
+ typename boost::mpl::if_
+ <
+ boost::is_const<ConstOrNonConstPoint>,
+ concept::Point<ConstOrNonConstPoint>,
+ concept::ConstPoint<ConstOrNonConstPoint>
+ >
+ ) );
+
+ typedef ConstOrNonConstPoint point_type;
+
+public:
+
+ point_type& first;
+ point_type& second;
+
+ inline segment(point_type& p1, point_type& p2)
+ : first(p1)
+ , second(p2)
+ {}
+};
+
+// Traits specializations for segment above
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename ConstOrNonConstPoint>
+struct tag<segment<ConstOrNonConstPoint> >
+{
+ typedef segment_tag type;
+};
+
+template <typename ConstOrNonConstPoint>
+struct point_type<segment<ConstOrNonConstPoint> >
+{
+ typedef ConstOrNonConstPoint type;
+};
+
+template <typename ConstOrNonConstPoint, std::size_t Dimension>
+struct indexed_access<segment<ConstOrNonConstPoint>, 0, Dimension>
+{
+ typedef segment<ConstOrNonConstPoint> segment_type;
+ typedef typename geometry::coordinate_type<segment_type>::type coordinate_type;
+
+ static inline coordinate_type get(segment_type const& s)
+ {
+ return geometry::get<Dimension>(s.first);
+ }
+
+ static inline void set(segment_type& s, coordinate_type const& value)
+ {
+ geometry::set<Dimension>(s.first, value);
+ }
+};
+
+
+template <typename ConstOrNonConstPoint, std::size_t Dimension>
+struct indexed_access<segment<ConstOrNonConstPoint>, 1, Dimension>
+{
+ typedef segment<ConstOrNonConstPoint> segment_type;
+ typedef typename geometry::coordinate_type<segment_type>::type coordinate_type;
+
+ static inline coordinate_type get(segment_type const& s)
+ {
+ return geometry::get<Dimension>(s.second);
+ }
+
+ static inline void set(segment_type& s, coordinate_type const& value)
+ {
+ geometry::set<Dimension>(s.second, value);
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_SEGMENT_HPP

Added: sandbox/geometry/boost/geometry/geometry.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/geometry.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,67 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Copyright (c) 2009 Mateusz Loskot <mateusz_at_[hidden]>
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GGL_HPP
+#define BOOST_GEOMETRY_GGL_HPP
+
+// Shortcut to include all header files
+
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/topological_dimension.hpp>
+
+#include <boost/geometry/core/replace_point_type.hpp>
+
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/arithmetic/dot_product.hpp>
+
+#include <boost/geometry/strategies/strategies.hpp>
+
+#include <boost/geometry/algorithms/append.hpp>
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/buffer.hpp>
+#include <boost/geometry/algorithms/centroid.hpp>
+#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/algorithms/convex_hull.hpp>
+#include <boost/geometry/algorithms/correct.hpp>
+#include <boost/geometry/algorithms/distance.hpp>
+#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/algorithms/for_each.hpp>
+#include <boost/geometry/algorithms/intermediate.hpp>
+#include <boost/geometry/algorithms/intersection.hpp>
+#include <boost/geometry/algorithms/intersects.hpp>
+#include <boost/geometry/algorithms/length.hpp>
+#include <boost/geometry/algorithms/make.hpp>
+#include <boost/geometry/algorithms/num_points.hpp>
+#include <boost/geometry/algorithms/perimeter.hpp>
+#include <boost/geometry/algorithms/sectionalize.hpp>
+#include <boost/geometry/algorithms/selected.hpp>
+#include <boost/geometry/algorithms/simplify.hpp>
+#include <boost/geometry/algorithms/transform.hpp>
+#include <boost/geometry/algorithms/union.hpp>
+#include <boost/geometry/algorithms/within.hpp>
+
+// check includes all concepts
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/util/copy.hpp>
+#include <boost/geometry/util/for_each_coordinate.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+#include <boost/geometry/util/write_dsv.hpp>
+
+#endif // BOOST_GEOMETRY_GGL_HPP

Added: sandbox/geometry/boost/geometry/iterators/base.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/iterators/base.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,59 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ITERATORS_BASE_HPP
+#define BOOST_GEOMETRY_ITERATORS_BASE_HPP
+
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+#include <boost/mpl/if.hpp>
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace boost { namespace geometry { namespace detail { namespace iterators {
+
+template <typename T, typename Iterator>
+struct iterator_base :
+ public boost::iterator_adaptor
+ <
+ T,
+ Iterator,
+ boost::use_default,
+ typename boost::mpl::if_
+ <
+ boost::is_convertible
+ <
+ typename boost::iterator_traversal<Iterator>::type,
+ boost::random_access_traversal_tag
+ >,
+ boost::bidirectional_traversal_tag,
+ boost::use_default
+ >::type
+ >
+{
+ // Define operator cast to Iterator to be able to write things like Iterator it = myit++
+ inline operator Iterator() const
+ {
+ return this->base();
+ }
+
+ /*inline bool operator==(const Iterator& other) const
+ {
+ return this->base() == other;
+ }
+ inline bool operator!=(const Iterator& other) const
+ {
+ return ! operator==(other);
+ }*/
+};
+
+}}}} // namespace boost::geometry::detail::iterators
+#endif
+
+
+#endif // BOOST_GEOMETRY_ITERATORS_BASE_HPP

Added: sandbox/geometry/boost/geometry/iterators/circular_iterator.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/iterators/circular_iterator.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,92 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ITERATORS_CIRCULAR_ITERATOR_HPP
+#define BOOST_GEOMETRY_ITERATORS_CIRCULAR_ITERATOR_HPP
+
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+
+#include <boost/geometry/iterators/base.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief Iterator which goes circular through a range, starting at a point, ending at that point
+ \tparam Iterator iterator on which this class is based on
+ \ingroup iterators
+*/
+template <typename Iterator>
+struct circular_iterator :
+ public detail::iterators::iterator_base
+ <
+ circular_iterator<Iterator>,
+ Iterator
+ >
+{
+ friend class boost::iterator_core_access;
+
+ explicit inline circular_iterator(Iterator begin, Iterator end, Iterator start)
+ : m_begin(begin)
+ , m_end(end)
+ , m_start(start)
+ {
+ this->base_reference() = start;
+ }
+
+ // Constructor to indicate the end of a range, to enable e.g. std::copy
+ explicit inline circular_iterator(Iterator end)
+ : m_begin(end)
+ , m_end(end)
+ , m_start(end)
+ {
+ this->base_reference() = end;
+ }
+
+ /// Navigate to a certain position, should be in [start .. end], it at end
+ /// it will circle again.
+ inline void moveto(Iterator it)
+ {
+ this->base_reference() = it;
+ check_end();
+ }
+
+private:
+
+ inline void increment()
+ {
+ if (this->base() != m_end)
+ {
+ (this->base_reference())++;
+ check_end();
+ }
+ }
+
+ inline void check_end()
+ {
+ if (this->base() == this->m_end)
+ {
+ this->base_reference() = this->m_begin;
+ }
+
+ if (this->base() == m_start)
+ {
+ this->base_reference() = this->m_end;
+ }
+ }
+
+ Iterator m_begin;
+ Iterator m_end;
+ Iterator m_start;
+};
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ITERATORS_CIRCULAR_ITERATOR_HPP

Added: sandbox/geometry/boost/geometry/iterators/ever_circling_iterator.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/iterators/ever_circling_iterator.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,95 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
+#define BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
+
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+
+#include <boost/geometry/iterators/base.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief Iterator which ever circles through a range
+ \tparam Iterator iterator on which this class is based on
+ \ingroup iterators
+ \details If the iterator arrives at range.end() it restarts from the
+ beginning. So it has to be stopped in another way.
+ Don't call for(....; it++) because it will turn in an endless loop
+ \note Name inspired on David Bowie's
+ "Chant Of The Ever Circling Skeletal Family"
+*/
+template <typename Iterator>
+struct ever_circling_iterator :
+ public detail::iterators::iterator_base
+ <
+ ever_circling_iterator<Iterator>,
+ Iterator
+ >
+{
+ friend class boost::iterator_core_access;
+
+ explicit inline ever_circling_iterator(Iterator begin, Iterator end,
+ bool skip_first = false)
+ : m_begin(begin)
+ , m_end(end)
+ , m_skip_first(skip_first)
+ {
+ this->base_reference() = begin;
+ }
+
+ explicit inline ever_circling_iterator(Iterator begin, Iterator end, Iterator start,
+ bool skip_first = false)
+ : m_begin(begin)
+ , m_end(end)
+ , m_skip_first(skip_first)
+ {
+ this->base_reference() = start;
+ }
+
+ /// Navigate to a certain position, should be in [start .. end], it at end
+ /// it will circle again.
+ inline void moveto(Iterator it)
+ {
+ this->base_reference() = it;
+ check_end();
+ }
+
+private:
+
+ inline void increment(bool possibly_skip = true)
+ {
+ (this->base_reference())++;
+ check_end(possibly_skip);
+ }
+
+ inline void check_end(bool possibly_skip = true)
+ {
+ if (this->base() == this->m_end)
+ {
+ this->base_reference() = this->m_begin;
+ if (m_skip_first && possibly_skip)
+ {
+ increment(false);
+ }
+ }
+ }
+
+ Iterator m_begin;
+ Iterator m_end;
+ bool m_skip_first;
+};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP

Added: sandbox/geometry/boost/geometry/iterators/range_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/iterators/range_type.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,82 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ITERATORS_RANGE_TYPE_HPP
+#define BOOST_GEOMETRY_ITERATORS_RANGE_TYPE_HPP
+
+#include <boost/type_traits.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename GeometryTag, typename Geometry>
+struct range_type
+{
+ // Even if it is not recognized, define itself as a type.
+ // This enables calling range_type over any range
+ // (not necessarily a geometry)
+
+ // Furthermore, applicable for ring/linestring
+ typedef Geometry type;
+};
+
+
+template <typename Geometry>
+struct range_type<point_tag, Geometry>
+{
+ typedef void type;
+};
+
+
+template <typename Geometry>
+struct range_type<polygon_tag, Geometry>
+{
+ typedef typename ring_type<Geometry>::type type;
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+/*!
+\brief Meta-function defining a type which is a boost-range.
+\details
+- For linestrings and rings, it defines the type itself.
+- For polygons it defines the ring type.
+- For multi-points, it defines the type itself
+- For multi-polygons and multi-linestrings, it defines the single-version
+ (so in the end the linestring and ring-type-of-multi-polygon)
+\ingroup iterators
+*/
+template <typename Geometry>
+struct range_type
+{
+ typedef typename dispatch::range_type
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ITERATORS_RANGE_TYPE_HPP

Added: sandbox/geometry/boost/geometry/iterators/segment_iterator.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/iterators/segment_iterator.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,137 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Mateusz Loskot 2009, mateusz_at_[hidden]
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP
+#define BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP
+
+// TODO: This is very experimental version of input iterator
+// reading collection of points as segments - proof of concept.
+// --mloskot
+
+// TODO: Move to boost::iterator_adaptor
+
+#include <iterator>
+
+#include <boost/assert.hpp>
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+
+#include <boost/geometry/algorithms/equals.hpp>
+#include <boost/geometry/geometries/segment.hpp>
+
+namespace boost { namespace geometry
+{
+
+template <typename Base, typename Point>
+struct segment_iterator
+{
+ typedef Base base_type;
+ typedef Point point_type;
+ typedef typename geometry::segment<Point> segment_type;
+
+ typedef std::input_iterator_tag iterator_category;
+ typedef typename std::iterator_traits<Base>::difference_type difference_type;
+ typedef segment_type value_type;
+ typedef segment_type* pointer;
+ typedef segment_type& reference;
+
+ explicit segment_iterator(Base const& end)
+ : m_segment(p1 , p2)
+ , m_prev(end)
+ , m_it(end)
+ , m_end(end)
+ {
+ }
+
+ segment_iterator(Base const& it, Base const& end)
+ : m_segment(p1 , p2)
+ , m_prev(it)
+ , m_it(it)
+ , m_end(end)
+ {
+ if (m_it != m_end)
+ {
+ BOOST_ASSERT(m_prev != m_end);
+ ++m_it;
+ }
+ }
+
+ reference operator*()
+ {
+ BOOST_ASSERT(m_it != m_end && m_prev != m_end);
+
+ p1 = *m_prev;
+ p2 = *m_it;
+
+ return m_segment;
+ }
+
+ pointer operator->()
+ {
+ return &(operator*());
+ }
+
+ segment_iterator& operator++()
+ {
+ ++m_prev;
+ ++m_it;
+ return *this;
+ }
+
+ segment_iterator operator++(int)
+ {
+ segment_iterator it(*this);
+ ++(*this);
+ return it;
+ }
+
+ Base const& base() const { return m_it; }
+
+private:
+
+ point_type p1;
+ point_type p2;
+ segment_type m_segment;
+
+ Base m_prev;
+ Base m_it;
+ Base m_end;
+};
+
+template <typename Base, typename Point>
+bool operator==(segment_iterator<Base, Point> const& lhs,
+ segment_iterator<Base, Point> const& rhs)
+{
+ return (lhs.base() == rhs.base());
+}
+
+template <typename Base, typename Point>
+bool operator!=(segment_iterator<Base, Point> const& lhs,
+ segment_iterator<Base, Point> const& rhs)
+{
+ return (lhs.base() != rhs.base());
+}
+
+template <typename C>
+segment_iterator
+<
+ typename C::iterator,
+ typename C::value_type
+>
+make_segment_iterator(C& c)
+{
+ typedef typename C::iterator base_iterator;
+ typedef typename C::value_type point_type;
+ return segment_iterator<base_iterator, point_type>(c.begin(), c.end());
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ITERATORS_SEGMENT_ITERATOR_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/area.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/area.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,47 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_AREA_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_AREA_HPP
+
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/multi/core/point_type.hpp>
+#include <boost/geometry/multi/algorithms/detail/multi_sum.hpp>
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+template <typename MultiGeometry, order_selector Order, typename Strategy>
+struct area<multi_polygon_tag, MultiGeometry, Order, Strategy>
+ : detail::multi_sum
+ <
+ typename Strategy::return_type,
+ MultiGeometry,
+ Strategy,
+ area
+ <
+ polygon_tag,
+ typename boost::range_value<MultiGeometry>::type,
+ Order,
+ Strategy
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_AREA_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/centroid.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/centroid.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,147 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_CENTROID_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_CENTROID_HPP
+
+#include <boost/geometry/algorithms/centroid.hpp>
+#include <boost/geometry/algorithms/num_points.hpp>
+#include <boost/geometry/multi/core/point_type.hpp>
+#include <boost/geometry/multi/algorithms/detail/multi_sum.hpp>
+#include <boost/geometry/multi/algorithms/num_points.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace centroid {
+
+
+/*!
+ \brief Building block of a multi-point, to be used as Policy in the
+ more generec centroid_multi
+*/
+template
+<
+ typename Point,
+ typename Strategy
+>
+struct centroid_multi_point_state
+{
+ static inline void apply(Point const& point,
+ Strategy const& strategy, typename Strategy::state_type& state)
+ {
+ strategy.apply(point, state);
+ }
+};
+
+
+
+/*!
+ \brief Generic implementation which calls a policy to calculate the
+ centroid of the total of its single-geometries
+ \details The Policy is, in general, the single-version, with state. So
+ detail::centroid::centroid_polygon_state is used as a policy for this
+ detail::centroid::centroid_multi
+
+*/
+template
+<
+ typename Multi,
+ typename Point,
+ typename Strategy,
+ typename Policy
+>
+struct centroid_multi
+{
+ static inline void apply(Multi const& multi, Point& centroid,
+ Strategy const& strategy)
+ {
+ // If there is nothing in any of the ranges, it is not possible
+ // to calculate the centroid
+ if (geometry::num_points(multi) == 0)
+ {
+ throw centroid_exception();
+ }
+
+ typename Strategy::state_type state;
+
+ for (typename boost::range_const_iterator<Multi>::type
+ it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ Policy::apply(*it, strategy, state);
+ }
+ Strategy::result(state, centroid);
+ }
+};
+
+
+
+}} // namespace detail::centroid
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename MultiPolygon,
+ typename Point,
+ typename Strategy
+>
+struct centroid<multi_polygon_tag, MultiPolygon, Point, Strategy>
+ : detail::centroid::centroid_multi
+ <
+ MultiPolygon,
+ Point,
+ Strategy,
+ detail::centroid::centroid_polygon_state
+ <
+ typename boost::range_value<MultiPolygon>::type,
+ Strategy
+ >
+ >
+{};
+
+
+template
+<
+ typename MultiPoint,
+ typename Point,
+ typename Strategy
+>
+struct centroid<multi_point_tag, MultiPoint, Point, Strategy>
+ : detail::centroid::centroid_multi
+ <
+ MultiPoint,
+ Point,
+ Strategy,
+ detail::centroid::centroid_multi_point_state
+ <
+ typename boost::range_value<MultiPoint>::type,
+ Strategy
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_CENTROID_HPP
+

Added: sandbox/geometry/boost/geometry/multi/algorithms/convex_hull.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/convex_hull.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,22 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_CONVEX_HULL_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_CONVEX_HULL_HPP
+
+
+#include <boost/geometry/multi/iterators/range_type.hpp>
+#include <boost/geometry/multi/util/for_each_range.hpp>
+
+// Note that this file is, furthermore, empty,
+// there is no specialization necessary
+// as this is in fact done by for_each_range
+
+// Might therefore be obsoleted.
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_CONVEX_HULL_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/correct.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/correct.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,64 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_CORRECT_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_CORRECT_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <boost/geometry/algorithms/correct.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace correct {
+
+template <typename MultiPolygon>
+struct correct_multi_polygon
+{
+ static inline void apply(MultiPolygon& mp)
+ {
+ typedef typename boost::range_value<MultiPolygon>::type polygon_type;
+ for (typename boost::range_iterator<MultiPolygon>::type it
+ = boost::begin(mp);
+ it != boost::end(mp);
+ ++it)
+ {
+ correct_polygon<polygon_type>::apply(*it);
+ }
+ }
+};
+
+}} // namespace detail::correct
+#endif
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Geometry>
+struct correct<multi_polygon_tag, Geometry>
+ : detail::correct::correct_multi_polygon<Geometry>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_CORRECT_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/detail/modify_with_predicate.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/detail/modify_with_predicate.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,46 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MODIFY_WITH_PREDICATE_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MODIFY_WITH_PREDICATE_HPP
+
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail {
+
+template <typename MultiGeometry, typename Predicate, typename Policy>
+struct multi_modify_with_predicate
+{
+ static inline void apply(MultiGeometry& multi, Predicate const& predicate)
+ {
+ typedef typename boost::range_iterator<MultiGeometry>::type iterator_type;
+ for (iterator_type it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ Policy::apply(*it, predicate);
+ }
+ }
+};
+
+
+} // namespace detail
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MODIFY_WITH_PREDICATE_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/detail/multi_sum.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/detail/multi_sum.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,53 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_SUM_HPP
+#define BOOST_GEOMETRY_MULTI_SUM_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+namespace boost { namespace geometry
+{
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template
+<
+ typename ReturnType,
+ typename MultiGeometry,
+ typename Strategy,
+ typename Policy
+>
+struct multi_sum
+{
+ static inline ReturnType apply(MultiGeometry const& geometry, Strategy const& strategy)
+ {
+ ReturnType sum = ReturnType();
+ for (typename boost::range_const_iterator
+ <
+ MultiGeometry
+ >::type it = boost::begin(geometry);
+ it != boost::end(geometry);
+ ++it)
+ {
+ sum += Policy::apply(*it, strategy);
+ }
+ return sum;
+ }
+};
+
+
+} // namespace detail
+#endif
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_SUM_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/detail/point_on_border.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/detail/point_on_border.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,90 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2010, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace point_on_border
+{
+
+
+template
+<
+ typename MultiGeometry,
+ typename Point,
+ typename Policy
+>
+struct point_on_multi
+{
+ static inline bool apply(MultiGeometry const& multi, Point& point)
+ {
+ // Take a point on the first multi-geometry
+ // (i.e. the first that is not empty)
+ for (typename boost::range_iterator
+ <
+ MultiGeometry const
+ >::type it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ if (Policy::apply(*it, point))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+
+
+
+}} // namespace detail::point_on_border
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template<typename Multi, typename Point>
+struct point_on_border<multi_polygon_tag, Multi, Point>
+ : detail::point_on_border::point_on_multi
+ <
+ Multi,
+ Point,
+ detail::point_on_border::point_on_polygon
+ <
+ typename boost::range_value<Multi>::type,
+ Point
+ >
+ >
+{};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/detail/sections/get_full_section.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/detail/sections/get_full_section.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,90 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_SECTIONS_GET_FULL_SECTION_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_SECTIONS_GET_FULL_SECTION_HPP
+
+
+#include <boost/assert.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/algorithms/detail/sections/get_full_section.hpp>
+
+
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace section
+{
+
+
+template
+<
+ typename MultiGeometry,
+ typename Section,
+ typename Iterator,
+ typename Policy
+>
+struct full_section_multi
+{
+ static inline void apply(MultiGeometry const& multi,
+ Section const& section,
+ Iterator& begin, Iterator& end)
+ {
+ BOOST_ASSERT
+ (
+ section.multi_index >= 0
+ && section.multi_index < boost::size(multi)
+ );
+
+ Policy::apply(multi[section.multi_index], section, begin, end);
+ }
+};
+
+
+}} // namespace detail::section
+#endif
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename MultiPolygon, typename Section, typename Iterator>
+struct get_full_section<multi_polygon_tag, MultiPolygon, Section, Iterator>
+ : detail::section::full_section_multi
+ <
+ MultiPolygon,
+ Section,
+ Iterator,
+ detail::section::full_section_polygon
+ <
+ typename boost::range_value<MultiPolygon>::type,
+ Section,
+ Iterator
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_SECTIONS_GET_FULL_SECTION_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/distance.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/distance.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,136 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DISTANCE_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DISTANCE_HPP
+
+
+#include <boost/numeric/conversion/bounds.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/core/is_multi.hpp>
+#include <boost/geometry/multi/core/geometry_id.hpp>
+#include <boost/geometry/multi/core/point_type.hpp>
+
+#include <boost/geometry/algorithms/distance.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+
+namespace boost { namespace geometry {
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace distance {
+
+
+template<typename Geometry, typename MultiGeometry, typename Strategy>
+struct distance_single_to_multi
+{
+ typedef typename Strategy::return_type return_type;
+ static inline return_type apply(Geometry const& geometry,
+ MultiGeometry const& multi,
+ Strategy const& strategy)
+ {
+ using namespace boost;
+
+ return_type mindist = make_distance_result<return_type>(
+ numeric::bounds
+ <
+ typename select_coordinate_type
+ <
+ Geometry,
+ MultiGeometry
+ >::type
+ >::highest());
+
+ for(typename range_const_iterator<MultiGeometry>::type it = begin(multi);
+ it != end(multi);
+ ++it)
+ {
+ return_type dist = geometry::distance(geometry, *it);
+ if (dist < mindist)
+ {
+ mindist = dist;
+ }
+ }
+
+ return mindist;
+ }
+};
+
+template<typename Multi1, typename Multi2, typename Strategy>
+struct distance_multi_to_multi
+{
+ typedef typename Strategy::return_type return_type;
+
+ static inline return_type apply(Multi1 const& multi1,
+ Multi2 const& multi2, Strategy const& strategy)
+ {
+ using namespace boost;
+
+ return_type mindist = make_distance_result<return_type>(
+ numeric::bounds
+ <
+ typename select_coordinate_type
+ <
+ Multi1,
+ Multi2
+ >::type
+ >::highest());
+
+ for(typename range_const_iterator<Multi1>::type it = begin(multi1);
+ it != end(multi1);
+ ++it)
+ {
+ return_type dist = distance_single_to_multi
+ <
+ typename range_value<Multi1>::type,
+ Multi2,
+ Strategy
+ >::apply(*it, multi2, strategy);
+ if (dist < mindist)
+ {
+ mindist = dist;
+ }
+ }
+
+ return mindist;
+ }
+};
+
+
+}} // namespace detail::distance
+#endif
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename GeometryTag1, typename GeometryTag2,
+ typename G1, typename G2, typename Strategy>
+struct distance<GeometryTag1, GeometryTag2, G1, G2, strategy_tag_distance_point_point, Strategy, false, true>
+ : detail::distance::distance_single_to_multi<G1, G2, Strategy>
+{};
+
+template <typename GeometryTag1, typename GeometryTag2,
+ typename G1, typename G2, typename Strategy>
+struct distance<GeometryTag1, GeometryTag2, G1, G2, strategy_tag_distance_point_point, Strategy, true, true>
+ : detail::distance::distance_multi_to_multi<G1, G2, Strategy>
+{};
+
+} // namespace dispatch
+#endif
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DISTANCE_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/envelope.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/envelope.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,110 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_ENVELOPE_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_ENVELOPE_HPP
+
+#include <vector>
+
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/algorithms/envelope.hpp>
+
+#include <boost/geometry/multi/core/point_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+
+namespace detail { namespace envelope {
+
+
+template<typename MultiLinestring, typename Box>
+struct envelope_multi_linestring
+{
+ static inline void apply(MultiLinestring const& mp, Box& mbr)
+ {
+ assign_inverse(mbr);
+ for (typename boost::range_const_iterator<MultiLinestring>::type
+ it = mp.begin();
+ it != mp.end();
+ ++it)
+ {
+ envelope_range_additional(*it, mbr);
+ }
+ }
+};
+
+
+// version for multi_polygon: outer linear_ring's of all polygons
+template<typename MultiPolygon, typename Box>
+struct envelope_multi_polygon
+{
+ static inline void apply(MultiPolygon const& mp, Box& mbr)
+ {
+ assign_inverse(mbr);
+ for (typename boost::range_const_iterator<MultiPolygon>::type
+ it = mp.begin();
+ it != mp.end();
+ ++it)
+ {
+ envelope_range_additional(exterior_ring(*it), mbr);
+ }
+ }
+};
+
+
+}} // namespace detail::envelope
+
+#endif
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Multi, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope<multi_point_tag, box_tag, Multi, Box, StrategyLess, StrategyGreater>
+ : detail::envelope::envelope_range<Multi, Box>
+{};
+
+template
+<
+ typename Multi, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope<multi_linestring_tag, box_tag, Multi, Box, StrategyLess, StrategyGreater>
+ : detail::envelope::envelope_multi_linestring<Multi, Box>
+{};
+
+
+template
+<
+ typename Multi, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope<multi_polygon_tag, box_tag, Multi, Box, StrategyLess, StrategyGreater>
+ : detail::envelope::envelope_multi_polygon<Multi, Box>
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_ENVELOPE_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/equals.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/equals.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,117 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2010, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_EQUALS_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_EQUALS_HPP
+
+
+#include <boost/geometry/multi/core/is_multi.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/core/geometry_id.hpp>
+
+#include <boost/geometry/algorithms/equals.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace equals {
+
+
+template <typename MultiPolygon1, typename MultiPolygon2>
+struct multi_polygon_twice
+{
+ static inline bool apply(MultiPolygon1 const& multi1,
+ MultiPolygon2 const& multi2)
+ {
+ if (boost::size(multi1) != boost::size(multi2))
+ {
+ return false;
+ }
+
+ typedef polygon_polygon
+ <
+ typename boost::range_value<MultiPolygon1>::type,
+ typename boost::range_value<MultiPolygon2>::type
+ > compare;
+
+ return range_range<compare>(multi1, multi2);
+ }
+};
+
+template <typename Polygon, typename MultiPolygon>
+struct single_eq_multi_polygon
+{
+ static inline bool apply(Polygon const& polygon,
+ MultiPolygon const& multi)
+ {
+ if (boost::size(multi) != 1)
+ {
+ return false;
+ }
+
+ return polygon_polygon
+ <
+ Polygon,
+ typename boost::range_value<MultiPolygon>::type
+ >::apply(polygon, multi.front());
+ }
+};
+
+
+
+}} // namespace detail::equals
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename MultiPolygon1, typename MultiPolygon2>
+struct equals
+ <
+ multi_polygon_tag, multi_polygon_tag,
+ true, true,
+ MultiPolygon1, MultiPolygon2,
+ 2
+ >
+ : detail::equals::multi_polygon_twice
+ <
+ MultiPolygon1,
+ MultiPolygon2
+ >
+{};
+
+
+
+template <typename Polygon, typename MultiPolygon>
+struct equals
+ <
+ polygon_tag, multi_polygon_tag,
+ false, true,
+ Polygon, MultiPolygon,
+ 2
+ >
+ : detail::equals::single_eq_multi_polygon
+ <
+ Polygon,
+ MultiPolygon
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_EQUALS_HPP
+

Added: sandbox/geometry/boost/geometry/multi/algorithms/for_each.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/for_each.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,126 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_FOR_EACH_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_FOR_EACH_HPP
+
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/core/is_multi.hpp>
+#include <boost/geometry/multi/core/point_type.hpp>
+
+
+#include <boost/geometry/algorithms/for_each.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace for_each {
+
+// Implementation of multi, for both point and segment,
+// just calling the single version.
+template
+<
+ typename MultiGeometry,
+ typename Functor,
+ bool IsConst,
+ typename Policy
+>
+struct for_each_multi
+{
+ static inline Functor apply(
+ typename add_const_if_c<IsConst, MultiGeometry>::type& multi,
+ Functor f)
+ {
+ typedef typename range_iterator_const_if_c
+ <
+ IsConst,
+ MultiGeometry
+ >::type iterator_type;
+
+ for(iterator_type it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ f = Policy::apply(*it, f);
+ }
+ return f;
+ }
+};
+
+
+}} // namespace detail::for_each
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename MultiTag,
+ typename MultiGeometry,
+ typename Functor,
+ bool IsConst
+>
+struct for_each_point<MultiTag, true, MultiGeometry, Functor, IsConst>
+ : detail::for_each::for_each_multi
+ <
+ MultiGeometry,
+ Functor,
+ IsConst,
+ // Specify the dispatch of the single-version as policy
+ for_each_point
+ <
+ typename single_tag<MultiTag>::type,
+ false,
+ typename boost::range_value<MultiGeometry>::type,
+ Functor,
+ IsConst
+ >
+ >
+{};
+
+
+template
+<
+ typename MultiTag,
+ typename MultiGeometry,
+ typename Functor,
+ bool IsConst
+>
+struct for_each_segment<MultiTag, true, MultiGeometry, Functor, IsConst>
+ : detail::for_each::for_each_multi
+ <
+ MultiGeometry,
+ Functor,
+ IsConst,
+ // Specify the dispatch of the single-version as policy
+ for_each_segment
+ <
+ typename single_tag<MultiTag>::type,
+ false,
+ typename boost::range_value<MultiGeometry>::type,
+ Functor,
+ IsConst
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_FOR_EACH_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/get_section.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/get_section.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,66 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_GET_SECTION_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_GET_SECTION_HPP
+
+
+#include <boost/assert.hpp>
+#include <boost/concept/requires.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+#include <boost/geometry/algorithms/get_section.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename MultiPolygon, typename Section>
+struct get_section<multi_polygon_tag, MultiPolygon, Section>
+{
+ typedef typename boost::range_const_iterator
+ <
+ typename geometry::range_type<MultiPolygon>::type
+ >::type iterator_type;
+
+ static inline void apply(MultiPolygon const& multi_polygon,
+ Section const& section,
+ iterator_type& begin, iterator_type& end)
+ {
+ BOOST_ASSERT(
+ section.multi_index >= 0
+ && section.multi_index < boost::size(multi_polygon)
+ );
+
+ get_section
+ <
+ polygon_tag,
+ typename boost::range_value<MultiPolygon>::type,
+ Section
+ >::apply(multi_polygon[section.multi_index], section, begin, end);
+ }
+};
+
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_GET_SECTION_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/intersection.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/intersection.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,35 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2010, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_INTERSECTION_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_INTERSECTION_HPP
+
+
+#include <boost/geometry/algorithms/intersection.hpp>
+#include <boost/geometry/multi/algorithms/overlay/assemble.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// Currently empty, all done in overlay / assemble
+
+
+
+} // namespace dispatch
+#endif
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_INTERSECTION_HPP
+

Added: sandbox/geometry/boost/geometry/multi/algorithms/length.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/length.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,45 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_LENGTH_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_LENGTH_HPP
+
+#include <boost/geometry/algorithms/length.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/algorithms/detail/multi_sum.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename MultiLinestring, typename Strategy>
+struct length<multi_linestring_tag, MultiLinestring, Strategy>
+ : detail::multi_sum
+ <
+ typename length_result<MultiLinestring>::type,
+ MultiLinestring,
+ Strategy,
+ detail::length::range_length
+ <
+ typename boost::range_value<MultiLinestring>::type,
+ Strategy
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_LENGTH_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/num_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/num_points.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,78 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_POINTS_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_POINTS_HPP
+
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/algorithms/num_points.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace num_points {
+
+
+template <typename MultiGeometry>
+struct multi_count
+{
+ static inline size_t apply(MultiGeometry const& geometry)
+ {
+ typedef typename boost::range_value<MultiGeometry>::type geometry_type;
+ typedef typename boost::remove_const<geometry_type>::type ncg;
+ typedef typename boost::range_const_iterator
+ <
+ MultiGeometry
+ >::type iterator_type;
+
+ size_t n = 0;
+ for (iterator_type it = boost::begin(geometry);
+ it != boost::end(geometry);
+ ++it)
+ {
+ n += dispatch::num_points<typename tag<ncg>::type,
+ geometry::is_linear<ncg>::value, ncg>::apply(*it);
+ }
+ return n;
+ }
+};
+
+
+}} // namespace detail::num_points
+#endif
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+
+template <typename Geometry>
+struct num_points<multi_point_tag, false, Geometry>
+ : detail::num_points::multi_count<Geometry> {};
+
+template <typename Geometry>
+struct num_points<multi_linestring_tag, false, Geometry>
+ : detail::num_points::multi_count<Geometry> {};
+
+template <typename Geometry>
+struct num_points<multi_polygon_tag, false, Geometry>
+ : detail::num_points::multi_count<Geometry> {};
+
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_POINTS_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/overlay/assemble.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/overlay/assemble.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,94 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2010, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_OVERLAY_ASSEMBLE_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_OVERLAY_ASSEMBLE_HPP
+
+
+#include <boost/assert.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/overlay/assemble.hpp>
+
+#include <boost/geometry/multi/core/ring_type.hpp>
+
+#include <boost/geometry/multi/algorithms/overlay/get_turns.hpp>
+#include <boost/geometry/multi/algorithms/overlay/copy_segments.hpp>
+#include <boost/geometry/multi/algorithms/overlay/copy_segment_point.hpp>
+#include <boost/geometry/multi/algorithms/detail/point_on_border.hpp>
+#include <boost/geometry/multi/algorithms/detail/sections/get_full_section.hpp>
+
+#include <boost/geometry/multi/algorithms/envelope.hpp>
+#include <boost/geometry/multi/algorithms/num_points.hpp>
+#include <boost/geometry/multi/algorithms/within.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+template <typename MultiPolygon>
+struct add_to_containment<multi_polygon_tag, MultiPolygon>
+{
+ template <typename ContainmentContainer, typename Map>
+ static inline void apply(ContainmentContainer& container,
+ ring_identifier const& id, MultiPolygon const& multi_polygon,
+ Map const& map)
+ {
+ ring_identifier copy = id;
+ copy.multi_index = 0;
+
+ // Add all rings with the updated index
+ for (typename boost::range_iterator<MultiPolygon const>::type it
+ = boost::begin(multi_polygon);
+ it != boost::end(multi_polygon);
+ ++it, ++copy.multi_index)
+ {
+ add_to_containment
+ <
+ polygon_tag,
+ typename boost::range_value<MultiPolygon>::type
+ >::apply(container, copy, *it, map);
+ }
+ }
+};
+
+
+
+template<>
+struct get_ring<multi_polygon_tag>
+{
+ template<typename MultiPolygon>
+ static inline typename ring_type<MultiPolygon>::type const& apply(
+ ring_identifier const& id,
+ MultiPolygon const& multi_polygon)
+ {
+ BOOST_ASSERT
+ (
+ id.multi_index >= 0
+ && id.multi_index < boost::size(multi_polygon)
+ );
+ return get_ring<polygon_tag>::apply(id,
+ multi_polygon[id.multi_index]);
+ }
+};
+
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif //GGL_ALGORITHMS_OVERLAY_ASSEMBLE_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/overlay/copy_segment_point.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/overlay/copy_segment_point.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,98 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2010, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_OVERLAY_COPY_SEGMENT_POINT_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_OVERLAY_COPY_SEGMENT_POINT_HPP
+
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/algorithms/overlay/copy_segment_point.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace copy_segments
+{
+
+
+template
+<
+ typename MultiGeometry,
+ typename SegmentIdentifier,
+ typename PointOut,
+ typename Policy
+>
+struct copy_segment_point_multi
+{
+ static inline bool apply(MultiGeometry const& multi,
+ SegmentIdentifier const& seg_id, bool second,
+ PointOut& point)
+ {
+
+ BOOST_ASSERT
+ (
+ seg_id.multi_index >= 0
+ && seg_id.multi_index < boost::size(multi)
+ );
+
+ // Call the single-version
+ return Policy::apply(multi[seg_id.multi_index], seg_id, second, point);
+ }
+};
+
+
+}} // namespace detail::copy_segments
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename MultiGeometry,
+ typename SegmentIdentifier,
+ typename PointOut
+>
+struct copy_segment_point
+ <
+ multi_polygon_tag,
+ MultiGeometry,
+ SegmentIdentifier,
+ PointOut
+ >
+ : detail::copy_segments::copy_segment_point_multi
+ <
+ MultiGeometry,
+ SegmentIdentifier,
+ PointOut,
+ detail::copy_segments::copy_segment_point_polygon
+ <
+ typename boost::range_value<MultiGeometry>::type,
+ SegmentIdentifier,
+ PointOut
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_OVERLAY_COPY_SEGMENT_POINT_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/overlay/copy_segments.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/overlay/copy_segments.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,104 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_OVERLAY_COPY_SEGMENTS_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_OVERLAY_COPY_SEGMENTS_HPP
+
+
+#include <boost/assert.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/overlay/copy_segments.hpp>
+
+#include <boost/geometry/multi/core/ring_type.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace copy_segments {
+
+
+template
+<
+ typename MultiGeometry,
+ typename SegmentIdentifier,
+ typename RangeOut,
+ typename Policy
+>
+struct copy_segments_multi
+{
+ static inline void apply(MultiGeometry const& multi_geometry,
+ SegmentIdentifier const& seg_id, int to_index,
+ RangeOut& current_output)
+ {
+
+ BOOST_ASSERT
+ (
+ seg_id.multi_index >= 0
+ && seg_id.multi_index < boost::size(multi_geometry)
+ );
+
+ // Call the single-version
+ Policy::apply(multi_geometry[seg_id.multi_index],
+ seg_id, to_index, current_output);
+ }
+};
+
+
+}} // namespace detail::copy_segments
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+
+
+template
+<
+ typename MultiPolygon,
+ typename SegmentIdentifier,
+ typename RangeOut
+>
+struct copy_segments
+ <
+ multi_polygon_tag,
+ MultiPolygon,
+ SegmentIdentifier,
+ RangeOut
+ >
+ : detail::copy_segments::copy_segments_multi
+ <
+ MultiPolygon,
+ SegmentIdentifier,
+ RangeOut,
+ detail::copy_segments::copy_segments_polygon
+ <
+ typename boost::range_value<MultiPolygon>::type,
+ SegmentIdentifier,
+ RangeOut
+ >
+ >
+{};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_OVERLAY_COPY_SEGMENTS_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/overlay/get_intersection_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/overlay/get_intersection_points.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,67 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_GET_INTERSECTION_POINTS_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_GET_INTERSECTION_POINTS_HPP
+
+#include <boost/geometry/multi/core/is_multi.hpp>
+
+#include <boost/geometry/multi/algorithms/distance.hpp>
+#include <boost/geometry/multi/algorithms/get_section.hpp>
+#include <boost/geometry/multi/algorithms/sectionalize.hpp>
+
+#include <boost/geometry/multi/iterators/range_type.hpp>
+
+#include <boost/geometry/algorithms/overlay/get_intersection_points.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename MultiTag1,
+ typename MultiTag2,
+ typename MultiGeometry1,
+ typename MultiGeometry2,
+ typename IntersectionPoints,
+ typename Strategy
+>
+struct get_intersection_points
+ <
+ MultiTag1, MultiTag2,
+ true, true,
+ MultiGeometry1, MultiGeometry2,
+ IntersectionPoints,
+ Strategy
+ >
+ : detail::get_intersection_points::get_ips_generic
+ <
+ MultiGeometry1,
+ MultiGeometry2,
+ IntersectionPoints,
+ Strategy
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_GET_INTERSECTION_POINTS_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/overlay/get_turns.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/overlay/get_turns.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,128 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2010, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_GET_TURNS_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_GET_TURNS_HPP
+
+#include <boost/geometry/multi/core/is_multi.hpp>
+
+#include <boost/geometry/multi/algorithms/distance.hpp>
+#include <boost/geometry/multi/algorithms/get_section.hpp>
+#include <boost/geometry/multi/algorithms/sectionalize.hpp>
+#include <boost/geometry/multi/iterators/range_type.hpp>
+
+#include <boost/geometry/algorithms/overlay/get_turns.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename MultiTag1,
+ typename MultiTag2,
+ typename MultiGeometry1,
+ typename MultiGeometry2,
+ typename IntersectionPoints,
+ typename Strategy,
+ typename AssignPolicy
+>
+struct get_turns
+ <
+ MultiTag1, MultiTag2,
+ true, true,
+ MultiGeometry1, MultiGeometry2,
+ IntersectionPoints,
+ Strategy,
+ AssignPolicy
+ >
+ : detail::get_turns::get_turns_generic
+ <
+ MultiGeometry1,
+ MultiGeometry2,
+ IntersectionPoints,
+ Strategy,
+ AssignPolicy
+ >
+{};
+
+
+template
+<
+ typename SingleTag,
+ typename MultiTag,
+ typename SingleGeometry,
+ typename MultiGeometry,
+ typename IntersectionPoints,
+ typename Strategy,
+ typename AssignPolicy
+>
+struct get_turns
+ <
+ SingleTag, MultiTag,
+ false, true,
+ SingleGeometry, MultiGeometry,
+ IntersectionPoints,
+ Strategy,
+ AssignPolicy
+ >
+ : detail::get_turns::get_turns_generic
+ <
+ SingleGeometry,
+ MultiGeometry,
+ IntersectionPoints,
+ Strategy,
+ AssignPolicy
+ >
+{};
+
+
+// Version for multi/single, necessary for multi_polygon/ring
+template
+<
+ typename MultiTag,
+ typename SingleTag,
+ typename MultiGeometry,
+ typename SingleGeometry,
+ typename IntersectionPoints,
+ typename Strategy,
+ typename AssignPolicy
+>
+struct get_turns
+ <
+ MultiTag, SingleTag,
+ true, false,
+ MultiGeometry, SingleGeometry,
+ IntersectionPoints,
+ Strategy,
+ AssignPolicy
+ >
+ : detail::get_turns::get_turns_generic
+ <
+ MultiGeometry,
+ SingleGeometry,
+ IntersectionPoints,
+ Strategy,
+ AssignPolicy
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_GET_TURNS_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/perimeter.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/perimeter.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,47 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_PERIMETER_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_PERIMETER_HPP
+
+#include <boost/geometry/algorithms/perimeter.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+#include <boost/geometry/multi/algorithms/detail/multi_sum.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+template <typename MultiPolygon, typename Strategy>
+struct perimeter<multi_polygon_tag, MultiPolygon, Strategy>
+ : detail::multi_sum
+ <
+ typename length_result<MultiPolygon>::type,
+ MultiPolygon,
+ Strategy,
+ perimeter
+ <
+ polygon_tag,
+ typename boost::range_value<MultiPolygon>::type,
+ Strategy
+ >
+ >
+{};
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_PERIMETER_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/sectionalize.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/sectionalize.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,86 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_SECTIONALIZE_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_SECTIONALIZE_HPP
+
+#include <cstddef>
+#include <vector>
+
+#include <boost/concept/requires.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/sectionalize.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace sectionalize {
+
+
+template <typename MultiGeometry, typename Sections, std::size_t DimensionCount, typename Policy>
+struct sectionalize_multi
+{
+ static inline void apply(MultiGeometry const& multi, Sections& sections)
+ {
+ int multi_index = 0;
+ for (typename boost::range_const_iterator<MultiGeometry>::type
+ it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it, ++multi_index)
+ {
+ Policy::apply(*it, sections, multi_index);
+ }
+ }
+};
+
+
+
+
+}} // namespace detail::sectionalize
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename MultiPolygon, typename Sections, std::size_t DimensionCount, std::size_t MaxCount>
+struct sectionalize<multi_polygon_tag, MultiPolygon, Sections, DimensionCount, MaxCount>
+ : detail::sectionalize::sectionalize_multi
+ <
+ MultiPolygon,
+ Sections,
+ DimensionCount,
+ detail::sectionalize::sectionalize_polygon
+ <
+ typename boost::range_value<MultiPolygon>::type,
+ Sections,
+ DimensionCount,
+ MaxCount
+ >
+ >
+
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_SECTIONALIZE_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/simplify.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/simplify.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,112 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_SIMPLIFY_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_SIMPLIFY_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/core/is_multi.hpp>
+
+#include <boost/geometry/multi/iterators/range_type.hpp>
+
+#include <boost/geometry/algorithms/simplify.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace simplify {
+
+template<typename MultiGeometry, typename Strategy, typename Policy>
+struct simplify_multi
+{
+ static inline void apply(MultiGeometry const& multi, MultiGeometry& out,
+ double max_distance, Strategy const& strategy)
+ {
+ out.resize(boost::size(multi));
+
+ typename boost::range_iterator<MultiGeometry>::type it_out
+ = boost::begin(out);
+ for (typename boost::range_const_iterator<MultiGeometry>::type it_in
+ = boost::begin(multi);
+ it_in != boost::end(multi);
+ ++it_in, ++it_out)
+ {
+ Policy::apply(*it_in, *it_out, max_distance, strategy);
+ }
+ }
+};
+
+
+
+}} // namespace detail::simplify
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename MultiPoint, typename Strategy>
+struct simplify<multi_point_tag, MultiPoint, Strategy>
+ : detail::simplify::simplify_copy
+ <
+ MultiPoint,
+ Strategy
+ >
+
+{};
+
+
+template <typename MultiLinestring, typename Strategy>
+struct simplify<multi_linestring_tag, MultiLinestring, Strategy>
+ : detail::simplify::simplify_multi
+ <
+ MultiLinestring,
+ Strategy,
+ detail::simplify::simplify_range
+ <
+ typename boost::range_value<MultiLinestring>::type,
+ Strategy,
+ 2
+ >
+ >
+
+{};
+
+
+template <typename MultiPolygon, typename Strategy>
+struct simplify<multi_polygon_tag, MultiPolygon, Strategy>
+ : detail::simplify::simplify_multi
+ <
+ MultiPolygon,
+ Strategy,
+ detail::simplify::simplify_polygon
+ <
+ typename boost::range_value<MultiPolygon>::type,
+ Strategy
+ >
+ >
+
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_SIMPLIFY_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/transform.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/transform.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,93 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_TRANSFORM_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_TRANSFORM_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/transform.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace transform {
+
+/*!
+ \brief Is able to transform any multi-geometry, calling the single-version as policy
+*/
+template <typename Multi1, typename Multi2, typename Policy>
+struct transform_multi
+{
+ template <typename S>
+ static inline bool apply(Multi1 const& multi1, Multi2& multi2, S const& strategy)
+ {
+ multi2.resize(boost::size(multi1));
+
+ typename boost::range_const_iterator<Multi1>::type it1
+ = boost::begin(multi1);
+ typename boost::range_iterator<Multi2>::type it2
+ = boost::begin(multi2);
+
+ for (; it1 != boost::end(multi1); ++it1, ++it2)
+ {
+ if (! Policy::apply(*it1, *it2, strategy))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+};
+
+
+
+
+}} // namespace detail::transform
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Multi1, typename Multi2, typename Strategy>
+struct transform
+ <
+ multi_polygon_tag, multi_polygon_tag,
+ Multi1, Multi2,
+ Strategy
+ >
+ : detail::transform::transform_multi
+ <
+ Multi1,
+ Multi2,
+ detail::transform::transform_polygon
+ <
+ typename boost::range_value<Multi1>::type,
+ typename boost::range_value<Multi2>::type,
+ Strategy
+ >
+ >
+{};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_TRANSFORM_HPP

Added: sandbox/geometry/boost/geometry/multi/algorithms/union.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/union.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,34 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2010, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_UNION_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_UNION_HPP
+
+
+#include <boost/geometry/algorithms/union.hpp>
+#include <boost/geometry/multi/algorithms/overlay/assemble.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// Currently empty, all done in overlay / assemble
+
+
+
+} // namespace dispatch
+#endif
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_UNION_HPP
+

Added: sandbox/geometry/boost/geometry/multi/algorithms/within.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/algorithms/within.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,82 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_WITHIN_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_WITHIN_HPP
+
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/within.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace within {
+
+
+template
+<
+ typename Geometry,
+ typename MultiGeometry,
+ typename Strategy,
+ typename Policy
+>
+struct geometry_in_multi
+{
+ static inline bool apply(Geometry const& geometry,
+ MultiGeometry const& multi,
+ Strategy const& strategy)
+ {
+ for (typename boost::range_const_iterator<MultiGeometry>::type it
+ = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ // Geometry within a multi: true if within one of them
+ if (Policy::apply(geometry, *it, strategy))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+}} // namespace detail::within
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Point, typename MultiPolygon, typename Strategy>
+struct within<point_tag, multi_polygon_tag, Point, MultiPolygon, Strategy>
+ : detail::within::geometry_in_multi
+ <
+ Point,
+ MultiPolygon,
+ Strategy,
+ detail::within::point_in_polygon
+ <
+ Point,
+ typename boost::range_value<MultiPolygon>::type,
+ Strategy
+ >
+ >
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_WITHIN_HPP

Added: sandbox/geometry/boost/geometry/multi/core/geometry_id.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/core/geometry_id.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,51 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_CORE_GEOMETRY_ID_HPP
+#define BOOST_GEOMETRY_MULTI_CORE_GEOMETRY_ID_HPP
+
+
+#include <boost/mpl/int.hpp>
+#include <boost/type_traits.hpp>
+
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/geometry_id.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <>
+struct geometry_id<multi_point_tag> : boost::mpl::int_<4> {};
+
+
+template <>
+struct geometry_id<multi_linestring_tag> : boost::mpl::int_<5> {};
+
+
+template <>
+struct geometry_id<multi_polygon_tag> : boost::mpl::int_<6> {};
+
+
+
+} // namespace core_dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_CORE_GEOMETRY_ID_HPP

Added: sandbox/geometry/boost/geometry/multi/core/is_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/core/is_multi.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,49 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_CORE_IS_MULTI_HPP
+#define BOOST_GEOMETRY_MULTI_CORE_IS_MULTI_HPP
+
+
+#include <boost/type_traits.hpp>
+
+
+#include <boost/geometry/core/is_multi.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <>
+struct is_multi<multi_point_tag> : boost::true_type {};
+
+
+template <>
+struct is_multi<multi_linestring_tag> : boost::true_type {};
+
+
+template <>
+struct is_multi<multi_polygon_tag> : boost::true_type {};
+
+
+} // namespace core_dispatch
+#endif
+
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_CORE_IS_MULTI_HPP

Added: sandbox/geometry/boost/geometry/multi/core/point_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/core/point_type.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,59 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_CORE_POINT_TYPE_HPP
+#define BOOST_GEOMETRY_MULTI_CORE_POINT_TYPE_HPP
+
+
+#include <boost/range/metafunctions.hpp>
+
+
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+
+namespace boost { namespace geometry {
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename MultiPoint>
+struct point_type<multi_point_tag, MultiPoint>
+{
+ typedef typename boost::range_value<MultiPoint>::type type;
+};
+
+
+template <typename MultiLinestring>
+struct point_type<multi_linestring_tag, MultiLinestring>
+{
+ typedef typename point_type<linestring_tag,
+ typename boost::range_value<MultiLinestring>::type>::type type;
+};
+
+
+
+template <typename MultiPolygon>
+struct point_type<multi_polygon_tag, MultiPolygon>
+{
+ typedef typename point_type<polygon_tag,
+ typename boost::range_value<MultiPolygon>::type>::type type;
+};
+
+
+
+
+}
+#endif
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_CORE_POINT_TYPE_HPP

Added: sandbox/geometry/boost/geometry/multi/core/ring_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/core/ring_type.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,48 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_CORE_RING_TYPE_HPP
+#define BOOST_GEOMETRY_MULTI_CORE_RING_TYPE_HPP
+
+
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename MultiPolygon>
+struct ring_type<multi_polygon_tag, MultiPolygon>
+{
+ typedef typename geometry::ring_type
+ <
+ typename boost::range_value<MultiPolygon>::type
+ >::type type;
+};
+
+
+
+
+} // namespace core_dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_CORE_RING_TYPE_HPP

Added: sandbox/geometry/boost/geometry/multi/core/tags.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/core/tags.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,66 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_CORE_TAGS_HPP
+#define BOOST_GEOMETRY_MULTI_CORE_TAGS_HPP
+
+#include <boost/geometry/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+/// OGC Multi point identifying tag
+struct multi_point_tag {};
+
+/// OGC Multi linestring identifying tag
+struct multi_linestring_tag {};
+
+/// OGC Multi polygon identifying tag
+struct multi_polygon_tag {};
+
+/// OGC Geometry Collection identifying tag
+struct geometry_collection_tag {};
+
+
+
+
+/*!
+ \brief Meta-function to get for a tag of a multi-geometry
+ the tag of the corresponding single-geometry
+*/
+template <typename Tag>
+struct single_tag
+{};
+
+#ifndef DOXYGEN_NO_DETAIL
+
+template <>
+struct single_tag<multi_point_tag>
+{
+ typedef point_tag type;
+};
+
+template <>
+struct single_tag<multi_linestring_tag>
+{
+ typedef linestring_tag type;
+};
+
+template <>
+struct single_tag<multi_polygon_tag>
+{
+ typedef polygon_tag type;
+};
+
+#endif
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_CORE_TAGS_HPP

Added: sandbox/geometry/boost/geometry/multi/core/topological_dimension.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/core/topological_dimension.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,45 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_TOPOLOGICAL_DIMENSION_HPP
+#define BOOST_GEOMETRY_MULTI_TOPOLOGICAL_DIMENSION_HPP
+
+
+#include <boost/mpl/int.hpp>
+
+
+#include <boost/geometry/core/topological_dimension.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+namespace boost { namespace geometry {
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <>
+struct top_dim<multi_point_tag> : boost::mpl::int_<0> {};
+
+
+template <>
+struct top_dim<multi_linestring_tag> : boost::mpl::int_<1> {};
+
+
+template <>
+struct top_dim<multi_polygon_tag> : boost::mpl::int_<2> {};
+
+
+} // namespace core_dispatch
+#endif
+
+}} // namespace boost::geometry
+
+
+#endif

Added: sandbox/geometry/boost/geometry/multi/geometries/adapted/boost_array_as_multi_point.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/geometries/adapted/boost_array_as_multi_point.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,49 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_ARRAY_AS_MULTI_POINT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_ARRAY_AS_MULTI_POINT_HPP
+
+
+#ifdef BOOST_GEOMETRY_ADAPTED_BOOST_ARRAY_AS_POINT_COLLECTION_TAG_DEFINED
+#error Include either "boost_array_as_linestring" or "boost_array_as_ring" \
+ or "boost_array_as_multi_point" to adapt a boost_array
+#endif
+
+#define BOOST_GEOMETRY_ADAPTED_BOOST_ARRAY_AS_POINT_COLLECTION_TAG_DEFINED
+
+
+#include <cstddef>
+
+#include <boost/array.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+ template <typename PointType, std::size_t DimensionCount>
+ struct tag< boost::array<PointType, DimensionCount> >
+ {
+ typedef multi_point_tag type;
+ };
+
+}
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_ARRAY_AS_MULTI_POINT_HPP

Added: sandbox/geometry/boost/geometry/multi/geometries/adapted/c_array_as_multi_point.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/geometries/adapted/c_array_as_multi_point.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,45 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_AS_MULTI_POINT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_AS_MULTI_POINT_HPP
+
+
+#ifdef BOOST_GEOMETRY_ADAPTED_C_ARRAY_AS_POINT_COLLECTION_TAG_DEFINED
+#error Include either "c_array_as_linestring" or "c_array_as_ring" \
+ or "c_array_as_multi_point" to adapt a c array
+#endif
+
+#define BOOST_GEOMETRY_ADAPTED_C_ARRAY_AS_POINT_COLLECTION_TAG_DEFINED
+
+
+#include <cstddef>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+ template <typename T, std::size_t PointCount, std::size_t DimensionCount>
+ struct tag< T[PointCount][DimensionCount] >
+ {
+ typedef multi_point_tag type;
+ };
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_AS_MULTI_POINT_HPP

Added: sandbox/geometry/boost/geometry/multi/geometries/adapted/std_as_multi_point.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/geometries/adapted/std_as_multi_point.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,65 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_AS_MULTI_POINT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_AS_MULTI_POINT_HPP
+
+
+#ifdef BOOST_GEOMETRY_ADAPTED_STD_AS_POINT_COLLECTION_TAG_DEFINED
+#error Include either "std_as_linestring" or "std_as_ring" \
+ or "std_as_multi_point" to adapt the std:: containers
+#endif
+
+#define BOOST_GEOMETRY_ADAPTED_STD_AS_POINT_COLLECTION_TAG_DEFINED
+
+
+#include <vector>
+#include <deque>
+#include <list>
+#include <utility>
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace util
+{
+ struct std_as_multi_point
+ {
+ typedef multi_point_tag type;
+ };
+
+}
+#endif
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+ // specialization for an iterator pair (read only)
+ template <typename P> struct tag< std::pair<P, P> > : util::std_as_multi_point {};
+
+ // specializations for the std:: containers: vector, deque, list
+ template <typename P> struct tag< std::vector<P> > : util::std_as_multi_point {};
+ template <typename P> struct tag< std::deque<P> > : util::std_as_multi_point {};
+ template <typename P> struct tag< std::list<P> > : util::std_as_multi_point {};
+
+}
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_AS_MULTI_POINT_HPP

Added: sandbox/geometry/boost/geometry/multi/geometries/concepts/check.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/geometries/concepts/check.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,76 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_CHECK_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_CHECK_HPP
+
+
+
+#include <boost/type_traits/is_const.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/multi/geometries/concepts/multi_point_concept.hpp>
+#include <boost/geometry/multi/geometries/concepts/multi_linestring_concept.hpp>
+#include <boost/geometry/multi/geometries/concepts/multi_polygon_concept.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Geometry>
+struct check<multi_point_tag, Geometry, true>
+ : detail::concept_check::check<concept::ConstMultiPoint<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<multi_point_tag, Geometry, false>
+ : detail::concept_check::check<concept::MultiPoint<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<multi_linestring_tag, Geometry, true>
+ : detail::concept_check::check<concept::ConstMultiLinestring<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<multi_linestring_tag, Geometry, false>
+ : detail::concept_check::check<concept::MultiLinestring<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<multi_polygon_tag, Geometry, true>
+ : detail::concept_check::check<concept::ConstMultiPolygon<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<multi_polygon_tag, Geometry, false>
+ : detail::concept_check::check<concept::MultiPolygon<Geometry> >
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_CHECK_HPP

Added: sandbox/geometry/boost/geometry/multi/geometries/concepts/multi_linestring_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/geometries/concepts/multi_linestring_concept.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,80 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_LINESTRING_CONCEPT_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_LINESTRING_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <boost/geometry/geometries/concepts/linestring_concept.hpp>
+
+
+namespace boost { namespace geometry { namespace concept {
+
+
+/*!
+\brief multi-linestring concept
+\ingroup concepts
+\par Formal definition:
+The multi linestring concept is defined as following:
+- there must be a specialization of traits::tag defining multi_linestring_tag as
+ type
+- it must behave like a Boost.Range
+- its range value must fulfil the Linestring concept
+
+*/
+template <typename Geometry>
+class MultiLinestring
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type linestring_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Linestring<linestring_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(MultiLinestring)
+ {
+ }
+#endif
+};
+
+
+/*!
+\brief concept for multi-linestring (const version)
+\ingroup const_concepts
+*/
+template <typename Geometry>
+class ConstMultiLinestring
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type linestring_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstLinestring<linestring_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstMultiLinestring)
+ {
+ }
+#endif
+};
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_LINESTRING_CONCEPT_HPP

Added: sandbox/geometry/boost/geometry/multi/geometries/concepts/multi_point_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/geometries/concepts/multi_point_concept.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,79 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POINT_CONCEPT_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POINT_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+
+namespace boost { namespace geometry { namespace concept {
+
+
+/*!
+\brief MultiPoint concept
+\ingroup concepts
+\par Formal definition:
+The multi point concept is defined as following:
+- there must be a specialization of traits::tag defining multi_point_tag as type
+- it must behave like a Boost.Range
+- its range value must fulfil the Point concept
+
+*/
+template <typename Geometry>
+class MultiPoint
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Point<point_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(MultiPoint)
+ {
+ }
+#endif
+};
+
+
+/*!
+\brief concept for multi-point (const version)
+\ingroup const_concepts
+*/
+template <typename Geometry>
+class ConstMultiPoint
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstMultiPoint)
+ {
+ }
+#endif
+};
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POINT_CONCEPT_HPP

Added: sandbox/geometry/boost/geometry/multi/geometries/concepts/multi_polygon_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/geometries/concepts/multi_polygon_concept.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,80 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POLYGON_CONCEPT_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POLYGON_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <boost/geometry/geometries/concepts/polygon_concept.hpp>
+
+
+namespace boost { namespace geometry { namespace concept {
+
+
+/*!
+\brief multi-polygon concept
+\ingroup concepts
+\par Formal definition:
+The multi polygon concept is defined as following:
+- there must be a specialization of traits::tag defining multi_polygon_tag
+ as type
+- it must behave like a Boost.Range
+- its range value must fulfil the Polygon concept
+
+*/
+template <typename Geometry>
+class MultiPolygon
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type polygon_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Polygon<polygon_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(MultiPolygon)
+ {
+ }
+#endif
+};
+
+
+/*!
+\brief concept for multi-polygon (const version)
+\ingroup const_concepts
+*/
+template <typename Geometry>
+class ConstMultiPolygon
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type polygon_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPolygon<polygon_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstMultiPolygon)
+ {
+ }
+#endif
+};
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POLYGON_CONCEPT_HPP

Added: sandbox/geometry/boost/geometry/multi/geometries/multi_linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/geometries/multi_linestring.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,63 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_LINESTRING_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_LINESTRING_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/requires.hpp>
+
+#include <boost/geometry/geometries/concepts/linestring_concept.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief multi_line, a collection of linestring
+ \details Multi-linestring can be used to group lines belonging to each other,
+ e.g. a highway (with interruptions)
+ \ingroup geometries
+*/
+template
+<
+ typename L,
+ template<typename, typename> class V = std::vector,
+ template<typename> class A = std::allocator
+>
+struct multi_linestring : public V<L, A<L> >
+{
+ BOOST_CONCEPT_ASSERT( (concept::Linestring<L>) );
+};
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename L,
+ template<typename, typename> class V,
+ template<typename> class A
+>
+struct tag< multi_linestring<L, V, A> >
+{
+ typedef multi_linestring_tag type;
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_LINESTRING_HPP

Added: sandbox/geometry/boost/geometry/multi/geometries/multi_point.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/geometries/multi_point.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,61 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POINT_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POINT_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/requires.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief multi_point, a collection of points
+ \details Multipoint can be used to group points belonging to each other,
+ e.g. a constellation
+ \ingroup geometries
+*/
+template
+<
+ typename P,
+ template<typename, typename> class V = std::vector,
+ template<typename> class A = std::allocator
+>
+struct multi_point : public V<P, A<P> >
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<P>) );
+};
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename P,
+ template<typename, typename> class V,
+ template<typename> class A
+>
+struct tag< multi_point<P, V, A> >
+{
+ typedef multi_point_tag type;
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POINT_HPP

Added: sandbox/geometry/boost/geometry/multi/geometries/multi_polygon.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/geometries/multi_polygon.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,61 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POLYGON_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POLYGON_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/requires.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+#include <boost/geometry/geometries/concepts/polygon_concept.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief multi_polygon, a collection of polygons
+ \details Multi-polygon can be used to group polygons belonging to each other,
+ e.g. Hawaii
+ \ingroup geometries
+*/
+template
+<
+ typename P,
+ template<typename, typename> class V = std::vector,
+ template<typename> class A = std::allocator
+>
+struct multi_polygon : public V<P, A<P> >
+{
+ BOOST_CONCEPT_ASSERT( (concept::Polygon<P>) );
+};
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename P,
+ template<typename, typename> class V,
+ template<typename> class A
+>
+struct tag< multi_polygon<P, V, A> >
+{
+ typedef multi_polygon_tag type;
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POLYGON_HPP

Added: sandbox/geometry/boost/geometry/multi/iterators/range_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/iterators/range_type.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,57 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ITERATORS_RANGE_TYPE_HPP
+#define BOOST_GEOMETRY_MULTI_ITERATORS_RANGE_TYPE_HPP
+
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/multi/core/is_multi.hpp>
+
+#include <boost/geometry/iterators/range_type.hpp>
+
+namespace boost { namespace geometry {
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// multi-point acts itself as a range
+template <typename Geometry>
+struct range_type<multi_point_tag, Geometry>
+{
+ typedef Geometry type;
+};
+
+
+template <typename Geometry>
+struct range_type<multi_linestring_tag, Geometry>
+{
+ typedef typename boost::range_value<Geometry>::type type;
+};
+
+
+template <typename Geometry>
+struct range_type<multi_polygon_tag, Geometry>
+{
+ // Call its single-version
+ typedef typename geometry::ring_type
+ <
+ typename boost::range_value<Geometry>::type
+ >::type type;
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_ITERATORS_RANGE_TYPE_HPP

Added: sandbox/geometry/boost/geometry/multi/multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/multi.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,63 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Mateusz Loskot 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_HPP
+#define BOOST_GEOMETRY_MULTI_HPP
+
+
+#include <boost/geometry/multi/core/geometry_id.hpp>
+#include <boost/geometry/multi/core/is_multi.hpp>
+#include <boost/geometry/multi/core/point_type.hpp>
+#include <boost/geometry/multi/core/ring_type.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/core/topological_dimension.hpp>
+
+
+#include <boost/geometry/multi/algorithms/area.hpp>
+#include <boost/geometry/multi/algorithms/centroid.hpp>
+#include <boost/geometry/multi/algorithms/convex_hull.hpp>
+#include <boost/geometry/multi/algorithms/correct.hpp>
+#include <boost/geometry/multi/algorithms/distance.hpp>
+#include <boost/geometry/multi/algorithms/envelope.hpp>
+#include <boost/geometry/multi/algorithms/equals.hpp>
+#include <boost/geometry/multi/algorithms/for_each.hpp>
+#include <boost/geometry/multi/algorithms/get_section.hpp>
+#include <boost/geometry/multi/algorithms/intersection.hpp>
+#include <boost/geometry/multi/algorithms/length.hpp>
+#include <boost/geometry/multi/algorithms/num_points.hpp>
+#include <boost/geometry/multi/algorithms/perimeter.hpp>
+#include <boost/geometry/multi/algorithms/sectionalize.hpp>
+#include <boost/geometry/multi/algorithms/simplify.hpp>
+#include <boost/geometry/multi/algorithms/transform.hpp>
+#include <boost/geometry/multi/algorithms/union.hpp>
+#include <boost/geometry/multi/algorithms/within.hpp>
+#include <boost/geometry/multi/algorithms/detail/modify_with_predicate.hpp>
+#include <boost/geometry/multi/algorithms/detail/multi_sum.hpp>
+#include <boost/geometry/multi/algorithms/overlay/copy_segments.hpp>
+#include <boost/geometry/multi/algorithms/overlay/get_intersection_points.hpp>
+
+
+#include <boost/geometry/multi/geometries/multi_point.hpp>
+#include <boost/geometry/multi/geometries/multi_linestring.hpp>
+#include <boost/geometry/multi/geometries/multi_polygon.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+#include <boost/geometry/multi/geometries/concepts/multi_point_concept.hpp>
+#include <boost/geometry/multi/geometries/concepts/multi_linestring_concept.hpp>
+#include <boost/geometry/multi/geometries/concepts/multi_polygon_concept.hpp>
+
+#include <boost/geometry/multi/iterators/range_type.hpp>
+
+#include <boost/geometry/multi/strategies/centroid.hpp>
+#include <boost/geometry/multi/strategies/cartesian/centroid_average.hpp>
+
+#include <boost/geometry/multi/util/write_dsv.hpp>
+
+
+
+#endif // BOOST_GEOMETRY_MULTI_HPP

Added: sandbox/geometry/boost/geometry/multi/strategies/cartesian/centroid_average.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/strategies/cartesian/centroid_average.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,96 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP
+#define BOOST_GEOMETRY_MULTI_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP
+
+
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/strategies/centroid.hpp>
+#include <boost/geometry/util/copy.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace centroid_ {
+
+
+template
+<
+ typename PointCentroid,
+ typename Point = PointCentroid
+>
+class centroid_average
+{
+private :
+
+ /*! subclass to keep state */
+ class sum
+ {
+ friend class centroid_average;
+ int count;
+ PointCentroid centroid;
+
+ public :
+ inline sum()
+ : count(0)
+ {
+ assign_zero(centroid);
+ }
+ };
+
+public :
+ typedef sum state_type;
+ typedef PointCentroid centroid_point_type;
+ typedef Point point_type;
+
+ static inline void apply(Point const& p, sum& state)
+ {
+ add_point(state.centroid, p);
+ state.count++;
+ }
+
+ static inline void result(sum const& state, PointCentroid& centroid)
+ {
+ centroid = state.centroid;
+ divide_value(centroid, state.count);
+ }
+
+};
+
+
+}} // namespace strategy::centroid
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+
+template <typename Point, typename Geometry>
+struct strategy_centroid<cartesian_tag, multi_point_tag, 2, Point, Geometry>
+{
+ typedef strategy::centroid_::centroid_average
+ <
+ Point,
+ typename point_type<Geometry>::type
+ > type;
+};
+
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP

Added: sandbox/geometry/boost/geometry/multi/strategies/centroid.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/strategies/centroid.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,38 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_STRATEGY_CENTROID_HPP
+#define BOOST_GEOMETRY_MULTI_STRATEGY_CENTROID_HPP
+
+#include <boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+template <typename Point, typename Geometry>
+struct strategy_centroid<cartesian_tag, multi_polygon_tag, 2, Point, Geometry>
+{
+ typedef strategy::centroid_::bashein_detmer
+ <
+ Point,
+ typename point_type<Geometry>::type
+ > type;
+};
+
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_STRATEGY_CENTROID_HPP

Added: sandbox/geometry/boost/geometry/multi/util/for_each_range.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/util/for_each_range.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,81 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_UTIL_FOR_EACH_RANGE_HPP
+#define BOOST_GEOMETRY_MULTI_UTIL_FOR_EACH_RANGE_HPP
+
+
+#include <boost/geometry/util/for_each_range.hpp>
+#include <boost/geometry/util/range_iterator_const_if_c.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace for_each {
+
+
+template <typename Multi, typename Actor, bool IsConst>
+struct fe_range_multi
+{
+ static inline void apply(
+ typename add_const_if_c<IsConst, Multi>::type& multi,
+ Actor& actor)
+ {
+ for (typename range_iterator_const_if_c<IsConst, Multi>::type
+ it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ geometry::for_each_range(*it, actor);
+ }
+ }
+};
+
+
+
+}} // namespace detail::for_each
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Geometry, typename Actor, bool IsConst>
+struct for_each_range<multi_linestring_tag, true, Geometry, Actor, IsConst>
+ : detail::for_each::fe_range_multi<Geometry, Actor, IsConst>
+{};
+
+
+template <typename Geometry, typename Actor, bool IsConst>
+struct for_each_range<multi_polygon_tag, true, Geometry, Actor, IsConst>
+ : detail::for_each::fe_range_multi<Geometry, Actor, IsConst>
+{};
+
+
+template <typename MultiPoint, typename Actor, bool IsConst>
+struct for_each_range<multi_point_tag, true, MultiPoint, Actor, IsConst>
+ : detail::for_each::fe_range_range<MultiPoint, Actor, IsConst>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_UTIL_FOR_EACH_RANGE_HPP

Added: sandbox/geometry/boost/geometry/multi/util/write_dsv.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/multi/util/write_dsv.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,72 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_UTIL_WRITE_DSV_HPP
+#define BOOST_GEOMETRY_MULTI_UTIL_WRITE_DSV_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/util/write_dsv.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace dsv {
+
+
+template <typename MultiGeometry>
+struct dsv_multi
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ MultiGeometry const& multi,
+ dsv_settings const& settings)
+ {
+ os << settings.list_open;
+
+ typedef typename boost::range_const_iterator
+ <
+ MultiGeometry
+ >::type iterator;
+ for(iterator it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ os << geometry::dsv(*it);
+ }
+ os << settings.list_close;
+ }
+};
+
+
+
+
+}} // namespace detail::dsv
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+
+template <typename Tag, typename Geometry>
+struct dsv<Tag, true, Geometry>
+ : detail::dsv::dsv_multi<Geometry>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_UTIL_WRITE_DSV_HPP

Added: sandbox/geometry/boost/geometry/policies/compare.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/policies/compare.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,270 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_POLICIES_COMPARE_HPP
+#define BOOST_GEOMETRY_POLICIES_COMPARE_HPP
+
+
+/*!
+\defgroup compare compare: define compare functors for points
+\details The compare policies enable to compare points in a way that they can
+be compared in many functions of the standard library.
+
+The functors do have an optional second template argument, \b dimension.
+If dimension is specified, comparison is only done on that dimension.
+
+This is useful for (a.o.):
+- std::sort (use geometry::less<P> or geometry::greater<P> or geometry::less<P, 1>)
+- std::map (use geometry::less<P>)
+- std::unique_copy (use geometry::equal_to<P>)
+
+\par Geometries:
+- \b point
+
+
+\par Example:
+Example showing how geometry::less can be used
+\dontinclude doxygen_3.cpp
+\skip example_less()
+\line {
+\until }
+
+
+\note There is a boolean function \ref equals "equals" as well, which returns
+true or false if a geometry is spatially equal to another geometry. That one
+is defined for OGC compatibility, while these ones are defined for
+compatibility with the std:: library. These ones are functors, operating on
+the same geometry type (currently only the point-type), the equals function is
+a free function operating on different point types or even different geometry
+types (a linestring can be spatially equal to a multi-linestring).
+*/
+
+#include <boost/geometry/strategies/compare.hpp>
+#include <boost/geometry/util/math.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace compare {
+
+
+template
+<
+ int Direction,
+ typename Point,
+ typename Strategy,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct compare_loop
+{
+ typedef typename strategy::compare::detail::select_strategy
+ <
+ Strategy, Direction, Point, Dimension
+ >::type compare_type;
+
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+
+ static inline bool apply(Point const& left, Point const& right)
+ {
+ coordinate_type const& cleft = geometry::get<Dimension>(left);
+ coordinate_type const& cright = geometry::get<Dimension>(right);
+
+ if (geometry::math::equals(cleft, cright))
+ {
+ return compare_loop
+ <
+ Direction, Point, Strategy,
+ Dimension + 1, DimensionCount
+ >::apply(left, right);
+ }
+ else
+ {
+ compare_type compare;
+ return compare(cleft, cright);
+ }
+ }
+};
+
+template
+<
+ int Direction,
+ typename Point,
+ typename Strategy,
+ std::size_t DimensionCount
+>
+struct compare_loop<Direction, Point, Strategy, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Point const&, Point const&)
+ {
+ // On coming here, points are equal. Return true if
+ // direction = 0 (equal), false if -1/1 (greater/less)
+ return Direction == 0;
+ }
+};
+
+
+template <int Direction, typename Point, typename Strategy>
+struct compare_in_all_dimensions
+{
+ inline bool operator()(Point const& left, Point const& right) const
+ {
+ return detail::compare::compare_loop
+ <
+ Direction, Point, Strategy,
+ 0, geometry::dimension<Point>::type::value
+ >::apply(left, right);
+ }
+};
+
+
+template <typename Point, typename Strategy, std::size_t Dimension>
+class compare_in_one_dimension
+{
+ Strategy compare;
+
+public :
+ inline bool operator()(Point const& left, Point const& right) const
+ {
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+
+ coordinate_type const& cleft = get<Dimension>(left);
+ coordinate_type const& cright = get<Dimension>(right);
+ return compare(cleft, cright);
+ }
+};
+
+}} // namespace detail::compare
+
+#endif
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ int Direction,
+ typename Point,
+ typename Strategy,
+ int Dimension
+>
+struct compare_geometries
+ : detail::compare::compare_in_one_dimension
+ <
+ Point,
+ typename strategy::compare::detail::select_strategy
+ <
+ Strategy, Direction, Point, Dimension
+ >::type,
+ Dimension
+ >
+{};
+
+
+// Specialization with -1: compare in all dimensions
+template <int Direction, typename Point, typename Strategy>
+struct compare_geometries<Direction, Point, Strategy, -1>
+ : detail::compare::compare_in_all_dimensions<Direction, Point, Strategy>
+{};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Less functor, to sort points in ascending order.
+\ingroup compare
+\details This functor compares points and orders them on x,
+ then on y, then on z coordinate.
+\tparam Geometry the geometry
+\tparam Dimension the dimension to sort on, defaults to -1,
+ indicating ALL dimensions. That's to say, first on x,
+ on equal x-es then on y, etc.
+ If a dimension is specified, only that dimension is considered
+\tparam Strategy underlying coordinate comparing functor,
+ defaults to the default comparison strategies
+ related to the point coordinate system. If specified, the specified
+ strategy is used. This can e.g. be std::less<double>.
+*/
+template
+<
+ typename Point,
+ int Dimension = -1,
+ typename Strategy = strategy::compare::default_strategy
+>
+struct less
+ : dispatch::compare_geometries
+ <
+ 1, // indicates ascending
+ Point,
+ Strategy,
+ Dimension
+ >
+{
+ typedef Point first_argument_type;
+ typedef Point second_argument_type;
+ typedef bool result_type;
+};
+
+
+/*!
+\brief Greater functor
+\ingroup compare
+\details Can be used to sort points in reverse order
+\see Less functor
+*/
+template
+<
+ typename Point,
+ int Dimension = -1,
+ typename Strategy = strategy::compare::default_strategy
+>
+struct greater
+ : dispatch::compare_geometries
+ <
+ -1, // indicates descending
+ Point,
+ Strategy,
+ Dimension
+ >
+{};
+
+
+/*!
+\brief Equal To functor, to compare if points are equal
+\ingroup compare
+\tparam Geometry the geometry
+\tparam Dimension the dimension to compare on, defaults to -1,
+ indicating ALL dimensions.
+ If a dimension is specified, only that dimension is considered
+\tparam Strategy underlying coordinate comparing functor
+*/
+template
+<
+ typename Point,
+ int Dimension = -1,
+ typename Strategy = strategy::compare::default_strategy
+>
+struct equal_to
+ : dispatch::compare_geometries
+ <
+ 0,
+ Point,
+ Strategy,
+ Dimension
+ >
+{};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_POLICIES_COMPARE_HPP

Added: sandbox/geometry/boost/geometry/policies/relate/direction.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/policies/relate/direction.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,343 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP
+#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP
+
+#include <boost/concept_check.hpp>
+
+#include <boost/geometry/strategies/side_info.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace policies { namespace relate {
+
+struct direction_type
+{
+ inline direction_type(side_info const& s, char h,
+ int ha, int hb,
+ int da = 0, int db = 0,
+ bool op = false)
+ : how(h)
+ , opposite(op)
+ , how_a(ha)
+ , how_b(hb)
+ , dir_a(da)
+ , dir_b(db)
+ , sides(s)
+ {
+ arrival[0] = ha;
+ arrival[1] = hb;
+ }
+
+ inline direction_type(char h, bool op, int ha = 0, int hb = 0)
+ : how(h)
+ , opposite(op)
+ , how_a(ha)
+ , how_b(hb)
+ , dir_a(0)
+ , dir_b(0)
+ {
+ arrival[0] = ha;
+ arrival[1] = hb;
+ }
+
+
+ // "How" is the intersection formed?
+ char how;
+
+ // Is it opposite (for collinear/equal cases)
+ bool opposite;
+
+ // Information on how A arrives at intersection, how B arrives at intersection
+ // 1: arrives at intersection
+ // -1: starts from intersection
+ int how_a;
+ int how_b;
+
+ // Direction: how is A positioned from B
+ // 1: points left, seen from IP
+ // -1: points right, seen from IP
+ // In case of intersection: B's TO direction
+ // In case that B's TO direction is at A: B's from direction
+ // In collinear cases: it is 0
+ int dir_a; // Direction of A-s TO from IP
+ int dir_b; // Direction of B-s TO from IP
+
+ // New information
+ side_info sides;
+ int arrival[2]; // 1=arrival, -1departure, 0=neutral; == how_a//how_b
+
+
+ // About arrival[0] (== arrival of a2 w.r.t. b) for COLLINEAR cases
+ // Arrival 1: a1--------->a2 (a arrives within b)
+ // b1----->b2
+
+ // Arrival 1: (a in b)
+ //
+
+
+ // Arrival -1: a1--------->a2 (a does not arrive within b)
+ // b1----->b2
+
+ // Arrival -1: (b in a) a_1-------------a_2
+ // b_1---b_2
+
+ // Arrival 0: a1------->a2 (a arrives at TO-border of b)
+ // b1--->b2
+
+};
+
+
+template <typename S1, typename S2, typename CalculationType = void>
+struct segments_direction
+{
+ typedef direction_type return_type;
+ typedef S1 segment_type1;
+ typedef S2 segment_type2;
+ typedef typename select_calculation_type
+ <
+ S1, S2, CalculationType
+ >::type coordinate_type;
+
+ // Get the same type, but at least a double
+ typedef typename select_most_precise<coordinate_type, double>::type rtype;
+
+
+ static inline return_type segments_intersect(side_info const& sides,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ coordinate_type const& dx2, coordinate_type const& dy2,
+ S1 const& s1, S2 const& s2)
+ {
+ bool const ra0 = sides.get<0,0>() == 0;
+ bool const ra1 = sides.get<0,1>() == 0;
+ bool const rb0 = sides.get<1,0>() == 0;
+ bool const rb1 = sides.get<1,1>() == 0;
+
+ return
+ // opposite and same starting point (FROM)
+ ra0 && rb0 ? calculate_side<1>(sides, dx1, dy1, s1, s2, 'f', -1, -1)
+
+ // opposite and point to each other (TO)
+ : ra1 && rb1 ? calculate_side<0>(sides, dx1, dy1, s1, s2, 't', 1, 1)
+
+ // not opposite, forming an angle, first a then b,
+ // directed either both left, or both right
+ // Check side of B2 from A. This is not calculated before
+ : ra1 && rb0 ? angle<1>(sides, dx1, dy1, s1, s2, 'a', 1, -1)
+
+ // not opposite, forming a angle, first b then a,
+ // directed either both left, or both right
+ : ra0 && rb1 ? angle<0>(sides, dx1, dy1, s1, s2, 'a', -1, 1)
+
+ // b starts from interior of a
+ : rb0 ? starts_from_middle(sides, dx1, dy1, s1, s2, 'B', 0, -1)
+
+ // a starts from interior of b (#39)
+ : ra0 ? starts_from_middle(sides, dx1, dy1, s1, s2, 'A', -1, 0)
+
+ // b ends at interior of a, calculate direction of A from IP
+ : rb1 ? b_ends_at_middle(sides, dx2, dy2, s1, s2)
+
+ // a ends at interior of b
+ : ra1 ? a_ends_at_middle(sides, dx1, dy1, s1, s2)
+
+ // normal intersection
+ : calculate_side<1>(sides, dx1, dy1, s1, s2, 'i', -1, -1)
+ ;
+ }
+
+ static inline return_type collinear_touch(
+ coordinate_type const& ,
+ coordinate_type const& , int arrival_a, int arrival_b)
+ {
+ // Though this is 'collinear', we handle it as To/From/Angle because it is the same.
+ // It only does NOT have a direction.
+ side_info sides;
+ //int const arrive = how == 'T' ? 1 : -1;
+ bool opposite = arrival_a == arrival_b;
+ return
+ ! opposite
+ ? return_type(sides, 'a', arrival_a, arrival_b)
+ : return_type(sides, arrival_a == 0 ? 't' : 'f', arrival_a, arrival_b, 0, 0, true);
+ }
+
+ template <typename S>
+ static inline return_type collinear_interior_boundary_intersect(S const& , bool,
+ int arrival_a, int arrival_b, bool opposite)
+ {
+ return_type r('c', opposite);
+ r.arrival[0] = arrival_a;
+ r.arrival[1] = arrival_b;
+ return r;
+ }
+
+ static inline return_type collinear_a_in_b(S1 const& , bool opposite)
+ {
+ return_type r('c', opposite);
+ r.arrival[0] = 1;
+ r.arrival[1] = -1;
+ return r;
+ }
+ static inline return_type collinear_b_in_a(S2 const& , bool opposite)
+ {
+ return_type r('c', opposite);
+ r.arrival[0] = -1;
+ r.arrival[1] = 1;
+ return r;
+ }
+
+ static inline return_type collinear_overlaps(
+ coordinate_type const& , coordinate_type const& ,
+ coordinate_type const& , coordinate_type const& ,
+ int arrival_a, int arrival_b, bool opposite)
+ {
+ return_type r('c', opposite);
+ r.arrival[0] = arrival_a;
+ r.arrival[1] = arrival_b;
+ return r;
+ }
+
+ static inline return_type segment_equal(S1 const& , bool opposite)
+ {
+ return return_type('e', opposite);
+ }
+
+ static inline return_type degenerate(S1 const& , bool)
+ {
+ return return_type('0', false);
+ }
+
+ static inline return_type disjoint()
+ {
+ return return_type('d', false);
+ }
+
+ static inline return_type collinear_disjoint()
+ {
+ return return_type('d', false);
+ }
+
+
+ static inline return_type parallel()
+ {
+ return return_type('p', false);
+ }
+
+ static inline return_type error(std::string const& msg)
+ {
+ // msg
+ return return_type('d', false);
+ }
+
+private :
+
+
+ template <std::size_t I>
+ static inline return_type calculate_side(side_info const& sides,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ S1 const& s1, S2 const& s2,
+ char how, int how_a, int how_b)
+ {
+ coordinate_type dpx = get<I, 0>(s2) - get<0, 0>(s1);
+ coordinate_type dpy = get<I, 1>(s2) - get<0, 1>(s1);
+
+ // This is a "side calculation" as in the strategies, but here two terms are precalculated
+ // We might merge this with side, offering a pre-calculated term
+ // Waiting for implementing spherical...
+
+ return dx1 * dpy - dy1 * dpx > 0
+ ? return_type(sides, how, how_a, how_b, -1, 1)
+ : return_type(sides, how, how_a, how_b, 1, -1);
+ }
+
+ template <std::size_t I>
+ static inline return_type angle(side_info const& sides,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ S1 const& s1, S2 const& s2,
+ char how, int how_a, int how_b)
+ {
+ coordinate_type dpx = get<I, 0>(s2) - get<0, 0>(s1);
+ coordinate_type dpy = get<I, 1>(s2) - get<0, 1>(s1);
+
+ return dx1 * dpy - dy1 * dpx > 0
+ ? return_type(sides, how, how_a, how_b, 1, 1)
+ : return_type(sides, how, how_a, how_b, -1, -1);
+ }
+
+
+ static inline return_type starts_from_middle(side_info const& sides,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ S1 const& s1, S2 const& s2,
+ char which,
+ int how_a, int how_b)
+ {
+ // Calculate ARROW of b segment w.r.t. s1
+ coordinate_type dpx = get<1, 0>(s2) - get<0, 0>(s1);
+ coordinate_type dpy = get<1, 1>(s2) - get<0, 1>(s1);
+
+ int dir = dx1 * dpy - dy1 * dpx > 0 ? 1 : -1;
+
+ // From other perspective, then reverse
+ bool const is_a = which == 'A';
+ if (is_a)
+ {
+ dir = -dir;
+ }
+
+ return return_type(sides, 's',
+ how_a,
+ how_b,
+ is_a ? dir : -dir,
+ ! is_a ? dir : -dir);
+ }
+
+
+
+ // To be harmonized
+ static inline return_type a_ends_at_middle(side_info const& sides,
+ coordinate_type const& dx, coordinate_type const& dy,
+ S1 const& s1, S2 const& s2)
+ {
+ coordinate_type dpx = get<1, 0>(s2) - get<0, 0>(s1);
+ coordinate_type dpy = get<1, 1>(s2) - get<0, 1>(s1);
+
+ // Ending at the middle, one ARRIVES, the other one is NEUTRAL
+ // (because it both "arrives" and "departs" there
+ return dx * dpy - dy * dpx > 0
+ ? return_type(sides, 'm', 1, 0, 1, 1)
+ : return_type(sides, 'm', 1, 0, -1, -1);
+ }
+
+
+ static inline return_type b_ends_at_middle(side_info const& sides,
+ coordinate_type const& dx, coordinate_type const& dy,
+ S1 const& s1, S2 const& s2)
+ {
+ coordinate_type dpx = get<1, 0>(s1) - get<0, 0>(s2);
+ coordinate_type dpy = get<1, 1>(s1) - get<0, 1>(s2);
+
+ return dx * dpy - dy * dpx > 0
+ ? return_type(sides, 'm', 0, 1, 1, 1)
+ : return_type(sides, 'm', 0, 1, -1, -1);
+ }
+
+};
+
+}} // namespace policies::relate
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP

Added: sandbox/geometry/boost/geometry/policies/relate/intersection_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/policies/relate/intersection_points.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,179 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
+#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
+
+#include <algorithm>
+
+#include <boost/concept_check.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/strategies/side_info.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace policies { namespace relate {
+
+
+template <typename S1, typename S2, typename ReturnType, typename CalculationType = void>
+struct segments_intersection_points
+{
+ typedef ReturnType return_type;
+ typedef S1 segment_type1;
+ typedef S2 segment_type2;
+ typedef typename select_calculation_type
+ <
+ S1, S2, CalculationType
+ >::type coordinate_type;
+
+ // Get the same type, but at least a double
+ typedef typename select_most_precise<coordinate_type, double>::type rtype;
+
+ static inline return_type segments_intersect(side_info const&,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ coordinate_type const& dx2, coordinate_type const& dy2,
+ S1 const& s1, S2 const& s2)
+ {
+ return_type result;
+ typedef typename geometry::coordinate_type
+ <
+ typename return_type::point_type
+ >::type coordinate_type;
+
+ // Get the same type, but at least a double (also used for divisions
+ typedef typename select_most_precise
+ <
+ coordinate_type, double
+ >::type promoted_type;
+
+ promoted_type const s1x = get<0, 0>(s1);
+ promoted_type const s1y = get<0, 1>(s1);
+
+ // Calculate other determinants - Cramers rule
+ promoted_type const wx = get<0, 0>(s1) - get<0, 0>(s2);
+ promoted_type const wy = get<0, 1>(s1) - get<0, 1>(s2);
+ promoted_type const d = (dy2 * dx1) - (dx2 * dy1);
+ promoted_type const da = (promoted_type(dx2) * wy) - (promoted_type(dy2) * wx);
+
+ // r: ratio 0-1 where intersection divides A/B
+ promoted_type const r = da / d;
+
+ result.count = 1;
+ set<0>(result.intersections[0],
+ boost::numeric_cast<coordinate_type>(s1x + r * promoted_type(dx1)));
+ set<1>(result.intersections[0],
+ boost::numeric_cast<coordinate_type>(s1y + r * promoted_type(dy1)));
+
+ return result;
+ }
+
+ static inline return_type collinear_touch(coordinate_type const& x,
+ coordinate_type const& y, int, int)
+ {
+ return_type result;
+ result.count = 1;
+ set<0>(result.intersections[0], x);
+ set<1>(result.intersections[0], y);
+ return result;
+ }
+
+ template <typename S>
+ static inline return_type collinear_inside(S const& s, int index1 = 0, int index2 = 1)
+ {
+ return_type result;
+ result.count = 2;
+ set<0>(result.intersections[index1], get<0, 0>(s));
+ set<1>(result.intersections[index1], get<0, 1>(s));
+ set<0>(result.intersections[index2], get<1, 0>(s));
+ set<1>(result.intersections[index2], get<1, 1>(s));
+ return result;
+ }
+
+ template <typename S>
+ static inline return_type collinear_interior_boundary_intersect(S const& s, bool a_in_b,
+ int, int, bool opposite)
+ {
+ int index1 = opposite && ! a_in_b ? 1 : 0;
+ return collinear_inside(s, index1, 1 - index1);
+ }
+
+ static inline return_type collinear_a_in_b(S1 const& s, bool opposite)
+ {
+ return collinear_inside(s);
+ }
+ static inline return_type collinear_b_in_a(S2 const& s, bool opposite)
+ {
+ int index1 = opposite ? 1 : 0;
+ return collinear_inside(s, index1, 1 - index1);
+ }
+
+ static inline return_type collinear_overlaps(
+ coordinate_type const& x1, coordinate_type const& y1,
+ coordinate_type const& x2, coordinate_type const& y2,
+ int, int, bool)
+ {
+ return_type result;
+ result.count = 2;
+ set<0>(result.intersections[0], x1);
+ set<1>(result.intersections[0], y1);
+ set<0>(result.intersections[1], x2);
+ set<1>(result.intersections[1], y2);
+ return result;
+ }
+
+ static inline return_type segment_equal(S1 const& s, bool opposite)
+ {
+ return_type result;
+ result.count = 2;
+ // TODO: order of IP's
+ set<0>(result.intersections[0], get<0, 0>(s));
+ set<1>(result.intersections[0], get<0, 1>(s));
+ set<0>(result.intersections[1], get<1, 0>(s));
+ set<1>(result.intersections[1], get<1, 1>(s));
+ return result;
+ }
+
+ static inline return_type disjoint()
+ {
+ return return_type();
+ }
+ static inline return_type error(std::string const& msg)
+ {
+ return return_type();
+ }
+
+ static inline return_type collinear_disjoint()
+ {
+ return return_type();
+ }
+ static inline return_type parallel()
+ {
+ return return_type();
+ }
+ static inline return_type degenerate(S1 const& s, bool)
+ {
+ return_type result;
+ result.count = 1;
+ set<0>(result.intersections[0], get<0, 0>(s));
+ set<1>(result.intersections[0], get<0, 1>(s));
+ return result;
+ }
+};
+
+
+}} // namespace policies::relate
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP

Added: sandbox/geometry/boost/geometry/policies/relate/intersection_points_determinant.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/policies/relate/intersection_points_determinant.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,172 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
+#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
+
+#include <boost/concept_check.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/strategies/side_info.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace policies { namespace relate {
+
+
+template <typename S1, typename S2, typename ReturnType, typename CalculationType = void>
+struct segments_intersection_points
+{
+ typedef ReturnType return_type;
+ typedef S1 segment_type1;
+ typedef S2 segment_type2;
+ typedef typename select_calculation_type
+ <
+ S1, S2, CalculationType
+ >::type coordinate_type;
+
+ // Get the same type, but at least a double
+ typedef typename select_most_precise<coordinate_type, double>::type rtype;
+
+ static inline return_type segments_intersect(side_info const&,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ coordinate_type const& dx2, coordinate_type const& dy2,
+ S1 const& s1, S2 const& s2)
+ {
+ return_type result;
+ typedef typename geometry::coordinate_type
+ <
+ typename return_type::point_type
+ >::type coordinate_type;
+
+ // Get the same type, but at least a double (also used for divisions
+ typedef typename select_most_precise
+ <
+ coordinate_type, double
+ >::type promoted_type;
+
+ coordinate_type const s1x = get<0, 0>(s1);
+ coordinate_type const s1y = get<0, 1>(s1);
+
+ // Calculate other determinants - Cramers rule
+ promoted_type const wx = get<0, 0>(s1) - get<0, 0>(s2);
+ promoted_type const wy = get<0, 1>(s1) - get<0, 1>(s2);
+ promoted_type const d = (dy2 * dx1) - (dx2 * dy1);
+ promoted_type const da = (dx2 * wy) - (dy2 * wx);
+
+ // r: ratio 0-1 where intersection divides A/B
+ promoted_type const r = da / d;
+
+ result.count = 1;
+ set<0>(result.intersections[0],
+ boost::numeric_cast<coordinate_type>(s1x + r * dx1));
+ set<1>(result.intersections[0],
+ boost::numeric_cast<coordinate_type>(s1y + r * dy1));
+
+ return result;
+ }
+
+ static inline return_type collinear_touch(coordinate_type const& x,
+ coordinate_type const& y, bool, char)
+ {
+ return_type result;
+ result.count = 1;
+ set<0>(result.intersections[0], x);
+ set<1>(result.intersections[0], y);
+ return result;
+ }
+
+ template <typename S>
+ static inline return_type collinear_inside(S const& s)
+ {
+ return_type result;
+ result.count = 2;
+ set<0>(result.intersections[0], get<0, 0>(s));
+ set<1>(result.intersections[0], get<0, 1>(s));
+ set<0>(result.intersections[1], get<1, 0>(s));
+ set<1>(result.intersections[1], get<1, 1>(s));
+ return result;
+ }
+
+ template <typename S>
+ static inline return_type collinear_interior_boundary_intersect(S const& s, bool, bool)
+ {
+ return collinear_inside(s);
+ }
+
+ static inline return_type collinear_a_in_b(S1 const& s, bool)
+ {
+ return collinear_inside(s);
+ }
+ static inline return_type collinear_b_in_a(S2 const& s, bool)
+ {
+ return collinear_inside(s);
+ }
+
+ static inline return_type collinear_overlaps(
+ coordinate_type const& x1, coordinate_type const& y1,
+ coordinate_type const& x2, coordinate_type const& y2, bool)
+ {
+ return_type result;
+ result.count = 2;
+ set<0>(result.intersections[0], x1);
+ set<1>(result.intersections[0], y1);
+ set<0>(result.intersections[1], x2);
+ set<1>(result.intersections[1], y2);
+ return result;
+ }
+
+ static inline return_type segment_equal(S1 const& s, bool)
+ {
+ return_type result;
+ result.count = 2;
+ set<0>(result.intersections[0], get<0, 0>(s));
+ set<1>(result.intersections[0], get<0, 1>(s));
+ set<0>(result.intersections[1], get<1, 0>(s));
+ set<1>(result.intersections[1], get<1, 1>(s));
+ return result;
+ }
+
+ static inline return_type disjoint()
+ {
+ return return_type();
+ }
+ static inline return_type error(std::string const& msg)
+ {
+ return return_type();
+ }
+
+ static inline return_type collinear_disjoint()
+ {
+ return return_type();
+ }
+ static inline return_type parallel()
+ {
+ return return_type();
+ }
+ static inline return_type degenerate(S1 const& s, bool)
+ {
+ return_type result;
+ result.count = 1;
+ set<0>(result.intersections[0], get<0, 0>(s));
+ set<1>(result.intersections[0], get<0, 1>(s));
+ return result;
+ }
+};
+
+
+}} // namespace policies::relate
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP

Added: sandbox/geometry/boost/geometry/policies/relate/intersection_points_slope.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/policies/relate/intersection_points_slope.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,209 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
+#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
+
+#include <boost/concept_check.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/strategies/side_info.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace policies { namespace relate {
+
+
+template <typename S1, typename S2, typename ReturnType, typename CalculationType = void>
+struct segments_intersection_points
+{
+ typedef ReturnType return_type;
+ typedef S1 segment_type1;
+ typedef S2 segment_type2;
+ typedef typename select_calculation_type
+ <
+ S1, S2, CalculationType
+ >::type coordinate_type;
+
+ // Get the same type, but at least a double (also used for divisions
+ typedef typename select_most_precise
+ <
+ coordinate_type, double
+ >::type promoted_type;
+
+ template <int Dimension>
+ static inline return_type rico(
+ coordinate_type const& dm1, coordinate_type const& dn1,
+ coordinate_type const& dm2, coordinate_type const& dn2,
+ S1 const& s1, S2 const& s2)
+ {
+ promoted_type const a1 = dn1 / dm1;
+ promoted_type const a2 = dn2 / dm2;
+ promoted_type const da = a1 - a2;
+
+ if (math::equals(da, 0))
+ {
+ return rico<1 - Dimension>(dn1, dm1, dn2, dm2, s1, s2);
+ }
+
+ promoted_type const b1 = get<0, Dimension>(s1) - a1 * get<0, 1 - Dimension>(s1);
+ promoted_type const b2 = get<0, Dimension>(s2) - a2 * get<0, 1 - Dimension>(s2);
+
+ promoted_type const v = (b2 - b1) / da;
+
+ return_type result;
+ result.count = 1;
+ set<1 - Dimension>(result.intersections[0],
+ boost::numeric_cast<coordinate_type>(v));
+ set<Dimension>(result.intersections[0],
+ boost::numeric_cast<coordinate_type>(a1 * v + b1));
+ return result;
+ }
+
+ static inline return_type cross(S1 const& s1, S2 const& s2)
+ {
+ // Take one of first segment, and one of second segment
+ return_type result;
+ result.count = 1;
+ set<0>(result.intersections[0], get<0, 0>(s1));
+ set<1>(result.intersections[0], get<0, 1>(s2));
+ return result;
+ }
+
+
+ static inline return_type segments_intersect(side_info const& sides,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ coordinate_type const& dx2, coordinate_type const& dy2,
+ S1 const& s1, S2 const& s2)
+ {
+ bool vertical1 = math::equals(dx1, 0);
+ bool horizontal2 = math::equals(dy2, 0);
+ if (vertical1 && horizontal2)
+ {
+ return cross(s1, s2);
+ }
+
+ bool vertical2 = math::equals(dx2, 0);
+ bool horizontal1 = math::equals(dy1, 0);
+ if (horizontal1 && vertical2)
+ {
+ return cross(s2, s1);
+ }
+ if (vertical1 || vertical2)
+ {
+ return rico<0>(dy1, dx1, dy2, dx2, s1, s2);
+ }
+ else
+ {
+ // Not crossing, take the most reasonable choice.
+ // We want to divide by the largest one.
+ //if (
+
+ return rico<1>(dx1, dy1, dx2, dy2, s1, s2);
+ }
+ }
+
+ static inline return_type collinear_touch(coordinate_type const& x,
+ coordinate_type const& y, bool, char)
+ {
+ return_type result;
+ result.count = 1;
+ set<0>(result.intersections[0], x);
+ set<1>(result.intersections[0], y);
+ return result;
+ }
+
+ template <typename S>
+ static inline return_type collinear_inside(S const& s)
+ {
+ return_type result;
+ result.count = 2;
+ set<0>(result.intersections[0], get<0, 0>(s));
+ set<1>(result.intersections[0], get<0, 1>(s));
+ set<0>(result.intersections[1], get<1, 0>(s));
+ set<1>(result.intersections[1], get<1, 1>(s));
+ return result;
+ }
+
+ template <typename S>
+ static inline return_type collinear_interior_boundary_intersect(S const& s, bool, bool)
+ {
+ return collinear_inside(s);
+ }
+
+ static inline return_type collinear_a_in_b(S1 const& s, bool)
+ {
+ return collinear_inside(s);
+ }
+ static inline return_type collinear_b_in_a(S2 const& s, bool)
+ {
+ return collinear_inside(s);
+ }
+
+ static inline return_type collinear_overlaps(
+ coordinate_type const& x1, coordinate_type const& y1,
+ coordinate_type const& x2, coordinate_type const& y2, bool)
+ {
+ return_type result;
+ result.count = 2;
+ set<0>(result.intersections[0], x1);
+ set<1>(result.intersections[0], y1);
+ set<0>(result.intersections[1], x2);
+ set<1>(result.intersections[1], y2);
+ return result;
+ }
+
+ static inline return_type segment_equal(S1 const& s, bool)
+ {
+ return_type result;
+ result.count = 2;
+ set<0>(result.intersections[0], get<0, 0>(s));
+ set<1>(result.intersections[0], get<0, 1>(s));
+ set<0>(result.intersections[1], get<1, 0>(s));
+ set<1>(result.intersections[1], get<1, 1>(s));
+ return result;
+ }
+
+ static inline return_type disjoint()
+ {
+ return return_type();
+ }
+ static inline return_type error(std::string const& msg)
+ {
+ return return_type();
+ }
+
+ static inline return_type collinear_disjoint()
+ {
+ return return_type();
+ }
+ static inline return_type parallel()
+ {
+ return return_type();
+ }
+ static inline return_type degenerate(S1 const& s, bool)
+ {
+ return_type result;
+ result.count = 1;
+ set<0>(result.intersections[0], get<0, 0>(s));
+ set<1>(result.intersections[0], get<0, 1>(s));
+ return result;
+ }
+};
+
+
+}} // namespace policies::relate
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP

Added: sandbox/geometry/boost/geometry/policies/relate/tupled.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/policies/relate/tupled.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,178 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_TUPLED_HPP
+#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_TUPLED_HPP
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/geometry/strategies/side_info.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace policies { namespace relate {
+
+
+// "tupled" to return intersection results together.
+// Now with two, with some meta-programming and derivations it can also be three (or more)
+template <typename Policy1, typename Policy2, typename CalculationType = void>
+struct segments_tupled
+{
+ typedef boost::tuple
+ <
+ typename Policy1::return_type,
+ typename Policy2::return_type
+ > return_type;
+
+ // Take segments of first policy, they should be equal
+ typedef typename Policy1::segment_type1 segment_type1;
+ typedef typename Policy1::segment_type2 segment_type2;
+
+ typedef typename select_calculation_type
+ <
+ segment_type1,
+ segment_type2,
+ CalculationType
+ >::type coordinate_type;
+
+ // Get the same type, but at least a double
+ typedef typename select_most_precise<coordinate_type, double>::type rtype;
+
+ static inline return_type segments_intersect(side_info const& sides,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ coordinate_type const& dx2, coordinate_type const& dy2,
+ segment_type1 const& s1, segment_type2 const& s2)
+ {
+ return boost::make_tuple
+ (
+ Policy1::segments_intersect(sides,
+ dx1, dy1, dx2, dy2, s1, s2),
+ Policy2::segments_intersect(sides,
+ dx1, dy1, dx2, dy2, s1, s2)
+ );
+ }
+
+ static inline return_type collinear_touch(coordinate_type const& x,
+ coordinate_type const& y, int arrival_a, int arrival_b)
+ {
+ return boost::make_tuple
+ (
+ Policy1::collinear_touch(x, y, arrival_a, arrival_b),
+ Policy2::collinear_touch(x, y, arrival_a, arrival_b)
+ );
+ }
+
+ template <typename S>
+ static inline return_type collinear_interior_boundary_intersect(S const& segment,
+ bool a_within_b,
+ int arrival_a, int arrival_b, bool opposite)
+ {
+ return boost::make_tuple
+ (
+ Policy1::collinear_interior_boundary_intersect(segment, a_within_b, arrival_a, arrival_b, opposite),
+ Policy2::collinear_interior_boundary_intersect(segment, a_within_b, arrival_a, arrival_b, opposite)
+ );
+ }
+
+ static inline return_type collinear_a_in_b(segment_type1 const& segment,
+ bool opposite)
+ {
+ return boost::make_tuple
+ (
+ Policy1::collinear_a_in_b(segment, opposite),
+ Policy2::collinear_a_in_b(segment, opposite)
+ );
+ }
+ static inline return_type collinear_b_in_a(segment_type2 const& segment,
+ bool opposite)
+ {
+ return boost::make_tuple
+ (
+ Policy1::collinear_b_in_a(segment, opposite),
+ Policy2::collinear_b_in_a(segment, opposite)
+ );
+ }
+
+
+ static inline return_type collinear_overlaps(
+ coordinate_type const& x1, coordinate_type const& y1,
+ coordinate_type const& x2, coordinate_type const& y2,
+ int arrival_a, int arrival_b, bool opposite)
+ {
+ return boost::make_tuple
+ (
+ Policy1::collinear_overlaps(x1, y1, x2, y2, arrival_a, arrival_b, opposite),
+ Policy2::collinear_overlaps(x1, y1, x2, y2, arrival_a, arrival_b, opposite)
+ );
+ }
+
+ static inline return_type segment_equal(segment_type1 const& s,
+ bool opposite)
+ {
+ return boost::make_tuple
+ (
+ Policy1::segment_equal(s, opposite),
+ Policy2::segment_equal(s, opposite)
+ );
+ }
+
+ static inline return_type degenerate(segment_type1 const& segment,
+ bool a_degenerate)
+ {
+ return boost::make_tuple
+ (
+ Policy1::degenerate(segment, a_degenerate),
+ Policy2::degenerate(segment, a_degenerate)
+ );
+ }
+
+ static inline return_type disjoint()
+ {
+ return boost::make_tuple
+ (
+ Policy1::disjoint(),
+ Policy2::disjoint()
+ );
+ }
+
+ static inline return_type error(std::string const& msg)
+ {
+ return boost::make_tuple
+ (
+ Policy1::error(msg),
+ Policy2::error(msg)
+ );
+ }
+
+ static inline return_type collinear_disjoint()
+ {
+ return boost::make_tuple
+ (
+ Policy1::collinear_disjoint(),
+ Policy2::collinear_disjoint()
+ );
+ }
+
+
+ static inline return_type parallel()
+ {
+ return boost::make_tuple
+ (
+ Policy1::parallel(),
+ Policy2::parallel()
+ );
+ }
+};
+
+}} // namespace policies::relate
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_TUPLED_HPP

Added: sandbox/geometry/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,427 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2009, Geodan, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP
+#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP
+
+
+#include <cstddef>
+#include <algorithm>
+#include <vector>
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/strategies/convex_hull.hpp>
+
+#include <boost/geometry/iterators/range_type.hpp>
+
+#include <boost/geometry/policies/compare.hpp>
+
+#include <boost/geometry/util/for_each_range.hpp>
+
+
+// Temporary, comparing sorting, this can be removed in the end
+//#define BOOST_GEOMETRY_USE_FLEX_SORT
+//#define BOOST_GEOMETRY_USE_FLEX_SORT2
+#if defined(GGL_USE_FLEX_SORT)
+# include <boost/algorithm/sorting/flex_sort.hpp>
+#endif
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace convex_hull {
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template
+<
+ typename InputRange,
+ typename RangeIterator,
+ typename StrategyLess,
+ typename StrategyGreater
+>
+struct get_extremes
+{
+ typedef typename point_type<InputRange>::type point_type;
+
+ point_type left, right;
+
+ bool first;
+
+ StrategyLess less;
+ StrategyGreater greater;
+
+ get_extremes()
+ : first(true)
+ {}
+
+ inline void apply(InputRange const& range)
+ {
+ // First iterate through this range
+ // (this two-stage approach avoids many point copies,
+ // because iterators are kept in memory. Because iterators are
+ // not persistent (in MSVC) this approach is not applicable
+ // for more ranges together)
+
+ RangeIterator left_it = boost::begin(range);
+ RangeIterator right_it = boost::begin(range);
+
+ for (RangeIterator it = boost::begin(range) + 1;
+ it != boost::end(range);
+ ++it)
+ {
+ if (less(*it, *left_it))
+ {
+ left_it = it;
+ }
+
+ if (greater(*it, *right_it))
+ {
+ right_it = it;
+ }
+ }
+
+ // Then compare with earlier
+ if (first && boost::size(range) > 0)
+ {
+ // First time, assign left/right
+ left = *left_it;
+ right = *right_it;
+ first = false;
+ }
+ else
+ {
+ // Next time, check if this range was left/right from
+ // the extremes already collected
+ if (less(*left_it, left))
+ {
+ left = *left_it;
+ }
+
+ if (greater(*right_it, right))
+ {
+ right = *right_it;
+ }
+ }
+ }
+};
+
+
+template
+<
+ typename InputRange,
+ typename RangeIterator,
+ typename Container,
+ typename SideStrategy
+>
+struct assign_range
+{
+ Container lower_points, upper_points;
+
+ typedef typename point_type<InputRange>::type point_type;
+
+ point_type const& most_left;
+ point_type const& most_right;
+
+ inline assign_range(point_type const& left, point_type const& right)
+ : most_left(left)
+ , most_right(right)
+ {}
+
+ inline void apply(InputRange const& range)
+ {
+ typedef SideStrategy side;
+
+ // Put points in one of the two output sequences
+ for (RangeIterator it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ // check if it is lying most_left or most_right from the line
+
+ int dir = side::apply(most_left, most_right, *it);
+ switch(dir)
+ {
+ case 1 : // left side
+ upper_points.push_back(*it);
+ break;
+ case -1 : // right side
+ lower_points.push_back(*it);
+ break;
+
+ // 0: on line most_left-most_right,
+ // or most_left, or most_right,
+ // -> all never part of hull
+ }
+ }
+ }
+};
+
+
+template <typename Range>
+static inline void sort(Range& range)
+{
+ typedef typename boost::range_value<Range>::type point_type;
+ typedef geometry::less<point_type> comparator;
+
+#if defined(GGL_USE_FLEX_SORT)
+
+ #if defined(GGL_USE_FLEX_SORT1)
+ typedef boost::detail::default_predicate
+ <
+ boost::sort_filter_cutoff
+ <
+ 18,
+ boost::detail::insert_sort_core,
+ boost::sort_filter_ground
+ <
+ 30,
+ boost::detail::heap_sort_core,
+ boost::detail::quick_sort_core
+ <
+ boost::pivot_median_of_three,
+ boost::default_partitionner
+ >
+ >
+ >,
+ comparator> my_sort;
+ my_sort sort;
+ #elif defined(GGL_USE_FLEX_SORT2)
+
+ // 1, 5, 9, 18, 25: 0.75
+ // 50: 0.81
+
+ typedef boost::detail::default_predicate<boost::sort_filter_cutoff
+ <
+ 35,
+ boost::detail::insert_sort_core,
+ boost::detail::quick_sort_core<boost::pivot_middle, boost::default_partitionner>
+ >, comparator
+ > barend_sort;
+
+ barend_sort sort;
+ #else
+ #error Define sub-flex-sort
+ #endif
+
+ sort(boost::begin(range), boost::end(range));
+
+#else
+ std::sort
+ (boost::begin(range), boost::end(range), comparator());
+#endif
+}
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief Graham scan strategy to calculate convex hull
+ \ingroup convex_hull
+ \note Completely reworked version inspired on the sources listed below
+ \see http://www.ddj.com/architect/201806315
+ \see http://marknelson.us/2007/08/22/convex
+
+ */
+template <typename InputGeometry, typename OutputPoint>
+class graham_andrew
+{
+public :
+ typedef OutputPoint point_type;
+ typedef InputGeometry geometry_type;
+
+private:
+
+ typedef typename cs_tag<point_type>::type cs_tag;
+
+ typedef typename std::vector<point_type> container_type;
+ typedef typename std::vector<point_type>::const_iterator iterator;
+ typedef typename std::vector<point_type>::const_reverse_iterator rev_iterator;
+
+
+ class partitions
+ {
+ friend class graham_andrew;
+
+ container_type m_lower_hull;
+ container_type m_upper_hull;
+ container_type m_copied_input;
+ };
+
+
+public:
+ typedef partitions state_type;
+
+
+ inline void apply(InputGeometry const& geometry, partitions& state) const
+ {
+ // First pass.
+ // Get min/max (in most cases left / right) points
+ // This makes use of the geometry::less/greater predicates with the optional
+ // direction template parameter to indicate x direction
+
+ typedef typename range_type<InputGeometry>::type range_type;
+
+ typedef typename boost::range_const_iterator
+ <
+ range_type
+ >::type range_iterator;
+
+ detail::get_extremes
+ <
+ range_type,
+ range_iterator,
+ geometry::less<point_type, 0>,
+ geometry::greater<point_type, 0>
+ > extremes;
+ geometry::for_each_range(geometry, extremes);
+
+ // Bounding left/right points
+ // Second pass, now that extremes are found, assign all points
+ // in either lower, either upper
+ detail::assign_range
+ <
+ range_type,
+ range_iterator,
+ container_type,
+ typename strategy_side<cs_tag>::type
+ > assigner(extremes.left, extremes.right);
+
+ geometry::for_each_range(geometry, assigner);
+
+
+ // Sort both collections, first on x(, then on y)
+ detail::sort(assigner.lower_points);
+ detail::sort(assigner.upper_points);
+
+ //std::cout << boost::size(assigner.lower_points) << std::endl;
+ //std::cout << boost::size(assigner.upper_points) << std::endl;
+
+ // And decide which point should be in the final hull
+ build_half_hull<-1>(assigner.lower_points, state.m_lower_hull,
+ extremes.left, extremes.right);
+ build_half_hull<1>(assigner.upper_points, state.m_upper_hull,
+ extremes.left, extremes.right);
+ }
+
+
+ template <typename OutputIterator>
+ inline void result(partitions const& state,
+ OutputIterator out, bool clockwise) const
+ {
+ if (clockwise)
+ {
+ get_range_forward(state.m_upper_hull, out);
+ get_range_reverse(state.m_lower_hull, out);
+ }
+ else
+ {
+ get_range_forward(state.m_lower_hull, out);
+ get_range_reverse(state.m_upper_hull, out);
+ }
+ }
+
+
+private:
+
+ template <int Factor>
+ static inline void build_half_hull(container_type const& input,
+ container_type& output,
+ point_type const& left, point_type const& right)
+ {
+ output.push_back(left);
+ for(iterator it = input.begin(); it != input.end(); ++it)
+ {
+ add_to_hull<Factor>(*it, output);
+ }
+ add_to_hull<Factor>(right, output);
+ }
+
+
+ template <int Factor>
+ static inline void add_to_hull(point_type const& p, container_type& output)
+ {
+ typedef typename strategy_side<cs_tag>::type side;
+
+ output.push_back(p);
+ register std::size_t output_size = output.size();
+ while (output_size >= 3)
+ {
+ rev_iterator rit = output.rbegin();
+ point_type const& last = *rit++;
+ point_type const& last2 = *rit++;
+
+ if (Factor * side::apply(*rit, last, last2) <= 0)
+ {
+ // Remove last two points from stack, and add last again
+ // This is much faster then erasing the one but last.
+ output.pop_back();
+ output.pop_back();
+ output.push_back(last);
+ output_size--;
+ }
+ else
+ {
+ return;
+ }
+ }
+ }
+
+
+ template <typename OutputIterator>
+ static inline void get_range_forward(container_type const& range, OutputIterator out)
+ {
+ for (iterator it = boost::begin(range);
+ it != boost::end(range);
+ ++it, ++out)
+ {
+ *out = *it;
+ }
+ }
+
+
+ template <typename OutputIterator>
+ static inline void get_range_reverse(container_type const& range, OutputIterator out)
+ {
+ // STL Port does not accept iterating from rbegin+1 to rend
+ std::size_t size = range.size();
+ if (size > 0)
+ {
+ rev_iterator it = range.rbegin() + 1;
+ for (std::size_t i = 1; i < size; ++i, ++it, ++out)
+ {
+ *out = *it;
+ }
+ }
+ }
+
+};
+
+}} // namespace strategy::convex_hull
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename InputGeometry, typename OutputPoint>
+struct strategy_convex_hull<cartesian_tag, InputGeometry, OutputPoint>
+{
+ typedef strategy::convex_hull::graham_andrew<InputGeometry, OutputPoint> type;
+};
+#endif
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP

Added: sandbox/geometry/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,189 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
+#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
+
+
+
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+#include <boost/geometry/strategies/point_in_poly.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace within {
+
+/*!
+ \brief Within detection using winding rule
+ \tparam Point point type of point to examine
+ \tparam PointOfSegment point type of segments, defaults to Point
+ \author Barend Gehrels
+ \note The implementation is inspired by terralib http://www.terralib.org (LGPL)
+ \note but totally revised afterwards, especially for cases on segments
+ \note Only dependant on "side", -> agnostic, suitable for spherical/latlong
+ */
+template
+<
+ typename Point,
+ typename PointOfSegment = Point,
+ typename CalculationType = void
+>
+class winding
+{
+ typedef typename select_calculation_type
+ <
+ Point,
+ PointOfSegment,
+ CalculationType
+ >::type calculation_type;
+
+
+ typedef typename strategy_side
+ <
+ typename cs_tag<Point>::type
+ >::type strategy_side_type;
+
+
+ /*! subclass to keep state */
+ class counter
+ {
+ int count;
+ bool touches;
+
+ inline bool within_no_touch() const
+ {
+ return ! touches && count != 0;
+ }
+ public :
+ friend class winding;
+
+ inline counter()
+ : count(0)
+ , touches(false)
+ {}
+
+ };
+
+
+ template <size_t D>
+ static inline int check_touch(Point const& point,
+ PointOfSegment const& seg1, PointOfSegment const& seg2,
+ counter& state)
+ {
+ calculation_type const p = get<D>(point);
+ calculation_type const s1 = get<D>(seg1);
+ calculation_type const s2 = get<D>(seg2);
+ if ((s1 <= p && s2 >= p) || (s2 <= p && s1 >= p))
+ {
+ state.touches = true;
+ }
+ return 0;
+ }
+
+
+ template <size_t D>
+ static inline int check_segment(Point const& point,
+ PointOfSegment const& seg1, PointOfSegment const& seg2,
+ counter& state)
+ {
+ calculation_type const p = get<D>(point);
+ calculation_type const s1 = get<D>(seg1);
+ calculation_type const s2 = get<D>(seg2);
+
+ // Check if one of segment endpoints is at same level of point
+ bool eq1 = math::equals(s1, p);
+ bool eq2 = math::equals(s2, p);
+
+ if (eq1 && eq2)
+ {
+ // Both equal p -> segment is horizontal (or vertical for D=0)
+ // The only thing which has to be done is check if point is ON segment
+ return check_touch<1 - D>(point, seg1, seg2,state);
+ }
+
+ return
+ eq1 ? (s2 > p ? 1 : -1) // Point on level s1, UP/DOWN depending on s2
+ : eq2 ? (s1 > p ? -1 : 1) // idem
+ : s1 < p && s2 > p ? 2 // Point between s1 -> s2 --> UP
+ : s2 < p && s1 > p ? -2 // Point between s2 -> s1 --> DOWN
+ : 0;
+ }
+
+
+
+
+public :
+
+ // Typedefs and static methods to fulfill the concept
+ typedef Point point_type;
+ typedef PointOfSegment segment_point_type;
+ typedef counter state_type;
+
+ static inline bool apply(Point const& point,
+ PointOfSegment const& s1, PointOfSegment const& s2,
+ counter& state)
+ {
+ int count = check_segment<1>(point, s1, s2, state);
+ if (count != 0)
+ {
+ int side = strategy_side_type::apply(s1, s2, point);
+ if (side == 0)
+ {
+ // Point is lying on segment
+ state.touches = true;
+ state.count = 0;
+ return false;
+ }
+
+ // Side is NEG for right, POS for left.
+ // The count is -2 for down, 2 for up (or -1/1)
+ // Side positive thus means UP and LEFTSIDE or DOWN and RIGHTSIDE
+ // See accompagnying figure (TODO)
+ if (side * count > 0)
+ {
+ state.count += count;
+ }
+
+ }
+ return ! state.touches;
+ }
+
+ static inline bool result(counter const& state)
+ {
+ return state.within_no_touch();
+ }
+};
+
+}} // namespace strategy::within
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+template <typename Point, typename PointOfSegment>
+struct strategy_within<cartesian_tag, cartesian_tag, Point, PointOfSegment>
+{
+ typedef strategy::within::winding<Point, PointOfSegment> type;
+};
+
+template <typename Point, typename PointOfSegment>
+struct strategy_within<geographic_tag, geographic_tag, Point, PointOfSegment>
+{
+ typedef strategy::within::winding<Point, PointOfSegment> type;
+};
+
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP

Added: sandbox/geometry/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,216 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP
+#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP
+
+#include <vector>
+#include <boost/range/functions.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/strategies/distance_result.hpp>
+#include <boost/geometry/util/copy.hpp>
+
+
+//#define GL_DEBUG_DOUGLAS_PEUCKER
+
+#ifdef GL_DEBUG_DOUGLAS_PEUCKER
+#include <boost/geometry/util/write_dsv.hpp>
+#endif
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace simplify {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+ /*!
+ \brief Small wrapper around a point, with an extra member "included"
+ \details
+ It has a const-reference to the original point (so no copy here)
+ \tparam the enclosed point type
+ */
+ template<typename Point>
+ struct douglas_peucker_point
+ {
+ Point const& p;
+ bool included;
+
+ inline douglas_peucker_point(Point const& ap)
+ : p(ap)
+ , included(false)
+ {}
+
+ // Necessary for proper compilation
+ inline douglas_peucker_point<Point> operator=(
+ douglas_peucker_point<Point> const& other)
+ {
+ return douglas_peucker_point<Point>(*this);
+ }
+ };
+}
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief Implements the simplify algorithm.
+ \ingroup simplify
+ \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:
+ \see http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
+ \see http://www2.dcs.hull.ac.uk/CISRG/projects/Royal-Inst/demos/dp.html
+ \tparam Point the point type
+ \tparam PointDistanceStrategy point-segment distance strategy to be used
+ \note This strategy uses itself a point-segment-distance strategy which
+ can be specified
+ \author Barend and Maarten, 1995/1996
+ \author Barend, revised for Generic Geometry Library, 2008
+*/
+template
+<
+ typename Point,
+ typename PointDistanceStrategy
+>
+class douglas_peucker
+{
+ typedef detail::douglas_peucker_point<Point> dp_point_type;
+ typedef typename std::vector<dp_point_type>::iterator iterator_type;
+
+ typedef typename PointDistanceStrategy::return_type return_type;
+
+ static inline void consider(iterator_type begin,
+ iterator_type end,
+ return_type const& max_dist, int& n,
+ PointDistanceStrategy const& ps_distance_strategy)
+ {
+ std::size_t size = end - begin;
+
+ // size must be at least 3
+ // because we want to consider a candidate point in between
+ if (size <= 2)
+ {
+#ifdef GL_DEBUG_DOUGLAS_PEUCKER
+ if (begin != end)
+ {
+ std::cout << "ignore between " << dsv(begin->p)
+ << " and " << dsv((end - 1)->p)
+ << " size=" << size << std::endl;
+ }
+ std::cout << "return because size=" << size << std::endl;
+#endif
+ return;
+ }
+
+ iterator_type last = end - 1;
+
+#ifdef GL_DEBUG_DOUGLAS_PEUCKER
+ std::cout << "find between " << dsv(begin->p)
+ << " and " << dsv(last->p)
+ << " size=" << size << std::endl;
+#endif
+
+
+ // Find most distance point, compare to the current segment
+ //geometry::segment<const Point> s(begin->p, last->p);
+ return_type md(-1.0); // any value < 0
+ iterator_type candidate;
+ for(iterator_type it = begin + 1; it != last; ++it)
+ {
+ return_type dist = ps_distance_strategy.apply(it->p, begin->p, last->p);
+
+#ifdef GL_DEBUG_DOUGLAS_PEUCKER
+ std::cout << "consider " << dsv(it->p)
+ << " at " << double(dist)
+ << ((dist > max_dist) ? " maybe" : " no")
+ << std::endl;
+
+#endif
+ if (dist > md)
+ {
+ md = dist;
+ candidate = it;
+ }
+ }
+
+ // If a point is found, set the include flag
+ // and handle segments in between recursively
+ if (md > max_dist)
+ {
+#ifdef GL_DEBUG_DOUGLAS_PEUCKER
+ std::cout << "use " << dsv(candidate->p) << std::endl;
+#endif
+
+ candidate->included = true;
+ n++;
+
+ consider(begin, candidate + 1, max_dist, n, ps_distance_strategy);
+ consider(candidate, end, max_dist, n, ps_distance_strategy);
+ }
+ }
+
+
+public :
+
+ typedef PointDistanceStrategy distance_strategy_type;
+
+
+ template <typename Range, typename OutputIterator>
+ static inline OutputIterator apply(Range const& range,
+ OutputIterator out, double max_distance)
+ {
+ PointDistanceStrategy strategy;
+
+ // Copy coordinates, a vector of references to all points
+ std::vector<dp_point_type> ref_candidates(boost::begin(range),
+ boost::end(range));
+
+ // 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
+ typedef typename PointDistanceStrategy::return_type return_type;
+
+ consider(boost::begin(ref_candidates), boost::end(ref_candidates),
+ make_distance_result<return_type>(max_distance), n, strategy);
+
+ // Copy included elements to the output
+ for(typename std::vector<dp_point_type>::const_iterator it
+ = boost::begin(ref_candidates);
+ it != boost::end(ref_candidates);
+ ++it)
+ {
+ if (it->included)
+ {
+ // copy-coordinates does not work because OutputIterator
+ // does not model Point (??)
+ //geometry::copy_coordinates(it->p, *out);
+ *out = it->p;
+ out++;
+ }
+ }
+ return out;
+ }
+
+};
+
+}} // namespace strategy::simplify
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP

Added: sandbox/geometry/boost/geometry/strategies/area.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/area.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,34 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_AREA_HPP
+#define BOOST_GEOMETRY_STRATEGIES_AREA_HPP
+
+#include <boost/geometry/strategies/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Traits class binding an area strategy to a coordinate system
+ \ingroup area
+ \tparam Tag tag of coordinate system
+ \tparam PointOfSegment point-type
+*/
+template <typename Tag, typename PointOfSegment>
+struct strategy_area
+{
+ typedef strategy::not_implemented type;
+};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_AREA_HPP

Added: sandbox/geometry/boost/geometry/strategies/area_result.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/area_result.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,45 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_AREA_RESULT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_AREA_RESULT_HPP
+
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/strategies/area.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief Meta-function defining return type of area function
+ \ingroup area
+ \note The strategy defines the return-type (so this situation is different
+ from length, where distance is sqr/sqrt, but length always squared)
+
+ */
+template <typename Geometry>
+struct area_result
+{
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename strategy_area
+ <
+ typename cs_tag<point_type>::type,
+ point_type
+ >::type strategy_type;
+
+ typedef typename strategy_type::return_type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_AREA_RESULT_HPP

Added: sandbox/geometry/boost/geometry/strategies/cartesian/area_by_triangles.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/cartesian/area_by_triangles.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,110 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_BY_TRIANGLES_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_BY_TRIANGLES_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/geometries/point_xy.hpp>
+
+
+namespace boost { namespace geometry
+
+{
+namespace strategy { namespace area {
+
+/*!
+ \brief Strategy functor for area calculation on point_xy points
+ \details Calculates area using well-known triangulation algorithm
+ \tparam PointOfSegment point type of segments
+*/
+template
+<
+ typename PointOfSegment,
+ typename CalculationType = void
+>
+class by_triangles
+{
+public :
+ // If user specified a calculation type, use that type,
+ // whatever it is and whatever the point-type is.
+ // Else, use the pointtype, but at least double
+ typedef typename
+ boost::mpl::if_c
+ <
+ boost::is_void<CalculationType>::type::value,
+ typename select_most_precise
+ <
+ typename coordinate_type<PointOfSegment>::type,
+ double
+ >::type,
+ CalculationType
+ >::type return_type;
+
+
+private :
+
+ class summation
+ {
+ friend class by_triangles;
+
+ return_type sum;
+ public :
+
+ inline summation() : sum(return_type())
+ {
+ // Strategy supports only 2D areas
+ assert_dimension<PointOfSegment, 2>();
+ }
+ inline return_type area() const
+ {
+ return_type result = sum;
+ result *= 0.5;
+ return result;
+ }
+ };
+
+public :
+ typedef summation state_type;
+ typedef PointOfSegment segment_point_type;
+
+ static inline void apply(PointOfSegment const& p1,
+ PointOfSegment const& p2,
+ summation& state)
+ {
+ // SUM += x2 * y1 - x1 * y2;
+ state.sum += get<0>(p2) * get<1>(p1) - get<0>(p1) * get<1>(p2);
+ }
+
+ static inline return_type result(summation const& state)
+ {
+ return state.area();
+ }
+
+};
+
+}} // namespace strategy::area
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+template <typename Point>
+struct strategy_area<cartesian_tag, Point>
+{
+ typedef strategy::area::by_triangles<Point> type;
+};
+
+#endif
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_BY_TRIANGLES_HPP

Added: sandbox/geometry/boost/geometry/strategies/cartesian/cart_intersect.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/cartesian/cart_intersect.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,430 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP
+
+#include <algorithm>
+
+#include <boost/geometry/core/exception.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/geometries/concepts/segment_concept.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+// Temporary / will be Strategy as template parameter
+#include <boost/geometry/strategies/side.hpp>
+#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
+
+#include <boost/geometry/strategies/side_info.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace intersection {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Segment, size_t Dimension>
+struct segment_arrange
+{
+ template <typename T>
+ static inline void apply(Segment const& s, T& s_1, T& s_2, bool& swapped)
+ {
+ s_1 = get<0, Dimension>(s);
+ s_2 = get<1, Dimension>(s);
+ if (s_1 > s_2)
+ {
+ std::swap(s_1, s_2);
+ swapped = true;
+ }
+ }
+};
+
+}
+#endif
+
+/***
+template <typename T>
+inline std::string rdebug(T const& value)
+{
+ if (math::equals(value, 0)) return "'0'";
+ if (math::equals(value, 1)) return "'1'";
+ if (value < 0) return "<0";
+ if (value > 1) return ">1";
+ return "<0..1>";
+}
+***/
+
+/*!
+ \see http://mathworld.wolfram.com/Line-LineIntersection.html
+ */
+template <typename Policy, typename CalculationType = void>
+struct relate_cartesian_segments
+{
+ typedef typename Policy::return_type return_type;
+ typedef typename Policy::segment_type1 segment_type1;
+ typedef typename Policy::segment_type2 segment_type2;
+
+ //typedef typename point_type<segment_type1>::type point_type;
+ //BOOST_CONCEPT_ASSERT( (concept::Point<point_type>) );
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstSegment<segment_type1>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstSegment<segment_type2>) );
+
+ typedef typename select_calculation_type
+ <segment_type1, segment_type2, CalculationType>::type coordinate_type;
+
+ /// Relate segments a and b
+ static inline return_type apply(segment_type1 const& a, segment_type2 const& b)
+ {
+ coordinate_type dx_a = get<1, 0>(a) - get<0, 0>(a); // distance in x-dir
+ coordinate_type dx_b = get<1, 0>(b) - get<0, 0>(b);
+ coordinate_type dy_a = get<1, 1>(a) - get<0, 1>(a); // distance in y-dir
+ coordinate_type dy_b = get<1, 1>(b) - get<0, 1>(b);
+ return apply(a, b, dx_a, dy_a, dx_b, dy_b);
+ }
+
+
+ // Relate segments a and b using precalculated differences.
+ // This can save two or four subtractions in many cases
+ static inline return_type apply(segment_type1 const& a, segment_type2 const& b,
+ coordinate_type const& dx_a, coordinate_type const& dy_a,
+ coordinate_type const& dx_b, coordinate_type const& dy_b)
+ {
+ // 1) Handle "disjoint", probably common case.
+ // per dimension, 2 cases: a_1----------a_2 b_1-------b_2 or B left of A
+ coordinate_type ax_1, ax_2, bx_1, bx_2;
+ bool ax_swapped = false, bx_swapped = false;
+ detail::segment_arrange<segment_type1, 0>::apply(a, ax_1, ax_2, ax_swapped);
+ detail::segment_arrange<segment_type2, 0>::apply(b, bx_1, bx_2, bx_swapped);
+ if (ax_2 < bx_1 || ax_1 > bx_2)
+ {
+ return Policy::disjoint();
+ }
+
+ // 1b) In Y-dimension
+ coordinate_type ay_1, ay_2, by_1, by_2;
+ bool ay_swapped = false, by_swapped = false;
+ detail::segment_arrange<segment_type1, 1>::apply(a, ay_1, ay_2, ay_swapped);
+ detail::segment_arrange<segment_type2, 1>::apply(b, by_1, by_2, by_swapped);
+ if (ay_2 < ay_1 || ay_1 > by_2)
+ {
+ return Policy::disjoint();
+ }
+
+ typedef side::side_by_triangle<coordinate_type> side;
+ side_info sides;
+
+ // 2) Calculate sides
+ // Note: Do NOT yet calculate the determinant here, but use the SIDE strategy.
+ // Determinant calculation is not robust; side (orient) can be made robust
+ // (and is much robuster even without measures)
+ sides.set<1>(side::apply(a.first, a.second, b.first),
+ side::apply(a.first, a.second, b.second));
+
+ if (sides.same<1>())
+ {
+ // Both points are at same side of other segment, we can leave
+ return Policy::disjoint();
+ }
+
+ // 2b) For other segment
+ sides.set<0>(side::apply(b.first, b.second, a.first),
+ side::apply(b.first, b.second, a.second));
+
+ if (sides.same<0>())
+ {
+ return Policy::disjoint();
+ }
+
+ // Degenerate cases: segments of single point, lying on other segment, non disjoint
+ if (math::equals(dx_a, 0) && math::equals(dy_a, 0))
+ {
+ return Policy::degenerate(a, true);
+ }
+ if (math::equals(dx_b, 0) && math::equals(dy_b, 0))
+ {
+ return Policy::degenerate(b, false);
+ }
+
+ bool collinear = sides.collinear();
+
+ // Get the same type, but at least a double (also used for divisions
+ typedef typename select_most_precise
+ <
+ coordinate_type, double
+ >::type promoted_type;
+
+
+ promoted_type const d = (dy_b * dx_a) - (dx_b * dy_a);
+ // Determinant d should be nonzero.
+ // If it is zero, we have an robustness issue here,
+ // (and besides that we cannot divide by it)
+ if(math::equals(d, 0) && ! collinear)
+ //if(! collinear && sides.as_collinear())
+ {
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ std::cout << "Determinant zero? Type : "
+ << typeid(coordinate_type).name()
+ << std::endl;
+
+ std::cout << " dx_a : " << dx_a << std::endl;
+ std::cout << " dy_a : " << dy_a << std::endl;
+ std::cout << " dx_b : " << dx_b << std::endl;
+ std::cout << " dy_b : " << dy_b << std::endl;
+
+ std::cout << " side a <-> b.first : " << sides.get<0,0>() << std::endl;
+ std::cout << " side a <-> b.second: " << sides.get<0,1>() << std::endl;
+ std::cout << " side b <-> a.first : " << sides.get<1,0>() << std::endl;
+ std::cout << " side b <-> a.second: " << sides.get<1,1>() << std::endl;
+#endif
+
+ if (sides.as_collinear())
+ {
+ sides.set<0>(0,0);
+ sides.set<1>(0,0);
+ collinear = true;
+ }
+ else
+ {
+ return Policy::error("Determinant zero!");
+ }
+ }
+
+ if(collinear)
+ {
+ // Segments are collinear. We'll find out how.
+ if (math::equals(dx_b, 0))
+ {
+ // Vertical -> Check y-direction
+ return relate_collinear(a, b,
+ ay_1, ay_2, by_1, by_2,
+ ay_swapped, by_swapped);
+ }
+ else
+ {
+ // Check x-direction
+ return relate_collinear(a, b,
+ ax_1, ax_2, bx_1, bx_2,
+ ax_swapped, bx_swapped);
+ }
+ }
+
+ return Policy::segments_intersect(sides,
+ dx_a, dy_a, dx_b, dy_b,
+ a, b);
+ }
+
+private :
+
+ /// Relate segments known collinear
+ static inline return_type relate_collinear(segment_type1 const& a
+ , segment_type2 const& b
+ , coordinate_type a_1, coordinate_type a_2
+ , coordinate_type b_1, coordinate_type b_2
+ , bool a_swapped, bool b_swapped)
+ {
+ // All ca. 150 lines are about collinear rays
+ // The intersections, if any, are always boundary points of the segments. No need to calculate anything.
+ // However we want to find out HOW they intersect, there are many cases.
+ // Most sources only provide the intersection (above) or that there is a collinearity (but not the points)
+ // or some spare sources give the intersection points (calculated) but not how they align.
+ // This source tries to give everything and still be efficient.
+ // It is therefore (and because of the extensive clarification comments) rather long...
+
+ // \see http://mpa.itc.it/radim/g50history/CMP/4.2.1-CERL-beta-libes/file475.txt
+ // \see http://docs.codehaus.org/display/GEOTDOC/Point+Set+Theory+and+the+DE-9IM+Matrix
+ // \see http://mathworld.wolfram.com/Line-LineIntersection.html
+
+ // Because of collinearity the case is now one-dimensional and can be checked using intervals
+ // This function is called either horizontally or vertically
+ // We get then two intervals:
+ // a_1-------------a_2 where a_1 < a_2
+ // b_1-------------b_2 where b_1 < b_2
+ // In all figures below a_1/a_2 denotes arranged intervals, a1-a2 or a2-a1 are still unarranged
+
+ // Handle "equal", in polygon neighbourhood comparisons a common case
+
+ // Check if segments are equal...
+ bool const a1_eq_b1 = math::equals(get<0, 0>(a), get<0, 0>(b))
+ && math::equals(get<0, 1>(a), get<0, 1>(b));
+ bool const a2_eq_b2 = math::equals(get<1, 0>(a), get<1, 0>(b))
+ && math::equals(get<1, 1>(a), get<1, 1>(b));
+ if (a1_eq_b1 && a2_eq_b2)
+ {
+ return Policy::segment_equal(a, false);
+ }
+
+ // ... or opposite equal
+ bool const a1_eq_b2 = math::equals(get<0, 0>(a), get<1, 0>(b))
+ && math::equals(get<0, 1>(a), get<1, 1>(b));
+ bool const a2_eq_b1 = math::equals(get<1, 0>(a), get<0, 0>(b))
+ && math::equals(get<1, 1>(a), get<0, 1>(b));
+ if (a1_eq_b2 && a2_eq_b1)
+ {
+ return Policy::segment_equal(a, true);
+ }
+
+
+ // The rest below will return one or two intersections.
+ // The delegated class can decide which is the intersection point, or two, build the Intersection Matrix (IM)
+ // For IM it is important to know which relates to which. So this information is given,
+ // without performance penalties to intersection calculation
+
+ bool const has_common_points = a1_eq_b1 || a1_eq_b2 || a2_eq_b1 || a2_eq_b2;
+
+
+ // "Touch" -> one intersection point -> one but not two common points
+ // --------> A (or B)
+ // <---------- B (or A)
+ // a_2==b_1 (b_2==a_1 or a_2==b1)
+
+ // The check a_2/b_1 is necessary because it excludes cases like
+ // ------->
+ // --->
+ // ... which are handled lateron
+
+ // Corresponds to 4 cases, of which the equal points are determined above
+ // #1: a1---->a2 b1--->b2 (a arrives at b's border)
+ // #2: a2<----a1 b2<---b1 (b arrives at a's border)
+ // #3: a1---->a2 b2<---b1 (both arrive at each others border)
+ // #4: a2<----a1 b1--->b2 (no arrival at all)
+ // Where the arranged forms have two forms:
+ // a_1-----a_2/b_1-------b_2 or reverse (B left of A)
+ if (has_common_points && (math::equals(a_2, b_1) || math::equals(b_2, a_1)))
+ {
+ if (a2_eq_b1) return Policy::collinear_touch(get<1, 0>(a), get<1, 1>(a), 0, -1);
+ if (a1_eq_b2) return Policy::collinear_touch(get<0, 0>(a), get<0, 1>(a), -1, 0);
+ if (a2_eq_b2) return Policy::collinear_touch(get<1, 0>(a), get<1, 1>(a), 0, 0);
+ if (a1_eq_b1) return Policy::collinear_touch(get<0, 0>(a), get<0, 1>(a), -1, -1);
+ }
+
+
+ // "Touch/within" -> there are common points and also an intersection of interiors:
+ // Corresponds to many cases:
+ // #1a: a1------->a2 #1b: a1-->a2
+ // b1--->b2 b1------->b2
+ // #2a: a2<-------a1 #2b: a2<--a1
+ // b1--->b2 b1------->b2
+ // #3a: a1------->a2 #3b: a1-->a2
+ // b2<---b1 b2<-------b1
+ // #4a: a2<-------a1 #4b: a2<--a1
+ // b2<---b1 b2<-------b1
+
+ // Note: next cases are similar and handled by the code
+ // #4c: a1--->a2
+ // b1-------->b2
+ // #4d: a1-------->a2
+ // b1-->b2
+
+ // For case 1-4: a_1 < (b_1 or b_2) < a_2, two intersections are equal to segment B
+ // For case 5-8: b_1 < (a_1 or a_2) < b_2, two intersections are equal to segment A
+ if (has_common_points)
+ {
+ bool const a_in_b = (b_1 < a_1 && a_1 < b_2) || (b_1 < a_2 && a_2 < b_2);
+ int const arrival_a = a_in_b ? 1 : -1;
+ if (a2_eq_b2) return Policy::collinear_interior_boundary_intersect(a_in_b ? a : b, a_in_b, 0, 0, false);
+ if (a1_eq_b2) return Policy::collinear_interior_boundary_intersect(a_in_b ? a : b, a_in_b, arrival_a, 0, true);
+ if (a2_eq_b1) return Policy::collinear_interior_boundary_intersect(a_in_b ? a : b, a_in_b, 0, -arrival_a, true);
+ if (a1_eq_b1) return Policy::collinear_interior_boundary_intersect(a_in_b ? a : b, a_in_b, arrival_a, -arrival_a, false);
+ }
+
+ bool const opposite = a_swapped ^ b_swapped;
+
+
+ // "Inside", a completely within b or b completely within a
+ // 2 cases:
+ // case 1:
+ // a_1---a_2 -> take A's points as intersection points
+ // b_1------------b_2
+ // case 2:
+ // a_1------------a_2
+ // b_1---b_2 -> take B's points
+ if (a_1 > b_1 && a_2 < b_2)
+ {
+ // A within B
+ return Policy::collinear_a_in_b(a, opposite);
+ }
+ if (b_1 > a_1 && b_2 < a_2)
+ {
+ // B within A
+ return Policy::collinear_b_in_a(b, opposite);
+ }
+
+
+ /*
+ Now that all cases with equal,touch,inside,disjoint,
+ degenerate are handled the only thing left is an overlap
+
+ Next table gives an overview.
+ The IP's are ordered following the line A1->A2
+
+ # Layout swapped arrival info IP info
+ #1: a1--------->a2 a arrives in b (b1,a2)
+ b1----->b2 -
+ #2: a2<---------a1 a - (a1,b1)
+ b1----->b2 -
+ #3: a1--------->a2 a arrives in b (b2,a2)
+ b2<-----b1 b b arrives in a
+ #4: a2<---------a1 a - (a1,b2)
+ b2<-----b1 b b arrives in a
+
+ #5: a1--------->a2 - (a1,b2)
+ b1----->b2 b arrives in a
+ #6: a2<---------a1 a a arrives in b (b2,a2)
+ b1----->b2 b arrives in a
+ #7: a1--------->a2 - (a1,b1)
+ b2<-----b1 b -
+ #8: a2<---------a1 a a arrives in b (b1,a2)
+ b2<-----b1 b -
+ */
+
+ bool no_swap = !a_swapped && !b_swapped;
+ if (a_1 < b_1 && b_1 < a_2)
+ {
+ // # 1,2,3,4
+ return
+ no_swap ? Policy::collinear_overlaps(get<0, 0>(b), get<0, 1>(b), get<1, 0>(a), get<1, 1>(a), 1, -1, opposite)
+ : a_swapped ? Policy::collinear_overlaps(get<0, 0>(a), get<0, 1>(a), get<0, 0>(b), get<0, 1>(b), -1, -1, opposite)
+ : b_swapped ? Policy::collinear_overlaps(get<1, 0>(b), get<1, 1>(b), get<1, 0>(a), get<1, 1>(a), 1, 1, opposite)
+ : Policy::collinear_overlaps(get<0, 0>(a), get<0, 1>(a), get<1, 0>(b), get<1, 1>(b), -1, 1, opposite)
+ ;
+ }
+ if (b_1 < a_1 && a_1 < b_2)
+ {
+ // # 5, 6, 7, 8
+ return
+ no_swap ? Policy::collinear_overlaps(get<0, 0>(a), get<0, 1>(a), get<1, 0>(b), get<1, 1>(b), -1, 1, opposite)
+ : a_swapped ? Policy::collinear_overlaps(get<1, 0>(b), get<1, 1>(b), get<1, 0>(a), get<1, 1>(a), 1, 1, opposite)
+ : b_swapped ? Policy::collinear_overlaps(get<0, 0>(a), get<0, 1>(a), get<0, 0>(b), get<0, 1>(b), -1, -1, opposite)
+ : Policy::collinear_overlaps(get<0, 0>(b), get<0, 1>(b), get<1, 0>(a), get<1, 1>(a), 1, -1, opposite)
+ ;
+ }
+
+ // Nothing should goes through. If any we have made an error
+ // Robustness: it can occur here...
+ return Policy::error("Robustness issue, non-logical behaviour");
+ }
+};
+
+
+}} // namespace strategy::intersection
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP

Added: sandbox/geometry/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,238 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/strategies/centroid.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+#include <boost/geometry/util/copy.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+// Note: when calling the namespace "centroid", it sometimes,
+// somehow, in gcc, gives compilation problems (confusion with function centroid).
+
+namespace strategy { namespace centroid_ {
+
+
+
+/*!
+ \brief Centroid calculation using algorith Bashein / Detmer
+ \details Calculates centroid using triangulation method published by
+ Bashein / Detmer
+ \tparam Point point type of centroid to calculate
+ \tparam PointOfSegment point type of segments, defaults to Point
+ \par Concepts for Point and PointOfSegment:
+ - 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 PostGIS but
+ differs from MySQL
+ (tried 5.0.21 / 5.0.45 / 5.0.51a / 5.1.23).
+
+ Without holes:
+ - this: POINT(4.06923363095238 1.65055803571429)
+ - geolib: POINT(4.07254 1.66819)
+ - MySQL: POINT(3.6636363636364 1.6272727272727)'
+ - PostGIS: POINT(4.06923363095238 1.65055803571429)
+ - Oracle: 4.06923363095238 1.65055803571429
+ - SQL Server: POINT(4.06923362245959 1.65055804168294)
+
+ Statements:
+ - \b MySQL/PostGIS: 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
+ - \b SQL Server 2008: select geometry::STGeomFromText(
+ '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))',0)
+ .STCentroid()
+ .STAsText()
+
+ With holes:
+ - this: POINT(4.04663 1.6349)
+ - geolib: POINT(4.04675 1.65735)
+ - MySQL: POINT(3.6090580503834 1.607573932092)
+ - PostGIS: POINT(4.0466265060241 1.63489959839357)
+ - Oracle: 4.0466265060241 1.63489959839357
+ - SQL Server: POINT(4.0466264962959677 1.6348996057331333)
+
+ Statements:
+ - \b MySQL/PostGIS: 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 Point,
+ typename PointOfSegment = Point,
+ typename CalculationType = void
+>
+class bashein_detmer
+{
+private :
+ // If user specified a calculation type, use that type,
+ // whatever it is and whatever the point-type(s) are.
+ // Else, use the most appropriate coordinate type
+ // of the two points, but at least double
+ typedef typename
+ boost::mpl::if_c
+ <
+ boost::is_void<CalculationType>::type::value,
+ typename select_most_precise
+ <
+ typename select_coordinate_type
+ <
+ Point,
+ PointOfSegment
+ >::type,
+ double
+ >::type,
+ CalculationType
+ >::type calculation_type;
+
+ /*! subclass to keep state */
+ class sums
+ {
+ friend class bashein_detmer;
+ int count;
+ calculation_type sum_a2;
+ calculation_type sum_x;
+ calculation_type sum_y;
+
+ public :
+ inline sums()
+ : count(0)
+ , sum_a2(calculation_type())
+ , sum_x(calculation_type())
+ , sum_y(calculation_type())
+ {
+ typedef calculation_type ct;
+ //std::cout << "-> calctype: " << typeid(ct).name()
+ // << " size: " << sizeof(ct)
+ // << " init: " << sum_a2
+ // << std::endl;
+ }
+ };
+
+public :
+ typedef sums state_type;
+ typedef Point point_type;
+ typedef PointOfSegment segment_point_type;
+
+ static inline void apply(PointOfSegment const& p1,
+ PointOfSegment const& p2, sums& state)
+ {
+ /* 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) )
+ */
+
+ // Get coordinates and promote them to calculation_type
+ calculation_type const x1 = boost::numeric_cast<calculation_type>(get<0>(p1));
+ calculation_type const y1 = boost::numeric_cast<calculation_type>(get<1>(p1));
+ calculation_type const x2 = boost::numeric_cast<calculation_type>(get<0>(p2));
+ calculation_type const y2 = boost::numeric_cast<calculation_type>(get<1>(p2));
+ calculation_type const ai = x1 * y2 - x2 * y1;
+ state.count++;
+ state.sum_a2 += ai;
+ state.sum_x += ai * (x1 + x2);
+ state.sum_y += ai * (y1 + y2);
+ }
+
+ static inline bool result(sums const& state, Point& centroid)
+ {
+ if (state.count > 0 && state.sum_a2 != 0)
+ {
+ calculation_type const v3 = 3;
+ calculation_type const a3 = v3 * state.sum_a2;
+
+ typedef typename geometry::coordinate_type
+ <
+ Point
+ >::type coordinate_type;
+
+ set<0>(centroid,
+ boost::numeric_cast<coordinate_type>(state.sum_x / a3));
+ set<1>(centroid,
+ boost::numeric_cast<coordinate_type>(state.sum_y / a3));
+ return true;
+ }
+
+ return false;
+ }
+
+};
+
+
+}} // namespace strategy::centroid
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+// Register this strategy for rings and polygons, in two dimensions
+template <typename Point, typename Geometry>
+struct strategy_centroid<cartesian_tag, ring_tag, 2, Point, Geometry>
+{
+ typedef strategy::centroid_::bashein_detmer
+ <
+ Point,
+ typename point_type<Geometry>::type
+ > type;
+};
+
+template <typename Point, typename Geometry>
+struct strategy_centroid<cartesian_tag, polygon_tag, 2, Point, Geometry>
+{
+ typedef strategy::centroid_::bashein_detmer
+ <
+ Point,
+ typename point_type<Geometry>::type
+ > type;
+};
+
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP

Added: sandbox/geometry/boost/geometry/strategies/cartesian/distance_projected_point.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/cartesian/distance_projected_point.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,168 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/arithmetic/dot_product.hpp>
+
+#include <boost/geometry/strategies/tags.hpp>
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/distance_result.hpp>
+#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
+
+#include <boost/geometry/util/select_coordinate_type.hpp>
+#include <boost/geometry/util/copy.hpp>
+
+
+// Helper geometry
+#include <boost/geometry/geometries/segment.hpp>
+
+namespace boost { namespace geometry {
+
+namespace strategy { namespace distance {
+
+
+
+/*!
+ \brief Strategy for distance point to segment
+ \ingroup distance
+ \details Calculates distance using projected-point method, and (optionally) Pythagoras
+ \author Adapted from: http://geometryalgorithms.com/Archive/algorithm_0102/algorithm_0102.htm
+ \tparam P point type
+ \tparam PointOfSegment segment type
+ \tparam Strategy strategy, optional, defaults to pythagoras
+ \par Concepts for Strategy:
+ - cartesian_distance operator(Point,Point)
+*/
+template
+<
+ typename Point,
+ typename PointOfSegment,
+ typename Strategy = pythagoras
+ <
+ Point,
+ typename point_type<PointOfSegment>::type
+ >
+>
+struct projected_point
+{
+ typedef Point point_type;
+ typedef PointOfSegment segment_point_type;
+ typedef typename select_coordinate_type
+ <
+ Point,
+ PointOfSegment
+ >::type coordinate_type;
+ typedef cartesian_distance<coordinate_type> return_type;
+
+ typedef Strategy point_strategy_type;
+
+
+ inline return_type apply(Point const& p,
+ PointOfSegment const& p1, PointOfSegment const& p2) const
+ {
+ assert_dimension_equal<Point, PointOfSegment>();
+
+ /* 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);
+ */
+
+
+ // Take here the first point type. It should have a default constructor.
+ // That is not required for the second point type.
+ Point v, w;
+
+ copy_coordinates(p2, v);
+ copy_coordinates(p, w);
+ subtract_point(v, p1);
+ subtract_point(w, p1);
+
+ Strategy strategy;
+
+ coordinate_type c1 = dot_product(w, v);
+ if (c1 <= 0)
+ {
+ return strategy.apply(p, p1);
+ }
+ coordinate_type c2 = dot_product(v, v);
+ if (c2 <= c1)
+ {
+ return strategy.apply(p, p2);
+ }
+
+ // Even in case of char's, we have to turn to a point<double/float>
+ // because of the division.
+ typedef typename geometry::select_most_precise<coordinate_type, double>::type divisor_type;
+ divisor_type b = c1 / c2;
+
+ // Note that distances with integer coordinates do NOT work because
+ // - the project point is integer
+ // - if we solve that, the used distance_strategy cannot handle double points
+ PointOfSegment projected;
+ copy_coordinates(p1, projected);
+ multiply_value(v, b);
+ add_point(projected, v);
+
+ return strategy.apply(p, projected);
+
+ }
+
+};
+
+}} // namespace strategy::distance
+
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+template <typename Point, typename PointOfSegment>
+struct strategy_distance_segment<cartesian_tag, cartesian_tag, Point, PointOfSegment>
+{
+ typedef typename point_type<PointOfSegment>::type segment_point_type;
+
+ typedef strategy::distance::projected_point
+ <
+ Point,
+ PointOfSegment,
+ typename strategy_distance
+ <
+ cartesian_tag, cartesian_tag, Point, segment_point_type
+ >::type
+ > type;
+};
+#endif
+
+
+template <typename Point, typename PointOfSegment, typename PPStrategy>
+struct strategy_tag<strategy::distance::projected_point<Point, PointOfSegment, PPStrategy> >
+{
+ typedef strategy_tag_distance_point_segment type;
+};
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP

Added: sandbox/geometry/boost/geometry/strategies/cartesian/distance_pythagoras.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/cartesian/distance_pythagoras.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,130 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/access.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/distance_result.hpp>
+
+#include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/util/copy.hpp>
+
+
+
+namespace boost { namespace geometry {
+
+namespace strategy { namespace distance {
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Point1, typename Point2, size_t I, typename T>
+struct compute_pythagoras
+{
+ static inline T apply(Point1 const& p1, Point2 const& p2)
+ {
+ T const c1 = boost::numeric_cast<T>(get<I-1>(p2));
+ T const c2 = boost::numeric_cast<T>(get<I-1>(p1));
+ T const d = c1 - c2;
+ return d * d + compute_pythagoras<Point1, Point2, I-1, T>::apply(p1, p2);
+ }
+};
+
+template <typename Point1, typename Point2, typename T>
+struct compute_pythagoras<Point1, Point2, 0, T>
+{
+ static inline T apply(Point1 const&, Point2 const&)
+ {
+ return boost::numeric_cast<T>(0);
+ }
+};
+
+}
+#endif // DOXYGEN_NO_DETAIL
+
+/*!
+ \brief Strategy for distance point to point: pythagoras
+ \ingroup distance
+ \tparam Point1 first point type
+ \tparam Point2 optional, second point type, defaults to first point type
+ \par Concepts for Point1 and Point2:
+ - specialized point_traits class
+*/
+template
+<
+ typename Point1,
+ typename Point2 = Point1,
+ typename CalculationType = void
+>
+struct pythagoras
+{
+ typedef typename select_calculation_type
+ <
+ Point1,
+ Point2,
+ CalculationType
+ >::type calculation_type;
+
+ typedef Point1 first_point_type;
+ typedef Point2 second_point_type;
+ typedef cartesian_distance<calculation_type> return_type;
+
+ inline return_type apply(Point1 const& p1, Point2 const& p2) const
+ {
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point1>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
+
+ // Calculate distance using Pythagoras
+ // (Leave comment above for Doxygen)
+
+ assert_dimension_equal<Point1, Point2>();
+
+ return return_type(detail::compute_pythagoras
+ <
+ Point1, Point2,
+ dimension<Point1>::value,
+ calculation_type
+ >::apply(p1, p2));
+ }
+};
+
+
+}} // namespace strategy::distance
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename Point1, typename Point2>
+struct strategy_distance<cartesian_tag, cartesian_tag, Point1, Point2>
+{
+ typedef strategy::distance::pythagoras<Point1, Point2> type;
+};
+
+
+#endif
+
+
+template <typename Point1, typename Point2>
+struct strategy_tag<strategy::distance::pythagoras<Point1, Point2> >
+{
+ typedef strategy_tag_distance_point_point type;
+};
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP

Added: sandbox/geometry/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,109 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP
+
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+
+namespace boost { namespace geometry
+
+{
+namespace strategy { namespace within {
+
+/*!
+ \brief Within detection using cross counting,
+ \see http://tog.acm.org/resources/GraphicsGems/gemsiv/ptpoly_haines/ptinpoly.c
+ \note Does NOT work correctly for point ON border
+ */
+
+template
+<
+ typename Point,
+ typename PointOfSegment = Point,
+ typename CalculationType = void
+>
+class crossings_multiply
+{
+ typedef typename select_calculation_type
+ <
+ Point,
+ PointOfSegment,
+ CalculationType
+ >::type calculation_type;
+
+ class flags
+ {
+ bool inside_flag;
+ bool first;
+ bool yflag0;
+
+ public :
+
+ friend class crossings_multiply;
+
+ inline flags()
+ : inside_flag(false)
+ , first(true)
+ , yflag0(false)
+ {}
+ };
+
+public :
+
+ typedef Point point_type;
+ typedef PointOfSegment segment_point_type;
+ typedef flags state_type;
+
+ static inline bool apply(Point const& point,
+ PointOfSegment const& seg1, PointOfSegment const& seg2,
+ flags& state)
+ {
+ calculation_type const tx = get<0>(point);
+ calculation_type const ty = get<1>(point);
+ calculation_type const x0 = get<0>(seg1);
+ calculation_type const y0 = get<1>(seg1);
+ calculation_type const x1 = get<0>(seg2);
+ calculation_type const y1 = get<1>(seg2);
+
+ if (state.first)
+ {
+ state.first = false;
+ state.yflag0 = y0 >= ty;
+ }
+
+
+ bool yflag1 = y1 >= ty;
+ if (state.yflag0 != yflag1)
+ {
+ if ( ((y1-ty) * (x0-x1) >= (x1-tx) * (y0-y1)) == yflag1 )
+ {
+ state.inside_flag = ! state.inside_flag;
+ }
+ }
+ state.yflag0 = yflag1;
+ return true;
+ }
+
+ static inline bool result(flags const& state)
+ {
+ return state.inside_flag;
+ }
+};
+
+
+
+}} // namespace strategy::within
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP

Added: sandbox/geometry/boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,104 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP
+
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+
+namespace boost { namespace geometry
+
+{
+namespace strategy { 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 Point,
+ typename PointOfSegment = Point,
+ typename CalculationType = void
+>
+class franklin
+{
+ typedef typename select_calculation_type
+ <
+ Point,
+ PointOfSegment,
+ CalculationType
+ >::type calculation_type;
+
+ /*! subclass to keep state */
+ class crossings
+ {
+ bool crosses;
+
+ public :
+
+ friend class franklin;
+ inline crossings()
+ : crosses(false)
+ {}
+ };
+
+public :
+
+ typedef Point point_type;
+ typedef PointOfSegment segment_point_type;
+ typedef crossings state_type;
+
+ static inline bool apply(Point const& point,
+ PointOfSegment const& seg1, PointOfSegment const& seg2,
+ crossings& state)
+ {
+ calculation_type const& px = get<0>(point);
+ calculation_type const& py = get<1>(point);
+ calculation_type const& x1 = get<0>(seg1);
+ calculation_type const& y1 = get<1>(seg1);
+ calculation_type const& x2 = get<0>(seg2);
+ calculation_type const& y2 = get<1>(seg2);
+
+ if (
+ ( (y2 <= py && py < y1) || (y1 <= py && py < y2) )
+ && (px < (x1 - x2) * (py - y2) / (y1 - y2) + x2)
+ )
+ {
+ state.crosses = ! state.crosses;
+ }
+ return true;
+ }
+
+ static inline bool result(crossings const& state)
+ {
+ return state.crosses;
+ }
+};
+
+
+
+}} // namespace strategy::within
+
+
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP

Added: sandbox/geometry/boost/geometry/strategies/cartesian/side_by_triangle.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/cartesian/side_by_triangle.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,103 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/access.hpp>
+
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+namespace strategy
+{
+ namespace side
+ {
+
+ // 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 CalculationType>
+ struct side_by_triangle
+ {
+
+ // Template member function, because it is not always trivial
+ // or convenient to explicitly mention the typenames in the
+ // strategy-struct itself.
+
+ // Types can be all three different. Therefore it is
+ // not implemented (anymore) as "segment"
+
+ template <typename P1, typename P2, typename P>
+ static inline int apply(P1 const& p1, P2 const& p2, P const& p)
+ {
+ typedef typename boost::mpl::if_c
+ <
+ boost::is_void<CalculationType>::type::value,
+ typename select_most_precise
+ <
+ typename select_most_precise
+ <
+ typename coordinate_type<P1>::type,
+ typename coordinate_type<P2>::type
+ >::type,
+ typename coordinate_type<P>::type
+ >::type,
+ CalculationType
+ >::type coordinate_type;
+
+//std::cout << "side: " << typeid(coordinate_type).name() << std::endl;
+ coordinate_type const x = get<0>(p);
+ coordinate_type const y = get<1>(p);
+
+ coordinate_type const sx1 = get<0>(p1);
+ coordinate_type const sy1 = get<1>(p1);
+ coordinate_type const sx2 = get<0>(p2);
+ coordinate_type const sy2 = get<1>(p2);
+
+ // Promote float->double, small int->int
+ typedef typename select_most_precise
+ <
+ coordinate_type,
+ double
+ >::type promoted_type;
+
+ promoted_type const dx = sx2 - sx1;
+ promoted_type const dy = sy2 - sy1;
+ promoted_type const dpx = x - sx1;
+ promoted_type const dpy = y - sy1;
+
+ promoted_type const s = dx * dpy - dy * dpx;
+
+ return math::equals(s, 0) ? 0 : s > 0 ? 1 : -1;
+ //return s > 0 ? 1 : s < 0 ? -1 : 0;
+ }
+ };
+
+ } // namespace side
+} // namespace strategy
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename CalculationType>
+struct strategy_side<cartesian_tag, CalculationType>
+{
+ typedef strategy::side::side_by_triangle<CalculationType> type;
+};
+#endif
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP

Added: sandbox/geometry/boost/geometry/strategies/centroid.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/centroid.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,45 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CENTROID_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CENTROID_HPP
+
+
+#include <boost/geometry/strategies/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Traits class binding a centroid calculation strategy to a coordinate system
+ \ingroup centroid
+ \tparam CsTag tag of coordinate system, for specialization
+ \tparam GeometryTag tag of geometry, for specialization
+ \tparam Dimension dimension of geometry, for specialization
+ \tparam Point point-type
+ \tparam Geometry
+*/
+template
+<
+ typename CsTag,
+ typename GeometryTag,
+ std::size_t Dimension,
+ typename Point,
+ typename Geometry
+>
+struct strategy_centroid
+{
+ typedef strategy::not_implemented type;
+};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CENTROID_HPP

Added: sandbox/geometry/boost/geometry/strategies/compare.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/compare.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,163 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 1995-2009, Geodan,. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_COMPARE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_COMPARE_HPP
+
+#include <cstddef>
+#include <functional>
+
+#include <boost/mpl/if.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+
+#include <boost/geometry/strategies/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Traits class binding a comparing strategy to a coordinate system
+ \ingroup util
+ \tparam Tag tag of coordinate system of point-type
+ \tparam Direction direction to compare on: 1 for less (-> ascending order)
+ and -1 for greater (-> descending order)
+ \tparam Point point-type
+ \tparam CoordinateSystem coordinate sytem of point
+ \tparam Dimension: the dimension to compare on
+*/
+template
+<
+ typename Tag,
+ int Direction,
+ typename Point,
+ typename CoordinateSystem,
+ std::size_t Dimension
+>
+struct strategy_compare
+{
+ typedef strategy::not_implemented type;
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+// For compare we add defaults specializations,
+// because they defaultly redirect to std::less / greater / equal_to
+template
+<
+ typename Tag,
+ typename Point,
+ typename CoordinateSystem,
+ std::size_t Dimension
+>
+struct strategy_compare<Tag, 1, Point, CoordinateSystem, Dimension>
+{
+ typedef std::less<typename coordinate_type<Point>::type> type;
+};
+
+
+template
+<
+ typename Tag,
+ typename Point,
+ typename CoordinateSystem,
+ std::size_t Dimension
+>
+struct strategy_compare<Tag, -1, Point, CoordinateSystem, Dimension>
+{
+ typedef std::greater<typename coordinate_type<Point>::type> type;
+};
+
+
+template
+<
+ typename Tag,
+ typename Point,
+ typename CoordinateSystem,
+ std::size_t Dimension
+>
+struct strategy_compare<Tag, 0, Point, CoordinateSystem, Dimension>
+{
+ typedef std::equal_to<typename coordinate_type<Point>::type> type;
+};
+
+
+#endif
+
+
+namespace strategy { namespace compare {
+
+
+/*!
+ \brief Default strategy, indicates the default strategy for comparisons
+ \details The default strategy for comparisons defer in most cases
+ to std::less (for ascending) and std::greater (for descending).
+ However, if a spherical coordinate system is used, and comparison
+ is done on longitude, it will take another strategy handling circular
+*/
+struct default_strategy {};
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail {
+
+template <typename Type>
+struct is_default : boost::false_type
+{};
+
+
+template <>
+struct is_default<default_strategy> : boost::true_type
+{};
+
+
+/*!
+ \brief Meta-function to select strategy
+ \details If "default_strategy" is specified, it will take the
+ traits-registered class for the specified coordinate system.
+ If another strategy is explicitly specified, it takes that one.
+*/
+template
+<
+ typename Strategy,
+ int Direction,
+ typename Point,
+ std::size_t Dimension
+>
+struct select_strategy
+{
+ typedef typename
+ boost::mpl::if_
+ <
+ is_default<Strategy>,
+ typename strategy_compare
+ <
+ typename cs_tag<Point>::type,
+ Direction,
+ Point,
+ typename coordinate_system<Point>::type,
+ Dimension
+ >::type,
+ Strategy
+ >::type type;
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace strategy::compare
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_COMPARE_HPP

Added: sandbox/geometry/boost/geometry/strategies/concepts/area_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/concepts/area_concept.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,69 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_AREA_CONCEPT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_AREA_CONCEPT_HPP
+
+
+
+#include <boost/concept_check.hpp>
+
+
+namespace boost { namespace geometry { namespace concept {
+
+
+/*!
+ \brief Checks strategy for area
+ \ingroup area
+*/
+template <typename Strategy>
+class AreaStrategy
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ // 1) must define state_type,
+ typedef typename Strategy::state_type state_type;
+
+ // 2) must define return_type,
+ typedef typename Strategy::return_type return_type;
+
+ // 3) must define point_type, of polygon (segments)
+ typedef typename Strategy::segment_point_type spoint_type;
+
+ struct check_methods
+ {
+ static void apply()
+ {
+ Strategy const* str;
+ state_type *st;
+
+ // 4) must implement a method apply with the following signature
+ spoint_type const* sp;
+ str->apply(*sp, *sp, *st);
+
+ // 5) must implement a static method result with the following signature
+ return_type r = str->result(*st);
+
+ boost::ignore_unused_variable_warning(r);
+ boost::ignore_unused_variable_warning(str);
+ }
+ };
+
+public :
+ BOOST_CONCEPT_USAGE(AreaStrategy)
+ {
+ check_methods::apply();
+ }
+
+#endif
+};
+
+
+
+}}} // namespace boost::geometry::concept
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_AREA_CONCEPT_HPP

Added: sandbox/geometry/boost/geometry/strategies/concepts/centroid_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/concepts/centroid_concept.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,71 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CENTROID_CONCEPT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CENTROID_CONCEPT_HPP
+
+
+
+#include <boost/concept_check.hpp>
+
+
+namespace boost { namespace geometry { namespace concept {
+
+
+/*!
+ \brief Checks strategy for centroid
+ \ingroup centroid
+*/
+template <typename Strategy>
+class CentroidStrategy
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ // 1) must define state_type,
+ typedef typename Strategy::state_type state_type;
+
+ // 2) must define point_type,
+ typedef typename Strategy::point_type point_type;
+
+ // 3) must define point_type, of polygon (segments)
+ typedef typename Strategy::segment_point_type spoint_type;
+
+ struct check_methods
+ {
+ static void apply()
+ {
+ Strategy *str;
+ state_type *st;
+
+ // 4) must implement a static method apply,
+ // getting two segment-points
+ spoint_type const* sp;
+ str->apply(*sp, *sp, *st);
+
+ // 5) must implement a static method result
+ // getting the centroid
+ point_type *c;
+ bool r = str->result(*st, *c);
+
+ boost::ignore_unused_variable_warning(str);
+ boost::ignore_unused_variable_warning(r);
+ }
+ };
+
+public :
+ BOOST_CONCEPT_USAGE(CentroidStrategy)
+ {
+ check_methods::apply();
+ }
+#endif
+};
+
+
+
+}}} // namespace boost::geometry::concept
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CENTROID_CONCEPT_HPP

Added: sandbox/geometry/boost/geometry/strategies/concepts/convex_hull_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/concepts/convex_hull_concept.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,68 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CONVEX_HULL_CONCEPT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CONVEX_HULL_CONCEPT_HPP
+
+
+#include <vector>
+
+#include <boost/concept_check.hpp>
+
+
+namespace boost { namespace geometry { namespace concept {
+
+
+/*!
+ \brief Checks strategy for convex_hull
+ \ingroup convex_hull
+*/
+template <typename Strategy>
+class ConvexHullStrategy
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ // 1) must define state_type
+ typedef typename Strategy::state_type state_type;
+
+ // 2) must define point_type
+ typedef typename Strategy::point_type point_type;
+
+ // 3) must define geometry_type
+ typedef typename Strategy::geometry_type geometry_type;
+
+ struct check_methods
+ {
+ static void apply()
+ {
+ Strategy const* str;
+
+ state_type* st;
+ geometry_type* sp;
+ std::vector<point_type> *v;
+
+ // 4) must implement a method apply, iterating over a range
+ str->apply(*sp, *st);
+
+ // 5) must implement a method result, with an output iterator
+ str->result(*st, std::back_inserter(*v), true);
+ }
+ };
+
+public :
+ BOOST_CONCEPT_USAGE(ConvexHullStrategy)
+ {
+ check_methods::apply();
+ }
+#endif
+};
+
+
+
+}}} // namespace boost::geometry::concept
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CONVEX_HULL_CONCEPT_HPP

Added: sandbox/geometry/boost/geometry/strategies/concepts/distance_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/concepts/distance_concept.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,138 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP
+
+#include <vector>
+#include <iterator>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/geometries/segment.hpp>
+
+
+namespace boost { namespace geometry { namespace concept {
+
+
+/*!
+ \brief Checks strategy for point-segment-distance
+ \ingroup distance
+*/
+template <typename Strategy>
+struct PointDistanceStrategy
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ private :
+
+ // 1) must define first_point_type
+ typedef typename Strategy::first_point_type ptype1;
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::ConstPoint<ptype1>)
+ );
+
+ // 2) must define second_point_type
+ typedef typename Strategy::second_point_type ptype2;
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::ConstPoint<ptype2>)
+ );
+
+ // 3) must define return_type
+ typedef typename Strategy::return_type rtype;
+
+ // 4) must implement apply with arguments
+ struct apply_checker
+ {
+ static void check()
+ {
+ Strategy* str;
+ ptype1 *p1;
+ ptype2 *p2;
+ rtype r = str->apply(*p1, *p2);
+
+ boost::ignore_unused_variable_warning(str);
+ boost::ignore_unused_variable_warning(r);
+ }
+ };
+
+ public :
+ BOOST_CONCEPT_USAGE(PointDistanceStrategy)
+ {
+ apply_checker::check();
+ }
+#endif
+};
+
+
+/*!
+ \brief Checks strategy for point-segment-distance
+ \ingroup strategy_concepts
+*/
+template <typename Strategy>
+struct PointSegmentDistanceStrategy
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ private :
+
+ // 1) must define point_type
+ typedef typename Strategy::point_type ptype;
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::ConstPoint<ptype>)
+ );
+
+ // 2) must define segment_point_type
+ typedef typename Strategy::segment_point_type sptype;
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::ConstPoint<sptype>)
+ );
+
+ // 3) must define return_type
+ typedef typename Strategy::return_type rtype;
+
+ // 4) must define underlying point-distance-strategy
+ typedef typename Strategy::point_strategy_type stype;
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::PointDistanceStrategy<stype>)
+ );
+
+
+ // 5) must implement method apply with arguments
+ struct apply_checker
+ {
+ static void check()
+ {
+ Strategy *str;
+ ptype *p;
+ sptype *sp1;
+ sptype *sp2;
+
+ rtype r = str->apply(*p, *sp1, *sp2);
+
+ boost::ignore_unused_variable_warning(str);
+ boost::ignore_unused_variable_warning(r);
+ }
+ };
+
+ public :
+ BOOST_CONCEPT_USAGE(PointSegmentDistanceStrategy)
+ {
+ apply_checker::check();
+ }
+#endif
+};
+
+
+
+}}} // namespace boost::geometry::concept
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP

Added: sandbox/geometry/boost/geometry/strategies/concepts/segment_intersect_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/concepts/segment_intersect_concept.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,71 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SEGMENT_INTERSECT_CONCEPT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SEGMENT_INTERSECT_CONCEPT_HPP
+
+
+//NOT FINISHED!
+
+#include <boost/concept_check.hpp>
+
+
+namespace boost { namespace geometry { namespace concept {
+
+
+/*!
+ \brief Checks strategy for segment intersection
+ \ingroup segment_intersection
+*/
+template <typename Strategy>
+class SegmentIntersectStrategy
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ // 1) must define return_type
+ typedef typename Strategy::return_type return_type;
+
+ // 2) must define point_type (of segment points)
+ //typedef typename Strategy::point_type point_type;
+
+ // 3) must define segment_type 1 and 2 (of segment points)
+ typedef typename Strategy::segment_type1 segment_type1;
+ typedef typename Strategy::segment_type2 segment_type2;
+
+
+ struct check_methods
+ {
+ static void apply()
+ {
+ Strategy const* str;
+
+ return_type* rt;
+ //point_type const* p;
+ segment_type1 const* s1;
+ segment_type2 const* s2;
+
+ // 4) must implement a method apply
+ // having two segments
+ *rt = str->apply(*s1, *s2);
+
+ }
+ };
+
+
+public :
+ BOOST_CONCEPT_USAGE(SegmentIntersectStrategy)
+ {
+ check_methods::apply();
+ }
+#endif
+};
+
+
+
+}}} // namespace boost::geometry::concept
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SEGMENT_INTERSECT_CONCEPT_HPP

Added: sandbox/geometry/boost/geometry/strategies/concepts/simplify_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/concepts/simplify_concept.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,72 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SIMPLIFY_CONCEPT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SIMPLIFY_CONCEPT_HPP
+
+#include <vector>
+#include <iterator>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/geometry/strategies/concepts/distance_concept.hpp>
+
+
+namespace boost { namespace geometry { namespace concept {
+
+
+/*!
+ \brief Checks strategy for simplify
+ \ingroup simplify
+*/
+template <typename Strategy>
+struct SimplifyStrategy
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ private :
+
+ // 1) must define distance_strategy_type,
+ // defining point-segment distance strategy (to be checked)
+ typedef typename Strategy::distance_strategy_type ds_type;
+
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::PointSegmentDistanceStrategy<ds_type>)
+ );
+
+ struct apply_checker
+ {
+ static void check()
+ {
+ Strategy *str;
+ std::vector<typename ds_type::point_type> const* v1;
+ std::vector<typename ds_type::point_type> * v2;
+
+ // 2) must implement method apply with arguments
+ // - Range
+ // - OutputIterator
+ // - floating point value
+ str->apply(*v1, std::back_inserter(*v2), 1.0);
+
+ boost::ignore_unused_variable_warning(str);
+ }
+ };
+
+ public :
+ BOOST_CONCEPT_USAGE(SimplifyStrategy)
+ {
+ apply_checker::check();
+
+ }
+#endif
+};
+
+
+
+}}} // namespace boost::geometry::concept
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SIMPLIFY_CONCEPT_HPP

Added: sandbox/geometry/boost/geometry/strategies/concepts/within_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/concepts/within_concept.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,73 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP
+
+
+
+#include <boost/concept_check.hpp>
+
+
+namespace boost { namespace geometry { namespace concept {
+
+
+/*!
+ \brief Checks strategy for within (point-in-polygon)
+ \ingroup within
+*/
+template <typename Strategy>
+class WithinStrategy
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ // 1) must define state_type,
+ typedef typename Strategy::state_type state_type;
+
+ // 2) must define point_type (of "point" in poly)
+ typedef typename Strategy::point_type point_type;
+
+ // 3) must define point_type, of polygon (segments)
+ typedef typename Strategy::segment_point_type spoint_type;
+
+
+ struct check_methods
+ {
+ static void apply()
+ {
+ Strategy const* str;
+
+ state_type* st;
+ point_type const* p;
+ spoint_type const* sp;
+
+ // 4) must implement a method apply
+ // having a point, two segment-points, and state
+ str->apply(*p, *sp, *sp, *st);
+
+ // 5) must implement a method result
+ bool r = str->result(*st);
+
+ boost::ignore_unused_variable_warning(r);
+ boost::ignore_unused_variable_warning(str);
+ }
+ };
+
+
+public :
+ BOOST_CONCEPT_USAGE(WithinStrategy)
+ {
+ check_methods::apply();
+ }
+#endif
+};
+
+
+
+}}} // namespace boost::geometry::concept
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP

Added: sandbox/geometry/boost/geometry/strategies/convex_hull.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/convex_hull.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,37 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP
+
+#include <boost/geometry/strategies/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+
+
+/*!
+ \brief Traits class binding a convex hull calculation strategy to a coordinate system
+ \ingroup convex_hull
+ \tparam Tag tag of coordinate system
+ \tparam Geometry the geometry type (hull operates internally per hull over geometry)
+ \tparam Point point-type of output points
+*/
+template <typename Tag, typename Geometry, typename Point>
+struct strategy_convex_hull
+{
+ typedef strategy::not_implemented type;
+};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP

Added: sandbox/geometry/boost/geometry/strategies/distance.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/distance.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,53 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_DISTANCE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_DISTANCE_HPP
+
+
+#include <boost/geometry/strategies/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Traits class binding a distance strategy to a (possibly two) coordinate system(s)
+ \ingroup distance
+ \tparam T1 tag of coordinate system of first point type
+ \tparam T2 tag of coordinate system of second point type
+ \tparam P1 first point-type
+ \tparam P2 second point-type
+*/
+template <typename T1, typename T2, typename P1, typename P2>
+struct strategy_distance
+{
+ typedef strategy::not_implemented type;
+};
+
+/*!
+ \brief Traits class binding a distance-to-segment strategy to a (possibly two) coordinate system(s)
+ \ingroup distance
+ \tparam CsTag1 tag of coordinate system of point type
+ \tparam CsTag2 tag of coordinate system of segment type, usually same as CsTag1
+ \tparam Point point-type
+ \tparam Segment segment-type
+*/
+template <typename CsTag1, typename CsTag2, typename Point, typename Segment>
+struct strategy_distance_segment
+{
+ typedef strategy::not_implemented type;
+};
+
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_DISTANCE_HPP

Added: sandbox/geometry/boost/geometry/strategies/distance_result.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/distance_result.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,333 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_DISTANCE_RESULT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_DISTANCE_RESULT_HPP
+
+#include <utility>
+#include <cmath>
+#include <limits>
+
+#include <boost/mpl/if.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+namespace boost { namespace geometry {
+
+/*!
+ \brief Encapsulate the results of distance calculation
+ \ingroup distance
+ \details Distance calculation for xy points or xyz points is done by taking the square
+ root. However, for distance comparison drawing the square root is not necessary.
+ Therefore the distance strategies are allowed to return the squares of the distance.
+ This structure contains the distance, and a boolean to indicate if it is squared.
+ It has an automatic conversion to a double value, which does the square root if necessary.
+ \note Thanks to Phil Endecott for his suggestion to change the pair to the double-convertable
+ http://article.gmane.org/gmane.comp.lib.boost.devel/172709/match=greatcircle_distance
+*/
+template<typename T = double>
+struct cartesian_distance
+{
+ private :
+ T m_squared_distance;
+
+ // Because result is square-rooted, for integer, the cast should
+ // go to double and NOT to T
+ typedef typename
+ boost::mpl::if_c
+ <
+ boost::is_integral<T>::type::value,
+ double,
+ T
+ >::type cast_type;
+
+
+
+
+ public :
+
+
+ /// Constructor with a value
+ explicit cartesian_distance(T const& v) : m_squared_distance(v) {}
+
+ /// Automatic conversion to double or higher precision,
+ /// taking squareroot if necessary
+ inline operator cast_type() const
+ {
+ return boost::numeric_cast<cast_type>
+ (
+#if defined(NUMERIC_ADAPTOR_INCLUDED)
+ boost::sqrt(
+#else
+ std::sqrt(
+#endif
+ boost::numeric_cast
+ <
+ typename select_most_precise<cast_type, double>::type
+ >(m_squared_distance)
+ )
+ );
+ }
+
+ // Compare squared values
+ inline bool operator<(cartesian_distance<T> const& other) const
+ {
+ return this->m_squared_distance < other.m_squared_distance;
+ }
+ inline bool operator>(cartesian_distance<T> const& other) const
+ {
+ return this->m_squared_distance > other.m_squared_distance;
+ }
+ inline bool operator==(cartesian_distance<T> const& other) const
+ {
+ return math::equals(this->m_squared_distance, other.m_squared_distance);
+ }
+
+ // Compare just with a corresponding POD value
+ // Note: this is NOT possible because of the cast to double,
+ // it makes it for the compiler ambiguous which to take
+ /*
+ inline bool operator<(T const& value) const
+ {
+ return this->m_squared_distance < (value * value);
+ }
+ inline bool operator>(T const& value) const
+ {
+ return this->m_squared_distance > (value * value);
+ }
+ inline bool operator==(T const& value) const
+ {
+ return this->m_squared_distance == (value * value);
+ }
+ */
+
+ // Utility method to compare without SQRT, but not with method above because for epsilon that
+ // makes no sense...
+ inline bool very_small() const
+ {
+ return m_squared_distance <= std::numeric_limits<T>::epsilon();
+ }
+
+ /// The "squared_value" method returns the internal squared value
+ inline T squared_value() const
+ {
+ return m_squared_distance;
+ }
+
+ /// Make streamable to enable std::cout << geometry::distance( )
+ template <typename Char, typename Traits>
+ inline friend std::basic_ostream<Char, Traits>&
+ operator<<(std::basic_ostream<Char, Traits>& os,
+ cartesian_distance<T> const& d)
+ {
+ // Avoid "ambiguous function call" for MSVC
+ cast_type const sq = d.m_squared_distance;
+
+ os <<
+#if defined(NUMERIC_ADAPTOR_INCLUDED)
+ boost::sqrt(sq);
+#else
+ std::sqrt(sq);
+#endif
+ return os;
+ }
+
+};
+
+
+
+/*
+
+ From Phil Endecott, on the list:
+
+ You can go further. If I'm searching through a long list of points to
+ find the closest to P then I'll avoid the squaring (and conversion to
+ double if my co-ordinates are integers) whenever possible. You can
+ achieve this with a more complex distance proxy:
+
+ class distance_proxy {
+ double dx;
+ double dy;
+ distance_proxy(double dx_, double dy_): dx(dx_), dy(dy_) {}
+ friend pythag_distance(point,point);
+ public:
+ operator double() { return sqrt(dx*dx+dy*dy); }
+ bool operator>(double d) {
+ return dx>d
+ || dy>d
+ || (dx*dx+dy*dy > d*d);
+ }
+ };
+
+ So this is convertible to double, but can be compared to a distance
+ without any need for sqrt() and only multiplication in some cases.
+ Further refinement is possible.
+
+
+ Barend:
+ feasable, needs to be templatized by the number of dimensions. For distance it
+ results in a nice "delayed calculation".
+ For searching you might take another approach, first calculate dx, if OK then dy,
+ if OK then the sqrs. So as above but than distance does not need to be calculated.
+ So it is in fact another strategy.
+
+
+*/
+
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+ namespace distance
+ {
+ template <typename R, typename T>
+ struct distance_result_maker
+ {
+ };
+
+ template <typename R, typename T>
+ struct distance_result_maker<geometry::cartesian_distance<R>, T>
+ {
+ static inline geometry::cartesian_distance<R> apply(T const& value)
+ {
+ return cartesian_distance<R>(value * value);
+ }
+ };
+
+ template <typename T>
+ struct distance_result_maker<double, T>
+ {
+ static inline double apply(T const& value)
+ {
+ return value;
+ }
+ };
+
+
+ template <typename T>
+ struct close_to_zero
+ {
+ static inline bool apply(T const& value)
+ {
+ return value <= std::numeric_limits<T>::epsilon();
+ }
+ };
+
+
+ template <typename T>
+ struct close_to_zero<geometry::cartesian_distance<T> >
+ {
+ static inline bool apply(geometry::cartesian_distance<T> const& value)
+ {
+ return value.very_small();
+ }
+ };
+
+
+ template <typename T>
+ struct fuzzy_equals
+ {
+ static inline bool apply(T const& left, T const& right)
+ {
+ return std::abs(left - right) < 0.01;
+ }
+ };
+
+
+ template <typename T>
+ struct fuzzy_equals<geometry::cartesian_distance<T> >
+ {
+ typedef geometry::cartesian_distance<T> D;
+ static inline bool apply(D const& left, D const& right)
+ {
+ return std::abs(left.squared_value() - right.squared_value()) < 1;
+ }
+ };
+
+ }
+}
+#endif
+
+
+
+/*!
+ \brief Shortcut to define return type of distance strategy
+ \ingroup distance
+ \tparam Geometry1 first geometry
+ \tparam Geometry2 second geometry
+ */
+template <typename Geometry1, typename Geometry2 = Geometry1>
+struct distance_result
+{
+ typedef typename point_type<Geometry1>::type point_type1;
+ typedef typename point_type<Geometry2>::type point_type2;
+ typedef typename strategy_distance
+ <
+ typename cs_tag<point_type1>::type,
+ typename cs_tag<point_type2>::type,
+ point_type1,
+ point_type2
+ >::type strategy_type;
+ typedef typename strategy_type::return_type type;
+};
+
+
+
+
+
+/*!
+ \brief Object generator to create instance which can be compared
+ \ingroup distance
+ \details If distance results have to be compared to a certain value it makes sense to use
+ this function to generate a distance result of a certain value, and compare the distance
+ result with this instance. SQRT calculations are then avoided
+ \tparam R distance result type
+ \tparam T arithmetic type, e.g. double
+ \param value the distance to compare with
+ \return the distance result
+*/
+template <typename R, typename T>
+inline R make_distance_result(T const& value)
+{
+ return detail::distance::distance_result_maker<R, T>::apply(value);
+}
+
+
+/*!
+ \brief Utility function to check if a distance is very small
+ \ingroup distance
+ \details Depending on the "distance result" type it checks if it is smaller than epsilon,
+ or (for Cartesian distances) if the square is smaller than epsilon
+ \tparam R the distance result type, either arithmetic or cartesian distance
+ \param value the distance result to check
+*/
+template <typename T>
+inline bool close_to_zero(T const& value)
+{
+ return detail::distance::close_to_zero<T>::apply(value);
+}
+
+template <typename T>
+inline bool fuzzy_equals(T const& left, T const& right)
+{
+ return detail::distance::fuzzy_equals<T>::apply(left, right);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_DISTANCE_RESULT_HPP

Added: sandbox/geometry/boost/geometry/strategies/intersection.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/intersection.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,89 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_INTERSECTION_HPP
+#define BOOST_GEOMETRY_STRATEGIES_INTERSECTION_HPP
+
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/geometries/segment.hpp>
+
+#include <boost/geometry/policies/relate/intersection_points.hpp>
+#include <boost/geometry/policies/relate/direction.hpp>
+#include <boost/geometry/policies/relate/tupled.hpp>
+
+#include <boost/geometry/strategies/side.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+#include <boost/geometry/strategies/intersection_result.hpp>
+
+#include <boost/geometry/strategies/cartesian/cart_intersect.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+// The intersection strategy is a "compound strategy",
+// it contains a segment-intersection-strategy
+// and a side-strategy
+template
+<
+ typename Tag,
+ typename Geometry1,
+ typename Geometry2,
+ typename IntersectionPoint,
+ typename CalculationType = void
+>
+struct strategy_intersection
+{
+private :
+ typedef typename geometry::point_type<Geometry1>::type point1_type;
+ typedef typename geometry::point_type<Geometry2>::type point2_type;
+ typedef typename geometry::segment<const point1_type> segment1_type;
+ typedef typename geometry::segment<const point2_type> segment2_type;
+
+ typedef segment_intersection_points
+ <
+ IntersectionPoint
+ > ip_type;
+
+public:
+ typedef strategy::intersection::relate_cartesian_segments
+ <
+ policies::relate::segments_tupled
+ <
+ policies::relate::segments_intersection_points
+ <
+ segment1_type,
+ segment2_type,
+ ip_type,
+ CalculationType
+ > ,
+ policies::relate::segments_direction
+ <
+ segment1_type,
+ segment2_type,
+ CalculationType
+ >,
+ CalculationType
+ >,
+ CalculationType
+ > segment_intersection_strategy_type;
+
+ typedef typename strategy_side
+ <
+ Tag,
+ CalculationType
+ >::type side_strategy_type;
+};
+
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_INTERSECTION_HPP

Added: sandbox/geometry/boost/geometry/strategies/intersection_result.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/intersection_result.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,171 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_INTERSECTION_RESULT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_INTERSECTION_RESULT_HPP
+
+#if defined(HAVE_MATRIX_AS_STRING)
+#include <string>
+#endif
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief Dimensionally Extended 9 Intersection Matrix
+ \details
+ \ingroup overlay
+ \see http://gis.hsr.ch/wiki/images/3/3d/9dem_springer.pdf
+*/
+struct de9im
+{
+ int ii, ib, ie,
+ bi, bb, be,
+ ei, eb, ee;
+
+ inline de9im()
+ : ii(-1), ib(-1), ie(-1)
+ , bi(-1), bb(-1), be(-1)
+ , ei(-1), eb(-1), ee(-1)
+ {
+ }
+
+ inline de9im(int ii0, int ib0, int ie0,
+ int bi0, int bb0, int be0,
+ int ei0, int eb0, int ee0)
+ : ii(ii0), ib(ib0), ie(ie0)
+ , bi(bi0), bb(bb0), be(be0)
+ , ei(ei0), eb(eb0), ee(ee0)
+ {}
+
+ inline bool equals() const
+ {
+ return ii >= 0 && ie < 0 && be < 0 && ei < 0 && eb < 0;
+ }
+
+ inline bool disjoint() const
+ {
+ return ii < 0 && ib < 0 && bi < 0 && bb < 0;
+ }
+
+ inline bool intersects() const
+ {
+ return ii >= 0 || bb >= 0 || bi >= 0 || ib >= 0;
+ }
+
+ inline bool touches() const
+ {
+ return ii < 0 && (bb >= 0 || bi >= 0 || ib >= 0);
+ }
+
+ inline bool crosses() const
+ {
+ return (ii >= 0 && ie >= 0) || (ii == 0);
+ }
+
+ inline bool overlaps() const
+ {
+ return ii >= 0 && ie >= 0 && ei >= 0;
+ }
+
+ inline bool within() const
+ {
+ return ii >= 0 && ie < 0 && be < 0;
+ }
+
+ inline bool contains() const
+ {
+ return ii >= 0 && ei < 0 && eb < 0;
+ }
+
+
+ static inline char as_char(int v)
+ {
+ return v >= 0 && v < 10 ? ('0' + char(v)) : '-';
+ }
+
+#if defined(HAVE_MATRIX_AS_STRING)
+ inline std::string matrix_as_string(std::string const& tab, std::string const& nl) const
+ {
+ std::string ret;
+ ret.reserve(9 + tab.length() * 3 + nl.length() * 3);
+ ret += tab; ret += as_char(ii); ret += as_char(ib); ret += as_char(ie); ret += nl;
+ ret += tab; ret += as_char(bi); ret += as_char(bb); ret += as_char(be); ret += nl;
+ ret += tab; ret += as_char(ei); ret += as_char(eb); ret += as_char(ee);
+ return ret;
+ }
+
+ inline std::string matrix_as_string() const
+ {
+ return matrix_as_string("", "");
+ }
+#endif
+
+};
+
+struct de9im_segment : public de9im
+{
+ bool collinear; // true if segments are aligned (for equal,overlap,touch)
+ bool opposite; // true if direction is reversed (for equal,overlap,touch)
+ bool parallel; // true if disjoint but parallel
+ bool degenerate; // true for segment(s) of zero length
+
+ double ra, rb; // temp
+
+ inline de9im_segment()
+ : de9im()
+ , collinear(false)
+ , opposite(false)
+ , parallel(false)
+ , degenerate(false)
+ {}
+
+ inline de9im_segment(double a, double b,
+ int ii0, int ib0, int ie0,
+ int bi0, int bb0, int be0,
+ int ei0, int eb0, int ee0,
+ bool c = false, bool o = false, bool p = false, bool d = false)
+ : de9im(ii0, ib0, ie0, bi0, bb0, be0, ei0, eb0, ee0)
+ , collinear(c)
+ , opposite(o)
+ , parallel(p)
+ , degenerate(d)
+ , ra(a), rb(b)
+ {}
+
+
+#if defined(HAVE_MATRIX_AS_STRING)
+ inline std::string as_string() const
+ {
+ std::string ret = matrix_as_string();
+ ret += collinear ? "c" : "-";
+ ret += opposite ? "o" : "-";
+ return ret;
+ }
+#endif
+};
+
+
+
+template <typename Point>
+struct segment_intersection_points
+{
+ std::size_t count;
+ Point intersections[2];
+ typedef Point point_type;
+
+ segment_intersection_points()
+ : count(0)
+ {}
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_INTERSECTION_RESULT_HPP

Added: sandbox/geometry/boost/geometry/strategies/length_result.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/length_result.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,40 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_LENGTH_RESULT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_LENGTH_RESULT_HPP
+
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief Meta-function defining return type of length function
+ \ingroup length
+ \note Length of a line of integer coordinates can be double.
+ So we take at least a double. If Big Number types are used,
+ we take that type.
+
+ */
+template <typename Geometry>
+struct length_result
+{
+ typedef typename select_most_precise
+ <
+ typename coordinate_type<Geometry>::type,
+ long double
+ >::type type;
+};
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_LENGTH_RESULT_HPP

Added: sandbox/geometry/boost/geometry/strategies/parse.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/parse.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,36 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_PARSE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_PARSE_HPP
+
+#include <boost/geometry/strategies/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+
+/*!
+ \brief Tagraits class binding a parsing strategy to a coordinate system
+ \ingroup parse
+ \tparam Tag tag of coordinate system of point-type
+ \tparam CoordinateSystem coordinate system
+*/
+template <typename Tag, typename CoordinateSystem>
+struct strategy_parse
+{
+ typedef strategy::not_implemented type;
+};
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_PARSE_HPP

Added: sandbox/geometry/boost/geometry/strategies/point_in_poly.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/point_in_poly.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,36 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_POINT_IN_POLY_HPP
+#define BOOST_GEOMETRY_STRATEGIES_POINT_IN_POLY_HPP
+
+#include <boost/geometry/strategies/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Traits class binding a within determination strategy to a coordinate system
+ \ingroup within
+ \tparam TagPoint tag of coordinate system of point-type
+ \tparam TagSegment tag of coordinate system of segment-type
+ \tparam Point point-type of input points
+ \tparam PointOfSegment point-type of input segment-points
+*/
+template <typename TagPoint, typename TagSegment, typename Point, typename PointOfSegment>
+struct strategy_within
+{
+ typedef strategy::not_implemented type;
+};
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_POINT_IN_POLY_HPP

Added: sandbox/geometry/boost/geometry/strategies/side.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/side.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,34 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SIDE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SIDE_HPP
+
+
+#include <boost/geometry/strategies/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Traits class binding a side determination strategy to a coordinate system
+ \ingroup util
+ \tparam Tag tag of coordinate system of point-type
+*/
+template <typename Tag, typename CalculationType = void>
+struct strategy_side
+{
+ typedef strategy::not_implemented type;
+};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SIDE_HPP

Added: sandbox/geometry/boost/geometry/strategies/side_info.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/side_info.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,87 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP
+
+
+#include <utility>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+\brief Class side_info: small class wrapping for sides (-1,0,1)
+*/
+class side_info
+{
+public :
+ inline side_info(int side_a1 = 0, int side_a2 = 0,
+ int side_b1 = 0, int side_b2 = 0)
+ {
+ sides[0].first = side_a1;
+ sides[0].second = side_a2;
+ sides[1].first = side_b1;
+ sides[1].second = side_b2;
+ }
+
+ template <int Which>
+ inline void set(int first, int second)
+ {
+ sides[Which].first = first;
+ sides[Which].second = second;
+ }
+
+ template <int Which, int Index>
+ inline int get() const
+ {
+ return Index == 0 ? sides[Which].first : sides[Which].second;
+ }
+
+
+ // Returns true if both lying on the same side WRT the other
+ // (so either 1,1 or -1-1)
+ template <int Which>
+ inline bool same() const
+ {
+ return sides[Which].first * sides[Which].second == 1;
+ }
+
+ inline bool collinear() const
+ {
+ return sides[0].first == 0
+ && sides[0].second == 0
+ && sides[1].first == 0
+ && sides[1].second == 0;
+ }
+
+ // If one of the segments is collinear, the other must be as well.
+ // So handle it as collinear.
+ // (In floating point margins it can occur that one of them is 1!)
+ inline bool as_collinear() const
+ {
+ return sides[0].first * sides[0].second == 0
+ || sides[1].first * sides[1].second == 0;
+ }
+
+ inline void reverse()
+ {
+ std::swap(sides[0], sides[1]);
+ }
+
+private :
+ std::pair<int, int> sides[2];
+
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP

Added: sandbox/geometry/boost/geometry/strategies/spherical/area_huiller.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/spherical/area_huiller.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,152 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP
+
+
+#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
+
+#include <boost/geometry/core/radian_access.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace area {
+
+
+
+/*!
+ \brief Area calculation by spherical excess / Huiller's formula
+ \tparam 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 PointOfSegment,
+ typename CalculationType = void
+>
+class huiller
+{
+protected :
+ struct excess_sum
+ {
+ double sum;
+
+ // Distances are calculated on unit sphere here
+ strategy::distance::haversine<PointOfSegment, PointOfSegment>
+ distance_over_unit_sphere;
+
+
+ inline excess_sum()
+ : sum(0)
+ , distance_over_unit_sphere(1)
+ {}
+ inline double area(double radius) const
+ {
+ return - sum * radius * radius;
+ }
+ };
+
+public :
+ typedef double return_type;
+ typedef PointOfSegment segment_point_type;
+ typedef excess_sum state_type;
+
+ inline huiller(double radius = 1.0)
+ : m_radius(radius)
+ {}
+
+ inline void apply(PointOfSegment const& p1,
+ PointOfSegment const& p2,
+ excess_sum& state) const
+ {
+ if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
+ {
+ // Distance p1 p2
+ double a = state.distance_over_unit_sphere.apply(p1, p2);
+
+ // Sides on unit sphere to south pole
+ double b = 0.5 * math::pi - geometry::get_as_radian<1>(p2);
+ double c = 0.5 * math::pi - geometry::get_as_radian<1>(p1);
+
+ // 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(std::abs(tan(s / 2)
+ * tan((s - a) / 2)
+ * tan((s - b) / 2)
+ * tan((s - c) / 2))));
+
+ E = std::abs(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 dateline into account.
+ // TODO: check this / enhance this, should be more robust. See also the "grow" for ll
+ // TODO: use minmax or "smaller"/"compare" strategy for this
+ double lon1 = geometry::get_as_radian<0>(p1) < 0
+ ? geometry::get_as_radian<0>(p1) + math::two_pi
+ : geometry::get_as_radian<0>(p1);
+
+ double lon2 = geometry::get_as_radian<0>(p2) < 0
+ ? geometry::get_as_radian<0>(p2) + math::two_pi
+ : geometry::get_as_radian<0>(p2);
+
+ if (lon2 < lon1)
+ {
+ E = -E;
+ }
+
+ state.sum += E;
+ }
+ }
+
+ inline return_type result(excess_sum const& state) const
+ {
+ return state.area(m_radius);
+ }
+
+private :
+ /// Radius of the sphere
+ double m_radius;
+};
+
+
+}} // namespace strategy::area
+
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+template <typename Point>
+struct strategy_area<spherical_tag, Point>
+{
+ typedef strategy::area::huiller<Point> type;
+};
+
+#endif
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP

Added: sandbox/geometry/boost/geometry/strategies/spherical/compare_circular.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/spherical/compare_circular.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,142 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/strategies/compare.hpp>
+
+namespace boost { namespace geometry {
+
+namespace strategy { namespace compare {
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail {
+
+template <typename Units>
+struct shift
+{
+};
+
+template <>
+struct shift<degree>
+{
+ static inline double full() { return 360.0; }
+ static inline double half() { return 180.0; }
+};
+
+template <>
+struct shift<radian>
+{
+ static inline double full() { return geometry::math::two_pi; }
+ static inline double half() { return geometry::math::pi; }
+};
+
+} // namespace detail
+#endif
+
+/*!
+ \brief Compare (in one direction) strategy for spherical coordinates
+ \ingroup util
+ \tparam Point point-type
+ \tparam Dimension dimension
+*/
+template <typename CoordinateType, typename Units, typename Compare>
+struct circular_comparator
+{
+ static inline CoordinateType put_in_range(CoordinateType const& c,
+ double min_border, double max_border)
+ {
+ CoordinateType value = c;
+ while (value < min_border)
+ {
+ value += detail::shift<Units>::full();
+ }
+ while (value > max_border)
+ {
+ value -= detail::shift<Units>::full();
+ }
+ return value;
+ }
+
+ inline bool operator()(CoordinateType const& c1, CoordinateType const& c2) const
+ {
+ Compare compare;
+
+ // Check situation that one of them is e.g. std::numeric_limits.
+ static const double full = detail::shift<Units>::full();
+ double mx = 10.0 * full;
+ if (c1 < -mx || c1 > mx || c2 < -mx || c2 > mx)
+ {
+ // do normal comparison, using circular is not useful
+ return compare(c1, c2);
+ }
+
+ static const double half = full / 2.0;
+ CoordinateType v1 = put_in_range(c1, -half, half);
+ CoordinateType v2 = put_in_range(c2, -half, half);
+
+ // Two coordinates on a circle are
+ // at max <= half a circle away from each other.
+ // So if it is more, shift origin.
+ CoordinateType diff = std::abs(v1 - v2);
+ if (diff > half)
+ {
+ v1 = put_in_range(v1, 0, full);
+ v2 = put_in_range(v2, 0, full);
+ }
+
+ return compare(v1, v2);
+ }
+};
+
+}} // namespace strategy::compare
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+// Specialize for the longitude (dim 0)
+template
+<
+ typename Point,
+ template<typename> class CoordinateSystem,
+ typename Units
+>
+struct strategy_compare<spherical_tag, 1, Point, CoordinateSystem<Units>, 0>
+{
+ typedef typename coordinate_type<Point>::type coordinate_type;
+ typedef strategy::compare::circular_comparator
+ <
+ coordinate_type,
+ Units,
+ std::less<coordinate_type>
+ > type;
+};
+
+template
+<
+ typename Point,
+ template<typename> class CoordinateSystem,
+ typename Units
+>
+struct strategy_compare<spherical_tag, -1, Point, CoordinateSystem<Units>, 0>
+{
+ typedef typename coordinate_type<Point>::type coordinate_type;
+ typedef strategy::compare::circular_comparator
+ <
+ coordinate_type,
+ Units,
+ std::greater<coordinate_type>
+ > type;
+};
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP

Added: sandbox/geometry/boost/geometry/strategies/spherical/distance_cross_track.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/spherical/distance_cross_track.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,158 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_HPP
+
+#include <boost/concept/requires.hpp>
+
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+
+
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/concepts/distance_concept.hpp>
+
+#include <boost/geometry/util/math.hpp>
+//#include <boost/geometry/util/write_dsv.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace distance {
+
+/*!
+ \brief Strategy functor for distance point to segment calculation
+ \ingroup distance
+ \details Class which calculates the distance of a point to a segment, using latlong points
+ \see http://williams.best.vwh.net/avform.htm
+ \tparam P point type
+ \tparam S segment type
+*/
+template <typename Point, typename PointOfSegment>
+class cross_track
+{
+public :
+ typedef double return_type;
+ typedef Point point_type;
+ typedef PointOfSegment segment_point_type;
+
+ typedef typename strategy_distance
+ <
+ typename geometry::cs_tag<Point>::type,
+ typename geometry::cs_tag<Point>::type,
+ Point, Point
+ >::type point_strategy_type;
+
+ BOOST_CONCEPT_ASSERT
+ (
+ (geometry::concept::PointDistanceStrategy<point_strategy_type>)
+ );
+
+
+
+ inline cross_track(double r = 1.0)
+ : m_radius(r)
+ , m_strategy(1.0) // Keep this 1.0 and not r
+ {}
+
+
+ // It might be useful in the future
+ // to overload constructor with strategy info.
+ // crosstrack(...) {}
+
+
+ inline return_type apply(Point const& p,
+ PointOfSegment const& sp1, PointOfSegment const& sp2) const
+ {
+ // http://williams.best.vwh.net/avform.htm#XTE
+ double d1 = m_strategy.apply(sp1, p);
+
+ // Actually, calculation of d2 not necessary if we know that the projected point is on the great circle...
+ double d2 = m_strategy.apply(sp2, p);
+
+ double crs_AD = course(sp1, p);
+ double crs_AB = course(sp1, sp2);
+ double XTD = std::abs(asin(sin(d1) * sin(crs_AD - crs_AB)));
+
+//std::cout << "Course " << dsv(sp1) << " to " << dsv(p) << " " << crs_AD * geometry::math::r2d << std::endl;
+//std::cout << "Course " << dsv(sp1) << " to " << dsv(sp2) << " " << crs_AB * geometry::math::r2d << std::endl;
+//std::cout << "XTD: " << (XTD * 6373.0) << " d1: " << (d1 * 6373.0) << " d2: " << (d2 * 6373.0) << std::endl;
+
+
+ // Return shortest distance, either to projected point on segment sp1-sp2, or to sp1, or to sp2
+ return return_type(m_radius * (std::min)((std::min)(d1, d2), XTD));
+ }
+
+private :
+ double m_radius;
+
+ // Point-point distances are calculated in radians, on the unit sphere
+ point_strategy_type m_strategy;
+
+ /// Calculate course (bearing) between two points. Might be moved to a "course formula" ...
+ inline double course(Point const& p1, Point const& p2) const
+ {
+ // http://williams.best.vwh.net/avform.htm#Crs
+ double dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1);
+ double cos_p2lat = cos(get_as_radian<1>(p2));
+
+ // "An alternative formula, not requiring the pre-computation of d"
+ return atan2(sin(dlon) * cos_p2lat,
+ cos(get_as_radian<1>(p1)) * sin(get_as_radian<1>(p2))
+ - sin(get_as_radian<1>(p1)) * cos_p2lat * cos(dlon));
+ }
+
+};
+
+
+}} // namespace strategy::distance
+
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+template <typename Point, typename Segment>
+struct strategy_distance_segment<spherical_tag, spherical_tag, Point, Segment>
+{
+ typedef strategy::distance::cross_track<Point, Segment> type;
+};
+
+
+// Use this point-segment for geographic as well. TODO: change this, extension!
+template <typename Point, typename Segment>
+struct strategy_distance_segment<geographic_tag, geographic_tag, Point, Segment>
+{
+ typedef strategy::distance::cross_track<Point, Segment> type;
+};
+
+
+template <typename Point, typename Segment>
+struct strategy_tag<strategy::distance::cross_track<Point, Segment> >
+{
+ typedef strategy_tag_distance_point_segment type;
+};
+
+
+
+#endif
+
+
+
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_HPP

Added: sandbox/geometry/boost/geometry/strategies/spherical/distance_haversine.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/spherical/distance_haversine.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,115 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_HAVERSINE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_HAVERSINE_HPP
+
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+
+
+#include <boost/geometry/strategies/distance.hpp>
+
+#include <boost/geometry/strategies/distance_result.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace distance {
+
+/*!
+ \brief Distance calculation for spherical coordinates
+ on a perfect sphere using haversine
+ \ingroup distance
+ \tparam P1 first point type
+ \tparam P2 optional second point type
+ \author Adapted from: http://williams.best.vwh.net/avform.htm
+ \see 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 Point1, typename Point2 = Point1>
+class haversine
+{
+public :
+ typedef Point1 first_point_type;
+ typedef Point2 second_point_type;
+ typedef double return_type;
+
+ inline haversine(double r = 1.0)
+ : m_radius(r)
+ {}
+
+ inline return_type apply(Point1 const& p1, Point2 const& p2) const
+ {
+ return calculate(get_as_radian<0>(p1), get_as_radian<1>(p1),
+ get_as_radian<0>(p2), get_as_radian<1>(p2));
+ }
+
+private :
+ double m_radius;
+ typedef typename coordinate_type<Point1>::type coordinate_type1;
+ typedef typename coordinate_type<Point2>::type coordinate_type2;
+
+ inline return_type calculate(coordinate_type1 const& lon1,
+ coordinate_type1 const& lat1,
+ coordinate_type2 const& lon2,
+ coordinate_type2 const& lat2) const
+ {
+ double a = math::hav(lat2 - lat1)
+ + cos(lat1) * cos(lat2) * math::hav(lon2 - lon1);
+ double c = 2.0 * asin(sqrt(a));
+ return return_type(m_radius * c);
+ }
+};
+
+
+}} // namespace strategy::distance
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename P1, typename P2>
+struct strategy_distance<spherical_tag, spherical_tag, P1, P2>
+{
+ typedef strategy::distance::haversine<P1, P2> type;
+};
+
+
+
+
+
+
+template <typename P1, typename P2>
+struct strategy_tag<strategy::distance::haversine<P1, P2> >
+{
+ typedef strategy_tag_distance_point_point type;
+};
+
+
+
+
+#endif
+
+
+
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_HAVERSINE_HPP

Added: sandbox/geometry/boost/geometry/strategies/spherical/side_by_cross_track.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/spherical/side_by_cross_track.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,105 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+#include <boost/geometry/strategies/side.hpp>
+//#include <boost/geometry/strategies/concepts/side_concept.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+namespace strategy
+{
+ namespace side
+ {
+ /// Calculate course (bearing) between two points. Might be moved to a "course formula" ...
+ template <typename Point>
+ static inline double course(Point const& p1, Point const& p2)
+ {
+ // http://williams.best.vwh.net/avform.htm#Crs
+ double dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1);
+ double cos_p2lat = cos(get_as_radian<1>(p2));
+
+ // "An alternative formula, not requiring the pre-computation of d"
+ return atan2(sin(dlon) * cos_p2lat,
+ cos(get_as_radian<1>(p1)) * sin(get_as_radian<1>(p2))
+ - sin(get_as_radian<1>(p1)) * cos_p2lat * cos(dlon));
+ }
+
+
+
+
+ // Check at which side of a segment a point lies
+ // from a Great Circle segment between two points:
+ // left of segment (> 0), right of segment (< 0), on segment (0)
+ template <typename CalculationType>
+ struct side_by_cross_track
+ {
+
+ // Types can be all three different. Therefore it is
+ // not implemented (anymore) as "segment"
+
+ template <typename P1, typename P2, typename P>
+ static inline int apply(P1 const& p1, P2 const& p2, P const& p)
+ {
+ typedef typename boost::mpl::if_c
+ <
+ boost::is_void<CalculationType>::type::value,
+ typename select_most_precise
+ <
+ typename select_most_precise
+ <
+ typename coordinate_type<P1>::type,
+ typename coordinate_type<P2>::type
+ >::type,
+ typename coordinate_type<P>::type
+ >::type,
+ CalculationType
+ >::type coordinate_type;
+
+ // Calculate the distance using the Haversine formula.
+ // That is also applicable on the spherical earth. A radius is not necessary.
+
+ double d1 = 0.001; // m_strategy.apply(sp1, p);
+ double crs_AD = course(p1, p);
+ double crs_AB = course(p1, p2);
+ double XTD = std::abs(asin(sin(d1) * sin(crs_AD - crs_AB)));
+
+ return math::equals(XTD, 0) ? 0 : XTD > 0 ? 1 : -1;
+ //return s > 0 ? 1 : s < 0 ? -1 : 0;
+ }
+ };
+
+ } // namespace side
+} // namespace strategy
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename CalculationType>
+struct strategy_side<spherical_tag, CalculationType>
+{
+ typedef strategy::side::side_by_cross_track<CalculationType> type;
+};
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP

Added: sandbox/geometry/boost/geometry/strategies/strategies.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/strategies.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,50 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_STRATEGIES_HPP
+#define BOOST_GEOMETRY_STRATEGIES_STRATEGIES_HPP
+
+
+#include <boost/geometry/strategies/tags.hpp>
+
+#include <boost/geometry/strategies/area.hpp>
+#include <boost/geometry/strategies/centroid.hpp>
+#include <boost/geometry/strategies/compare.hpp>
+#include <boost/geometry/strategies/convex_hull.hpp>
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+#include <boost/geometry/strategies/parse.hpp>
+#include <boost/geometry/strategies/point_in_poly.hpp>
+#include <boost/geometry/strategies/side.hpp>
+#include <boost/geometry/strategies/transform.hpp>
+
+#include <boost/geometry/strategies/cartesian/area_by_triangles.hpp>
+#include <boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp>
+#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
+#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp>
+#include <boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp>
+#include <boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp>
+#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
+
+#include <boost/geometry/strategies/spherical/area_huiller.hpp>
+#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
+#include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
+#include <boost/geometry/strategies/spherical/compare_circular.hpp>
+
+#include <boost/geometry/strategies/agnostic/hull_graham_andrew.hpp>
+#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
+#include <boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp>
+
+#include <boost/geometry/strategies/strategy_transform.hpp>
+
+#include <boost/geometry/strategies/transform/matrix_transformers.hpp>
+#include <boost/geometry/strategies/transform/map_transformer.hpp>
+#include <boost/geometry/strategies/transform/inverse_transformer.hpp>
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_STRATEGIES_HPP

Added: sandbox/geometry/boost/geometry/strategies/strategy_transform.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/strategy_transform.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,358 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP
+#define BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP
+
+#include <cstddef>
+#include <cmath>
+#include <functional>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+
+#include <boost/geometry/util/copy.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace transform {
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template
+<
+ typename Src, typename Dst,
+ std::size_t D, std::size_t N,
+ template <typename> class F
+>
+struct transform_coordinates
+{
+ static inline void transform(Src const& source, Dst& dest, double value)
+ {
+ typedef typename select_coordinate_type<Src, Dst>::type coordinate_type;
+
+ F<coordinate_type> function;
+ set<D>(dest, boost::numeric_cast<coordinate_type>(function(get<D>(source), value)));
+ transform_coordinates<Src, Dst, D + 1, N, F>::transform(source, dest, value);
+ }
+};
+
+template
+<
+ typename Src, typename Dst,
+ std::size_t N,
+ template <typename> class F
+>
+struct transform_coordinates<Src, Dst, N, N, F>
+{
+ static inline void transform(Src const& source, Dst& dest, double value)
+ {
+ }
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief Transformation strategy to copy one point to another using assignment operator
+ \ingroup transform
+ \tparam P point type
+ */
+template <typename P>
+struct copy_direct
+{
+ inline bool apply(P const& p1, P& p2) const
+ {
+ p2 = p1;
+ return true;
+ }
+};
+
+/*!
+ \brief Transformation strategy to do copy a point, copying per coordinate.
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ */
+template <typename P1, typename P2>
+struct copy_per_coordinate
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ // Defensive check, dimensions are equal, selected by specialization
+ assert_dimension_equal<P1, P2>();
+
+ copy_coordinates(p1, p2);
+ return true;
+ }
+};
+
+
+/*!
+ \brief Transformation strategy to go from degree to radian and back
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ \tparam F additional functor to divide or multiply with d2r
+ */
+template <typename P1, typename P2, template <typename> class F>
+struct degree_radian_vv
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ // Spherical coordinates always have 2 coordinates measured in angles
+ // The optional third one is distance/height, provided in another strategy
+ // Polar coordinates having one angle, will be also in another strategy
+ assert_dimension<P1, 2>();
+ assert_dimension<P2, 2>();
+
+ detail::transform_coordinates<P1, P2, 0, 2, F>::transform(p1, p2, math::d2r);
+ return true;
+ }
+};
+
+template <typename P1, typename P2, template <typename> class F>
+struct degree_radian_vv_3
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ assert_dimension<P1, 3>();
+ assert_dimension<P2, 3>();
+
+ detail::transform_coordinates<P1, P2, 0, 2, F>::transform(p1, p2, math::d2r);
+ // Copy height or other third dimension
+ set<2>(p2, get<2>(p1));
+ return true;
+ }
+};
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+ /// Helper function for conversion, phi/theta are in radians
+ template <typename P>
+ inline void spherical_to_cartesian(double phi, double theta, double r, P& p)
+ {
+ assert_dimension<P, 3>();
+
+ // http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_spherical_coordinates
+ // Phi = first, theta is second, r is third, see documentation on cs::spherical
+ double const sin_theta = std::sin(theta);
+ set<0>(p, r * sin_theta * std::cos(phi));
+ set<1>(p, r * sin_theta * std::sin(phi));
+ set<2>(p, r * std::cos(theta));
+ }
+
+ /// Helper function for conversion
+ template <typename P>
+ inline bool cartesian_to_spherical2(double x, double y, double z, P& p)
+ {
+ assert_dimension<P, 2>();
+
+ // http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_Cartesian_coordinates
+
+ // TODO: MAYBE ONLY IF TO BE CHECKED?
+ double const r = std::sqrt(x * x + y * y + z * z);
+
+ // Unit sphere, r should be 1
+ typedef typename coordinate_type<P>::type coordinate_type;
+ if (std::abs(r - 1.0) > std::numeric_limits<coordinate_type>::epsilon())
+ {
+ return false;
+ }
+ // end todo
+
+ set_from_radian<0>(p, std::atan2(y, x));
+ set_from_radian<1>(p, std::acos(z));
+ return true;
+ }
+
+ template <typename P>
+ inline bool cartesian_to_spherical3(double x, double y, double z, P& p)
+ {
+ assert_dimension<P, 3>();
+
+ // http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_Cartesian_coordinates
+ double const r = std::sqrt(x * x + y * y + z * z);
+ set<2>(p, r);
+ set_from_radian<0>(p, std::atan2(y, x));
+ if (r > 0.0)
+ {
+ set_from_radian<1>(p, std::acos(z / r));
+ return true;
+ }
+ return false;
+ }
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief Transformation strategy for 2D spherical (phi,theta) to 3D cartesian (x,y,z)
+ \details on Unit sphere
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ */
+template <typename P1, typename P2>
+struct from_spherical_2_to_cartesian_3
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ assert_dimension<P1, 2>();
+ detail::spherical_to_cartesian(get_as_radian<0>(p1), get_as_radian<1>(p1), 1.0, p2);
+ return true;
+ }
+};
+
+/*!
+ \brief Transformation strategy for 3D spherical (phi,theta,r) to 3D cartesian (x,y,z)
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ */
+template <typename P1, typename P2>
+struct from_spherical_3_to_cartesian_3
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ assert_dimension<P1, 3>();
+ detail::spherical_to_cartesian(
+ get_as_radian<0>(p1), get_as_radian<1>(p1), get<2>(p1), p2);
+ return true;
+ }
+};
+
+/*!
+ \brief Transformation strategy for 3D cartesian (x,y,z) to 2D spherical (phi,theta)
+ \details on Unit sphere
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ \note If x,y,z point is not lying on unit sphere, transformation will return false
+ */
+template <typename P1, typename P2>
+struct from_cartesian_3_to_spherical_2
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ assert_dimension<P1, 3>();
+ return detail::cartesian_to_spherical2(get<0>(p1), get<1>(p1), get<2>(p1), p2);
+ }
+};
+
+
+/*!
+ \brief Transformation strategy for 3D cartesian (x,y,z) to 3D spherical (phi,theta,r)
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ */
+template <typename P1, typename P2>
+struct from_cartesian_3_to_spherical_3
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ assert_dimension<P1, 3>();
+ return detail::cartesian_to_spherical3(get<0>(p1), get<1>(p1), get<2>(p1), p2);
+ }
+};
+
+}} // namespace strategy::transform
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+/// Specialization for same coordinate system family, same system, same dimension, same point type, can be copied
+template <typename CoordSysTag, typename CoordSys, std::size_t D, typename P>
+struct strategy_transform<CoordSysTag, CoordSysTag, CoordSys, CoordSys, D, D, P, P>
+{
+ typedef strategy::transform::copy_direct<P> type;
+};
+
+/// Specialization for same coordinate system family and system, same dimension, different point type, copy per coordinate
+template <typename CoordSysTag, typename CoordSys, std::size_t D, typename P1, typename P2>
+struct strategy_transform<CoordSysTag, CoordSysTag, CoordSys, CoordSys, D, D, P1, P2>
+{
+ typedef strategy::transform::copy_per_coordinate<P1, P2> type;
+};
+
+/// Specialization to convert from degree to radian for any coordinate system / point type combination
+template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
+struct strategy_transform<CoordSysTag, CoordSysTag, CoordSys<degree>, CoordSys<radian>, 2, 2, P1, P2>
+{
+ typedef strategy::transform::degree_radian_vv<P1, P2, std::multiplies> type;
+};
+
+/// Specialization to convert from radian to degree for any coordinate system / point type combination
+template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
+struct strategy_transform<CoordSysTag, CoordSysTag, CoordSys<radian>, CoordSys<degree>, 2, 2, P1, P2>
+{
+ typedef strategy::transform::degree_radian_vv<P1, P2, std::divides> type;
+};
+
+
+/// Specialization degree->radian in 3D
+template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
+struct strategy_transform<CoordSysTag, CoordSysTag, CoordSys<degree>, CoordSys<radian>, 3, 3, P1, P2>
+{
+ typedef strategy::transform::degree_radian_vv_3<P1, P2, std::multiplies> type;
+};
+
+/// Specialization radian->degree in 3D
+template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
+struct strategy_transform<CoordSysTag, CoordSysTag, CoordSys<radian>, CoordSys<degree>, 3, 3, P1, P2>
+{
+ typedef strategy::transform::degree_radian_vv_3<P1, P2, std::divides> type;
+};
+
+/// Specialization to convert from unit sphere(phi,theta) to XYZ
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
+struct strategy_transform<spherical_tag, cartesian_tag, CoordSys1, CoordSys2, 2, 3, P1, P2>
+{
+ typedef strategy::transform::from_spherical_2_to_cartesian_3<P1, P2> type;
+};
+
+/// Specialization to convert from sphere(phi,theta,r) to XYZ
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
+struct strategy_transform<spherical_tag, cartesian_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
+{
+ typedef strategy::transform::from_spherical_3_to_cartesian_3<P1, P2> type;
+};
+
+/// Specialization to convert from XYZ to unit sphere(phi,theta)
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
+struct strategy_transform<cartesian_tag, spherical_tag, CoordSys1, CoordSys2, 3, 2, P1, P2>
+{
+ typedef strategy::transform::from_cartesian_3_to_spherical_2<P1, P2> type;
+};
+
+/// Specialization to convert from XYZ to sphere(phi,theta,r)
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
+struct strategy_transform<cartesian_tag, spherical_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
+{
+ typedef strategy::transform::from_cartesian_3_to_spherical_3<P1, P2> type;
+};
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP

Added: sandbox/geometry/boost/geometry/strategies/tags.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/tags.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,44 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_TAGS_HPP
+#define BOOST_GEOMETRY_STRATEGIES_TAGS_HPP
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy
+{
+ /*!
+ \brief Indicate compiler/library user that strategy is not implemented.
+ \details Strategies are defined 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 {};
+}
+
+
+
+
+struct strategy_tag_unknown {};
+struct strategy_tag_distance_point_point {};
+struct strategy_tag_distance_point_segment {};
+
+template <typename T>
+struct strategy_tag
+{
+ typedef strategy_tag_unknown type;
+};
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_TAGS_HPP

Added: sandbox/geometry/boost/geometry/strategies/transform.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/transform.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,46 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_HPP
+#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_HPP
+
+#include <cstddef>
+
+#include <boost/geometry/strategies/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief Traits class binding a transformation strategy to a coordinate system
+ \ingroup transform
+ \details Can be specialized
+ - per coordinate system family (tag)
+ - per coordinate system (or groups of them)
+ - per dimension
+ - per point type
+ \tparam CoordinateSystemTag 1,2 coordinate system tags
+ \tparam CoordinateSystem 1,2 coordinate system
+ \tparam D 1, 2 dimension
+ \tparam Point 1, 2 point type
+ */
+template
+<
+ typename CoordinateSystemTag1, typename CoordinateSystemTag2,
+ typename CoordinateSystem1, typename CoordinateSystem2,
+ std::size_t Dimension1, std::size_t Dimension2,
+ typename Point1, typename Point2
+>
+struct strategy_transform
+{
+ typedef strategy::not_implemented type;
+};
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_HPP

Added: sandbox/geometry/boost/geometry/strategies/transform/inverse_transformer.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/transform/inverse_transformer.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,70 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP
+#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP
+
+// Remove the ublas checking, otherwise the inverse might fail
+// (while nothing seems to be wrong)
+#define BOOST_UBLAS_TYPE_CHECK 0
+
+#include <boost/numeric/ublas/lu.hpp>
+#include <boost/numeric/ublas/io.hpp>
+
+#include <boost/geometry/strategies/transform/matrix_transformers.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace transform {
+
+/*!
+ \brief Transformation strategy to do an inverse ransformation in Cartesian system
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ */
+template <typename P1, typename P2>
+struct inverse_transformer
+ : ublas_transformer<P1, P2, dimension<P1>::type::value, dimension<P2>::type::value>
+{
+ typedef typename select_coordinate_type<P1, P2>::type T;
+
+ template <typename MatrixType>
+ inline inverse_transformer(const MatrixType& input)
+ {
+ typedef boost::numeric::ublas::matrix<double> matrix_type;
+ // create a working copy of the input
+ matrix_type copy(input.matrix());
+
+ // create a permutation matrix for the LU-factorization
+ typedef boost::numeric::ublas::permutation_matrix<> permutation_matrix;
+ permutation_matrix pm(copy.size1());
+
+ // perform LU-factorization
+ int res = boost::numeric::ublas::lu_factorize<matrix_type>(copy, pm);
+ if( res == 0 )
+ {
+ // create identity matrix
+ this->m_matrix.assign(boost::numeric::ublas::identity_matrix<T>(copy.size1()));
+
+ // backsubstitute to get the inverse
+ boost::numeric::ublas::lu_substitute(copy, pm, this->m_matrix);
+ }
+ }
+
+
+};
+
+
+}} // namespace strategy::transform
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP

Added: sandbox/geometry/boost/geometry/strategies/transform/map_transformer.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/transform/map_transformer.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,148 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP
+#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP
+
+
+#include <boost/geometry/strategies/transform/matrix_transformers.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace transform {
+
+/*!
+ \brief Transformation strategy to do map from one to another Cartesian system
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ \tparam Mirror if true map is mirrored upside-down (in most cases pixels
+ are from top to bottom, while map is from bottom to top)
+ */
+template
+<
+ typename P1, typename P2,
+ bool Mirror, bool SameScale = true,
+ std::size_t Dimension1 = dimension<P1>::type::value,
+ std::size_t Dimension2 = dimension<P2>::type::value
+>
+struct map_transformer
+ : ublas_transformer<P1, P2, Dimension1, Dimension2>
+{
+ typedef typename select_coordinate_type<P1, P2>::type T;
+ typedef boost::numeric::ublas::matrix<T> M;
+
+ template <typename B, typename D>
+ explicit inline map_transformer(B const& box, D const& width, D const& height)
+ {
+ set_transformation(
+ get<min_corner, 0>(box), get<min_corner, 1>(box),
+ get<max_corner, 0>(box), get<max_corner, 1>(box),
+ width, height);
+ }
+
+ template <typename W, typename D>
+ explicit inline map_transformer(W const& wx1, W const& wy1, W const& wx2, W const& wy2,
+ D const& width, D const& height)
+ {
+ set_transformation(wx1, wy1, wx2, wy2, width, height);
+ }
+
+
+ private :
+ void set_transformation_point(double wx, double wy, double px, double py, double scalex, double scaley)
+ {
+
+ // Translate to a coordinate system centered on world coordinates (-wx, -wy)
+ M t1(3,3);
+ t1(0,0) = 1; t1(0,1) = 0; t1(0,2) = -wx;
+ t1(1,0) = 0; t1(1,1) = 1; t1(1,2) = -wy;
+ t1(2,0) = 0; t1(2,1) = 0; t1(2,2) = 1;
+
+ // Scale the map
+ M s(3,3);
+ s(0,0) = scalex; s(0,1) = 0; s(0,2) = 0;
+ s(1,0) = 0; s(1,1) = scaley; s(1,2) = 0;
+ s(2,0) = 0; s(2,1) = 0; s(2,2) = 1;
+
+ // Translate to a coordinate system centered on the specified pixels (+px, +py)
+ M t2(3, 3);
+ t2(0,0) = 1; t2(0,1) = 0; t2(0,2) = px;
+ t2(1,0) = 0; t2(1,1) = 1; t2(1,2) = py;
+ t2(2,0) = 0; t2(2,1) = 0; t2(2,2) = 1;
+
+ // Calculate combination matrix in two steps
+ this->m_matrix = boost::numeric::ublas::prod(s, t1);
+ this->m_matrix = boost::numeric::ublas::prod(t2, this->m_matrix);
+ }
+
+
+ template <typename W, typename D>
+ void set_transformation(W const& wx1, W const& wy1, W const& wx2, W const& wy2,
+ D const& width, D const& height)
+ {
+ D px1 = 0;
+ D py1 = 0;
+ D px2 = width;
+ D py2 = height;
+
+ // Get the same type, but at least a double
+ typedef typename select_most_precise<D, double>::type type;
+
+
+ // Calculate appropriate scale, take min because whole box must fit
+ // Scale is in PIXELS/MAPUNITS (meters)
+ type sx = type(px2 - px1) / type(wx2 - wx1);
+ type sy = type(py2 - py1) / type(wy2 - wy1);
+
+ if (SameScale)
+ {
+ type scale = (std::min)(sx, sy);
+ sx = scale;
+ sy = scale;
+ }
+
+ // Calculate centerpoints
+ type wmx = type(wx1 + wx2) / 2.0;
+ type wmy = type(wy1 + wy2) / 2.0;
+ type pmx = type(px1 + px2) / 2.0;
+ type pmy = type(py1 + py2) / 2.0;
+
+ set_transformation_point(wmx, wmy, pmx, pmy, sx, sy);
+
+ if (Mirror)
+ {
+ // Mirror in y-direction
+ M m(3,3);
+ m(0,0) = 1; m(0,1) = 0; m(0,2) = 0;
+ m(1,0) = 0; m(1,1) = -1; m(1,2) = 0;
+ m(2,0) = 0; m(2,1) = 0; m(2,2) = 1;
+
+ // Translate in y-direction such that it fits again
+ M y(3, 3);
+ y(0,0) = 1; y(0,1) = 0; y(0,2) = 0;
+ y(1,0) = 0; y(1,1) = 1; y(1,2) = height;
+ y(2,0) = 0; y(2,1) = 0; y(2,2) = 1;
+
+ // Calculate combination matrix in two steps
+ this->m_matrix = boost::numeric::ublas::prod(m, this->m_matrix);
+ this->m_matrix = boost::numeric::ublas::prod(y, this->m_matrix);
+ }
+ }
+};
+
+}} // namespace strategy::transform
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP

Added: sandbox/geometry/boost/geometry/strategies/transform/matrix_transformers.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/strategies/transform/matrix_transformers.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,398 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP
+#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP
+
+// Remove the ublas checking, otherwise the inverse might fail
+// (while nothing seems to be wrong)
+#define BOOST_UBLAS_TYPE_CHECK 0
+
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/numeric/ublas/vector.hpp>
+#include <boost/numeric/ublas/matrix.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+namespace boost { namespace geometry {
+
+namespace strategy { namespace transform {
+
+/*!
+ \brief Affine transformation strategy in Cartesian system.
+ \details The strategy serves as a generic definition of affine transformation matrix
+ and procedure of application it to given point.
+ \see http://en.wikipedia.org/wiki/Affine_transformation
+ and http://www.devmaster.net/wiki/Transformation_matrices
+ \ingroup transform
+ \tparam P1 first point type (source)
+ \tparam P2 second point type (target)
+ \tparam Dimension1 number of dimensions to transform from first point, optional
+ \tparam Dimension1 number of dimensions to transform to second point, optional
+ */
+template
+<
+ typename P1, typename P2,
+ std::size_t Dimension1,
+ std::size_t Dimension2
+>
+class ublas_transformer
+{
+};
+
+
+template <typename P1, typename P2>
+class ublas_transformer<P1, P2, 2, 2>
+{
+protected :
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+ typedef coordinate_type ct; // Abbreviation
+ typedef boost::numeric::ublas::matrix<coordinate_type> matrix_type;
+ matrix_type m_matrix;
+
+public :
+
+ inline ublas_transformer(
+ ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
+ ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
+ ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
+ : m_matrix(3, 3)
+ {
+ m_matrix(0,0) = m_0_0; m_matrix(0,1) = m_0_1; m_matrix(0,2) = m_0_2;
+ m_matrix(1,0) = m_1_0; m_matrix(1,1) = m_1_1; m_matrix(1,2) = m_1_2;
+ m_matrix(2,0) = m_2_0; m_matrix(2,1) = m_2_1; m_matrix(2,2) = m_2_2;
+ }
+
+ inline ublas_transformer(matrix_type const& matrix)
+ : m_matrix(matrix)
+ {}
+
+
+ inline ublas_transformer() : m_matrix(3, 3) {}
+
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ assert_dimension_greater_equal<P1, 2>();
+ assert_dimension_greater_equal<P2, 2>();
+
+ coordinate_type const& c1 = get<0>(p1);
+ coordinate_type const& c2 = get<1>(p1);
+
+ typedef typename geometry::coordinate_type<P2>::type ct2;
+
+ set<0>(p2, boost::numeric_cast<ct2>(
+ c1 * m_matrix(0,0) + c2 * m_matrix(0,1) + m_matrix(0,2)));
+ set<1>(p2, boost::numeric_cast<ct2>(
+ c1 * m_matrix(1,0) + c2 * m_matrix(1,1) + m_matrix(1,2)));
+
+ return true;
+ }
+
+ matrix_type const& matrix() const { return m_matrix; }
+};
+
+
+// It IS possible to go from 3 to 2 coordinates
+template <typename P1, typename P2>
+struct ublas_transformer<P1, P2, 3, 2> : public ublas_transformer<P1, P2, 2, 2>
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+ typedef coordinate_type ct; // Abbreviation
+
+ inline ublas_transformer(
+ ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
+ ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
+ ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
+ : ublas_transformer<P1, P2, 2, 2>(
+ m_0_0, m_0_1, m_0_2,
+ m_1_0, m_1_1, m_1_2,
+ m_2_0, m_2_1, m_2_2)
+ {}
+
+ inline ublas_transformer()
+ : ublas_transformer<P1, P2, 2, 2>()
+ {}
+};
+
+
+template <typename P1, typename P2>
+class ublas_transformer<P1, P2, 3, 3>
+{
+protected :
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+ typedef coordinate_type ct; // Abbreviation
+ typedef boost::numeric::ublas::matrix<coordinate_type> matrix_type;
+ matrix_type m_matrix;
+
+ inline ublas_transformer(
+ ct const& m_0_0, ct const& m_0_1, ct const& m_0_2, ct const& m_0_3,
+ ct const& m_1_0, ct const& m_1_1, ct const& m_1_2, ct const& m_1_3,
+ ct const& m_2_0, ct const& m_2_1, ct const& m_2_2, ct const& m_2_3,
+ ct const& m_3_0, ct const& m_3_1, ct const& m_3_2, ct const& m_3_3
+ )
+ : m_matrix(4, 4)
+ {
+ m_matrix(0,0) = m_0_0; m_matrix(0,1) = m_0_1; m_matrix(0,2) = m_0_2; m_matrix(0,3) = m_0_3;
+ m_matrix(1,0) = m_1_0; m_matrix(1,1) = m_1_1; m_matrix(1,2) = m_1_2; m_matrix(1,3) = m_1_3;
+ m_matrix(2,0) = m_2_0; m_matrix(2,1) = m_2_1; m_matrix(2,2) = m_2_2; m_matrix(2,3) = m_2_3;
+ m_matrix(3,0) = m_3_0; m_matrix(3,1) = m_3_1; m_matrix(3,2) = m_3_2; m_matrix(3,3) = m_3_3;
+ }
+
+ inline ublas_transformer() : m_matrix(4, 4) {}
+
+public :
+
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ coordinate_type const& c1 = get<0>(p1);
+ coordinate_type const& c2 = get<1>(p1);
+ coordinate_type const& c3 = get<2>(p1);
+
+ typedef typename geometry::coordinate_type<P2>::type ct2;
+
+ set<0>(p2, boost::numeric_cast<ct2>(
+ c1 * m_matrix(0,0) + c2 * m_matrix(0,1) + c3 * m_matrix(0,2) + m_matrix(0,3)));
+ set<1>(p2, boost::numeric_cast<ct2>(
+ c1 * m_matrix(1,0) + c2 * m_matrix(1,1) + c3 * m_matrix(1,2) + m_matrix(1,3)));
+ set<2>(p2, boost::numeric_cast<ct2>(
+ c1 * m_matrix(2,0) + c2 * m_matrix(2,1) + c3 * m_matrix(2,2) + m_matrix(2,3)));
+
+ return true;
+ }
+
+ matrix_type const& matrix() const { return m_matrix; }
+};
+
+
+/*!
+ \brief Strategy of translate transformation in Cartesian system.
+ \details Translate moves a geometry a fixed distance in 2 or 3 dimensions.
+ \see http://en.wikipedia.org/wiki/Translation_%28geometry%29
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ \tparam Dimension1 number of dimensions to transform from first point, optional
+ \tparam Dimension1 number of dimensions to transform to second point, optional
+ */
+template
+<
+ typename P1, typename P2,
+ std::size_t Dimension1 = geometry::dimension<P1>::type::value,
+ std::size_t Dimension2 = geometry::dimension<P2>::type::value
+>
+struct translate_transformer
+{
+};
+
+
+template <typename P1, typename P2>
+struct translate_transformer<P1, P2, 2, 2> : ublas_transformer<P1, P2, 2, 2>
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+
+ // To have translate transformers compatible for 2/3 dimensions, the
+ // constructor takes an optional third argument doing nothing.
+ inline translate_transformer(coordinate_type const& translate_x,
+ coordinate_type const& translate_y,
+ coordinate_type const& dummy = 0)
+ : ublas_transformer<P1, P2, 2, 2>(
+ 1, 0, translate_x,
+ 0, 1, translate_y,
+ 0, 0, 1)
+ {}
+};
+
+
+template <typename P1, typename P2>
+struct translate_transformer<P1, P2, 3, 3> : ublas_transformer<P1, P2, 3, 3>
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+
+ inline translate_transformer(coordinate_type const& translate_x,
+ coordinate_type const& translate_y,
+ coordinate_type const& translate_z)
+ : ublas_transformer<P1, P2, 3, 3>(
+ 1, 0, 0, translate_x,
+ 0, 1, 0, translate_y,
+ 0, 0, 1, translate_z,
+ 0, 0, 0, 1)
+ {}
+
+};
+
+
+/*!
+ \brief Strategy of scale transformation in Cartesian system.
+ \details Scale scales a geometry up or down in all its dimensions.
+ \see http://en.wikipedia.org/wiki/Scaling_%28geometry%29
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ \tparam Dimension1 number of dimensions to transform from first point, optional
+ \tparam Dimension1 number of dimensions to transform to second point, optional
+*/
+template
+<
+ typename P1, typename P2 = P1,
+ std::size_t Dimension1 = geometry::dimension<P1>::type::value,
+ std::size_t Dimension2 = geometry::dimension<P2>::type::value
+>
+struct scale_transformer
+{
+};
+
+
+template <typename P1, typename P2>
+struct scale_transformer<P1, P2, 2, 2> : ublas_transformer<P1, P2, 2, 2>
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+
+ inline scale_transformer(coordinate_type const& scale_x,
+ coordinate_type const& scale_y,
+ coordinate_type const& dummy = 0)
+ : ublas_transformer<P1, P2, 2, 2>(
+ scale_x, 0, 0,
+ 0, scale_y, 0,
+ 0, 0, 1)
+ {}
+
+
+ inline scale_transformer(coordinate_type const& scale)
+ : ublas_transformer<P1, P2, 2, 2>(
+ scale, 0, 0,
+ 0, scale, 0,
+ 0, 0, 1)
+ {}
+};
+
+
+template <typename P1, typename P2>
+struct scale_transformer<P1, P2, 3, 3> : ublas_transformer<P1, P2, 3, 3>
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+
+ inline scale_transformer(coordinate_type const& scale_x,
+ coordinate_type const& scale_y,
+ coordinate_type const& scale_z)
+ : ublas_transformer<P1, P2, 3, 3>(
+ scale_x, 0, 0, 0,
+ 0, scale_y, 0, 0,
+ 0, 0, scale_z, 0,
+ 0, 0, 0, 1)
+ {}
+
+
+ inline scale_transformer(coordinate_type const& scale)
+ : ublas_transformer<P1, P2, 3, 3>(
+ scale, 0, 0, 0,
+ 0, scale, 0, 0,
+ 0, 0, scale, 0,
+ 0, 0, 0, 1)
+ {}
+};
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail {
+
+template <typename DegreeOrRadian>
+struct as_radian
+{
+};
+
+template <>
+struct as_radian<radian>
+{
+ template <typename T>
+ static inline T get(T const& value)
+ {
+ return value;
+ }
+};
+
+template <>
+struct as_radian<degree>
+{
+ template <typename T>
+ static inline T get(T const& value)
+ {
+ return value * math::d2r;
+ }
+
+};
+
+
+template
+<
+ typename P1, typename P2,
+ std::size_t Dimension1 = geometry::dimension<P1>::type::value,
+ std::size_t Dimension2 = geometry::dimension<P2>::type::value
+>
+struct rad_rotate_transformer
+ : ublas_transformer<P1, P2, Dimension1, Dimension2>
+{
+ // Angle has type of coordinate type, but at least a double
+ typedef typename select_most_precise
+ <
+ typename select_coordinate_type<P1, P2>::type,
+ double
+ >::type angle_type;
+
+ inline rad_rotate_transformer(angle_type const& angle)
+ : ublas_transformer<P1, P2, Dimension1, Dimension2>(
+ cos(angle), sin(angle), 0,
+ -sin(angle), cos(angle), 0,
+ 0, 0, 1)
+ {}
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief Strategy of rotate transformation in Cartesian system.
+ \details Rotate rotates a geometry of specified angle about a fixed point (e.g. origin).
+ \see http://en.wikipedia.org/wiki/Rotation_%28mathematics%29
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ \tparam DegreeOrRadian degree/or/radian, type of rotation angle specification
+ \note A single angle is needed to specify a rotation in 2D.
+ Not yet in 3D, the 3D version requires special things to allow
+ for rotation around X, Y, Z or arbitrary axis.
+ \todo The 3D version will not compile.
+ */
+template <typename P1, typename P2, typename DegreeOrRadian>
+struct rotate_transformer : detail::rad_rotate_transformer<P1, P2>
+{
+ // Angle has type of coordinate type, but at least a double
+ typedef typename select_most_precise
+ <
+ typename select_coordinate_type<P1, P2>::type,
+ double
+ >::type angle_type;
+
+ inline rotate_transformer(angle_type const& angle)
+ : detail::rad_rotate_transformer
+ <
+ P1, P2
+ >(detail::as_radian<DegreeOrRadian>::get(angle))
+ {}
+};
+
+}} // namespace strategy::transform
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP

Added: sandbox/geometry/boost/geometry/util/add_const_if_c.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/util/add_const_if_c.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,50 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_ADD_CONST_IF_C_HPP
+#define BOOST_GEOMETRY_UTIL_ADD_CONST_IF_C_HPP
+
+
+#include <boost/mpl/if.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Meta-function to define a const or non const type
+ \ingroup utility
+ \details If the boolean template parameter is true, the type parameter
+ will be defined as const, otherwise it will be defined as it was.
+ This meta-function is used to have one implementation for both
+ const and non const references
+ \note This traits class is completely independant from GGL and might be a
+ separate addition to Boost
+ \note Used in a.o. for_each, interior_rings, exterior_ring
+ \par Example
+ \code
+ void foo(typename add_const_if_c<IsConst, Point>::type& point)
+ \endcode
+*/
+template <bool IsConst, typename Type>
+struct add_const_if_c
+{
+ typedef typename boost::mpl::if_c
+ <
+ IsConst,
+ const Type,
+ Type
+ >::type type;
+};
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_UTIL_ADD_CONST_IF_C_HPP

Added: sandbox/geometry/boost/geometry/util/as_range.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/util/as_range.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,98 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_AS_RANGE_HPP
+#define BOOST_GEOMETRY_UTIL_AS_RANGE_HPP
+
+#include <boost/type_traits.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/is_multi.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/util/add_const_if_c.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename GeometryTag, typename Geometry, typename Range, bool IsConst>
+struct as_range
+{
+ static inline typename add_const_if_c<IsConst, Range>::type& get(
+ typename add_const_if_c<IsConst, Geometry>::type& input)
+ {
+ return input;
+ }
+};
+
+
+template <typename Geometry, typename Range, bool IsConst>
+struct as_range<polygon_tag, Geometry, Range, IsConst>
+{
+ static inline typename add_const_if_c<IsConst, Range>::type& get(
+ typename add_const_if_c<IsConst, Geometry>::type& input)
+ {
+ return exterior_ring(input);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Function getting either the range (ring, linestring) itself
+or the outer ring (polygon)
+\details Utility to handle polygon's outer ring as a range
+\ingroup utility
+*/
+template <typename Range, typename Geometry>
+inline Range& as_range(Geometry& input)
+{
+ return dispatch::as_range
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Range,
+ false
+ >::get(input);
+}
+
+
+/*!
+\brief Function getting either the range (ring, linestring) itself
+or the outer ring (polygon), const version
+\details Utility to handle polygon's outer ring as a range
+\ingroup utility
+*/
+template <typename Range, typename Geometry>
+inline Range const& as_range(Geometry const& input)
+{
+ return dispatch::as_range
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Range,
+ true
+ >::get(input);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_UTIL_AS_RANGE_HPP

Added: sandbox/geometry/boost/geometry/util/copy.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/util/copy.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,80 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_COPY_HPP
+#define BOOST_GEOMETRY_UTIL_COPY_HPP
+
+#include <cstddef>
+
+#include <boost/concept/requires.hpp>
+#include <boost/concept_check.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace copy {
+
+template <typename Src, typename Dst, std::size_t D, std::size_t N>
+struct copy_coordinates
+{
+ static inline void copy(Src const& source, Dst& dest)
+ {
+ typedef typename coordinate_type<Dst>::type coordinate_type;
+
+ set<D>(dest, boost::numeric_cast<coordinate_type>(get<D>(source)));
+ copy_coordinates<Src, Dst, D + 1, N>::copy(source, dest);
+ }
+};
+
+template <typename Src, typename Dst, std::size_t N>
+struct copy_coordinates<Src, Dst, N, N>
+{
+ static inline void copy(Src const& , Dst& )
+ {
+ }
+};
+
+}} // namespace detail::copy
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief Copies coordinates from source to destination point
+ \ingroup assign
+ \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 Src, typename Dst>
+inline void copy_coordinates(Src const& source, Dst& dest)
+{
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Src>) );
+ BOOST_CONCEPT_ASSERT( (concept::Point<Dst>) );
+
+
+ //assert_dimension_equal<Dst, Src>();
+ detail::copy::copy_coordinates
+ <
+ Src,
+ Dst,
+ 0,
+ dimension<Src>::type::value
+ >::copy(source, dest);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_UTIL_COPY_HPP

Added: sandbox/geometry/boost/geometry/util/for_each_coordinate.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/util/for_each_coordinate.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,64 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_FOR_EACH_COORDINATE_HPP
+#define BOOST_GEOMETRY_UTIL_FOR_EACH_COORDINATE_HPP
+
+#include <boost/concept/requires.hpp>
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Point, int Dimension, int DimensionCount>
+struct coordinates_scanner
+{
+ template <typename Op>
+ static inline void apply(Point& point, Op operation)
+ {
+ operation.template apply<Point, Dimension>(point);
+ coordinates_scanner
+ <
+ Point,
+ Dimension+1,
+ DimensionCount
+ >::apply(point, operation);
+ }
+};
+
+template <typename Point, int DimensionCount>
+struct coordinates_scanner<Point, DimensionCount, DimensionCount>
+{
+ template <typename Op>
+ static inline void apply(Point&, Op)
+ {}
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+template <typename Point, typename Op>
+inline void for_each_coordinate(Point& point, Op operation)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+ typedef typename detail::coordinates_scanner
+ <
+ Point, 0, dimension<Point>::type::value
+ > scanner;
+
+ scanner::apply(point, operation);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_UTIL_FOR_EACH_COORDINATE_HPP

Added: sandbox/geometry/boost/geometry/util/for_each_range.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/util/for_each_range.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,116 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_FOR_EACH_RANGE_HPP
+#define BOOST_GEOMETRY_UTIL_FOR_EACH_RANGE_HPP
+
+
+#include <boost/concept/requires.hpp>
+
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/is_multi.hpp>
+
+#include <boost/geometry/util/add_const_if_c.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace for_each {
+
+
+template <typename Range, typename Actor, bool IsConst>
+struct fe_range_range
+{
+ static inline void apply(
+ typename add_const_if_c<IsConst, Range>::type& range,
+ Actor& actor)
+ {
+ actor.apply(range);
+ }
+};
+
+
+template <typename Polygon, typename Actor, bool IsConst>
+struct fe_range_polygon
+{
+ static inline void apply(
+ typename add_const_if_c<IsConst, Polygon>::type& polygon,
+ Actor& actor)
+ {
+ actor.apply(exterior_ring(polygon));
+
+ // TODO: If some flag says true, also do the inner rings.
+ // for convex hull, it's not necessary
+ }
+};
+
+
+}} // namespace detail::for_each
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Tag,
+ bool IsMulti,
+ typename Geometry,
+ typename Actor,
+ bool IsConst
+>
+struct for_each_range {};
+
+
+template <typename Linestring, typename Actor, bool IsConst>
+struct for_each_range<linestring_tag, false, Linestring, Actor, IsConst>
+ : detail::for_each::fe_range_range<Linestring, Actor, IsConst>
+{};
+
+
+template <typename Ring, typename Actor, bool IsConst>
+struct for_each_range<ring_tag, false, Ring, Actor, IsConst>
+ : detail::for_each::fe_range_range<Ring, Actor, IsConst>
+{};
+
+
+template <typename Polygon, typename Actor, bool IsConst>
+struct for_each_range<polygon_tag, false, Polygon, Actor, IsConst>
+ : detail::for_each::fe_range_polygon<Polygon, Actor, IsConst>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+template <typename Geometry, typename Actor>
+inline void for_each_range(Geometry const& geometry, Actor& actor)
+{
+ dispatch::for_each_range
+ <
+ typename tag<Geometry>::type,
+ is_multi<Geometry>::type::value,
+ Geometry,
+ Actor,
+ true
+ >::apply(geometry, actor);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_UTIL_FOR_EACH_RANGE_HPP

Added: sandbox/geometry/boost/geometry/util/math.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/util/math.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,132 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_MATH_HPP
+#define BOOST_GEOMETRY_UTIL_MATH_HPP
+
+#include <cmath>
+#include <limits>
+
+#include <boost/math/constants/constants.hpp>
+
+#include <boost/geometry/util/select_most_precise.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace math {
+
+
+template <typename T, bool Floating>
+struct equals
+{
+ static inline bool apply(T const& a, T const& b)
+ {
+ return a == b;
+ }
+};
+
+template <typename T>
+struct equals<T, true>
+{
+ static inline bool apply(T const& a, T const& b)
+ {
+ // See http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17,
+ // FUTURE: replace by some boost tool or boost::test::close_at_tolerance
+ return std::abs(a - b) <= std::numeric_limits<T>::epsilon() * std::abs(a);
+ }
+};
+
+
+}} // namespace detail::math
+#endif
+
+namespace math
+{
+
+
+// Maybe replace this by boost equals or boost ublas numeric equals or so
+
+/*!
+ \brief returns true if both arguments are equal.
+ \ingroup utility
+ \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. If one of the types is non-fundamental, it might
+ be a high-precision number and comparison is done using the == operator
+ of that class.
+*/
+
+template <typename T1, typename T2>
+inline bool equals(T1 const& a, T2 const& b)
+{
+ typedef typename select_most_precise<T1, T2>::type select_type;
+ return detail::math::equals
+ <
+ select_type,
+ boost::is_floating_point<select_type>::type::value
+ >::apply(a, b);
+}
+
+
+// TODO: The idea is to replace "double const globals" with inline
+// template functions, so code/data is generated if not necessary.
+// --mloskot
+//template <typename T>
+//inline T pi()
+//{
+// return boost::math::constants::pi<T>();
+//}
+//
+//template <>
+//inline double pi<double>()
+//{
+// return boost::math::constants::pi<double>();
+//}
+double const pi = boost::math::constants::pi<double>();
+double const two_pi = 2.0 * pi;
+double const d2r = pi / 180.0;
+double const r2d = 1.0 / d2r;
+
+/*!
+ \brief Calculates the haversine of an angle
+ \ingroup utility
+ \note See http://en.wikipedia.org/wiki/Haversine_formula
+ haversin(alpha) = sin2(alpha/2)
+*/
+template <typename T>
+inline T hav(T const& theta)
+{
+ using boost::math::constants::half;
+ T const sn = std::sin(half<T>() * theta);
+ return sn * sn;
+}
+
+/*!
+\brief Short utility to return the square
+\ingroup utility
+\param value Value to calculate the square from
+\return The squared value
+*/
+template <typename T>
+inline T sqr(T const& value)
+{
+ return value * value;
+}
+
+} // namespace math
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_UTIL_MATH_HPP

Added: sandbox/geometry/boost/geometry/util/range_iterator_const_if_c.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/util/range_iterator_const_if_c.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,45 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_RANGE_ITERATOR_CONST_IF_C_HPP
+#define BOOST_GEOMETRY_UTIL_RANGE_ITERATOR_CONST_IF_C_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Meta-function to define a const or non const boost range iterator
+ \ingroup utility
+ \details Is used to have one implementation for both const and non const
+ range iterators
+ \note This traits class is completely independant from GGL and might be a
+ separate addition to Boost
+ \note Used in for_each
+*/
+template <bool IsConst, typename Range>
+struct range_iterator_const_if_c
+{
+ typedef typename boost::mpl::if_c
+ <
+ IsConst,
+ typename boost::range_const_iterator<Range>::type,
+ typename boost::range_iterator<Range>::type
+ >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_UTIL_RANGE_ITERATOR_CONST_IF_C_HPP

Added: sandbox/geometry/boost/geometry/util/select_calculation_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/util/select_calculation_type.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,51 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_SELECT_CALCULATION_TYPE_HPP
+#define BOOST_GEOMETRY_UTIL_SELECT_CALCULATION_TYPE_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Meta-function selecting the "calculation" type
+ \details Based on two input geometry types, and an input calculation type,
+ (which defaults to void in the calling function), this meta-function
+ selects the most appropriate:
+ - if calculation type is specified, that one is used,
+ - if it is void, the most precise of the two points is used
+ \ingroup utility
+ */
+template <typename Geometry1, typename Geometry2, typename CalculationType>
+struct select_calculation_type
+{
+ typedef typename
+ boost::mpl::if_c
+ <
+ boost::is_void<CalculationType>::type::value,
+ typename select_coordinate_type
+ <
+ Geometry1,
+ Geometry2
+ >::type,
+ CalculationType
+ >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_UTIL_SELECT_CALCULATION_TYPE_HPP

Added: sandbox/geometry/boost/geometry/util/select_coordinate_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/util/select_coordinate_type.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,56 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_SELECT_COORDINATE_TYPE_HPP
+#define BOOST_GEOMETRY_UTIL_SELECT_COORDINATE_TYPE_HPP
+
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+/*!
+\defgroup utility utility: utility meta-functions and functions
+\details The utilities, mostly in folder util, contain several headerfiles
+not fitting in one of the other folders.
+
+The following meta-functions are general and do not relate to GGL:
+- add_const_if_c
+- range_iterator_const_if_c
+- select_most_precise
+
+They might fit into boost as a separate trait or utility, or there might
+be a Boost equivalent which is yet unnoticed by the authors.
+
+
+*/
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Meta-function selecting the most precise coordinate type
+ of two geometries
+ \ingroup utility
+ */
+template <typename T1, typename T2>
+struct select_coordinate_type
+{
+ typedef typename select_most_precise
+ <
+ typename coordinate_type<T1>::type,
+ typename coordinate_type<T2>::type
+ >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_UTIL_SELECT_COORDINATE_TYPE_HPP

Added: sandbox/geometry/boost/geometry/util/select_most_precise.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/util/select_most_precise.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,156 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
+#define BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+
+namespace detail { namespace select_most_precise {
+
+
+// At least one of the types is non-fundamental. Take that one.
+// if both are non-fundamental, the type-to-be-selected
+// is unknown, it should be defined by explicit specialization.
+template <bool Fundamental1, bool Fundamental2, typename T1, typename T2>
+struct select_non_fundamental
+{
+ typedef T1 type;
+};
+
+template <typename T1, typename T2>
+struct select_non_fundamental<true, false, T1, T2>
+{
+ typedef T2 type;
+};
+
+template <typename T1, typename T2>
+struct select_non_fundamental<false, true, T1, T2>
+{
+ typedef T1 type;
+};
+
+
+// Selection of largest type (e.g. int of <short int,int>
+// It defaults takes the first one, if second is larger, take the second one
+template <bool SecondLarger, typename T1, typename T2>
+struct select_largest
+{
+ typedef T1 type;
+};
+
+template <typename T1, typename T2>
+struct select_largest<true, T1, T2>
+{
+ typedef T2 type;
+};
+
+
+
+// Selection of floating point and specializations:
+// both FP or both !FP does never occur...
+template <bool FP1, bool FP2, typename T1, typename T2>
+struct select_floating_point
+{
+ typedef char type;
+};
+
+
+// ... so if ONE but not both of these types is floating point, take that one
+template <typename T1, typename T2>
+struct select_floating_point<true, false, T1, T2>
+{
+ typedef T1 type;
+};
+
+
+template <typename T1, typename T2>
+struct select_floating_point<false, true, T1, T2>
+{
+ typedef T2 type;
+};
+
+
+}} // namespace detail::select_most_precise
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief Meta-function to select, of two types, the most accurate type for
+ calculations
+ \ingroup utility
+ \details select_most_precise classes, 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 result can be an integer.
+ \note It is different from the "promote" class, already in boost. That
+ class promotes e.g. a (one) float to a double. This class selects a
+ type from two types. It takes the most accurate, but does not promote
+ afterwards.
+ \note This traits class is completely independant from GGL and might be a
+ separate addition to Boost
+ \note If the input is a non-fundamental type, it might be a calculation
+ type such as a GMP-value or another high precision value. Therefore,
+ if one is non-fundamental, that one is chosen.
+ \note If both types are non-fundamental, the result is indeterminate and
+ currently the first one is chosen.
+*/
+template <typename T1, typename T2>
+struct select_most_precise
+{
+ static const bool second_larger = sizeof(T2) > sizeof(T1);
+ static const bool one_not_fundamental = !
+ (boost::is_fundamental<T1>::type::value
+ && boost::is_fundamental<T2>::type::value);
+
+ static const bool both_same =
+ boost::is_floating_point<T1>::type::value
+ == boost::is_floating_point<T2>::type::value;
+
+ typedef typename boost::mpl::if_c
+ <
+ one_not_fundamental,
+ typename detail::select_most_precise::select_non_fundamental
+ <
+ boost::is_fundamental<T1>::type::value,
+ boost::is_fundamental<T2>::type::value,
+ T1,
+ T2
+ >::type,
+ typename boost::mpl::if_c
+ <
+ both_same,
+ typename detail::select_most_precise::select_largest
+ <
+ second_larger,
+ T1,
+ T2
+ >::type,
+ typename detail::select_most_precise::select_floating_point
+ <
+ boost::is_floating_point<T1>::type::value,
+ boost::is_floating_point<T2>::type::value,
+ T1,
+ T2
+ >::type
+ >::type
+ >::type type;
+};
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP

Added: sandbox/geometry/boost/geometry/util/write_dsv.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/util/write_dsv.hpp 2010-01-31 16:11:12 EST (Sun, 31 Jan 2010)
@@ -0,0 +1,389 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_WRITE_DSV_HPP
+#define BOOST_GEOMETRY_UTIL_WRITE_DSV_HPP
+
+#include <ostream>
+#include <string>
+
+#include <boost/concept_check.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/convert.hpp>
+
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/is_multi.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace dsv {
+
+
+struct dsv_settings
+{
+ std::string coordinate_separator;
+ std::string point_open;
+ std::string point_close;
+ std::string point_separator;
+ std::string list_open;
+ std::string list_close;
+ std::string list_separator;
+
+ dsv_settings(std::string const& sep
+ , std::string const& open
+ , std::string const& close
+ , std::string const& psep
+ , std::string const& lopen
+ , std::string const& lclose
+ , std::string const& lsep
+ )
+ : coordinate_separator(sep)
+ , point_open(open)
+ , point_close(close)
+ , point_separator(psep)
+ , list_open(lopen)
+ , list_close(lclose)
+ , list_separator(lsep)
+ {}
+};
+
+/*!
+\brief Stream coordinate of a point as \ref DSV
+*/
+template <typename Point, std::size_t Dimension, std::size_t Count>
+struct stream_coordinate
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Point const& point,
+ dsv_settings const& settings)
+ {
+ os << (Dimension > 0 ? settings.coordinate_separator : "")
+ << get<Dimension>(point);
+
+ stream_coordinate
+ <
+ Point, Dimension + 1, Count
+ >::apply(os, point, settings);
+ }
+};
+
+template <typename Point, std::size_t Count>
+struct stream_coordinate<Point, Count, Count>
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>&,
+ Point const&,
+ dsv_settings const& )
+ {
+ }
+};
+
+
+/*!
+\brief Stream indexed coordinate of a box/segment as \ref DSV
+*/
+template
+<
+ typename Geometry,
+ std::size_t Index,
+ std::size_t Dimension,
+ std::size_t Count
+>
+struct stream_indexed
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Geometry const& geometry,
+ dsv_settings const& settings)
+ {
+ os << (Dimension > 0 ? settings.coordinate_separator : "")
+ << get<Index, Dimension>(geometry);
+ stream_indexed
+ <
+ Geometry, Index, Dimension + 1, Count
+ >::apply(os, geometry, settings);
+ }
+};
+
+template <typename Geometry, std::size_t Index, std::size_t Count>
+struct stream_indexed<Geometry, Index, Count, Count>
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>&, Geometry const&,
+ dsv_settings const& )
+ {
+ }
+};
+
+
+
+/*!
+\brief Stream points as \ref DSV
+*/
+template <typename Point>
+struct dsv_point
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Point const& p,
+ dsv_settings const& settings)
+ {
+ os << settings.point_open;
+ stream_coordinate<Point, 0, dimension<Point>::type::value>::apply(os, p, settings);
+ os << settings.point_close;
+ }
+};
+
+/*!
+\brief Stream ranges as DSV
+\note policy is used to stream prefix/postfix, enabling derived classes to override this
+*/
+template <typename Range>
+struct dsv_range
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Range const& range,
+ dsv_settings const& settings)
+ {
+ typedef typename boost::range_const_iterator<Range>::type iterator_type;
+
+ bool first = true;
+
+ os << settings.list_open;
+
+ for (iterator_type it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ os << (first ? "" : settings.point_separator)
+ << settings.point_open;
+
+ stream_coordinate
+ <
+ point_type, 0, dimension<point_type>::type::value
+ >::apply(os, *it, settings);
+ os << settings.point_close;
+
+ first = false;
+ }
+
+ os << settings.list_close;
+ }
+
+private:
+ typedef typename boost::range_value<Range>::type point_type;
+};
+
+/*!
+\brief Stream sequence of points as DSV-part, e.g. (1 2),(3 4)
+\note Used in polygon, all multi-geometries
+*/
+
+
+template <typename Polygon>
+struct dsv_poly
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Polygon const& poly,
+ dsv_settings const& settings)
+ {
+ typedef typename ring_type<Polygon>::type ring;
+ typedef typename boost::range_const_iterator
+ <
+ typename interior_type<Polygon>::type
+ >::type iterator_type;
+
+ os << settings.list_open;
+
+ dsv_range<ring>::apply(os, exterior_ring(poly), settings);
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly));
+ ++it)
+ {
+ os << settings.list_separator;
+ dsv_range<ring>::apply(os, *it, settings);
+ }
+ os << settings.list_close;
+ }
+};
+
+template <typename Geometry, std::size_t Index>
+struct dsv_per_index
+{
+ typedef typename point_type<Geometry>::type point_type;
+
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Geometry const& geometry,
+ dsv_settings const& settings)
+ {
+ os << settings.point_open;
+ stream_indexed
+ <
+ Geometry, Index, 0, dimension<Geometry>::type::value
+ >::apply(os, geometry, settings);
+ os << settings.point_close;
+ }
+};
+
+
+template <typename Geometry>
+struct dsv_indexed
+{
+ typedef typename point_type<Geometry>::type point_type;
+
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Geometry const& geometry,
+ dsv_settings const& settings)
+ {
+ os << settings.list_open;
+ dsv_per_index<Geometry, 0>::apply(os, geometry, settings);
+ os << settings.point_separator;
+ dsv_per_index<Geometry, 1>::apply(os, geometry, settings);
+ os << settings.list_close;
+ }
+};
+
+}} // namespace detail::dsv
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+template <typename Tag, bool IsMulti, typename Geometry>
+struct dsv {};
+
+
+template <typename Point>
+struct dsv<point_tag, false, Point>
+ : detail::dsv::dsv_point<Point>
+{};
+
+
+template <typename Linestring>
+struct dsv<linestring_tag, false, Linestring>
+ : detail::dsv::dsv_range<Linestring>
+{};
+
+
+template <typename Box>
+struct dsv<box_tag, false, Box>
+ : detail::dsv::dsv_indexed<Box>
+{};
+
+template <typename Segment>
+struct dsv<segment_tag, false, Segment>
+ : detail::dsv::dsv_indexed<Segment>
+{};
+
+
+template <typename Ring>
+struct dsv<ring_tag, false, Ring>
+ : detail::dsv::dsv_range<Ring>
+{};
+
+
+template <typename Polygon>
+struct dsv<polygon_tag, false, Polygon>
+ : detail::dsv::dsv_poly<Polygon>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace dsv {
+
+
+
+// FIXME: This class is not copyable/assignable but it is used as such --mloskot
+template <typename Geometry>
+class dsv_manipulator
+{
+public:
+
+ inline dsv_manipulator(Geometry const& g,
+ dsv_settings const& settings)
+ : m_geometry(g)
+ , m_settings(settings)
+ {}
+
+ template <typename Char, typename Traits>
+ inline friend std::basic_ostream<Char, Traits>& operator<<(
+ std::basic_ostream<Char, Traits>& os,
+ dsv_manipulator const& m)
+ {
+ dispatch::dsv
+ <
+ typename tag<Geometry>::type,
+ is_multi<Geometry>::type::value,
+ Geometry
+ >::apply(os, m.m_geometry, m.m_settings);
+ os.flush();
+ return os;
+ }
+
+private:
+ Geometry const& m_geometry;
+ dsv_settings m_settings;
+};
+
+}} // namespace detail::dsv
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+\brief Main DSV-streaming function
+\details DSV stands for Delimiter Separated Values. Geometries can be streamed
+ as DSV. There are defaults for all separators.
+\note Useful for examples and testing purposes
+\note With this function GeoJSON objects can be created, using the right
+ delimiters
+\ingroup utility
+*/
+template <typename Geometry>
+inline detail::dsv::dsv_manipulator<Geometry> dsv(Geometry const& geometry
+ , std::string const& coordinate_separator = ", "
+ , std::string const& point_open = "("
+ , std::string const& point_close = ")"
+ , std::string const& point_separator = ", "
+ , std::string const& list_open = "("
+ , std::string const& list_close = ")"
+ , std::string const& list_separator = ", "
+ )
+{
+ concept::check<const Geometry>();
+
+ return detail::dsv::dsv_manipulator<Geometry>(geometry,
+ detail::dsv::dsv_settings(coordinate_separator,
+ point_open, point_close, point_separator,
+ list_open, list_close, list_separator));
+}
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_UTIL_WRITE_DSV_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