|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r56731 - in sandbox/ggl/formal_review_request: . boost boost/ggl boost/ggl/algorithms boost/ggl/algorithms/detail boost/ggl/algorithms/overlay boost/ggl/arithmetic boost/ggl/core boost/ggl/core/concepts boost/ggl/extensions boost/ggl/extensions/gis boost/ggl/extensions/gis/io boost/ggl/extensions/gis/io/wkt boost/ggl/extensions/gis/io/wkt/detail boost/ggl/extensions/io boost/ggl/extensions/io/svg boost/ggl/geometries boost/ggl/geometries/adapted boost/ggl/geometries/register boost/ggl/iterators boost/ggl/multi boost/ggl/multi/algorithms boost/ggl/multi/algorithms/detail boost/ggl/multi/algorithms/overlay boost/ggl/multi/core boost/ggl/multi/geometries boost/ggl/multi/iterators boost/ggl/policies boost/ggl/policies/relate boost/ggl/strategies boost/ggl/strategies/agnostic boost/ggl/strategies/cartesian boost/ggl/strategies/spherical boost/ggl/strategies/transform boost/ggl/util libs libs/test
From: barend.gehrels_at_[hidden]
Date: 2009-10-12 08:58:31
Author: barendgehrels
Date: 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
New Revision: 56731
URL: http://svn.boost.org/trac/boost/changeset/56731
Log:
Added branch for formal review request
Added:
sandbox/ggl/formal_review_request/
sandbox/ggl/formal_review_request/boost/
sandbox/ggl/formal_review_request/boost/ggl/
sandbox/ggl/formal_review_request/boost/ggl/algorithms/
sandbox/ggl/formal_review_request/boost/ggl/algorithms/append.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/area.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/assign.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/buffer.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/centroid.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/clear.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/combine.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/convert.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/convex_hull.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/correct.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/detail/
sandbox/ggl/formal_review_request/boost/ggl/algorithms/detail/calculate_null.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/detail/not.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/disjoint.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/distance.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/envelope.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/equals.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/for_each.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/get_section.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/intermediate.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/intersection.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/intersection_linestring.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/intersects.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/length.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/make.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/num_points.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlaps.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/
sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/adapt_turns.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/copy_segments.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/enrich_intersection_points.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/get_intersection_points.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/intersection_point.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/merge_intersection_points.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/segment_identifier.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/self_intersection_points.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/traverse.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/perimeter.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/sectionalize.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/selected.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/simplify.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/transform.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/algorithms/within.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/arithmetic/
sandbox/ggl/formal_review_request/boost/ggl/arithmetic/arithmetic.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/arithmetic/dot_product.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/
sandbox/ggl/formal_review_request/boost/ggl/core/access.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/concepts/
sandbox/ggl/formal_review_request/boost/ggl/core/concepts/box_concept.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/concepts/linestring_concept.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/concepts/nsphere_concept.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/concepts/point_concept.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/concepts/polygon_concept.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/concepts/ring_concept.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/concepts/segment_concept.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/coordinate_dimension.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/coordinate_system.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/coordinate_type.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/cs.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/exception.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/exterior_ring.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/geometry_id.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/interior_rings.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/is_linear.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/is_multi.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/point_type.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/radian_access.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/radius.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/replace_point_type.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/reverse_dispatch.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/ring_type.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/tag.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/tags.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/core/topological_dimension.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/extensions/
sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/
sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/
sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/
sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/detail/
sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/detail/wkt.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/detail/wkt_multi.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/read_wkt.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/read_wkt_multi.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/stream_wkt.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/wkt.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/write_wkt.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/write_wkt_multi.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/extensions/io/
sandbox/ggl/formal_review_request/boost/ggl/extensions/io/svg/
sandbox/ggl/formal_review_request/boost/ggl/extensions/io/svg/write_svg.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/extensions/io/svg/write_svg_multi.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/
sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/
sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/boost_array_as_linestring.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/boost_array_as_ring.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/c_array.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/c_array_cartesian.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/std_as_linestring.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/std_as_ring.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/tuple.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/tuple_cartesian.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/box.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/cartesian2d.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/cartesian3d.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/geometries.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/linear_ring.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/linestring.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/nsphere.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/point.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/point_xy.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/polygon.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/register/
sandbox/ggl/formal_review_request/boost/ggl/geometries/register/box.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/register/linestring.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/register/point.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/register/register_box.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/register/register_point.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/register/ring.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/geometries/segment.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/ggl.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/iterators/
sandbox/ggl/formal_review_request/boost/ggl/iterators/base.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/iterators/ever_circling_iterator.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/iterators/point_const_iterator.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/iterators/segment_iterator.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/area.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/centroid.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/convex_hull.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/correct.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/detail/
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/detail/modify_with_predicate.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/detail/multi_sum.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/distance.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/envelope.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/foreach.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/get_section.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/intersection.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/length.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/num_points.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/overlay/
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/overlay/copy_segments.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/overlay/get_intersection_points.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/perimeter.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/sectionalize.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/simplify.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/transform.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/within.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/core/
sandbox/ggl/formal_review_request/boost/ggl/multi/core/geometry_id.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/core/is_multi.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/core/point_type.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/core/ring_type.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/core/tags.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/core/topological_dimension.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/geometries/
sandbox/ggl/formal_review_request/boost/ggl/multi/geometries/multi_linestring.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/geometries/multi_point.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/geometries/multi_polygon.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/multi/iterators/
sandbox/ggl/formal_review_request/boost/ggl/multi/iterators/point_const_iterator.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/policies/
sandbox/ggl/formal_review_request/boost/ggl/policies/relate/
sandbox/ggl/formal_review_request/boost/ggl/policies/relate/de9im.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/policies/relate/direction.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/policies/relate/intersection_points.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/policies/relate/tupled.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/
sandbox/ggl/formal_review_request/boost/ggl/strategies/agnostic/
sandbox/ggl/formal_review_request/boost/ggl/strategies/agnostic/agn_convex_hull.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/agnostic/agn_simplify.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/agnostic/agn_within.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/
sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_area.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_centroid.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_compare.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_distance.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_envelope.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_intersect.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_side.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_within.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/distance_result.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/intersection_result.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/spherical/
sandbox/ggl/formal_review_request/boost/ggl/strategies/spherical/haversine.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/spherical/sph_area.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/spherical/sph_envelope.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/strategies.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/strategy_traits.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/strategy_transform.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/transform/
sandbox/ggl/formal_review_request/boost/ggl/strategies/transform/inverse_transformer.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/transform/map_transformer.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/strategies/transform/matrix_transformers.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/util/
sandbox/ggl/formal_review_request/boost/ggl/util/as_range.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/util/assign_box_corner.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/util/copy.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/util/for_each_coordinate.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/util/get_cs_as_radian.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/util/less.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/util/loop.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/util/math.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/util/select_coordinate_type.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/util/select_most_precise.hpp (contents, props changed)
sandbox/ggl/formal_review_request/boost/ggl/util/write_dsv.hpp (contents, props changed)
sandbox/ggl/formal_review_request/libs/
sandbox/ggl/formal_review_request/libs/test/
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/append.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/append.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,197 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_APPEND_HPP
+#define GGL_ALGORITHMS_APPEND_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/concept_check.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/point_type.hpp>
+#include <ggl/core/tags.hpp>
+#include <ggl/util/copy.hpp>
+
+namespace ggl
+{
+
+namespace traits
+{
+
+/*!
+ \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:
+ - run
+ */
+template <typename G, typename P>
+struct append_point
+{
+};
+
+} // namespace traits
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace append {
+
+template <typename G, typename P, bool Std>
+struct append_point {};
+
+template <typename G, typename P>
+struct append_point<G, P, true>
+{
+ static inline void apply(G& geometry, P const& point, int , int )
+ {
+ typename point_type<G>::type point_type;
+
+ copy_coordinates(point, point_type);
+ geometry.push_back(point_type);
+ }
+};
+
+template <typename G, typename P>
+struct append_point<G, P, false>
+{
+ static inline void apply(G& geometry, P const& point, int ring_index, int multi_index)
+ {
+ traits::append_point<G, P>::apply(geometry, point, ring_index, multi_index);
+ }
+};
+
+template <typename G, typename R, bool Std>
+struct append_range
+{
+ typedef typename boost::range_value<R>::type point_type;
+
+ static inline void apply(G& geometry, R const& range, int ring_index, int multi_index)
+ {
+ for (typename boost::range_const_iterator<R>::type it = boost::begin(range);
+ it != boost::end(range); ++it)
+ {
+ append_point<G, point_type, Std>::apply(geometry, *it, ring_index, multi_index);
+ }
+ }
+};
+
+template <typename P, typename T, bool Std>
+struct point_to_poly
+{
+ typedef typename ring_type<P>::type range_type;
+
+ static inline void apply(P& polygon, T const& point, int ring_index, int multi_index)
+ {
+ boost::ignore_unused_variable_warning(multi_index);
+
+ if (ring_index == -1)
+ {
+ append_point<range_type, T, Std>::apply(exterior_ring(polygon), point, -1, -1);
+ }
+ else if (ring_index < boost::size(interior_rings(polygon)))
+ {
+ append_point<range_type, T, Std>::apply(interior_rings(polygon)[ring_index], point, -1, -1);
+ }
+ }
+};
+
+template <typename P, typename R, bool Std>
+struct range_to_poly
+{
+ typedef typename ring_type<P>::type ring_type;
+
+ static inline void apply(P& polygon, R const& range, int ring_index, int multi_index)
+ {
+ if (ring_index == -1)
+ {
+ append_range<ring_type, R, Std>::apply(exterior_ring(polygon), range, -1, -1);
+ }
+ else if (ring_index < boost::size(interior_rings(polygon)))
+ {
+ append_range<ring_type, R, 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 P, typename RoP, bool Std>
+struct append<point_tag, TagRoP, P, RoP, Std> {};
+
+template <typename TagRoP, typename B, typename RoP, bool Std>
+struct append<box_tag, TagRoP, B, RoP, Std> {};
+
+template <typename TagRoP, typename N, typename RoP, bool Std>
+struct append<nsphere_tag, TagRoP, N, RoP, Std> {};
+
+template <typename P, typename TAG_R, typename R, bool Std>
+struct append<polygon_tag, TAG_R, P, R, Std>
+ : detail::append::range_to_poly<P, R, Std> {};
+
+template <typename P, typename T, bool Std>
+struct append<polygon_tag, point_tag, P, T, Std>
+ : detail::append::point_to_poly<P, T, 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, linear-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 G, typename RoP>
+inline void append(G& geometry, const RoP& range_or_point,
+ int ring_index = -1, int multi_index = 0)
+{
+ typedef typename boost::remove_const<G>::type ncg_type;
+
+ dispatch::append
+ <
+ typename tag<G>::type,
+ typename tag<RoP>::type,
+ ncg_type,
+ RoP,
+ traits::use_std<ncg_type>::value
+ >::apply(geometry, range_or_point, ring_index, multi_index);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_APPEND_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/area.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/area.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,252 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_AREA_HPP
+#define GGL_ALGORITHMS_AREA_HPP
+
+#include <boost/concept/requires.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/algorithms/detail/calculate_null.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+#include <ggl/core/ring_type.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/core/concepts/nsphere_concept.hpp>
+#include <ggl/strategies/strategies.hpp>
+#include <ggl/util/loop.hpp>
+#include <ggl/util/math.hpp>
+
+/*!
+\defgroup area area calculation
+
+\par Performance
+2776 * 1000 area calculations are done in 0.11 seconds (other libraries: 0.125 seconds, 0.125 seconds, 0.5 seconds)
+
+\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, circle, polygon, multi_polygon. The units are the square of the units used for the points
+defining the surface. If the polygon is defined in meters, the area is in square meters.
+
+\par Example:
+Example showing area calculation of polygons built of xy-points and of latlong-points
+\dontinclude doxygen_examples.cpp
+\skip example_area_polygon()
+\line {
+\until }
+
+*/
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace area {
+
+template<typename B, typename S>
+struct box_area
+{
+ typedef typename coordinate_type<B>::type return_type;
+
+ static inline return_type apply(B const& b, S const&)
+ {
+ // Currently only works for Cartesian boxes
+ // Todo: use strategy
+ // Todo: use concept
+ assert_dimension<B, 2>();
+
+ return_type const dx = get<max_corner, 0>(b) - get<min_corner, 0>(b);
+ return_type const dy = get<max_corner, 1>(b) - get<min_corner, 1>(b);
+
+ return dx * dy;
+ }
+};
+
+
+template<typename C, typename S>
+struct circle_area
+{
+ typedef typename coordinate_type<C>::type coordinate_type;
+
+ // Returning the coordinate precision, but if integer, returning a double
+ typedef typename boost::mpl::if_c
+ <
+ boost::is_integral<coordinate_type>::type::value,
+ double,
+ coordinate_type
+ >::type return_type;
+
+ static inline return_type apply(C const& c, S const&)
+ {
+ // Currently only works for Cartesian circles
+ // Todo: use strategy
+ // Todo: use concept
+ assert_dimension<C, 2>();
+
+ return_type r = get_radius<0>(c);
+ r *= r * ggl::math::pi;
+ return r;
+ }
+};
+
+
+// Area of a linear linear_ring, assuming a closed linear_ring
+template<typename R, typename S>
+struct ring_area
+{
+ typedef typename S::return_type type;
+ static inline type apply(R const& ring, S const& strategy)
+ {
+ assert_dimension<R, 2>();
+
+ // A closed linear_ring has at least four points, if not there is no area
+ if (boost::size(ring) >= 4)
+ {
+ typename S::state_type state_type;
+ if (loop(ring, strategy, state_type))
+ {
+ return state_type.area();
+ }
+ }
+
+ return type();
+ }
+};
+
+// Area of a polygon, either clockwise or anticlockwise
+template<typename Polygon, typename Strategy>
+class polygon_area
+{
+ typedef typename Strategy::return_type type;
+ static inline type call_abs(type const& v)
+ {
+#if defined(NUMERIC_ADAPTOR_INCLUDED)
+ return boost::abs(v);
+#else
+ return std::abs(v);
+#endif
+ }
+
+public:
+ static inline type apply(Polygon const& poly,
+ Strategy const& strategy)
+ {
+ assert_dimension<Polygon, 2>();
+
+ typedef typename ring_type<Polygon>::type ring_type;
+ typedef typename boost::range_const_iterator
+ <
+ typename interior_type<Polygon>::type
+ >::type iterator_type;
+
+ type a = call_abs(
+ ring_area<ring_type, Strategy>::apply(exterior_ring(poly), strategy));
+
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly)); ++it)
+ {
+ a -= call_abs(ring_area<ring_type, Strategy>::apply(*it, strategy));
+ }
+ return a;
+ }
+};
+
+}} // namespace detail::area
+
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+template <typename Tag, typename G, typename S>
+struct area : detail::calculate_null<typename S::return_type, G, S> {};
+
+
+template <typename G, typename S>
+struct area<box_tag, G, S> : detail::area::box_area<G, S> {};
+
+
+template <typename G, typename S>
+struct area<nsphere_tag, G, S> : detail::area::circle_area<G, S> {};
+
+
+// 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 G, typename S>
+struct area<ring_tag, G, S> : detail::area::ring_area<G, S> {};
+
+template <typename G, typename S>
+struct area<polygon_tag, G, S> : detail::area::polygon_area<G, S> {};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+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 return_type;
+};
+
+/*!
+ \brief Calculate area of a geometry
+ \ingroup area
+ \details The function area returns the area of a polygon, ring, box or circle,
+ using the default area-calculation strategy. Strategies are
+ provided for cartesian ans spherical points
+ The geometries should correct, polygons should be closed and orientated clockwise, holes,
+ if any, must be orientated counter clockwise
+ \param geometry a geometry
+ \return the area
+ */
+template <typename Geometry>
+inline typename area_result<Geometry>::return_type area(Geometry const& geometry)
+{
+ typedef typename area_result<Geometry>::strategy_type strategy_type;
+
+ return dispatch::area
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ strategy_type
+ >::apply(geometry, strategy_type());
+}
+
+/*!
+ \brief Calculate area of a geometry using a 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)
+{
+ return dispatch::area
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Strategy
+ >::apply(geometry, strategy);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_AREA_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/assign.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/assign.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,410 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef GGL_ALGORITHMS_ASSIGN_HPP
+#define GGL_ALGORITHMS_ASSIGN_HPP
+
+#include <cstddef>
+
+#include <boost/concept/requires.hpp>
+#include <boost/concept_check.hpp>
+#include <boost/numeric/conversion/bounds.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <ggl/algorithms/append.hpp>
+#include <ggl/algorithms/clear.hpp>
+#include <ggl/core/access.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/radius.hpp>
+#include <ggl/core/tags.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/util/copy.hpp>
+#include <ggl/util/for_each_coordinate.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
+
+*/
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace assign {
+
+template <typename C>
+struct assign_operation
+{
+ inline assign_operation(C const& value)
+ : m_value(value)
+ {}
+
+ template <typename P, std::size_t I>
+ inline void apply(P& point) const
+ {
+ set<I>(point, m_value);
+ }
+
+private:
+
+ C 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 P>
+inline void assign_value(P& p, typename coordinate_type<P>::type const& value)
+{
+ for_each_coordinate(p,
+ assign_operation<typename coordinate_type<P>::type>(value));
+}
+
+
+
+template <typename B, std::size_t C, std::size_t I, std::size_t D>
+struct initialize
+{
+ typedef typename coordinate_type<B>::type coordinate_type;
+
+ static inline void apply(B& box, const coordinate_type& value)
+ {
+ set<C, I>(box, value);
+ initialize<B, C, I + 1, D>::apply(box, value);
+ }
+};
+
+template <typename B, std::size_t C, std::size_t D>
+struct initialize<B, C, D, D>
+{
+ typedef typename coordinate_type<B>::type coordinate_type;
+
+ static inline void apply(B& box, const coordinate_type& value)
+ {
+ boost::ignore_unused_variable_warning(box);
+ boost::ignore_unused_variable_warning(value);
+ }
+};
+
+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;
+
+ initialize
+ <
+ Box, min_corner, 0, dimension<Box>::type::value
+ >::apply(
+ box, boost::numeric::bounds<coordinate_type>::highest());
+ initialize
+ <
+ Box, max_corner, 0, dimension<Box>::type::value
+ >::apply(
+ box, boost::numeric::bounds<coordinate_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());
+ }
+};
+
+
+
+
+}} // 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 P>
+struct assign<point_tag, P, 2>
+{
+ typedef typename coordinate_type<P>::type coordinate_type;
+
+ template <typename T>
+ static inline void apply(P& 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 P>
+struct assign<point_tag, P, 3>
+{
+ typedef typename coordinate_type<P>::type coordinate_type;
+
+ template <typename T>
+ static inline void apply(P& 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 B>
+struct assign<box_tag, B, 2>
+{
+ typedef typename coordinate_type<B>::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(B& 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 S>
+struct assign<nsphere_tag, S, 2>
+{
+ typedef typename coordinate_type<S>::type coordinate_type;
+ typedef typename radius_type<S>::type radius_type;
+
+ /// 2-value version for an n-sphere is valid for circle and sets the center
+ template <typename T>
+ static inline void apply(S& sphercle, T const& c1, T const& c2)
+ {
+ set<0>(sphercle, boost::numeric_cast<coordinate_type>(c1));
+ set<1>(sphercle, boost::numeric_cast<coordinate_type>(c2));
+ }
+
+ template <typename T, typename R>
+ static inline void apply(S& sphercle, T const& c1,
+ T const& c2, R const& radius)
+ {
+ set<0>(sphercle, boost::numeric_cast<coordinate_type>(c1));
+ set<1>(sphercle, boost::numeric_cast<coordinate_type>(c2));
+ set_radius<0>(sphercle, boost::numeric_cast<radius_type>(radius));
+ }
+};
+
+template <typename S>
+struct assign<nsphere_tag, S, 3>
+{
+ typedef typename coordinate_type<S>::type coordinate_type;
+ typedef typename radius_type<S>::type radius_type;
+
+ /// 4-value version for an n-sphere is valid for a sphere and sets the center and the radius
+ template <typename T>
+ static inline void apply(S& sphercle, T const& c1, T const& c2, T const& c3)
+ {
+ set<0>(sphercle, boost::numeric_cast<coordinate_type>(c1));
+ set<1>(sphercle, boost::numeric_cast<coordinate_type>(c2));
+ set<2>(sphercle, boost::numeric_cast<coordinate_type>(c3));
+ }
+
+ /// 4-value version for an n-sphere is valid for a sphere and sets the center and the radius
+ template <typename T, typename R>
+ static inline void apply(S& sphercle, T const& c1,
+ T const& c2, T const& c3, R const& radius)
+ {
+
+ set<0>(sphercle, boost::numeric_cast<coordinate_type>(c1));
+ set<1>(sphercle, boost::numeric_cast<coordinate_type>(c2));
+ set<2>(sphercle, boost::numeric_cast<coordinate_type>(c3));
+ set_radius<0>(sphercle, boost::numeric_cast<radius_type>(radius));
+ }
+
+};
+
+
+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 G, typename T>
+inline void assign(G& geometry, T const& c1, T const& c2)
+{
+ dispatch::assign
+ <
+ typename tag<G>::type,
+ G,
+ ggl::dimension<G>::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 G, typename T>
+inline void assign(G& geometry, T const& c1, T const& c2, T const& c3)
+{
+ dispatch::assign
+ <
+ typename tag<G>::type,
+ G,
+ ggl::dimension<G>::type::value
+ >::apply(geometry, c1, c2, c3);
+}
+
+/*!
+ \brief assign center + radius to a sphere
+ \ingroup access
+ */
+template <typename G, typename T>
+inline void assign(G& geometry, T const& c1, T const& c2, T const& c3, T const& c4)
+{
+ dispatch::assign
+ <
+ typename tag<G>::type,
+ G,
+ ggl::dimension<G>::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 G, typename R>
+inline void assign(G& geometry, R const& range)
+{
+ clear(geometry);
+ ggl::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 G>
+inline void assign_inverse(G& geometry)
+{
+ dispatch::assign_inverse
+ <
+ typename tag<G>::type,
+ G
+ >::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 G the geometry type
+ */
+template <typename G>
+inline void assign_zero(G& geometry)
+{
+ dispatch::assign_zero
+ <
+ typename tag<G>::type,
+ G
+ >::apply(geometry);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_ASSIGN_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/buffer.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/buffer.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,153 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_BUFFER_HPP
+#define GGL_ALGORITHMS_BUFFER_HPP
+
+#include <cstddef>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <ggl/arithmetic/arithmetic.hpp>
+#include <ggl/core/concepts/box_concept.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/util/assign_box_corner.hpp>
+
+// Buffer functions
+// Was before: "grow" but then only for box
+// Now "buffer", but still only implemented for a box...
+
+/*!
+\defgroup buffer buffer calculation
+\par Source description:
+- OGC: Returns a geometric object that represents all Points whose distance
+from this geometric object is less than or equal to distance. Calculations are in the spatial reference system of
+this geometric object. Because of the limitations of linear interpolation, there will often be some relatively
+small error in this distance, but it should be near the resolution of the coordinates used
+\see http://en.wikipedia.org/wiki/Buffer_(GIS)
+*/
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace buffer {
+
+template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t D, std::size_t N>
+struct box_loop
+{
+ typedef typename coordinate_type<BoxOut>::type coordinate_type;
+
+ static inline void apply(BoxIn const& box_in, T const& distance, BoxOut& box_out)
+ {
+ set<C, D>(box_out, boost::numeric_cast<coordinate_type>(get<C, D>(box_in) + distance));
+ box_loop<BoxIn, BoxOut, T, C, D + 1, N>::apply(box_in, distance, box_out);
+ }
+};
+
+template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t N>
+struct box_loop<BoxIn, BoxOut, T, C, N, N>
+{
+ static inline void apply(BoxIn const&, T const&, BoxOut&) {}
+};
+
+// Extends a box with the same amount in all directions
+template<typename BoxIn, typename BoxOut, typename T>
+inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out)
+{
+ assert_dimension_equal<BoxIn, BoxOut>();
+
+ static const std::size_t N = dimension<BoxIn>::value;
+
+ box_loop<BoxIn, BoxOut, T, min_corner, 0, N>::apply(box_in, -distance, box_out);
+ box_loop<BoxIn, BoxOut, T, max_corner, 0, N>::apply(box_in, +distance, box_out);
+}
+
+}} // namespace detail::buffer
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename TagIn, typename TagOut, typename Input, typename T, typename Output>
+struct buffer {};
+
+
+template <typename BoxIn, typename T, typename BoxOut>
+struct buffer<box_tag, box_tag, BoxIn, T, BoxOut>
+{
+ static inline void apply(BoxIn const& box_in, T const& distance,
+ T const& chord_length, BoxIn& box_out)
+ {
+ detail::buffer::buffer_box(box_in, distance, box_out);
+ }
+};
+
+// Many things to do. Point is easy, other geometries require self intersections
+// For point, note that it should output as a polygon (like the rest). Buffers
+// of a set of geometries are often lateron combined using a "dissolve" operation.
+// Two points close to each other get a combined kidney shaped buffer then.
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Calculate buffer (= new geometry) around specified distance of geometry
+ \ingroup buffer
+ \param geometry_in input geometry
+ \param distance the distance used in buffer
+ \param chord_length length of the chord's in the generated arcs around points or bends
+ \param geometry_out buffered geometry
+ \note Currently only implemented for box, the trivial case, but still useful
+ \par Use case:
+ BOX + distance -> BOX: it is allowed that "geometry_out" the same object as "geometry_in"
+ */
+template <typename Input, typename Output, typename T>
+inline void buffer(const Input& geometry_in, Output& geometry_out,
+ T const& distance, T const& chord_length = -1)
+{
+ dispatch::buffer
+ <
+ typename tag<Input>::type,
+ typename tag<Output>::type,
+ Input,
+ T,
+ Output
+ >::apply(geometry_in, distance, chord_length, geometry_out);
+}
+
+/*!
+ \brief Calculate and return buffer (= new geometry) around specified distance of geometry
+ \ingroup buffer
+ \param geometry input geometry
+ \param distance the distance used in buffer
+ \param chord_length length of the chord's in the generated arcs around points or bends
+ \return the buffered geometry
+ \note See also: buffer
+ */
+template <typename Output, typename Input, typename T>
+Output make_buffer(const Input& geometry, T const& distance, T const& chord_length = -1)
+{
+ Output geometry_out;
+
+ dispatch::buffer
+ <
+ typename tag<Input>::type,
+ typename tag<Output>::type,
+ Input,
+ T,
+ Output
+ >::apply(geometry, distance, chord_length, geometry_out);
+
+ return geometry_out;
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_BUFFER_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/centroid.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/centroid.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,277 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_CENTROID_HPP
+#define GGL_ALGORITHMS_CENTROID_HPP
+
+#include <cstddef>
+
+#include <boost/concept/requires.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/core/cs.hpp>
+#include <ggl/core/exception.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/strategies/strategies.hpp>
+#include <ggl/util/copy.hpp>
+#include <ggl/util/loop.hpp>
+
+/*!
+\defgroup centroid centroid calculation
+\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 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 There are versions where the centroid calculation strategy can be specified
+\par Geometries:
+- RING: \image html centroid_ring.png
+- BOX: the centroid of a 2D or 3D box is the center of the box
+- CIRCLE: the centroid of a circle or a sphere is its center
+- POLYGON \image html centroid_polygon.png
+- POINT, LINESTRING, SEGMENT: trying to calculate the centroid will result in a compilation error
+*/
+
+namespace ggl
+{
+
+class centroid_exception : public ggl::exception
+{
+public:
+
+ centroid_exception() {}
+
+ virtual char const* what() const throw()
+ {
+ return "centroid calculation exception";
+ }
+};
+
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace centroid {
+
+/*!
+ \brief Generic function which checks if enough points are present
+*/
+template<typename P, typename R>
+inline bool ring_ok(R const& ring, P& c)
+{
+ std::size_t const n = boost::size(ring);
+ if (n > 1)
+ {
+ return true;
+ }
+ else if (n <= 0)
+ {
+ throw centroid_exception();
+ }
+ else
+ {
+ // n == 1: Take over the first point in a "coordinate neutral way"
+ copy_coordinates(ring.front(), c);
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \brief Calculate the centroid of a ring.
+*/
+template<typename Ring, typename Point, typename Strategy>
+struct centroid_ring
+{
+ static inline void apply(Ring const& ring, Point& c, Strategy const& strategy)
+ {
+ if (ring_ok(ring, c))
+ {
+ typename Strategy::state_type state;
+ loop(ring, strategy, state);
+ state.centroid(c);
+ }
+ }
+};
+
+
+/*!
+ \brief Centroid of a polygon.
+ \note Because outer ring is clockwise, inners are counter clockwise,
+ triangle approach is OK and works for polygons with rings.
+*/
+template<typename Polygon, typename Point, typename Strategy>
+struct centroid_polygon
+{
+ static inline void apply(Polygon const& poly, Point& c, Strategy const& strategy)
+ {
+ if (ring_ok(exterior_ring(poly), c))
+ {
+ typename Strategy::state_type state;
+
+ loop(exterior_ring(poly), strategy, state);
+
+ typedef typename boost::range_const_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)
+ {
+ loop(*it, strategy, state);
+ }
+ state.centroid(c);
+ }
+ }
+};
+
+/*!
+ \brief Calculate centroid (==center) of a box
+ \todo Implement strategy
+*/
+template<typename Box, typename Point, typename Strategy>
+struct centroid_box
+{
+ static inline void apply(Box const& box, Point& c, Strategy const&)
+ {
+ // TODO: adapt using strategies
+ assert_dimension<Box, 2>();
+ set<0>(c, (get<min_corner, 0>(box) + get<max_corner, 0>(box)) / 2);
+ set<1>(c, (get<min_corner, 1>(box) + get<max_corner, 1>(box)) / 2);
+ }
+};
+
+}} // 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 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 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
+ \ingroup centroid
+ \details The function centroid calculates the centroid of a geometry using the default strategy.
+ A polygon should be closed and orientated clockwise, holes, if any, must be orientated
+ counter clockwise
+ \param geometry a geometry (e.g. closed ring or polygon)
+ \param c reference to point which will contain the centroid
+ \exception centroid_exception if calculation is not successful, e.g. because polygon didn't contain points
+ \par Example:
+ Example showing centroid calculation
+ \dontinclude doxygen_examples.cpp
+ \skip example_centroid_polygon
+ \line {
+ \until }
+ */
+template<typename G, typename P>
+inline void centroid(const G& geometry, P& c)
+{
+ typedef typename point_type<G>::type point_type;
+ typedef typename strategy_centroid
+ <
+ typename cs_tag<point_type>::type,
+ P,
+ point_type
+ >::type strategy_type;
+
+ dispatch::centroid
+ <
+ typename tag<G>::type,
+ G,
+ P,
+ strategy_type
+ >::apply(geometry, c, strategy_type());
+}
+
+/*!
+ \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
+ \exception centroid_exception if calculation is not successful, e.g. because polygon didn't contain points
+ */
+template<typename G, typename P, typename S>
+inline void centroid(const G& geometry, P& c, S const& strategy)
+{
+ dispatch::centroid
+ <
+ typename tag<G>::type,
+ G,
+ P,
+ S
+ >::apply(geometry, c, strategy);
+}
+
+// Versions returning a centroid
+
+/*!
+ \brief Calculate and return centroid
+ \ingroup centroid
+ \param geometry the geometry to calculate centroid from
+ \return the centroid
+ \exception centroid_exception if calculation is not successful, e.g. because polygon didn't contain points
+ */
+template<typename P, typename G>
+inline P make_centroid(const G& geometry)
+{
+ P c;
+ centroid(geometry, c);
+ return c;
+}
+
+/*!
+ \brief Calculate and return centroid
+ \ingroup centroid
+ \param geometry the geometry to calculate centroid from
+ \param strategy Calculation strategy for centroid
+ \return the centroid
+ \exception centroid_exception if calculation is not successful, e.g. because polygon didn't contain points
+ */
+template<typename P, typename G, typename S>
+inline P make_centroid(const G& geometry, S const& strategy)
+{
+ P c;
+ centroid(geometry, c, strategy);
+ return c;
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_CENTROID_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/clear.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/clear.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,161 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_CLEAR_HPP
+#define GGL_ALGORITHMS_CLEAR_HPP
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+
+namespace ggl
+{
+
+// This traits is currently NOT defined in ../core/ but here, just because it default
+// does not have to be implemented
+namespace traits
+{
+
+/*!
+ \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 G>
+struct clear
+{
+};
+
+} // namespace traits
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace clear {
+
+template <typename G>
+struct use_std_clear
+{
+ static inline void apply(G& geometry)
+ {
+ geometry.clear();
+ }
+};
+
+template <typename G>
+struct use_traits_clear
+{
+ static inline void apply(G& geometry)
+ {
+ traits::clear<G>::apply(geometry);
+ }
+};
+
+template <typename P>
+struct polygon_clear
+{
+ static inline void apply(P& polygon)
+ {
+ interior_rings(polygon).clear();
+ exterior_ring(polygon).clear();
+ }
+};
+
+template <typename G>
+struct no_action
+{
+ static inline void apply(G& geometry)
+ {
+ }
+};
+
+}} // namespace detail::clear
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, bool Std, typename G>
+struct clear
+{};
+
+// True (default for all geometry types, unless otherwise implemented in traits)
+// uses std::clear
+template <typename Tag, typename G>
+struct clear<Tag, true, G>
+ : detail::clear::use_std_clear<G>
+{};
+
+// If any geometry specializes use_std<G> to false, specialize to use the traits clear.
+template <typename Tag, typename G>
+struct clear<Tag, false, G>
+ : detail::clear::use_traits_clear<G>
+{};
+
+// Point/box/nsphere/segment do not have clear. So specialize to do nothing.
+template <typename G>
+struct clear<point_tag, true, G>
+ : detail::clear::no_action<G>
+{};
+
+template <typename G>
+struct clear<box_tag, true, G>
+ : detail::clear::no_action<G>
+{};
+
+template <typename G>
+struct clear<segment_tag, true, G>
+ : detail::clear::no_action<G>
+{};
+
+
+template <typename G>
+struct clear<nsphere_tag, true, G>
+ : detail::clear::no_action<G>
+{};
+
+
+// Polygon can (indirectly) use std for clear
+template <typename P>
+struct clear<polygon_tag, true, P>
+ : detail::clear::polygon_clear<P>
+{};
+
+
+} // 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 G>
+inline void clear(G& geometry)
+{
+ typedef typename boost::remove_const<G>::type ncg_type;
+
+ dispatch::clear
+ <
+ typename tag<G>::type,
+ traits::use_std<ncg_type>::value,
+ ncg_type
+ >::apply(geometry);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_CLEAR_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/combine.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/combine.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,189 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_COMBINE_HPP
+#define GGL_ALGORITHMS_COMBINE_HPP
+
+#include <cstddef>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <ggl/arithmetic/arithmetic.hpp>
+#include <ggl/core/coordinate_dimension.hpp>
+#include <ggl/core/concepts/box_concept.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/util/assign_box_corner.hpp>
+#include <ggl/util/select_coordinate_type.hpp>
+
+/*!
+\defgroup combine combine: add a geometry to a bounding box
+\par Geometries:
+- BOX + BOX -> BOX: the box will be combined with the other box \image html combine_box_box.png
+- BOX + POINT -> BOX: the box will combined with the point \image html combine_box_point.png
+\note Previously called "grow"
+*/
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace combine {
+
+template
+<
+ typename Box, typename Point,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct point_loop
+{
+ typedef typename coordinate_type<Point>::type coordinate_type;
+
+ static inline void apply(Box& box, Point const& source)
+ {
+ coordinate_type const coord = get<Dimension>(source);
+
+ if (coord < get<min_corner, Dimension>(box))
+ {
+ set<min_corner, Dimension>(box, coord );
+ }
+
+ if (coord > get<max_corner, Dimension>(box))
+ {
+ set<max_corner, Dimension>(box, coord);
+ }
+
+ point_loop<Box, Point, Dimension + 1, DimensionCount>::apply(box, source);
+ }
+};
+
+
+template
+<
+ typename Box, typename Point,
+ std::size_t DimensionCount
+>
+struct point_loop<Box, Point, DimensionCount, DimensionCount>
+{
+ static inline void apply(Box&, Point const&) {}
+};
+
+
+template
+<
+ typename BoxIn, typename BoxOut,
+ std::size_t Corner,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct box_loop
+{
+ typedef typename select_coordinate_type<BoxIn, BoxOut>::type coordinate_type;
+
+ static inline void apply(BoxIn& box, BoxOut const& source)
+ {
+ coordinate_type const coord = get<Corner, Dimension>(source);
+
+ if (coord < get<min_corner, Dimension>(box))
+ {
+ set<min_corner, Dimension>(box, coord);
+ }
+
+ if (coord > get<max_corner, Dimension>(box))
+ {
+ set<max_corner, Dimension>(box, coord);
+ }
+
+ box_loop
+ <
+ BoxIn, BoxOut, Corner, Dimension + 1, DimensionCount
+ >::apply(box, source);
+ }
+};
+
+
+template
+<
+ typename BoxIn, typename BoxOut,
+ std::size_t Corner, std::size_t DimensionCount
+>
+struct box_loop<BoxIn, BoxOut, Corner, DimensionCount, DimensionCount>
+{
+ static inline void apply(BoxIn&, BoxOut const&) {}
+};
+
+
+// Changes a box b such that it also contains point p
+template<typename Box, typename Point>
+struct combine_box_with_point
+ : point_loop<Box, Point, 0, dimension<Point>::type::value>
+{};
+
+
+// Changes a box such that the other box is also contained by the box
+template<typename BoxOut, typename BoxIn>
+struct combine_box_with_box
+{
+ static inline void apply(BoxOut& b, BoxIn const& other)
+ {
+ box_loop<BoxOut, BoxIn, min_corner, 0,
+ dimension<BoxIn>::type::value>::apply(b, other);
+ box_loop<BoxOut, BoxIn, max_corner, 0,
+ dimension<BoxIn>::type::value>::apply(b, other);
+ }
+};
+
+}} // namespace detail::combine
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, typename BoxOut, typename Geometry>
+struct combine
+{};
+
+
+// Box + point -> new box containing also point
+template <typename BoxOut, typename Point>
+struct combine<point_tag, BoxOut, Point>
+ : detail::combine::combine_box_with_point<BoxOut, Point>
+{};
+
+
+// Box + box -> new box containing two input boxes
+template <typename BoxOut, typename BoxIn>
+struct combine<box_tag, BoxOut, BoxIn>
+ : detail::combine::combine_box_with_box<BoxOut, BoxIn>
+{};
+
+
+} // 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
+ */
+template <typename Box, typename Geometry>
+inline void combine(Box& box, Geometry const& geometry)
+{
+ assert_dimension_equal<Box, Geometry>();
+ dispatch::combine
+ <
+ typename tag<Geometry>::type,
+ Box, Geometry
+ >::apply(box, geometry);
+}
+
+} // namespace ggl
+
+#endif // GGL_COMBINE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/convert.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/convert.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,161 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_CONVERT_HPP
+#define GGL_ALGORITHMS_CONVERT_HPP
+
+#include <cstddef>
+
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/algorithms/append.hpp>
+#include <ggl/algorithms/for_each.hpp>
+#include <ggl/core/cs.hpp>
+#include <ggl/geometries/segment.hpp>
+#include <ggl/strategies/strategies.hpp>
+
+/*!
+\defgroup convert convert geometries from one type to another
+\details Convert from one geometry type to another type, for example from BOX to POLYGON
+*/
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace convert {
+
+template <typename P, typename B, std::size_t C, std::size_t D, std::size_t N>
+struct point_to_box
+{
+ static inline void apply(P const& point, B& box)
+ {
+ typedef typename coordinate_type<B>::type coordinate_type;
+
+ set<C, D>(box, boost::numeric_cast<coordinate_type>(get<D>(point)));
+ point_to_box<P, B, C, D + 1, N>::apply(point, box);
+ }
+};
+
+template <typename P, typename B, std::size_t C, std::size_t N>
+struct point_to_box<P, B, C, N, N>
+{
+ static inline void apply(P const& point, B& box)
+ {}
+};
+
+}} // namespace detail::convert
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename T1, typename T2, typename G1, typename G2>
+struct convert
+{
+};
+
+template <typename T, typename G1, typename G2>
+struct convert<T, T, G1, G2>
+{
+ // Same geometry type -> copy coordinates from G1 to G2
+};
+
+template <typename T, typename G>
+struct convert<T, T, G, G>
+{
+ // Same geometry -> can be copied
+};
+
+
+// Partial specializations
+template <typename B, typename R>
+struct convert<box_tag, ring_tag, B, R>
+{
+ static inline void apply(B const& box, R& ring)
+ {
+ // go from box to ring -> add coordinates in correct order
+ // only valid for 2D
+ assert_dimension<B, 2>();
+
+ ring.clear();
+ typename point_type<B>::type point;
+
+ ggl::assign(point, get<min_corner, 0>(box), get<min_corner, 1>(box));
+ ggl::append(ring, point);
+
+ ggl::assign(point, get<min_corner, 0>(box), get<max_corner, 1>(box));
+ ggl::append(ring, point);
+
+ ggl::assign(point, get<max_corner, 0>(box), get<max_corner, 1>(box));
+ ggl::append(ring, point);
+
+ ggl::assign(point, get<max_corner, 0>(box), get<min_corner, 1>(box));
+ ggl::append(ring, point);
+
+ ggl::assign(point, get<min_corner, 0>(box), get<min_corner, 1>(box));
+ ggl::append(ring, point);
+ }
+};
+
+template <typename B, typename P>
+struct convert<box_tag, polygon_tag, B, P>
+{
+ static inline void apply(B const& box, P& polygon)
+ {
+ typedef typename ring_type<P>::type ring_type;
+
+ convert<box_tag, ring_tag, B, ring_type>::apply(box, exterior_ring(polygon));
+ }
+};
+
+template <typename P, typename B>
+struct convert<point_tag, box_tag, P, B>
+{
+ static inline void apply(P const& point, B& box)
+ {
+ // go from point to box -> box with volume of zero, 2D or 3D
+ static const std::size_t N = dimension<P>::value;
+
+ detail::convert::point_to_box<P, B, min_corner, 0, N>::apply(point, box);
+ detail::convert::point_to_box<P, B, max_corner, 0, N>::apply(point, box);
+ }
+};
+
+} // 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 G1 first geometry type
+ \tparam G2 second geometry type
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ */
+template <typename G1, typename G2>
+inline void convert(G1 const& geometry1, G2& geometry2)
+{
+ dispatch::convert
+ <
+ typename tag<G1>::type,
+ typename tag<G2>::type,
+ G1,
+ G2
+ >::apply(geometry1, geometry2);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_CONVERT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/convex_hull.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/convex_hull.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,127 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_CONVEX_HULL_HPP
+#define GGL_ALGORITHMS_CONVEX_HULL_HPP
+
+
+#include <boost/concept/requires.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <ggl/core/cs.hpp>
+#include <ggl/core/is_multi.hpp>
+
+#include <ggl/core/concepts/point_concept.hpp>
+
+
+#include <ggl/strategies/strategies.hpp>
+#include <ggl/util/as_range.hpp>
+
+
+/*!
+\defgroup convex_hull convex hull calculation
+\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.52 seconds (other libraries: 2.8 seconds, 2.4 seconds, 3.4 seconds, 1.1 seconds)
+
+\note The convex hull is always a ring, holes are not possible. Therefore it is modelled as an output iterator.
+This gives the most flexibility, the user can decide what to do with it.
+\par Geometries:
+In the images below the convex hull is painted in red.
+- POINT: will not compile
+- POLYGON: will deliver a polygon without holes \image html convexhull_polygon_polygon.png
+*/
+namespace ggl {
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace convex_hull {
+
+template <typename Geometry, typename OutputIterator>
+struct hull
+{
+ static inline OutputIterator apply(Geometry const& geometry,
+ OutputIterator out)
+ {
+ typedef typename point_type<Geometry>::type point_type;
+
+ typedef typename strategy_convex_hull
+ <
+ typename cs_tag<point_type>::type,
+ point_type
+ >::type strategy_type;
+
+ strategy_type s(as_range<typename as_range_type<Geometry>::type>(geometry));
+ s.get(out);
+ return out;
+ }
+};
+
+
+}} // namespace detail::convex_hull
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename GeometryTag,
+ bool IsMulti,
+ typename Geometry,
+ typename OutputIterator
+ >
+struct convex_hull {};
+
+template <typename Linestring, typename OutputIterator>
+struct convex_hull<linestring_tag, false, Linestring, OutputIterator>
+ : detail::convex_hull::hull<Linestring, OutputIterator>
+{};
+
+template <typename Ring, typename OutputIterator>
+struct convex_hull<ring_tag, false, Ring, OutputIterator>
+ : detail::convex_hull::hull<Ring, OutputIterator>
+{};
+
+template <typename Polygon, typename OutputIterator>
+struct convex_hull<polygon_tag, false, Polygon, OutputIterator>
+ : detail::convex_hull::hull<Polygon, OutputIterator>
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+/*!
+ \brief Calculate the convex hull of a geometry
+ \ingroup convex_hull
+ \param geometry the geometry to calculate convex hull from
+ \param out an output iterator outputing points of the convex hull
+ \return the output iterator
+ */
+template<typename Geometry, typename OutputIterator>
+inline OutputIterator convex_hull(Geometry const& geometry, OutputIterator out)
+{
+ typedef typename boost::remove_const<Geometry>::type ncg_type;
+
+ return dispatch::convex_hull
+ <
+ typename tag<ncg_type>::type,
+ is_multi<ncg_type>::type::value,
+ Geometry,
+ OutputIterator
+ >::apply(geometry, out);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_CONVEX_HULL_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/correct.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/correct.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,161 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_CORRECT_HPP
+#define GGL_ALGORITHMS_CORRECT_HPP
+
+#include <algorithm>
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/core/cs.hpp>
+#include <ggl/core/ring_type.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+
+#include <ggl/core/concepts/point_concept.hpp>
+
+#include <ggl/algorithms/area.hpp>
+#include <ggl/algorithms/disjoint.hpp>
+
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace correct {
+
+// correct an box: make min/max are correct
+template <typename B>
+inline void correct_box(B& b)
+{
+ // Currently only for Cartesian coordinates
+ // TODO: adapt using strategies
+ // TODO: adapt using traits
+ typedef typename coordinate_type<B>::type coordinate_type;
+
+ if (get<min_corner, 0>(b) > get<max_corner, 0>(b))
+ {
+ coordinate_type max_value = get<min_corner, 0>(b);
+ coordinate_type min_value = get<max_corner, 0>(b);
+ set<min_corner, 0>(b, min_value);
+ set<max_corner, 0>(b, max_value);
+ }
+
+ if (get<min_corner, 1>(b) > get<max_corner, 1>(b))
+ {
+ coordinate_type max_value = get<min_corner, 1>(b);
+ coordinate_type min_value = get<max_corner, 1>(b);
+ set<min_corner, 1>(b, min_value);
+ set<max_corner, 1>(b, max_value);
+ }
+}
+
+// close a linear_ring, if not closed
+template <typename R>
+inline void ensure_closed_ring(R& r)
+{
+ if (boost::size(r) > 2)
+ {
+ // check if closed, if not, close it
+ if (ggl::disjoint(r.front(), r.back()))
+ {
+ r.push_back(r.front());
+ }
+ }
+}
+
+// correct a polygon: normalizes all rings, sets outer linear_ring clockwise, sets all
+// inner rings counter clockwise
+template <typename Y>
+inline void correct_polygon(Y& poly)
+{
+ typename ring_type<Y>::type& outer = exterior_ring(poly);
+ ensure_closed_ring(outer);
+
+ typedef typename point_type<Y>::type point_type;
+ typedef typename ring_type<Y>::type ring_type;
+ typedef typename strategy_area
+ <
+ typename cs_tag<point_type>::type,
+ point_type
+ >::type strategy_type;
+
+ strategy_type strategy;
+
+ if (detail::area::ring_area<ring_type, strategy_type>::apply(outer, strategy) < 0)
+ {
+ std::reverse(boost::begin(outer), boost::end(outer));
+ }
+
+ typedef typename boost::range_iterator
+ <
+ typename interior_type<Y>::type
+ >::type iterator_type;
+
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly)); ++it)
+ {
+ ensure_closed_ring(*it);
+ if (detail::area::ring_area<ring_type, strategy_type>::apply(*it, strategy) > 0)
+ {
+ std::reverse(boost::begin(*it), boost::end(*it));
+ }
+ }
+}
+
+}} // namespace detail::correct
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, typename G>
+struct correct {};
+
+template <typename B>
+struct correct<box_tag, B>
+{
+ static inline void apply(B& box)
+ {
+ detail::correct::correct_box(box);
+ }
+};
+
+template <typename R>
+struct correct<ring_tag, R>
+{
+ static inline void apply(R& ring)
+ {
+ detail::correct::ensure_closed_ring(ring);
+ }
+};
+
+template <typename P>
+struct correct<polygon_tag, P>
+{
+ static inline void apply(P& poly)
+ {
+ detail::correct::correct_polygon(poly);
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+template <typename G>
+inline void correct(G& geometry)
+{
+ dispatch::correct<typename tag<G>::type, G>::apply(geometry);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_CORRECT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/detail/calculate_null.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/detail/calculate_null.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,33 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP
+#define GGL_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template<typename ReturnValue, typename Geometry, typename Strategy>
+struct calculate_null
+{
+ static inline ReturnValue apply(Geometry const& , Strategy const&)
+ {
+ return ReturnValue();
+ }
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/detail/not.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/detail/not.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,45 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_DETAIL_NOT_HPP
+#define GGL_ALGORITHMS_DETAIL_NOT_HPP
+
+namespace ggl
+{
+
+#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 ggl
+
+#endif // GGL_ALGORITHMS_DETAIL_NOT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/disjoint.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/disjoint.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,221 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_DISJOINT_HPP
+#define GGL_ALGORITHMS_DISJOINT_HPP
+
+#include <boost/mpl/if.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/static_assert.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/coordinate_dimension.hpp>
+#include <ggl/core/is_multi.hpp>
+#include <ggl/core/reverse_dispatch.hpp>
+#include <ggl/util/math.hpp>
+#include <ggl/util/select_coordinate_type.hpp>
+
+
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace disjoint {
+
+template <typename P1, typename P2, std::size_t D, std::size_t N>
+struct point_point
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+
+ static inline bool apply(P1 const& p1, P2 const& p2)
+ {
+ if (! math::equals(get<D>(p1), get<D>(p2)))
+ {
+ return true;
+ }
+ return point_point<P1, P2, D + 1, N>::apply(p1, p2);
+ }
+};
+
+template <typename P1, typename P2, std::size_t N>
+struct point_point<P1, P2, N, N>
+{
+ static inline bool apply(P1 const& , P2 const& )
+ {
+ return false;
+ }
+};
+
+
+template <typename P, typename B, std::size_t D, std::size_t N>
+struct point_box
+{
+ static inline bool apply(P const& point, B const& box)
+ {
+ if (get<D>(point) < get<min_corner, D>(box)
+ || get<D>(point) > get<max_corner, D>(box))
+ {
+ return true;
+ }
+ return point_box<P, B, D + 1, N>::apply(point, box);
+ }
+};
+
+template <typename P, typename B, std::size_t N>
+struct point_box<P, B, N, N>
+{
+ static inline bool apply(P const& , B const& )
+ {
+ return false;
+ }
+};
+
+
+template <typename B1, typename B2, std::size_t D, std::size_t N>
+struct box_box
+{
+ static inline bool apply(B1 const& box1, B2 const& box2)
+ {
+ if (get<max_corner, D>(box1) < get<min_corner, D>(box2))
+ {
+ return true;
+ }
+ if (get<min_corner, D>(box1) > get<max_corner, D>(box2))
+ {
+ return true;
+ }
+ return box_box<B1, B2, D + 1, N>::apply(box1, box2);
+ }
+};
+
+template <typename B1, typename B2, std::size_t N>
+struct box_box<B1, B2, N, N>
+{
+ static inline bool apply(B1 const& , B2 const& )
+ {
+ return false;
+ }
+};
+
+
+
+}} // namespace detail::disjoint
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2,
+ typename G1, typename G2,
+ bool IsMulti1, bool IsMulti2,
+ std::size_t DimensionCount
+>
+struct disjoint
+{
+};
+
+template <typename P1, typename P2, std::size_t DimensionCount>
+struct disjoint<point_tag, point_tag, P1, P2, false, false, DimensionCount>
+ : detail::disjoint::point_point<P1, P2, 0, DimensionCount>
+{
+};
+
+template <typename B1, typename B2, std::size_t DimensionCount>
+struct disjoint<box_tag, box_tag, B1, B2, false, false, DimensionCount>
+ : detail::disjoint::box_box<B1, B2, 0, DimensionCount>
+{
+};
+
+template <typename P, typename B, std::size_t DimensionCount>
+struct disjoint<point_tag, box_tag, P, B, false, false, DimensionCount>
+ : detail::disjoint::point_box<P, B, 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 boolean_relations
+ \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)
+{
+ assert_dimension_equal<Geometry1, 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 ggl
+
+#endif // GGL_ALGORITHMS_DISJOINT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/distance.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/distance.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,360 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_DISTANCE_HPP
+#define GGL_ALGORITHMS_DISTANCE_HPP
+
+#include <boost/mpl/if.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/static_assert.hpp>
+
+#include <ggl/core/cs.hpp>
+#include <ggl/core/is_multi.hpp>
+#include <ggl/core/reverse_dispatch.hpp>
+#include <ggl/geometries/segment.hpp>
+#include <ggl/strategies/distance_result.hpp>
+#include <ggl/strategies/strategies.hpp>
+
+/*!
+\defgroup distance distance calculation
+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_examples.cpp
+\skip example_distance_point_point
+\line {
+\until }
+*/
+
+namespace ggl
+{
+
+#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(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,
+ Segment
+ >::type segment_strategy;
+
+ return segment_strategy(point, segment);
+ }
+};
+
+
+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(point, *boost::begin(linestring));
+ }
+
+
+ // start with first segment distance
+ return_type d = ps_strategy(point, segment_type(*prev, *it));
+
+ // check if other segments are closer
+ prev = it++;
+ while(it != boost::end(linestring))
+ {
+ return_type ds = ps_strategy(point, segment_type(*prev, *it));
+ if (ggl::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 typename point_type<Linestring>::type> segment_type;
+ typedef typename ggl::strategy_distance_segment
+ <
+ typename cs_tag<Point>::type,
+ typename cs_tag<segment_type>::type,
+ Point,
+ segment_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);
+ }
+};
+
+
+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>
+{};
+
+
+// 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_examples.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_c
+ <
+ ggl::reverse_dispatch<Geometry1, Geometry2>::type::value,
+ 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)
+{
+ 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
+ <
+ ggl::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 ggl
+
+#endif // GGL_ALGORITHMS_DISTANCE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/envelope.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/envelope.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,329 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_ENVELOPE_HPP
+#define GGL_ALGORITHMS_ENVELOPE_HPP
+
+#include <boost/concept/requires.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <ggl/algorithms/combine.hpp>
+#include <ggl/algorithms/convert.hpp>
+#include <ggl/core/cs.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/concepts/box_concept.hpp>
+#include <ggl/core/concepts/linestring_concept.hpp>
+#include <ggl/core/concepts/nsphere_concept.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/core/concepts/polygon_concept.hpp>
+#include <ggl/core/concepts/ring_concept.hpp>
+#include <ggl/strategies/strategies.hpp>
+
+/*!
+\defgroup envelope envelope calculation
+\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)
+- either of them has an optional strategy
+
+\par Geometries:
+- POINT: a box with zero area, the maximum and the minimum point of the box are
+set to the point itself.
+- LINESTRING, RING or 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).
+- POLYGON, the envelope of the outer ring
+\image html envelope_polygon.png
+
+\par Example:
+Example showing envelope calculation
+\dontinclude doxygen_examples.cpp
+\skip example_envelope_linestring
+\line {
+\until }
+*/
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace envelope {
+
+/// Calculate envelope of an n-sphere, circle or sphere (currently only for Cartesian 2D points)
+template<typename B, typename S, typename Strategy>
+struct envelope_nsphere
+{
+ static inline void apply(S const& s, B& mbr, Strategy const&)
+ {
+ assert_dimension<S, 2>();
+ assert_dimension<B, 2>();
+
+ typename radius_type<S>::type r = get_radius<0>(s);
+ set<min_corner, 0>(mbr, get<0>(s) - r);
+ set<min_corner, 1>(mbr, get<1>(s) - r);
+ set<max_corner, 0>(mbr, get<0>(s) + r);
+ set<max_corner, 1>(mbr, get<1>(s) + r);
+ }
+};
+
+
+/// Calculate envelope of an 2D or 3D point
+template<typename P, typename B, typename Strategy>
+struct envelope_point
+{
+ static inline void apply(P const& p, B& mbr, Strategy const&)
+ {
+ // Envelope of a point is an empty box, a box with zero volume, located at the point.
+ // We just use the convert algorithm here
+ ggl::convert(p, mbr);
+ }
+};
+
+
+/// Calculate envelope of an 2D or 3D segment
+template<typename S, typename B, typename Strategy>
+struct envelope_segment
+{
+ static inline void apply(S const& s, B& mbr, Strategy const&)
+ {
+ ggl::assign_inverse(mbr);
+ ggl::combine(mbr, s.first);
+ ggl::combine(mbr, s.second);
+ }
+};
+
+
+/// Version with state iterating through range (also used in multi*)
+template<typename R, typename Strategy>
+inline void envelope_range_state(R const& range, Strategy const& strategy, typename Strategy::state_type& state)
+{
+ typedef typename boost::range_const_iterator<R>::type iterator_type;
+
+ for (iterator_type it = boost::begin(range); it != boost::end(range); it++)
+ {
+ strategy(*it, state);
+ }
+}
+
+
+
+/// Generic range dispatching struct
+template <typename R, typename B, typename Strategy>
+struct envelope_range
+{
+ /// Calculate envelope of range using a strategy
+ static inline void apply(R const& range, B& mbr, Strategy const& strategy)
+ {
+ typename Strategy::state_type state(mbr);
+ envelope_range_state(range, strategy, state);
+ }
+};
+
+}} // namespace detail::envelope
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag1, typename Tag2,
+ typename Geometry, typename Box,
+ typename Strategy
+>
+struct envelope {};
+
+
+template <typename P, typename B, typename Strategy>
+struct envelope<point_tag, box_tag, P, B, Strategy>
+ : detail::envelope::envelope_point<P, B, Strategy>
+{
+private:
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<P>) );
+ BOOST_CONCEPT_ASSERT( (concept::Box<B>) );
+};
+
+
+template <typename B, typename Strategy>
+struct envelope<box_tag, box_tag, B, B, Strategy>
+{
+ /*!
+ \brief Calculate envelope of a box
+ \details The envelope of a box is itself, provided for consistency
+ for consistency, on itself it is not useful.
+ */
+ static inline void apply(B const& b, B& mbr, Strategy const&)
+ {
+ mbr = b;
+ }
+
+private:
+ BOOST_CONCEPT_ASSERT( (concept::Box<B>) );
+};
+
+
+template <typename S, typename B, typename Strategy>
+struct envelope<segment_tag, box_tag, S, B, Strategy>
+ : detail::envelope::envelope_segment<S, B, Strategy>
+{};
+
+
+template <typename S, typename B, typename Strategy>
+struct envelope<nsphere_tag, box_tag, S, B, Strategy>
+ : detail::envelope::envelope_nsphere<S, B, Strategy>
+{
+private:
+ BOOST_CONCEPT_ASSERT( (concept::ConstNsphere<S>) );
+ BOOST_CONCEPT_ASSERT( (concept::Box<B>) );
+};
+
+template <typename L, typename B, typename Strategy>
+struct envelope<linestring_tag, box_tag, L, B, Strategy>
+ : detail::envelope::envelope_range<L, B, Strategy>
+{
+private:
+ BOOST_CONCEPT_ASSERT( (concept::ConstLinestring<L>) );
+ BOOST_CONCEPT_ASSERT( (concept::Box<B>) );
+};
+
+
+template <typename R, typename B, typename Strategy>
+struct envelope<ring_tag, box_tag, R, B, Strategy>
+ : detail::envelope::envelope_range<R, B, Strategy>
+{
+private:
+ BOOST_CONCEPT_ASSERT( (concept::ConstRing<R>) );
+ BOOST_CONCEPT_ASSERT( (concept::Box<B>) );
+};
+
+
+template <typename P, typename B, typename Strategy>
+struct envelope<polygon_tag, box_tag, P, B, Strategy>
+{
+ static inline void apply(P const& poly, B& mbr, Strategy const& strategy)
+ {
+ // For polygon inspecting outer linear_ring is sufficient
+
+ detail::envelope::envelope_range
+ <
+ typename ring_type<P>::type,
+ B,
+ Strategy
+ >::apply(exterior_ring(poly), mbr, strategy);
+ }
+
+private:
+ BOOST_CONCEPT_ASSERT( (concept::ConstPolygon<P>) );
+ BOOST_CONCEPT_ASSERT( (concept::Box<B>) );
+};
+
+
+} // namespace dispatch
+#endif
+
+
+/*!
+\brief Calculate envelope of a geometry, using a specified strategy
+\ingroup envelope
+\param geometry the geometry
+\param mbr the box receiving the envelope
+\param strategy strategy to be used
+*/
+template<typename G, typename B, typename S>
+inline void envelope(G const& geometry, B& mbr, S const& strategy)
+{
+ dispatch::envelope
+ <
+ typename tag<G>::type, typename tag<B>::type,
+ G, B, S
+ >::apply(geometry, mbr, strategy);
+}
+
+
+
+
+/*!
+\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_examples.cpp
+\skip example_envelope_polygon
+\line {
+\until }
+*/
+template<typename G, typename B>
+inline void envelope(G const& geometry, B& mbr)
+{
+ typename strategy_envelope
+ <
+ typename cs_tag<typename point_type<G>::type>::type,
+ typename cs_tag<typename point_type<B>::type>::type,
+ typename point_type<G>::type,
+ B
+ >::type strategy;
+
+ envelope(geometry, mbr, strategy);
+}
+
+
+/*!
+\brief Calculate and return envelope of a geometry
+\ingroup envelope
+\param geometry the geometry
+\param strategy the strategy to be used
+*/
+template<typename B, typename G, typename S>
+inline B make_envelope(G const& geometry, S const& strategy)
+{
+ B box;
+ dispatch::envelope
+ <
+ typename tag<G>::type, typename tag<B>::type,
+ G, B, S
+ >::apply(geometry, box, strategy);
+
+ return box;
+}
+
+
+/*!
+\brief Calculate and return envelope of a geometry
+\ingroup envelope
+\param geometry the geometry
+*/
+template<typename B, typename G>
+inline B make_envelope(G const& geometry)
+{
+ typename strategy_envelope
+ <
+ typename cs_tag<typename point_type<G>::type>::type,
+ typename cs_tag<typename point_type<B>::type>::type,
+ typename point_type<G>::type,
+ B
+ >::type strategy;
+ return make_envelope<B>(geometry, strategy);
+}
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_ENVELOPE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/equals.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/equals.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,134 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_EQUALS_HPP
+#define GGL_ALGORITHMS_EQUALS_HPP
+
+#include <cstddef>
+
+#include <boost/static_assert.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/coordinate_dimension.hpp>
+#include <ggl/core/is_multi.hpp>
+#include <ggl/algorithms/disjoint.hpp>
+#include <ggl/algorithms/detail/not.hpp>
+#include <ggl/util/math.hpp>
+
+/*!
+
+\defgroup boolean_relations boolean relationships (equals, disjoint, overlaps, etc)
+
+*/
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace equals {
+
+template <typename B1, typename B2, std::size_t D, std::size_t N>
+struct box_box
+{
+ static inline bool apply(B1 const& box1, B2 const& box2)
+ {
+ if (!math::equals(get<min_corner, D>(box1), get<min_corner, D>(box2))
+ || !math::equals(get<max_corner, D>(box1), get<max_corner, D>(box2)))
+ {
+ return false;
+ }
+ return box_box<B1, B2, D + 1, N>::apply(box1, box2);
+ }
+};
+
+template <typename B1, typename B2, std::size_t N>
+struct box_box<B1, B2, N, N>
+{
+ static inline bool apply(B1 const& , B2 const& )
+ {
+ return true;
+ }
+};
+
+}} // namespace detail::equals
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename GeometryTag,
+ bool IsMulti,
+ typename G1,
+ typename G2,
+ std::size_t DimensionCount
+>
+struct equals
+{
+};
+
+template <typename P1, typename P2, std::size_t DimensionCount>
+struct equals<point_tag, false, P1, P2, DimensionCount>
+ : ggl::detail::not_
+ <
+ P1,
+ P2,
+ detail::disjoint::point_point<P1, P2, 0, DimensionCount>
+ >
+{
+};
+
+template <typename B1, typename B2, std::size_t DimensionCount>
+struct equals<box_tag, false, B1, B2, DimensionCount>
+ : detail::equals::box_box<B1, B2, 0, DimensionCount>
+{
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Calculate if two geometries are equals
+ \ingroup boolean_relations
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \return true if equals, else false
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ assert_dimension_equal<Geometry1, Geometry2>();
+
+// TODO: assert types equal:
+// typename tag<ncg1_type>::type, typename tag<ncg2_type>::type,
+// (LATER): NO! a linestring can be spatially equal to a multi_linestring
+
+ typedef typename boost::remove_const<Geometry1>::type ncg1_type;
+ typedef typename boost::remove_const<Geometry2>::type ncg2_type;
+
+ return dispatch::equals
+ <
+ typename tag<ncg1_type>::type,
+ is_multi<ncg1_type>::type::value,
+ ncg1_type,
+ ncg2_type,
+ dimension<ncg1_type>::type::value
+ >::apply(geometry1, geometry2);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_EQUALS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/for_each.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/for_each.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,268 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_FOR_EACH_HPP
+#define GGL_ALGORITHMS_FOR_EACH_HPP
+
+/*!
+\defgroup loop loops and for-each functionality
+There are several algorithms provided which walk through the points or segments
+of linestrings and polygons. They are called for_each_point, for_each_segment, after
+the standard library, and \b loop which is more adapted and of which the functor
+could break out if necessary.
+Of the for_each algorithms there is a \b const and a non-const version provided.
+*/
+
+#include <algorithm>
+
+#include <boost/concept/requires.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/geometries/segment.hpp>
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace for_each {
+
+template <typename P, typename F>
+struct fe_point
+{
+ static inline F for_each_const_point(P const& p, F f)
+ {
+ f(p);
+ return (f);
+ }
+
+ static inline F for_each_point(P& p, F f)
+ {
+ f(p);
+ return (f);
+ }
+};
+
+template <typename R, typename F>
+struct fe_range
+{
+ static inline F for_each_const_point(R const& range, F f)
+ {
+ return (std::for_each(boost::begin(range), boost::end(range), f));
+ }
+
+ static inline F for_each_point(R& range, F f)
+ {
+ return (std::for_each(boost::begin(range), boost::end(range), f));
+ }
+
+ static inline F for_each_const_segment(R const& range, F f)
+ {
+ typedef typename boost::range_const_iterator<R>::type iterator_type;
+
+ iterator_type it = boost::begin(range);
+ iterator_type previous = it++;
+ while(it != boost::end(range))
+ {
+ segment<typename point_type<R>::type> s(*previous, *it);
+ f(s);
+ previous = it++;
+ }
+
+ return (f);
+ }
+
+ static inline F for_each_segment(R& range, F f)
+ {
+ typedef typename boost::range_iterator<R>::type iterator_type;
+
+ iterator_type it = boost::begin(range);
+ iterator_type previous = it++;
+ while(it != boost::end(range))
+ {
+ segment<typename point_type<R>::type> s(*previous, *it);
+ f(s);
+ previous = it++;
+ }
+
+ return (f);
+ }
+};
+
+template <typename P, typename F>
+struct fe_polygon
+{
+ static inline F for_each_const_point(P const& poly, F f)
+ {
+ typedef typename ring_type<P>::type ring_type;
+ typedef typename boost::range_const_iterator
+ <
+ typename interior_type<P>::type
+ >::type iterator_type;
+
+ f = fe_range<ring_type, F>::for_each_const_point(exterior_ring(poly), f);
+
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly)); it++)
+ {
+ f = fe_range<ring_type, F>::for_each_const_point(*it, f);
+ }
+
+ return (f);
+ }
+
+ static inline F for_each_point(P& poly, F f)
+ {
+ typedef typename ring_type<P>::type ring_type;
+ typedef typename boost::range_iterator
+ <
+ typename interior_type<P>::type
+ >::type iterator_type;
+
+ f = fe_range<ring_type, F>::for_each_point(exterior_ring(poly), f);
+
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly)); it++)
+ {
+ f = fe_range<ring_type, F>::for_each_point(*it, f);
+ }
+
+ return (f);
+ }
+
+ static inline F for_each_const_segment(P const& poly, F f)
+ {
+ typedef typename ring_type<P>::type ring_type;
+ typedef typename boost::range_const_iterator
+ <
+ typename interior_type<P>::type
+ >::type iterator_type;
+
+ f = fe_range<ring_type, F>::for_each_const_segment(exterior_ring(poly), f);
+
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly)); it++)
+ {
+ f = fe_range<ring_type, F>::for_each_const_segment(*it, f);
+ }
+
+ return (f);
+ }
+
+ static inline F for_each_segment(P& poly, F f)
+ {
+ typedef typename ring_type<P>::type ring_type;
+ typedef typename boost::range_iterator
+ <
+ typename interior_type<P>::type
+ >::type iterator_type;
+
+ f = fe_range<ring_type, F>::for_each_segment(exterior_ring(poly), f);
+
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly)); it++)
+ {
+ f = fe_range<ring_type, F>::for_each_segment(*it, f);
+ }
+
+ return (f);
+ }
+};
+
+}} // namespace detail::for_each
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename T, typename G, typename F>
+struct for_each {};
+
+template <typename P, typename F>
+struct for_each<point_tag, P, F> : detail::for_each::fe_point<P, F> {};
+
+template <typename L, typename F>
+struct for_each<linestring_tag, L, F> : detail::for_each::fe_range<L, F> {};
+
+template <typename R, typename F>
+struct for_each<ring_tag, R, F> : detail::for_each::fe_range<R, F> {};
+
+template <typename P, typename F>
+struct for_each<polygon_tag, P, F> : detail::for_each::fe_polygon<P, F> {};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+/*!
+ \brief Calls functor for geometry
+ \ingroup loop
+ \param geometry geometry to loop through
+ \param f functor to use
+ \details Calls the functor the specified \b const geometry
+*/
+template<typename G, typename F>
+inline F for_each_point(G const& geometry, F f)
+{
+ typedef typename dispatch::for_each
+ <
+ typename tag<G>::type,
+ G,
+ F
+ >::for_each_const_point for_each_type;
+
+ return for_each_type(geometry, f);
+}
+
+/*!
+ \brief Calls functor for geometry
+ \ingroup loop
+ \param geometry geometry to loop through
+ \param f functor to use
+ \details Calls the functor for the specified geometry
+*/
+template<typename G, typename F>
+inline F for_each_point(G& geometry, F f)
+{
+ return (dispatch::for_each<typename tag<G>::type, G, F>::for_each_point(geometry, f));
+}
+
+/*!
+ \brief Calls functor for segments on linestrings, rings, polygons, ...
+ \ingroup loop
+ \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 G, typename F>
+inline F for_each_segment(const G& geometry, F f)
+{
+ return (dispatch::for_each<typename tag<G>::type, G, F>::for_each_const_segment(geometry, f));
+}
+
+
+/*!
+ \brief Calls functor for segments on linestrings, rings, polygons, ...
+ \ingroup loop
+ \param geometry geometry to loop through
+ \param f functor to use
+ \details Calls the functor all segments of the specified geometry
+*/
+template<typename G, typename F>
+inline F for_each_segment(G& geometry, F f)
+{
+ return (dispatch::for_each<typename tag<G>::type, G, F>::for_each_segment(geometry, f));
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_FOR_EACH_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/get_section.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/get_section.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,102 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_GET_SECTION_HPP
+#define GGL_ALGORITHMS_GET_SECTION_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/concept/requires.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+
+#include <ggl/iterators/point_const_iterator.hpp>
+
+#include <ggl/geometries/segment.hpp>
+
+
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, typename Geometry, typename Section>
+struct get_section
+{
+ typedef typename ggl::point_const_iterator<Geometry>::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 ggl::point_const_iterator<Polygon>::type iterator_type;
+ static inline void apply(Polygon const& polygon, Section const& section,
+ iterator_type& begin, iterator_type& end)
+ {
+ typedef typename ggl::ring_type<Polygon>::type ring_type;
+ ring_type const& ring = section.ring_index < 0
+ ? ggl::exterior_ring(polygon)
+ : ggl::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 point_const_iterator<Geometry>::type& begin,
+ typename point_const_iterator<Geometry>::type& end)
+{
+ dispatch::get_section
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Section
+ >::apply(geometry, section, begin, end);
+}
+
+
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_GET_SECTION_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/intermediate.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/intermediate.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,126 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_INTERMEDIATE_HPP
+#define GGL_ALGORITHMS_INTERMEDIATE_HPP
+
+#include <cstddef>
+#include <iterator>
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/core/cs.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/strategies/strategies.hpp>
+
+/*!
+\defgroup intermediate intermediate calculation
+The intermediate algorithm calculate points IN BETWEEN of other points
+\par Purpose:
+- Remove corners in rectangular lines / polygons. Calling them several times will result in smooth lines
+- Creating 3D models
+*/
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intermediate {
+
+template <typename Src, typename Dst, std::size_t Dimension, std::size_t DimensionCount>
+struct calculate_coordinate
+{
+ static inline void apply(Src const& p1, Src const& p2, Dst& p)
+ {
+ ggl::set<Dimension>(p,
+ (ggl::get<Dimension>(p1) + ggl::get<Dimension>(p2)) / 2.0);
+ calculate_coordinate<Src, Dst, Dimension + 1, DimensionCount>::apply(p1, p2, p);
+ }
+};
+
+template <typename Src, typename Dst, std::size_t DimensionCount>
+struct calculate_coordinate<Src, Dst, DimensionCount, DimensionCount>
+{
+ static inline void apply(Src const&, Src const&, Dst&)
+ {
+ }
+};
+
+template<typename R, typename Iterator>
+struct range_intermediate
+{
+ static inline void apply(R const& range, bool start_and_end, Iterator out)
+ {
+ typedef typename point_type<R>::type point_type;
+ typedef typename boost::range_const_iterator<R>::type iterator_type;
+
+ iterator_type it = boost::begin(range);
+
+ if (start_and_end)
+ {
+ (*out++) = *it;
+ }
+
+ iterator_type prev = it++;
+ for (; it != boost::end(range); prev = it++)
+ {
+ point_type p;
+ calculate_coordinate
+ <
+ point_type,
+ point_type,
+ 0,
+ dimension<point_type>::type::value
+ >::apply(*prev, *it, p);
+ *(out++) = p;
+ }
+
+ if (start_and_end)
+ {
+ (*out++) = *prev;
+ }
+ }
+};
+
+}} // namespace detail::intermediate
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename GeometryTag, typename G, typename Iterator>
+struct intermediate {};
+
+template <typename G, typename Iterator>
+struct intermediate<ring_tag, G, Iterator>
+ : detail::intermediate::range_intermediate<G, Iterator> {};
+
+template <typename G, typename Iterator>
+struct intermediate<linestring_tag, G, Iterator>
+ : detail::intermediate::range_intermediate<G, Iterator> {};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Calculate intermediate of a geometry
+ \ingroup intermediate
+ */
+template<typename G, typename Iterator>
+inline void intermediate(const G& geometry, bool start_and_end, Iterator out)
+{
+ dispatch::intermediate<typename tag<G>::type, G, Iterator>::apply(geometry, start_and_end, out);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_INTERMEDIATE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/intersection.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/intersection.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,455 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_INTERSECTION_HPP
+#define GGL_ALGORITHMS_INTERSECTION_HPP
+
+#include <deque>
+
+#include <ggl/algorithms/intersection_linestring.hpp>
+
+#include <ggl/algorithms/overlay/get_intersection_points.hpp>
+#include <ggl/algorithms/overlay/merge_intersection_points.hpp>
+#include <ggl/algorithms/overlay/adapt_turns.hpp>
+#include <ggl/algorithms/overlay/enrich_intersection_points.hpp>
+#include <ggl/algorithms/overlay/traverse.hpp>
+
+#include <ggl/algorithms/assign.hpp>
+#include <ggl/algorithms/convert.hpp>
+#include <ggl/algorithms/within.hpp>
+
+
+
+/*!
+\defgroup overlay overlay operations (intersection, union, clipping)
+\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
+
+\note Used strategies still have to be modelled. Working only for cartesian
+\par Geometries:
+The intersection result is painted with a red outline.
+- clip: POLYGON + BOX -> output iterator of polygons
+\image html clip_polygon.png
+- clip: LINESTRING + BOX -> output iterator of linestrings
+\image html clip_linestring.png
+\note There are some difficulties to model an intersection in the template world. The intersection of two segments can
+result into nothing, into a point, into another segment. At compiletime the result type is not known. An output iterator
+iterating points is appropriate here.
+\image html clip_segment_segment.png
+An intersection of two linestrings can result into nothing, one or more points, one or more segments or one or more
+linestrings. So an output iterator will NOT do here.
+So the output might be changed into a unified algorithm where the output is a multi-geometry.
+For the current clip-only operations the output iterator will do.
+
+\par Example:
+Example showing clipping of linestring with box
+\dontinclude doxygen_examples.cpp
+\skip example_intersection_linestring1
+\line {
+\until }
+\par Example:
+Example showing clipping of vector, outputting vectors, with box
+\dontinclude doxygen_examples.cpp
+\skip example_intersection_linestring2
+\line {
+\until }
+\par Example:
+Example showing clipping of polygon with box
+\dontinclude doxygen_examples.cpp
+\skip example_intersection_polygon1
+\line {
+\until }
+*/
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersection {
+
+
+template
+<
+ typename Polygon1, typename Polygon2,
+ typename OutputIterator, typename GeometryOut
+>
+struct intersection_polygon_polygon
+{
+ static inline OutputIterator apply(Polygon1 const& polygon1,
+ Polygon2 const& polygon2, OutputIterator out)
+ {
+ typedef detail::intersection::intersection_point
+ <
+ typename ggl::point_type<GeometryOut>::type
+ > ip_type;
+ typedef std::deque<ip_type> ips_container;
+
+ typedef typename ggl::ring_type<GeometryOut>::type ring_type;
+
+ ips_container ips;
+
+ bool trivial = ggl::get_intersection_points(polygon1, polygon2, ips);
+
+ if (ips.size() <= 0)
+ {
+ // If there are no IP-s, check if one point is in other polygon
+ // assume both polygons having points
+ if (ggl::within(ggl::exterior_ring(polygon1).front(), polygon2))
+ {
+ // Assume same type (output = input)
+ // TODO: solve this (we go to specialize again...)
+ *out = polygon1;
+ out++;
+ }
+ else if (ggl::within(ggl::exterior_ring(polygon2).front(), polygon1))
+ {
+ *out = polygon2;
+ out++;
+ }
+ }
+ else
+ {
+ if (! trivial)
+ {
+ ggl::merge_intersection_points(ips);
+ ggl::adapt_turns(ips);
+
+ }
+
+ ggl::enrich_intersection_points(ips, trivial);
+
+
+ std::vector<ring_type> v;
+ ggl::traverse<ring_type>
+ (
+ polygon1,
+ polygon2,
+ -1,
+ ips,
+ trivial,
+ std::back_inserter(v)
+ );
+
+
+ // TODO:
+ // assemble rings / inner rings / to polygons
+ for (typename std::vector<ring_type>::const_iterator it = v.begin();
+ it != v.end(); ++it)
+ {
+ // How can we avoid the double copy here! It is really bad!
+ // We have to create a polygon, then copy it to the output iterator.
+ // Having an output-vector would have been better: append it to the vector!
+ // So output iterators are not that good.
+ GeometryOut poly;
+ poly.outer() = *it;
+ *out = poly;
+ out++;
+ }
+ }
+
+
+ return out;
+ }
+};
+
+
+
+
+template
+<
+ typename Polygon, typename Box,
+ typename OutputIterator, typename GeometryOut
+>
+struct intersection_polygon_box
+{
+ static inline OutputIterator apply(Polygon const& polygon,
+ Box const& box, OutputIterator out)
+ {
+ typedef typename ggl::point_type<GeometryOut>::type point_type;
+ typedef detail::intersection::intersection_point<point_type> ip_type;
+ typedef std::deque<ip_type> ips_container;
+
+ typedef typename ggl::ring_type<GeometryOut>::type ring_type;
+
+ ips_container ips;
+
+ bool trivial = ggl::get_intersection_points(polygon, box, ips);
+
+ // TODO: share this all with polygon_polygon using an "assemble" function!
+ // It is only different in the 'within' calls, can be sorted out with specialization
+
+
+ if (ips.size() <= 0)
+ {
+ // If there are no IP-s, check if one point is in other polygon
+ // assume both polygons having points
+ if (ggl::within(ggl::exterior_ring(polygon).front(), box))
+ {
+ // Assume same type (output = input)
+ // TODO: solve this (we go to specialize again...)
+ *out = polygon;
+ out++;
+ }
+ else
+ {
+ typename ggl::point_type<Box>::type p;
+ ggl::set<0>(p, ggl::get<min_corner, 0>(box));
+ ggl::set<1>(p, ggl::get<min_corner, 1>(box));
+ if (ggl::within(p, polygon))
+ {
+ GeometryOut boxpoly;
+ ggl::convert(box, boxpoly);
+ *out = boxpoly;
+ out++;
+ }
+ }
+ }
+ else
+ {
+ if (trivial)
+ {
+ ggl::merge_intersection_points(ips);
+ }
+
+ ggl::enrich_intersection_points(ips, trivial);
+
+ std::vector<ring_type> v;
+ ggl::traverse<ring_type>
+ (
+ polygon,
+ box,
+ -1,
+ ips,
+ trivial,
+ std::back_inserter(v)
+ );
+
+ // TODO:
+ // assemble rings / inner rings / to polygons
+ for (typename std::vector<ring_type>::const_iterator it = v.begin();
+ it != v.end(); ++it)
+ {
+ // How can we avoid the double copy here! It is really bad!
+ // We have to create a polygon, then copy it to the output iterator.
+ // Having an output-vector would have been better: append it to the vector!
+ // So output iterators are not that good.
+ GeometryOut poly;
+ poly.outer() = *it;
+ *out = poly;
+ out++;
+ }
+ }
+
+
+ return out;
+ }
+};
+
+
+}} // namespace detail::intersection
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag1, typename Tag2, typename Tag3,
+ typename G1, typename G2,
+ typename OutputIterator,
+ typename GeometryOut
+>
+struct intersection {};
+
+
+template
+<
+ typename Segment1, typename Segment2,
+ typename OutputIterator, typename GeometryOut
+>
+struct intersection
+ <
+ segment_tag, segment_tag, point_tag,
+ Segment1, Segment2,
+ OutputIterator, GeometryOut
+ >
+{
+ static inline OutputIterator apply(Segment1 const& segment1,
+ Segment2 const& segment2, OutputIterator out)
+ {
+ 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>
+ >
+ >::relate(segment1, segment2);
+ for (int i = 0; i < is.count; i++)
+ {
+ GeometryOut p;
+ ggl::copy_coordinates(is.intersections[i], p);
+ *out = p;
+ out++;
+ }
+ return out;
+ }
+};
+
+
+template
+<
+ typename Linestring, typename Box,
+ typename OutputIterator, typename GeometryOut
+>
+struct intersection
+ <
+ linestring_tag, box_tag, linestring_tag,
+ Linestring, Box,
+ OutputIterator, GeometryOut
+ >
+{
+ static inline OutputIterator apply(Linestring const& linestring,
+ Box const& box, OutputIterator out)
+ {
+ typedef typename point_type<GeometryOut>::type point_type;
+ strategy::intersection::liang_barsky<Box, point_type> strategy;
+ return detail::intersection::clip_linestring_with_box<GeometryOut>(box, linestring, out, strategy);
+ }
+};
+
+
+template
+<
+ typename Polygon1, typename Polygon2,
+ typename OutputIterator, typename GeometryOut
+>
+struct intersection
+ <
+ polygon_tag, polygon_tag, polygon_tag,
+ Polygon1, Polygon2,
+ OutputIterator, GeometryOut
+ >
+ : detail::intersection::intersection_polygon_polygon
+ <Polygon1, Polygon2, OutputIterator, GeometryOut>
+{};
+
+
+
+template
+<
+ typename Polygon, typename Box,
+ typename OutputIterator, typename GeometryOut
+>
+struct intersection
+<
+ polygon_tag, box_tag, polygon_tag,
+ Polygon, Box,
+ OutputIterator, GeometryOut
+>
+ : detail::intersection::intersection_polygon_box
+ <Polygon, Box, OutputIterator, GeometryOut>
+{};
+
+
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2, typename GeometryTag3,
+ typename G1, typename G2,
+ typename OutputIterator, typename GeometryOut
+>
+struct intersection_reversed
+{
+ static inline OutputIterator apply(G1 const& g1, G2 const& g2, OutputIterator out)
+ {
+ return intersection
+ <
+ GeometryTag2, GeometryTag1, GeometryTag3,
+ G2, G1,
+ OutputIterator, GeometryOut
+ >::apply(g2, g1, out);
+ }
+};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+/*!
+ \brief Intersects two geometries which each other
+ \ingroup overlay
+ \details A sequence of points is intersected (clipped) by the specified box
+ and the resulting linestring, or pieces of linestrings, 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 (currently only a BOX)
+ \param geometry2 second geometry (range, linestring, polygon)
+ \param out the output iterator, outputting linestrings or polygons
+ \return the output iterator
+ \note For linestrings: the default clipping strategy, Liang-Barsky, is used. The algorithm is currently only
+ implemented for 2D xy points. It could be generic for most ll cases, but not across the 180
+ meridian so that issue is still on the todo-list.
+*/
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename OutputIterator
+>
+inline OutputIterator intersection(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ OutputIterator out)
+{
+
+ return boost::mpl::if_c
+ <
+ reverse_dispatch<Geometry1, Geometry2>::type::value,
+ dispatch::intersection_reversed
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ typename tag<GeometryOut>::type,
+ Geometry1,
+ Geometry2,
+ OutputIterator, GeometryOut
+ >,
+ dispatch::intersection
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ typename tag<GeometryOut>::type,
+ Geometry1,
+ Geometry2,
+ OutputIterator, GeometryOut
+ >
+ >::type::apply(geometry1, geometry2, out);
+}
+
+} // ggl
+
+#endif //GGL_ALGORITHMS_INTERSECTION_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/intersection_linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/intersection_linestring.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,236 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_INTERSECTION_LINESTRING_HPP
+#define GGL_ALGORITHMS_INTERSECTION_LINESTRING_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/algorithms/append.hpp>
+#include <ggl/algorithms/clear.hpp>
+#include <ggl/util/copy.hpp>
+#include <ggl/util/select_coordinate_type.hpp>
+#include <ggl/geometries/segment.hpp>
+
+namespace ggl
+{
+
+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
+ \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 B, typename P>
+class liang_barsky
+{
+private:
+ typedef ggl::segment<P> segment_type;
+
+ inline bool check_edge(double const& p, double const& q, double& t1, double& t2) const
+ {
+ bool visible = true;
+
+ if(p < 0)
+ {
+ // TODO: Move r definition one scope level up to reuse --mloskot
+ double const r = q / p;
+ if (r > t2)
+ visible = false;
+ else if (r > t1)
+ t1 = r;
+ }
+ else if(p > 0)
+ {
+ double const r = q / p;
+ if (r < t1)
+ visible = false;
+ else if (r < t2)
+ t2 = r;
+ }
+ else
+ {
+ if (q < 0)
+ visible = false;
+ }
+
+ return visible;
+ }
+
+public:
+
+ bool clip_segment(B const& b, segment_type& s, bool& sp1_clipped, bool& sp2_clipped) const
+ {
+ typedef typename select_coordinate_type<B, P>::type coordinate_type;
+
+ double t1 = 0;
+ double 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;
+
+ // TODO: maybe round coordinates in case of integer? define some round_traits<> or so?
+ // Take boost-round of Fernando
+ 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 L, typename OutputIterator>
+ inline void add(L& line_out, OutputIterator out) const
+ {
+ if (!boost::empty(line_out))
+ {
+ *out = line_out;
+ ++out;
+ ggl::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 "add"
+*/
+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.add(line_out, out);
+ }
+ else
+ {
+ // a. If necessary, finish the line and add a start a new one
+ if (c1)
+ {
+ strategy.add(line_out, out);
+ }
+
+ // b. Add p1 only if it is the first point, then add p2
+ if (boost::empty(line_out))
+ {
+ ggl::append(line_out, p1);
+ }
+ ggl::append(line_out, p2);
+
+ // c. If c2 is clipped, finish the line
+ if (c2)
+ {
+ strategy.add(line_out, out);
+ }
+ }
+
+ }
+
+ // Add last part
+ strategy.add(line_out, out);
+ return out;
+}
+
+}} // namespace detail::intersection
+#endif // DOXYGEN_NO_DETAIL
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_INTERSECTION_LINESTRING_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/intersects.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/intersects.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,61 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_INTERSECTS_HPP
+#define GGL_ALGORITHMS_INTERSECTS_HPP
+
+#include <ggl/algorithms/intersection_linestring.hpp>
+
+#include <ggl/algorithms/overlay/get_intersection_points.hpp>
+#include <ggl/algorithms/overlay/self_intersection_points.hpp>
+#include <ggl/algorithms/overlay/adapt_turns.hpp>
+#include <ggl/algorithms/overlay/enrich_intersection_points.hpp>
+#include <ggl/algorithms/overlay/traverse.hpp>
+
+#include <ggl/algorithms/assign.hpp>
+#include <ggl/algorithms/convert.hpp>
+#include <ggl/algorithms/within.hpp>
+
+
+
+namespace ggl
+{
+
+/*!
+ \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 overlay
+ \tparam Geometry geometry type
+ \param geometry geometry
+ \return TRUE if there are intersections, else FALSE
+ */
+template <typename Geometry>
+inline bool intersects(Geometry const& geometry)
+{
+ typedef typename boost::remove_const<Geometry>::type ncg_type;
+
+ typedef std::vector<ggl::detail::intersection::intersection_point
+ <typename ggl::point_type<Geometry>::type> > ip_vector;
+
+ ip_vector ips;
+
+ dispatch::self_intersection_points
+ <
+ typename tag<ncg_type>::type,
+ is_multi<ncg_type>::type::value,
+ ncg_type,
+ ip_vector
+ >::apply(geometry, true, ips);
+ return ips.size() > 0;
+}
+
+} // ggl
+
+#endif //GGL_ALGORITHMS_INTERSECTS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/length.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/length.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,181 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_LENGTH_HPP
+#define GGL_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 <ggl/algorithms/detail/calculate_null.hpp>
+#include <ggl/core/cs.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/strategies/strategies.hpp>
+
+/*!
+\defgroup length length calculation
+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_examples.cpp
+\skip example_length_linestring_iterators1
+\line {
+\until }
+*/
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace length {
+
+
+template<typename Segment, typename Strategy>
+struct segment_length
+{
+ static inline double apply(Segment const& segment, Strategy const& strategy)
+ {
+ // BSG 10 APR 2009
+ // TODO: the segment concept has to be such that it is easy to return a point from it.
+ // Now it only accesses per coordinate
+ return strategy(segment.first, segment.second);
+ }
+};
+
+/*!
+\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
+{
+ static inline double apply(Range const& range, Strategy const& strategy)
+ {
+ typedef typename ggl::coordinate_type<Range>::type coordinate_type;
+
+ // 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<coordinate_type>::type::value,
+ double,
+ coordinate_type
+ >::type calculation_type;
+
+ calculation_type sum = 0.0;
+
+ 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(*previous, *it);
+ previous = it++;
+ }
+ }
+
+ return sum;
+ }
+};
+
+}} // namespace detail::length
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Tag, typename G, typename S>
+struct length : detail::calculate_null<double, G, S>
+{};
+
+
+template <typename G, typename S>
+struct length<linestring_tag, G, S>
+ : detail::length::range_length<G, S>
+{};
+
+
+// RING: length is currently 0.0 but it might be argued that it is the "perimeter"
+template <typename G, typename S>
+struct length<segment_tag, G, S> : detail::length::segment_length<G, S>
+{};
+
+
+} // 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 ggl::linestring, vector, iterator pair, or any other boost compatible range
+ \return the length
+ Example showing length calculation on a vector
+ \dontinclude doxygen_examples.cpp
+ \skip example_length_linestring_iterators2
+ \line {
+ \until }
+ */
+template<typename G>
+inline double length(const G& geometry)
+{
+ typedef typename point_type<G>::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<G>::type,
+ G,
+ 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 ggl::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_examples.cpp
+ \skip example_length_linestring_iterators3
+ \line {
+ \until }
+ */
+template<typename G, typename S>
+inline double length(G const& geometry, S const& strategy)
+{
+ return dispatch::length<typename tag<G>::type, G, S>::apply(geometry, strategy);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_LENGTH_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/make.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/make.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,123 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_MAKE_HPP
+#define GGL_ALGORITHMS_MAKE_HPP
+
+#include <ggl/algorithms/assign.hpp>
+
+namespace ggl
+{
+
+/*!
+ \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.
+ \tparam G the geometry type
+ \tparam T the coordinate type
+ \return the geometry
+ */
+template <typename G, typename T>
+inline G make(T const& c1, T const& c2)
+{
+ G geometry;
+ dispatch::assign
+ <
+ typename tag<G>::type,
+ G,
+ ggl::dimension<G>::type::value
+ >::apply(geometry, c1, c2);
+ return geometry;
+}
+
+/*!
+ \brief Make a geometry
+ \ingroup access
+ \return a 3D point, a circle
+ */
+template <typename G, typename T>
+inline G make(T const& c1, T const& c2, T const& c3)
+{
+ G geometry;
+ dispatch::assign
+ <
+ typename tag<G>::type,
+ G,
+ ggl::dimension<G>::type::value
+ >::apply(geometry, c1, c2, c3);
+ return geometry;
+}
+
+template <typename G, typename T>
+inline G make(T const& c1, T const& c2, T const& c3, T const& c4)
+{
+ G geometry;
+ dispatch::assign
+ <
+ typename tag<G>::type,
+ G,
+ ggl::dimension<G>::type::value
+ >::apply(geometry, c1, c2, c3, c4);
+ return geometry;
+}
+
+
+
+template <typename G, typename R>
+inline G make(R const& range)
+{
+ G 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 G the geometry type
+ \return the box
+ */
+template <typename G>
+inline G make_inverse()
+{
+ G geometry;
+ dispatch::assign_inverse
+ <
+ typename tag<G>::type,
+ G
+ >::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 G the geometry type
+ \return the geometry
+ */
+template <typename G>
+inline G make_zero()
+{
+ G geometry;
+ dispatch::assign_zero
+ <
+ typename tag<G>::type,
+ G
+ >::apply(geometry);
+ return geometry;
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_MAKE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/num_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/num_points.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,147 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_NUM_POINTS_HPP
+#define GGL_ALGORITHMS_NUM_POINTS_HPP
+
+#include <cstddef>
+
+#include <boost/range.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <ggl/core/is_linear.hpp>
+#include <ggl/core/interior_rings.hpp>
+
+
+namespace ggl
+{
+
+#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<nsphere_tag, false, Geometry>
+ : detail::num_points::other_count<Geometry, 1>
+{
+};
+
+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)
+{
+ 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);
+}
+
+}
+
+
+#endif // GGL_ALGORITHMS_NUM_POINTS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlaps.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlaps.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,49 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_OVERLAPS_HPP
+#define GGL_ALGORITHMS_OVERLAPS_HPP
+
+#include <ggl/core/access.hpp>
+
+
+namespace ggl
+{
+
+/*!
+ \brief Determines overlap between two geometries
+ \details parameters are now boxes but in the future will be geometries
+ \ingroup boolean_relations
+ \return true if there is overlap
+
+
+ \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.
+
+ \note Implemented in scratch the Generic Geometry library. Will be reworked internally to support more geometries
+ but function call will stay as it is now.
+ \see http://docs.codehaus.org/display/GEOTDOC/02+Geometry+Relationships#02GeometryRelationships-Overlaps
+ where is stated that "inside" is not an "overlap", this is probably true and should then be implemented as such.
+
+ */
+template <typename B>
+inline bool overlaps(const B& b1, const B& b2)
+{
+ return !(
+ get<max_corner, 0>(b1) <= get<min_corner, 0>(b2) ||
+ get<min_corner, 0>(b1) >= get<max_corner, 0>(b2) ||
+ get<max_corner, 1>(b1) <= get<min_corner, 1>(b2) ||
+ get<min_corner, 1>(b1) >= get<max_corner, 1>(b2)
+ );
+
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_OVERLAPS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/adapt_turns.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/adapt_turns.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,556 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ADAPT_TURNS_HPP
+#define GGL_ADAPT_TURNS_HPP
+
+#include <algorithm>
+
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <ggl/core/coordinate_type.hpp>
+
+#include <ggl/algorithms/equals.hpp>
+
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersection {
+
+
+
+// TEMP: another COPY of side
+// TODO: solve this inside SIDE!!!
+template <typename P1, typename P2, typename P>
+inline int the_side(P1 const& p1, P2 const& p2, P const& p)
+{
+ typedef typename select_coordinate_type<P, P1>::type T;
+
+ T dx = get<0>(p2) - get<0>(p1);
+ T dy = get<1>(p2) - get<1>(p1);
+ T dpx = get<0>(p) - get<0>(p1);
+ T dpy = get<1>(p) - get<1>(p1);
+ T product = dx * dpy - dy * dpx;
+ return product > 0 ? 1 : product < 0 ? -1 : 0;
+}
+
+template <typename T>
+inline void join_adapt(T& info, int direction)
+{
+ info.first->direction = direction;
+ info.second->direction = direction;
+}
+
+
+
+template <typename T>
+inline void both_same(T const& pi, T & pk, T const& qu, T& qw, int dir_p, int dir_q, int direction)
+{
+ // Comments are for "both Left"
+ if (dir_q == direction) // If (Qw left-of Qu)
+ {
+ if (dir_p == -direction) // if (Pk right-of Pi)
+ {
+ // make Pk Right, Qw Left
+ join_adapt(pk, -direction);
+ join_adapt(qw, direction);
+ }
+ else if (pk.first->direction == -direction) // else if (Pk right-of Qu)
+ {
+ // make both Right
+ join_adapt(pk, -direction);
+ join_adapt(qw, -direction);
+ }
+ }
+ else
+ {
+ if (dir_p == -direction // if (Pk right-of Pi
+ || pk.first->direction == direction) // || Pk left-of Qu)
+ {
+ // make both Left
+ join_adapt(pk, direction);
+ join_adapt(qw, direction);
+ }
+ }
+}
+
+template <typename T>
+inline void crossing(T const& pi, T & pk, T const& qu, T& qw, int dir_p, int dir_q, int direction)
+{
+ if (dir_p == direction) // If (Pk left-of Pi)
+ {
+ if (pk.first->direction == -direction) // if (Pk right-of Qu)
+ {
+ // make both Right
+ join_adapt(pk, -direction);
+ join_adapt(qw, -direction);
+ }
+ else
+ {
+ // make Pk Left, Qw Right
+ join_adapt(pk, direction);
+ join_adapt(qw, -direction);
+ }
+ }
+}
+
+
+
+template <typename T>
+inline void collinear(T const& pi, T & pk, T const& qu, T& qw, int dir_p, int dir_q, int direction)
+{
+ if (dir_p == direction // If (Pk left-of Pi
+ && dir_q == direction // && Qw left-of Qu
+ && pk.first->direction == -direction) // && Pk right-of Qu
+ {
+ // make both Right
+ join_adapt(pk, -direction);
+ join_adapt(qw, -direction);
+ }
+ else if (dir_p == -direction // If (Pk right-of Pi
+ && dir_q == -direction) // && Qw right-of Qu
+ {
+ // make both Left
+ join_adapt(pk, direction);
+ join_adapt(qw, direction);
+ }
+
+}
+
+template <typename T, typename P>
+inline void assign_pq(T const& info, P& p, P& q)
+{
+ if (info.seg_id.source_index == 0)
+ {
+ if (info.arrival == 1)
+ {
+ p.first = info.other_point;
+ }
+ else if (info.arrival == -1)
+ {
+ p.second = info.other_point;
+ }
+ }
+ else
+ {
+ if (info.arrival == 1)
+ {
+ q.first = info.other_point;
+ }
+ else if (info.arrival == -1)
+ {
+ q.second = info.other_point;
+ }
+ }
+}
+
+template <typename Info, typename Point>
+inline void touch_in_the_middle(Info& info, Point const& point)
+{
+ typedef typename boost::range_iterator<Info>::type iterator;
+
+ // Determine which is Q, and assign points
+ iterator qu, qw, p;
+ int count = 0;
+
+ // Find out which one is arriving/departing from the middle
+ for (iterator it = boost::begin(info);
+ it != boost::end(info);
+ ++it)
+ {
+ // One arrives AND departs in the middle of the other.
+ if(it->how == 'm' && it->arrival == 1)
+ {
+ qu = it;
+ count |= 1;
+ }
+ else if(it->how == 's' && it->arrival == -1)
+ {
+ qw = it;
+ count |= 2;
+ }
+ else if (it->how == 's') // or m, does not really matter
+ {
+ p = it;
+ count |= 4;
+ }
+
+ }
+ // Adapt it
+ if (count == 7
+ && qu->direction == qw->direction
+ && qu->seg_id.source_index == qw->seg_id.source_index)
+ {
+ int dir_q = the_side(qu->other_point, point, qw->other_point);
+
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Both "
+ << (qu->direction == 1 ? "Left" : "Right")
+ << ", Turn " << (dir_q == 1 ? "Left" : dir_q == -1 ? "Right" : "?")
+ << std::endl;
+#endif
+
+ // Let P also be starting
+ p->arrival = -1;
+
+ // This is also symmetric. See slides:
+ // Qu left-of P && Qw left-of P
+ if (qu->direction == 1 && dir_q == -1)
+ {
+ // make both Left
+ p->direction = 1;
+ qw->direction = 1;
+ }
+ // else, symmetric version
+ else if (qu->direction == -1 && dir_q == 1)
+ {
+ p->direction = -1;
+ qw->direction = -1;
+ }
+ }
+}
+
+
+
+
+template <typename Info>
+inline void arrive_in_the_middle(Info& info)
+{
+ typedef typename boost::range_iterator<Info>::type iterator;
+
+ // Find out which one is NOT arriving in the middle,
+ // and the direction of the one arriving in the middle
+ int departing = -1;
+ int direction = 0;
+ for (iterator it = boost::begin(info);
+ it != boost::end(info);
+ ++it)
+ {
+ if(it->how == 'm')
+ {
+ switch(it->arrival)
+ {
+ case 1 : direction = it->direction; break;
+ default : departing = it->seg_id.source_index;
+ }
+ }
+ }
+
+ // Make this the departing one, following collinear in opposite segment,
+ // same direction as established above
+ for (iterator it = boost::begin(info);
+ it != boost::end(info);
+ ++it)
+ {
+ if (it->how == 'c' && it->seg_id.source_index == departing)
+ {
+ it->arrival = -1;
+ it->direction = direction;
+ }
+ }
+}
+
+template <typename Info>
+inline void start_in_the_middle(Info& info, bool opposite)
+{
+ typedef typename boost::range_iterator<Info>::type iterator;
+
+ for (iterator it = boost::begin(info);
+ it != boost::end(info);
+ ++it)
+ {
+ if(it->how == 's')
+ {
+ if (! opposite)
+ {
+ // Not opposite, all "start" traversals can also be made "departing"
+ it->arrival = -1;
+ }
+ else if (opposite && it->arrival == 0)
+ {
+ // Prevent the collinear the "start" from "departing",
+ // if it is in opposite direction
+ it->arrival = 1;
+ it->direction = 0;
+ it->flagged = true; // might be deleted
+ }
+ }
+ }
+}
+
+
+template <typename V>
+inline void adapt_turns(V& intersection_points)
+{
+ typedef typename boost::range_iterator<V>::type iterator_type;
+ typedef typename boost::range_value<V>::type ip_type;
+ typedef typename ip_type::traversal_type info_type;
+
+ typedef typename boost::range_value<V>::type::traversal_vector vector_type;
+ typedef typename boost::range_iterator<vector_type>::type tvit_type;
+
+ for (iterator_type it = boost::begin(intersection_points);
+ it != boost::end(intersection_points);
+ ++it)
+ {
+ if (! it->trivial)
+ {
+ if (boost::size(it->info) == 4)
+ {
+ /*
+ can be ARRIVE/START from the middle (#11)
+ src 0 seg 1 (// 1.0) how m[A R] p // qu
+ src 0 seg 1 (// 1.1) how s[D L] p // qw
+ src 1 seg 0 (// 0.1) how m[A R] qu / p
+ src 1 seg 1 (// 0.1) how s[D R] qw / p
+
+ or can be ARRIVE at COLLINEARITY (#8, #13)
+ src 0 seg 1 (// 1.1) how m[A L] p // qu
+ src 0 seg 1 (// 1.2) how c[- -] p // qw
+ src 1 seg 1 (// 0.1) how m[A L] qu // p
+ src 1 seg 2 (// 0.1) how c[- -] qw // p
+
+ or can be START from COLLINEARITY (#8, #13)
+ src 0 seg 1 (// 1.2) how c[- -] p // qu
+ src 0 seg 1 (// 1.0) how s[D R] p // qw
+ src 1 seg 2 (// 0.1) how c[- -] qu // p
+ src 1 seg 0 (// 0.1) how s[D L] qw // p
+ */
+
+ // First detect the case and if it is opposite
+ int count_m = 0, count_s = 0, count_c = 0;
+
+ bool opposite = false;
+ for (tvit_type tvit = boost::begin(it->info);
+ tvit != boost::end(it->info);
+ ++tvit)
+ {
+ switch(tvit->how)
+ {
+ case 'm' : count_m++; break;
+ case 's' : count_s++; break;
+ case 'c' : count_c++; break;
+ }
+ if (tvit->opposite)
+ {
+ opposite = true;
+ }
+ }
+
+
+ if (count_m == 2 && count_s == 2)
+ {
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Touching the middle " << std::endl;
+#endif
+
+ touch_in_the_middle(it->info, it->point);
+ }
+ else if (count_m == 2 && count_c == 2 && opposite)
+ {
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Arriving the middle/collinearity, opposite" << std::endl;
+#endif
+
+ arrive_in_the_middle(it->info);
+ }
+ else if (count_s == 2 && count_c == 2)
+ {
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Starting from middle/collinearity"
+ << (opposite ? " , opposite" : "")
+ << std::endl;
+#endif
+
+ start_in_the_middle(it->info, opposite);
+ }
+ }
+
+ if (boost::size(it->info) == 8)
+ {
+ /*
+ src 0 seg 1 (// 1.0) how t[A R] pi // qu pi.first
+ src 0 seg 1 (// 1.1) how a[A R] pi // qw pi.second
+ src 0 seg 2 (// 1.0) how a[D R] pk // qu pk.first
+ src 0 seg 2 (// 1.1) how f[D L] pk // qw pk.second
+
+ src 1 seg 0 (// 0.1) how t[A L] qu // pi
+ src 1 seg 0 (// 0.2) how a[A R] qu // pk
+ src 1 seg 1 (// 0.1) how a[D R] qw // pi
+ src 1 seg 1 (// 0.2) how f[D R] qw // pk
+ */
+
+ std::pair<tvit_type, tvit_type> pi, pk, qu, qw;
+ std::pair<typename info_type::point_type, typename info_type::point_type> p, q;
+
+
+ // Find out which is which
+ for (tvit_type tvit = boost::begin(it->info);
+ tvit != boost::end(it->info);
+ ++tvit)
+ {
+ assign_pq(*tvit, p, q);
+ if (tvit->seg_id.source_index == 0)
+ {
+ if (tvit->arrival == 1)
+ {
+ if(tvit->how != 'a')
+ {
+ pi.first = tvit;
+ }
+ else
+ {
+ pi.second = tvit;
+ }
+
+ }
+ else if (tvit->arrival == -1)
+ {
+ if (tvit->how == 'a')
+ {
+ pk.first = tvit;
+ }
+ else
+ {
+ pk.second = tvit;
+ }
+ }
+ }
+ else
+ {
+ if (tvit->arrival == 1)
+ {
+ if(tvit->how != 'a')
+ {
+ qu.first = tvit;
+ }
+ else
+ {
+ qu.second = tvit;
+ }
+ }
+ else if (tvit->arrival == -1)
+ {
+ if (tvit->how == 'a')
+ {
+ qw.first = tvit;
+ }
+ else
+ {
+ qw.second = tvit;
+ }
+ }
+ }
+ }
+
+ int dir_p = the_side(p.first, it->point, p.second);
+ int dir_q = the_side(q.first, it->point, q.second);
+
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Pi//Qu : " << *pi.first << std::endl;
+ std::cout << "Pi//Qw : " << *pi.second << std::endl;
+ std::cout << "Pk//Qu : " << *pk.first << std::endl;
+ std::cout << "Pk//Qw : " << *pk.second << std::endl;
+ std::cout << "Qu//Pi : " << *qu.first << std::endl;
+ std::cout << "Qu//Pk : " << *qu.second << std::endl;
+ std::cout << "Qw//Pi : " << *qw.first << std::endl;
+ std::cout << "Qw//Pk : " << *qw.second << std::endl;
+ if (dir_p == 1) std::cout << "P turns left" << std::endl;
+ if (dir_p == -1) std::cout << "P turns right" << std::endl;
+ if (dir_q == 1) std::cout << "Q turns left" << std::endl;
+ if (dir_q == -1) std::cout << "Q turns right" << std::endl;
+#endif
+
+ if (qu.first->direction == qw.first->direction)
+ {
+ // Both Right or Both Left
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Both "
+ << (qu.first->direction == 1 ? "Left" : "Right")
+ << std::endl;
+#endif
+
+ both_same(pi, pk, qu, qw, dir_p, dir_q, qu.first->direction);
+ }
+ else if (qu.first->direction == -qw.first->direction)
+ {
+ // From Left to Right, or from Right to Left
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Left to/from Right" << std::endl;
+#endif
+ crossing(pi, pk, qu, qw, dir_p, dir_q, qu.first->direction);
+ }
+ else if (qw.first->direction == 1 || qu.first->direction == 1)
+ {
+ // Collinear left
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Collinear left" << std::endl;
+#endif
+ collinear(pi, pk, qu, qw, dir_p, dir_q, 1);
+ }
+ else if (qw.first->direction == -1 || qu.first->direction == -1)
+ {
+ // Collinear right
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Collinear right" << std::endl;
+#endif
+ collinear(pi, pk, qu, qw, dir_p, dir_q, -1);
+ }
+
+
+ for (tvit_type tvit = boost::begin(it->info);
+ tvit != boost::end(it->info);
+ ++tvit)
+ {
+ if (tvit->how == 'a')
+ {
+ tvit->direction = 0;
+ }
+ }
+
+
+ }
+ }
+ }
+
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Adapted turns: " << std::endl;
+ report_ip(intersection_points);
+#endif
+}
+
+
+
+}} // namespace detail::intersection
+#endif //DOXYGEN_NO_DETAIL
+
+
+
+template <typename V>
+inline void adapt_turns(V& intersection_points)
+{
+ // If there are merges, there might be merged IP's which have right turns
+ detail::intersection::adapt_turns(intersection_points);
+
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Merged (2): " << std::endl;
+ report_ip(intersection_points);
+#endif
+
+}
+
+
+} // namespace ggl
+
+#endif // GGL_ADAPT_TURNS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/copy_segments.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/copy_segments.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,211 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_OVERLAY_COPY_SEGMENTS_HPP
+#define GGL_ALGORITHMS_OVERLAY_COPY_SEGMENTS_HPP
+
+
+#include <ggl/core/ring_type.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+
+#include <ggl/algorithms/overlay/intersection_point.hpp>
+
+#include <ggl/iterators/ever_circling_iterator.hpp>
+#include <ggl/iterators/point_const_iterator.hpp>
+
+
+namespace ggl
+{
+
+
+#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 ggl::point_const_iterator<Ring>::type iterator;
+ typedef ggl::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)
+ {
+ // TODO: use 'copy coordinates' to handle different point types
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << " add: ("
+ << ggl::get<0>(*it) << ", " << ggl::get<1>(*it) << ")"
+ << std::endl;
+#endif
+ current_output.push_back(*it);
+ }
+ }
+};
+
+
+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 ggl::ring_type<Polygon>::type,
+ SegmentIdentifier,
+ RangeOut
+ >::apply
+ (
+ seg_id.ring_index < 0
+ ? ggl::exterior_ring(polygon)
+ : ggl::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)
+{
+ dispatch::copy_segments
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ SegmentIdentifier,
+ RangeOut
+ >::apply(geometry, seg_id, to_index, range_out);
+}
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_OVERLAY_COPY_SEGMENTS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/enrich_intersection_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/enrich_intersection_points.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,501 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_ENRICH_INTERSECTION_POINTS_HPP
+#define GGL_ALGORITHMS_ENRICH_INTERSECTION_POINTS_HPP
+
+#include <cstddef>
+#include <algorithm>
+#include <map>
+#include <vector>
+#ifdef GGL_DEBUG_INTERSECTION
+#include <iostream>
+#endif
+
+#include <boost/concept_check.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersection {
+
+#ifdef GGL_DEBUG_INTERSECTION
+
+template <typename M>
+inline void report_map(M const& map)
+{
+ std::cout << "Map [source,segment(,ring,multi)] -> [count]:" << std::endl;
+ for (typename M::const_iterator it = map.begin(); it != map.end(); it++)
+ {
+ std::cout << "(" << it->first << ")"
+ << " -> " << "(" << it->second << ")" << std::endl;
+ }
+}
+
+
+template <typename V>
+inline void report_indexed(V const& index)
+{
+ typedef typename boost::range_const_iterator<V>::type iterator_type;
+
+ for (iterator_type it = boost::begin(index); it != boost::end(index); ++it)
+ {
+ std::cout << it->index << ": " << it->subject;
+ }
+}
+
+#endif // GGL_DEBUG_INTERSECTION
+
+
+template <typename T>
+struct indexed_source_segment
+{
+ std::size_t index;
+ T subject;
+
+ inline indexed_source_segment() {}
+
+ inline indexed_source_segment(std::size_t i, T const& s, segment_identifier const& seg_id)
+ : index(i)
+ {
+ s.clone_except_info(subject);
+
+ typedef typename T::traversal_vector vector_type;
+ for (typename boost::range_const_iterator<vector_type>::type it = s.info.begin();
+ it != s.info.end(); ++it)
+ {
+ // Copy info-record if belonging to source and to segment
+ if (it->seg_id == seg_id)
+ {
+ subject.info.push_back(*it);
+ }
+ }
+ }
+};
+
+
+template <typename T>
+struct indexed_source
+{
+ T subject;
+ std::size_t index;
+
+ inline indexed_source() {}
+
+ inline indexed_source(std::size_t i, T const& s,
+ int source_index, int multi_index, int ring_index)
+ : index(i)
+ {
+ s.clone_except_info(subject);
+
+ typedef typename T::traversal_vector vector_type;
+ for (typename boost::range_const_iterator<vector_type>::type it = s.info.begin();
+ it != s.info.end(); ++it)
+ {
+ // Copy info-record if belonging to source
+ if (it->seg_id.source_index == source_index
+ && it->seg_id.multi_index == multi_index
+ && it->seg_id.ring_index == ring_index)
+ {
+ subject.info.push_back(*it);
+ }
+ }
+ }
+};
+
+
+template <typename Indexed>
+struct sort_on_distance
+{
+ inline bool operator()(Indexed const& left, Indexed const& right) const
+ {
+ // Sanity check, there should be info-records because only those are copied
+ BOOST_ASSERT (left.subject.info.size() > 0 && right.subject.info.size() > 0);
+
+ return left.subject.info.front().distance < right.subject.info.front().distance;
+ }
+};
+
+// Sorts on segment + ring_index + multi_index
+template <typename Indexed>
+struct sort_on_segment_identifier
+{
+ inline bool operator()(Indexed const& left, Indexed const& right) const
+ {
+ // Sanity check
+ BOOST_ASSERT (left.subject.info.size() > 0 && right.subject.info.size() > 0);
+
+ segment_identifier const& sl = left.subject.info.front().seg_id;
+ segment_identifier const& sr = right.subject.info.front().seg_id;
+
+ return sl == sr
+ ? left.subject.info.front().distance < right.subject.info.front().distance
+ : sl < sr;
+ }
+};
+
+
+template <typename Info>
+struct on_source_segment_dir
+{
+ inline bool operator()(Info const& left, Info const& right) const
+ {
+ int ldir = left.direction;
+ int rdir = right.direction;
+ if (ldir == -1) ldir = 2;
+ if (rdir == -1) rdir = 2;
+
+
+ return left.seg_id.source_index == right.seg_id.source_index
+ ? (left.seg_id.segment_index == right.seg_id.segment_index
+ ? ldir < rdir
+ : left.seg_id.segment_index < right.seg_id.segment_index
+ )
+
+ : left.seg_id.source_index < right.seg_id.source_index;
+ }
+};
+
+
+
+
+
+// Assigns IP[index] . info[source/multi/ring/segment] . next_ip_index
+template <typename V>
+static inline void assign_next_ip_index(V& intersection_points, int index,
+ segment_identifier const& seg_id,
+ int next_ip_index)
+{
+ typedef typename boost::range_value<V>::type ip_type;
+ typedef typename ip_type::traversal_vector vector_type;
+ typedef typename boost::range_iterator<vector_type>::type iterator_type;
+
+ ip_type& ip = intersection_points[index];
+
+ for (iterator_type it = boost::begin(ip.info);
+ it != boost::end(ip.info);
+ ++it)
+ {
+ if (it->seg_id == seg_id)
+ {
+ it->next_ip_index = next_ip_index;
+ // Note: there can be MORE than one here. So do NOT return
+ }
+ }
+}
+
+
+// Assigns IP[index] . info[source_index] . travels_to_[vertex,ip]_index
+template <typename V>
+static inline void assign_last_vertex(V& intersection_points, int index,
+ int source_index,
+ int travels_to_vertex_index, int travels_to_ip_index)
+{
+ typedef typename boost::range_value<V>::type ip_type;
+ typedef typename ip_type::traversal_vector vector_type;
+ typedef typename boost::range_iterator<vector_type>::type iterator_type;
+
+ ip_type& ip = intersection_points[index];
+
+ for (iterator_type it = boost::begin(ip.info); it != boost::end(ip.info); ++it)
+ {
+ if (it->seg_id.source_index == source_index)
+ {
+ it->travels_to_vertex_index = travels_to_vertex_index;
+ it->travels_to_ip_index = travels_to_ip_index;
+ // do not return here, there can be more than one
+ }
+ }
+}
+
+
+// Creates selection of IP-s of only this unique source/segment,
+// then sorts on distance,
+// then assigns for each IP which is the next IP on this segment.
+// This is only applicable (but essential) for segments having
+// more than one IP on it. It is not the usual situation, so not
+// computational intensive.
+template <typename V>
+static inline bool assign_next_points(V& intersection_points,
+ segment_identifier const& seg_id)
+{
+ typedef typename boost::range_value<V>::type ip_type;
+ typedef typename boost::range_const_iterator<V>::type iterator_type;
+ typedef indexed_source_segment<ip_type> indexed_type;
+ typedef typename ip_type::traversal_vector vector_type;
+ typedef typename boost::range_const_iterator<vector_type>::type tvit_type;
+
+ // Create a copy of all IP's on this segment from this source
+
+ std::vector<indexed_type> copy;
+ copy.reserve(intersection_points.size());
+ std::size_t index = 0;
+ for (iterator_type it = boost::begin(intersection_points);
+ it != boost::end(intersection_points);
+ ++it, ++index)
+ {
+ bool to_be_copied = false;
+ for (tvit_type tvit = boost::begin(it->info);
+ !to_be_copied && tvit != boost::end(it->info);
+ ++tvit)
+ {
+ if (tvit->seg_id == seg_id)
+ {
+ to_be_copied = true;
+ }
+ }
+
+ if (to_be_copied)
+ {
+ // Copy this row, plus ONLY the related information
+ copy.push_back(indexed_type(index, *it, seg_id));
+ }
+ }
+
+ // Normally there are more elements in "copy".
+ // But in case of merges there could be only one.
+ if (boost::size(copy) <= 1)
+ {
+ return false;
+ }
+
+ std::sort(copy.begin(), copy.end(), sort_on_distance<indexed_type>());
+
+
+ // Now that it is sorted, do the main purpose: assign the next points
+ typedef typename boost::range_iterator
+ <
+ std::vector<indexed_type>
+ >::type indexed_iterator_type;
+
+ indexed_iterator_type it = boost::begin(copy);
+ for (indexed_iterator_type prev = it++; it != boost::end(copy); prev = it++)
+ {
+ for (
+#ifdef GGL_DEBUG_INTERSECTION
+ typename boost::range_iterator<vector_type>::type
+#else
+ tvit_type
+#endif
+ tvit = boost::begin(it->subject.info);
+ tvit != boost::end(it->subject.info);
+ ++tvit)
+ {
+ if (tvit->seg_id == seg_id)
+ {
+ assign_next_ip_index(intersection_points, prev->index, seg_id, it->index);
+
+#ifdef GGL_DEBUG_INTERSECTION
+ tvit->next_ip_index = it->index;
+#endif
+
+ }
+ }
+ }
+
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Enrichment - sorted (on distance, " << seg_id << "): " << std::endl;
+ report_indexed(copy);
+#endif
+
+ return true;
+}
+
+
+// If a segment has more than one IP, we determine what is the next IP
+// on that segment
+template <typename M, typename V>
+static inline bool assign_next_points(M& map, V& intersection_points)
+{
+ bool assigned = false;
+ for (typename M::iterator mit = map.begin(); mit != map.end(); ++mit)
+ {
+ // IF there are more IP's on this segment
+ if (mit->second > 1)
+ {
+ if (assign_next_points(intersection_points, mit->first))
+ {
+ assigned = true;
+ }
+ }
+ }
+
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Enrichment - assigned next points on same segment: " << std::endl;
+ report_ip(intersection_points);
+#endif
+
+ return assigned;
+}
+
+
+template <typename V>
+static inline bool assign_order(V& intersection_points,
+ int source_index, int multi_index, int ring_index)
+{
+ typedef typename boost::range_value<V>::type ip_type;
+ typedef typename boost::range_const_iterator<V>::type iterator_type;
+ typedef indexed_source<ip_type> indexed_type;
+ typedef typename ip_type::traversal_vector vector_type;
+ typedef typename boost::range_const_iterator<vector_type>::type tvit_type;
+
+ // Create a copy of all IP's from this source
+ std::vector<indexed_type> copy;
+ copy.reserve(intersection_points.size());
+ std::size_t index = 0;
+ for (iterator_type it = boost::begin(intersection_points);
+ it != boost::end(intersection_points);
+ ++it, ++index)
+ {
+ bool to_be_copied = false;
+ for (tvit_type tvit = boost::begin(it->info);
+ !to_be_copied && tvit != boost::end(it->info);
+ ++tvit)
+ {
+ if (tvit->seg_id.source_index == source_index
+ && tvit->seg_id.multi_index == multi_index
+ && tvit->seg_id.ring_index == ring_index)
+ {
+ to_be_copied = true;
+ }
+ }
+
+ if (to_be_copied)
+ {
+ // Copy this row, plus ONLY the related information
+ copy.push_back(indexed_type(index, *it, source_index, multi_index, ring_index));
+ }
+ }
+
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Enrichment - ordered/copy (on segment "
+ << " src: " << source_index
+ << "): " << std::endl;
+ report_indexed(copy);
+#endif
+
+ std::sort(copy.begin(), copy.end(), sort_on_segment_identifier<indexed_type>());
+
+ typedef typename boost::range_const_iterator<std::vector<indexed_type> >::type iit_type;
+
+ // Now that it is sorted, do the main purpose:
+ // assign travel-to-vertex/ip index for each IP
+ // Because IP's are circular, PREV starts at the very last one,
+ // being assigned from the first one.
+ iit_type it = boost::begin(copy);
+ for (iit_type prev = it + (boost::size(copy) - 1);
+ it != boost::end(copy);
+ prev = it++)
+ {
+ for (tvit_type tvit = boost::begin(it->subject.info);
+ tvit != boost::end(it->subject.info);
+ ++tvit)
+ {
+ if (tvit->seg_id.source_index == source_index
+ && tvit->seg_id.multi_index == multi_index
+ && tvit->seg_id.ring_index == ring_index)
+ {
+ assign_last_vertex(intersection_points, prev->index, source_index,
+ tvit->seg_id.segment_index, it->index);
+ }
+ }
+ }
+
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Enrichment - ordered on segment (src: "
+ << source_index << "): " << std::endl;
+ report_ip(intersection_points);
+#endif
+
+ return true;
+}
+
+template <typename M, typename V>
+static inline void assign_order(M const& map, V& intersection_points)
+{
+ typename M::const_iterator prev;
+ bool first = true;
+ for (typename M::const_iterator mit = map.begin(); mit != map.end(); ++mit)
+ {
+ if (first
+ || prev->first.source_index != mit->first.source_index
+ || prev->first.ring_index != mit->first.ring_index
+ || prev->first.multi_index != mit->first.multi_index)
+ {
+ assign_order(intersection_points, mit->first.source_index,
+ mit->first.multi_index, mit->first.ring_index);
+ first = false;
+ }
+ prev = mit;
+ }
+
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Enrichment - assigned order: " << std::endl;
+ report_ip(intersection_points);
+#endif
+
+}
+
+
+
+
+}} // namespace detail::intersection
+#endif //DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief All intersection points are enriched with successor information
+ \ingroup overlay
+ \tparam IntersectionPoints type of intersection container (e.g. vector of "intersection_point"'s)
+ \param intersection_points container containing intersectionpoints
+ \param trivial Boolean flag to indicate that it is trivial, only intersections,
+ no touch, collinearities, etc.
+ */
+template <typename IntersectionPoints>
+inline void enrich_intersection_points(IntersectionPoints& intersection_points, bool trivial)
+{
+
+ // Create a map of segment<source_index,segment_index,ring_index,multi_index>
+ // to <number of IP's on this segment>
+ // Purpose: count IP's per source/segment, sort them lateron
+ std::map<segment_identifier, int> map;
+
+ typedef typename boost::range_const_iterator<IntersectionPoints>::type iterator_type;
+ for (iterator_type it = boost::begin(intersection_points);
+ it != boost::end(intersection_points);
+ ++it)
+ {
+ typedef typename boost::range_value
+ <
+ IntersectionPoints
+ >::type::traversal_vector vector_type;
+ typedef typename boost::range_const_iterator<vector_type>::type tvit_type;
+ for (tvit_type tvit = boost::begin(it->info);
+ tvit != boost::end(it->info);
+ ++tvit)
+ {
+ map[tvit->seg_id]++;
+ }
+ }
+
+#ifdef GGL_DEBUG_INTERSECTION
+ detail::intersection::report_map(map);
+#endif
+
+ detail::intersection::assign_next_points(map, intersection_points);
+
+ detail::intersection::assign_order(map, intersection_points);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_ENRICH_INTERSECTION_POINTS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/get_intersection_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/get_intersection_points.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,722 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_GET_INTERSECTION_POINTS_HPP
+#define GGL_ALGORITHMS_GET_INTERSECTION_POINTS_HPP
+
+#include <cstddef>
+
+#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 <ggl/core/access.hpp>
+#include <ggl/core/coordinate_dimension.hpp>
+#include <ggl/core/is_multi.hpp>
+#include <ggl/core/reverse_dispatch.hpp>
+
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+#include <ggl/core/ring_type.hpp>
+
+#include <ggl/util/math.hpp>
+
+#include <ggl/geometries/box.hpp>
+
+#include <ggl/strategies/cartesian/cart_intersect.hpp>
+#include <ggl/strategies/intersection_result.hpp>
+
+#include <ggl/policies/relate/intersection_points.hpp>
+#include <ggl/policies/relate/direction.hpp>
+#include <ggl/policies/relate/tupled.hpp>
+
+#include <ggl/algorithms/overlay/intersection_point.hpp>
+
+#include <ggl/algorithms/distance.hpp>
+#include <ggl/algorithms/disjoint.hpp>
+#include <ggl/algorithms/sectionalize.hpp>
+#include <ggl/algorithms/get_section.hpp>
+#include <ggl/algorithms/within.hpp>
+
+
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace get_intersection_points {
+
+
+template <typename Segment1, typename Segment2, typename IntersectionPoints>
+struct relate
+{
+ static inline bool apply(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;
+ typedef segment_intersection_points<intersection_point> ip_type;
+
+ typedef boost::tuple
+ <
+ ip_type,
+ policies::relate::direction_type
+ > result_type;
+
+ result_type result = strategy::intersection::relate_cartesian_segments
+ <
+ policies::relate::segments_tupled
+ <
+ policies::relate::segments_intersection_points
+ <
+ Segment1,
+ Segment2,
+ ip_type
+ > ,
+ policies::relate::segments_direction
+ <
+ Segment1,
+ Segment2
+ >
+ >
+ >::relate(s1, s2);
+
+ ip_type& is = result.get<0>();
+ policies::relate::direction_type & dir = result.get<1>();
+
+ for (int i = 0; i < is.count; i++)
+ {
+ typedef typename point_type<Segment1>::type point1_type;
+ typedef typename cs_tag<point1_type>::type tag;
+
+ typename intersection_point::traversal_type info;
+
+ info.how = dir.how;
+ info.opposite = dir.opposite;
+
+ // First info-record, containing info about segment 1
+ info.seg_id = seg_id1;
+ info.other_id = seg_id2;
+ info.other_point = dir.how_a == 1 ? s1.first : s1.second;
+
+ info.distance = ggl::distance(is.intersections[i], s1.first);
+
+ //info.distance = dir.ra; // NOTE: not possible for collinear intersections!
+ info.arrival = dir.how_a;
+ info.direction = dir.dir_a;
+ is.intersections[i].info.push_back(info);
+
+
+ // Second info-record, containing info about segment 2
+ info.seg_id = seg_id2;
+ info.other_id = seg_id1;
+ info.other_point = dir.how_b == 1 ? s2.first : s2.second;
+
+ info.distance = ggl::distance(is.intersections[i], s2.first);
+ //info.distance = dir.rb;
+
+ info.arrival = dir.how_b;
+ info.direction = dir.dir_b;
+ is.intersections[i].info.push_back(info);
+
+ if (dir.how != 'i')
+ {
+ trivial = false;
+ is.intersections[i].trivial = false;
+ }
+
+ // Robustness: due to IEEE floating point errors, also in double, it might be
+ // that the IP is at the same location as s1.first/s1.second, and still
+ // being classified as an 'i' (normal intersection). Then handle it as non-trivial,
+ // such that the IP's will be merged lateron.
+
+ double eps = 1.0e-10;
+ if (dir.how == 'i'
+ && (dir.ra < eps
+ || dir.rb < eps
+ || 1.0 - dir.ra < eps
+ || 1.0 - dir.rb < eps
+ )
+ )
+ {
+ // Handle them as non-trivial. This will case a "merge" lateron,
+ // which could be done anyway (because of other intersections)
+ // So it is never harmful to do this with a larger epsilon.
+ // However, it has to be handled (more) carefully lateron, in
+ // 'merge' or 'adapt_turns'
+ trivial = false;
+ is.intersections[i].trivial = false;
+
+
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "INTERSECTION suspicious: " << std::setprecision(20)
+ << " ra: " << dir.ra
+ << " rb: " << dir.rb
+ << std::endl
+ << " dist1: " << ggl::distance(is.intersections[i], s1.first)
+ << " dist2: " << ggl::distance(is.intersections[i], s1.second)
+ << std::endl;
+#endif
+ }
+
+ out.push_back(is.intersections[i]);
+ }
+ return is.count > 0;
+ }
+};
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Section1, typename Section2,
+ typename IntersectionPoints
+>
+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 ggl::point_const_iterator
+ <
+ Geometry1
+ >::type range1_iterator;
+ typedef typename ggl::point_const_iterator
+ <
+ Geometry2
+ >::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>
+ ::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 ggl::point_type<Geometry1>::type point1_type;
+ typedef typename ggl::point_type<Geometry2>::type point2_type;
+ typedef typename ggl::segment<const point1_type> segment1_type;
+ typedef typename ggl::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
+>
+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>
+ ::apply(
+ source_id1, ring, sec1,
+ source_id2, box, sec2,
+ false,
+ intersection_points, trivial);
+ }
+};
+
+
+
+
+template<typename Geometry1, typename Geometry2, typename IntersectionPoints>
+struct get_ips_generic
+{
+ 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
+ typedef typename ggl::sections
+ <
+ ggl::box < typename ggl::point_type<Geometry1>::type >, 1
+ > sections1_type;
+ typedef typename ggl::sections
+ <
+ ggl::box < typename ggl::point_type<Geometry2>::type >, 1
+ > sections2_type;
+
+ sections1_type sec1;
+ sections2_type sec2;
+
+ ggl::sectionalize(geometry1, sec1);
+ ggl::sectionalize(geometry2, sec2);
+
+ bool trivial = true;
+ for (typename boost::range_const_iterator<sections1_type>::type
+ it1 = sec1.begin();
+ it1 != sec1.end();
+ ++it1)
+ {
+ for (typename boost::range_const_iterator<sections2_type>::type
+ it2 = sec2.begin();
+ it2 != sec2.end();
+ ++it2)
+ {
+ if (! ggl::disjoint(it1->bounding_box, it2->bounding_box))
+ {
+ get_ips_in_sections
+ <
+ Geometry1,
+ Geometry2,
+ typename boost::range_value<sections1_type>::type,
+ typename boost::range_value<sections2_type>::type,
+ IntersectionPoints
+ >::apply(
+ source_id1, geometry1, *it1,
+ source_id2, geometry2, *it2,
+ false,
+ intersection_points, trivial);
+ }
+ }
+ }
+ return trivial;
+ }
+};
+
+
+
+template<typename Range, typename Box, typename IntersectionPoints>
+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 ggl::point_type<Box>::type box_point_type;
+ typedef typename ggl::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)
+ )
+ )
+ {
+ segment_identifier seg_id(source_id1,
+ multi_index, ring_index, index);
+
+ typedef relate
+ <
+ segment_type, box_segment_type, IntersectionPoints
+ > relater;
+
+ // Todo: 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);
+
+ }
+ }
+ }
+
+
+ template<std::size_t Index, typename Point>
+ static inline int get_side(Box const& box, Point const& point)
+ {
+ // Note: border has to be included because of boundary cases
+
+ if (get<Index>(point) <= get<min_corner, Index>(box)) return -1;
+ else if (get<Index>(point) >= get<max_corner, Index>(box)) 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
+
+>
+struct get_intersection_points
+{
+};
+
+
+template<typename Polygon, typename Box, typename IntersectionPoints>
+struct get_intersection_points
+ <
+ polygon_tag, box_tag, false, false,
+ Polygon, Box,
+ IntersectionPoints
+ >
+{
+
+ 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 ggl::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> intersector_type;
+
+ bool trivial = true;
+ intersector_type::apply(
+ source_id1, ggl::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 Ring1, typename Ring2, typename IntersectionPoints>
+struct get_intersection_points
+ <
+ ring_tag, ring_tag, false, false,
+ Ring1, Ring2,
+ IntersectionPoints
+ >
+ : detail::get_intersection_points::get_ips_generic
+ <
+ Ring1,
+ Ring2,
+ IntersectionPoints
+ >
+{};
+
+
+template<typename Polygon1, typename Polygon2, typename IntersectionPoints>
+struct get_intersection_points
+ <
+ polygon_tag, polygon_tag, false, false,
+ Polygon1, Polygon2,
+ IntersectionPoints
+ >
+ : detail::get_intersection_points::get_ips_generic
+ <
+ Polygon1,
+ Polygon2,
+ IntersectionPoints
+ >
+{};
+
+template
+<
+ typename LineString1,
+ typename LineString2,
+ typename IntersectionPoints
+>
+struct get_intersection_points
+ <
+ linestring_tag, linestring_tag, false, false,
+ LineString1, LineString2,
+ IntersectionPoints
+ >
+ : detail::get_intersection_points::get_ips_generic
+ <
+ LineString1,
+ LineString2,
+ IntersectionPoints
+ >
+{};
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2,
+ bool IsMulti1, bool IsMulti2,
+ typename Geometry1, typename Geometry2,
+ typename IntersectionPoints
+>
+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
+ >::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
+ \return TRUE if it is trivial, else FALSE
+ */
+template <typename Geometry1, typename Geometry2, typename IntersectionPoints>
+inline bool get_intersection_points(Geometry1 const& geometry1,
+ Geometry2 const& geometry2, IntersectionPoints& intersection_points)
+{
+ assert_dimension_equal<Geometry1, 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::get_intersection_points_reversed
+ <
+ typename tag<ncg1_type>::type,
+ typename tag<ncg2_type>::type,
+ is_multi<ncg1_type>::type::value,
+ is_multi<ncg2_type>::type::value,
+ ncg1_type,
+ ncg2_type,
+ IntersectionPoints
+ >,
+ dispatch::get_intersection_points
+ <
+ typename tag<ncg1_type>::type,
+ typename tag<ncg2_type>::type,
+ is_multi<ncg1_type>::type::value,
+ is_multi<ncg2_type>::type::value,
+ ncg1_type,
+ ncg2_type,
+ IntersectionPoints
+ >
+ >::type::apply(
+ 0, geometry1,
+ 1, geometry2,
+ intersection_points);
+}
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_GET_INTERSECTION_POINTS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/intersection_point.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/intersection_point.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,255 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_INTERSECTION_POINT_HPP
+#define GGL_ALGORITHMS_INTERSECTION_POINT_HPP
+
+#include <vector>
+
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/coordinate_dimension.hpp>
+
+#include <ggl/strategies/distance_result.hpp>
+#include <ggl/strategies/strategy_traits.hpp>
+
+#include <ggl/algorithms/overlay/segment_identifier.hpp>
+
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersection {
+
+
+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(ggl::make_distance_result<distance_type>(0))
+ , direction(0)
+ , how('?')
+ , arrival(0)
+ , opposite(false)
+ , visit_code(0)
+ , 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;
+
+ int visit_code;
+
+ bool flagged; // flagged for deletion
+
+#ifdef GGL_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)
+ {
+ 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" : "")
+ << "]"
+ << " nxt seg " << info.travels_to_vertex_index
+ << " , ip " << info.travels_to_ip_index
+ << " , or " << info.next_ip_index
+ << " dst " << std::setprecision(12) << double(info.distance);
+ if (info.visit_code != 0)
+ {
+ os << " VIS: " << int(info.visit_code);
+ }
+ return os;
+ }
+#endif
+};
+
+
+template<typename P>
+struct intersection_point
+{
+ public :
+ inline intersection_point()
+ : visit_code(0) // VISIT_NONE
+ , trivial(true)
+ , shared(false)
+ , flagged(false)
+ {
+ }
+
+
+#ifdef GGL_DEBUG_INTERSECTION
+ friend std::ostream& operator<<(std::ostream &os, intersection_point<P> const& p)
+ {
+ os << "IP (" << ggl::get<0>(p.point) << "," << ggl::get<1>(p.point) << ")"
+ << " visited: " << int(p.visit_code)
+ << (p.shared ? " SHARED" : "")
+ << (p.flagged ? " FLAGGED" : "")
+ << std::endl;
+
+ for (unsigned int i = 0; i < p.info.size(); i++)
+ {
+ os << p.info[i] << std::endl;
+ }
+ return os;
+ }
+#endif
+ typedef intersection_info<P> traversal_type;
+ typedef std::vector<traversal_type> traversal_vector;
+
+ P point;
+
+ int visit_code;
+ 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.visit_code = visit_code;
+ other.trivial = trivial;
+ other.shared = shared;
+ other.flagged = flagged;
+ }
+};
+
+
+
+
+}} // namespace detail::intersection
+#endif //DOXYGEN_NO_DETAIL
+
+
+// Register the intersection point as being a point fulfilling the ggl Point Concept
+namespace traits
+{
+
+ template <typename P>
+ struct coordinate_type<ggl::detail::intersection::intersection_point<P> >
+ {
+ typedef typename ggl::coordinate_type<P>::type type;
+ };
+
+ template <typename P>
+ struct coordinate_system<ggl::detail::intersection::intersection_point<P> >
+ {
+ typedef typename ggl::coordinate_system<P>::type type;
+ };
+
+ template <typename P>
+ struct dimension<ggl::detail::intersection::intersection_point<P> >
+ : ggl::dimension<P>
+ {};
+
+ template <typename P>
+ struct tag<ggl::detail::intersection::intersection_point<P> >
+ {
+ typedef point_tag type;
+ };
+
+ template <typename P>
+ struct access<ggl::detail::intersection::intersection_point<P> >
+ {
+ template <int Index>
+ static inline typename coordinate_type<P>::type get(
+ ggl::detail::intersection::intersection_point<P> const& p)
+ {
+ return ggl::get<Index>(p.point);
+ }
+
+ template <int Index>
+ static inline void set(ggl::detail::intersection::intersection_point<P>& p,
+ typename coordinate_type<P>::type const& value)
+ {
+ ggl::set<Index>(p.point, value);
+ }
+ };
+
+}
+
+
+#ifdef GGL_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 // GGL_DEBUG_INTERSECTION
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_INTERSECTION_POINT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/merge_intersection_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/merge_intersection_points.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,254 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_MERGE_INTERSECTION_POINTS_HPP
+#define GGL_ALGORITHMS_MERGE_INTERSECTION_POINTS_HPP
+
+#include <algorithm>
+
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <ggl/core/coordinate_type.hpp>
+
+#include <ggl/algorithms/equals.hpp>
+
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersection {
+
+template <typename PointType>
+struct on_increasing_dimension
+{
+ typedef typename ggl::coordinate_type<PointType>::type coordinate_type;
+
+ inline bool operator()(PointType const& lhs, PointType const& rhs) const
+ {
+ coordinate_type const& left0 = ggl::get<0>(lhs);
+ coordinate_type const& right0 = ggl::get<0>(rhs);
+
+ return math::equals(left0, right0)
+ ? ggl::get<1>(lhs) < ggl::get<1>(rhs)
+ : left0 < right0;
+ }
+};
+
+
+
+// T can be an intersection_point or intersection_info record
+template <typename T>
+struct is_flagged
+{
+ inline bool operator()(T const& object) const
+ {
+ return object.flagged;
+ }
+};
+
+
+
+template <typename V>
+inline void remove_collinearities(V& intersection_points)
+{
+ typedef typename boost::range_iterator<V>::type iterator_type;
+ typedef typename boost::range_value<V>::type ip_type;
+ typedef typename ip_type::traversal_type info_type;
+
+
+ for (iterator_type it = boost::begin(intersection_points);
+ it != boost::end(intersection_points);
+ ++it)
+ {
+ if (! it->trivial && ! it->flagged)
+ {
+ // Remove anything having to do with collinearity
+ typedef typename boost::range_value<V>::type::traversal_vector vector_type;
+ typedef typename boost::range_iterator<vector_type>::type tvit_type;
+
+ bool has_flag = false;
+
+ // Note, this is done n*m, in case of collinearity, but it is only done if not trivial
+ // or if there
+ bool middle = false;
+ for (tvit_type tvit = boost::begin(it->info);
+ ! middle && tvit != boost::end(it->info);
+ ++tvit)
+ {
+ if (tvit->how == 'e' || tvit->how == 'c')
+ {
+ tvit->flagged = true;
+ has_flag = true;
+
+ for (tvit_type tvit2 = boost::begin(it->info);
+ tvit2 != boost::end(it->info); ++tvit2)
+ {
+ // Do NOT remove anything starting from collinear, or ending on, in the middle.
+ if (tvit2->how != 'm' && tvit2->how != 's')
+ {
+ if (tvit->seg_id == tvit2->seg_id
+ || tvit->seg_id == tvit2->other_id
+ || tvit->other_id == tvit2->seg_id
+ || tvit->other_id == tvit2->other_id
+ )
+ {
+ tvit2->flagged = true;
+ }
+ }
+ else
+ {
+ tvit->flagged = false;
+ has_flag = false;
+ middle = true;
+ }
+ }
+ }
+ }
+
+ if (has_flag)
+ {
+ it->info.erase(
+ std::remove_if(
+ boost::begin(it->info),
+ boost::end(it->info),
+ is_flagged<info_type>()),
+ boost::end(it->info));
+
+ // Mark for deletion afterwards if there are no info-records left
+ if (boost::size(it->info) == 0)
+ {
+ it->flagged = true;
+ }
+
+ // Cases, previously forming an 'angle' (test #19)
+ // will be normal (neutral) case now,
+ // so to continue traversal:
+ if (it->info.size() == 2
+ && it->info.front().how == 'a'
+ && it->info.back().how == 'a')
+ {
+ it->info.front().direction = 1;
+ it->info.back().direction = 1;
+ }
+ }
+ }
+ }
+
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Removed collinearities: " << std::endl;
+ report_ip(intersection_points);
+#endif
+}
+
+
+
+
+
+}} // namespace detail::intersection
+#endif //DOXYGEN_NO_DETAIL
+
+
+
+/*!
+ \brief Merges intersection points such that points at the same location will be merged, having one point
+ and their info-records appended
+ \ingroup overlay
+ \tparam IntersectionPoints type of intersection container (e.g. vector of "intersection_point"'s)
+ \param intersection_points container containing intersectionpoints
+ */
+template <typename IntersectionPoints>
+inline void merge_intersection_points(IntersectionPoints& intersection_points)
+{
+ typedef typename boost::range_value<IntersectionPoints>::type trav_type;
+
+ if (boost::size(intersection_points) <= 1)
+ {
+ return;
+ }
+
+
+ // Sort all IP's from left->right, ymin->ymax such that
+ // all same IP's are consecutive
+ // (and we need this order lateron again)
+ // This order is NOT changed here and should not be after
+ // (otherwise indexes are wrong)
+ std::sort(boost::begin(intersection_points),
+ boost::end(intersection_points),
+ detail::intersection::on_increasing_dimension<trav_type>());
+
+ typedef typename boost::range_iterator<IntersectionPoints>::type iterator;
+
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Sorted (x then y): " << std::endl;
+ for (iterator it = boost::begin(intersection_points);
+ it != boost::end(intersection_points); ++it)
+ {
+ std::cout << *it;
+ }
+#endif
+ bool has_merge = false;
+
+ // Merge all same IP's, combining there IP/segment-info entries
+ iterator it = boost::begin(intersection_points);
+ for (iterator prev = it++; it != boost::end(intersection_points); ++it)
+ {
+ // IP can be merged if the point is equal
+ if (ggl::equals(prev->point, it->point))
+ {
+ has_merge = true;
+ prev->shared = true;
+ prev->trivial = false;
+ it->flagged = true;
+ std::copy(it->info.begin(), it->info.end(),
+ std::back_inserter(prev->info));
+ }
+ else
+ {
+ prev = it;
+ }
+ }
+
+
+ if (has_merge)
+ {
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Merged (1): " << std::endl;
+ report_ip(intersection_points);
+#endif
+
+ // If there merges, there might be collinearities
+ detail::intersection::remove_collinearities(intersection_points);
+
+ // Remove all IP's which are flagged for deletion
+ intersection_points.erase(
+ std::remove_if(
+ boost::begin(intersection_points),
+ boost::end(intersection_points),
+ detail::intersection::is_flagged<trav_type>()),
+ boost::end(intersection_points));
+
+
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "Merged (2): " << std::endl;
+ report_ip(intersection_points);
+#endif
+
+
+ }
+
+}
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_MERGE_INTERSECTION_POINTS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/segment_identifier.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/segment_identifier.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,86 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_OVERLAY_SEGMENT_IDENTIFIER_HPP
+#define GGL_ALGORITHMS_OVERLAY_SEGMENT_IDENTIFIER_HPP
+
+#include <vector>
+
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/coordinate_dimension.hpp>
+
+#include <ggl/strategies/distance_result.hpp>
+#include <ggl/strategies/strategy_traits.hpp>
+
+namespace ggl
+{
+
+
+// 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
+ ;
+ }
+
+#ifdef GGL_DEBUG_INTERSECTION
+ 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 ggl
+
+#endif // GGL_ALGORITHMS_OVERLAY_SEGMENT_IDENTIFIER_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/self_intersection_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/self_intersection_points.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,167 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_SELF_INTERSECTION_POINTS_HPP
+#define GGL_ALGORITHMS_SELF_INTERSECTION_POINTS_HPP
+
+#include <cstddef>
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/coordinate_dimension.hpp>
+#include <ggl/core/is_multi.hpp>
+
+#include <ggl/algorithms/overlay/get_intersection_points.hpp>
+
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace self_intersection_points {
+
+template
+<
+ typename Geometry,
+ typename IntersectionPoints
+>
+struct check_ips
+{
+ static inline bool apply(
+ Geometry const& geometry,
+ bool return_if_found,
+ IntersectionPoints& intersection_points)
+ {
+ typedef typename ggl::sections
+ <
+ ggl::box < typename ggl::point_type<Geometry>::type >, 1
+ > sections_type;
+
+ sections_type sec;
+ ggl::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 (! ggl::disjoint(it1->bounding_box, it2->bounding_box)
+ && ! it1->duplicate
+ && ! it2->duplicate
+ )
+ {
+ ggl::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
+ >::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
+
+>
+struct self_intersection_points
+{
+};
+
+
+template<typename Ring, typename IntersectionPoints>
+struct self_intersection_points
+ <
+ ring_tag, false, Ring,
+ IntersectionPoints
+ >
+ : detail::self_intersection_points::check_ips
+ <
+ Ring,
+ IntersectionPoints
+ >
+{};
+
+
+template<typename Polygon, typename IntersectionPoints>
+struct self_intersection_points
+ <
+ polygon_tag, false, Polygon,
+ IntersectionPoints
+ >
+ : detail::self_intersection_points::check_ips
+ <
+ Polygon,
+ IntersectionPoints
+ >
+{};
+
+
+} // 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)
+{
+ 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
+ >::apply(geometry, false, intersection_points);
+}
+
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_SELF_INTERSECTION_POINTS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/traverse.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/overlay/traverse.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,437 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_OVERLAY_TRAVERSE_HPP
+#define GGL_ALGORITHMS_OVERLAY_TRAVERSE_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/coordinate_dimension.hpp>
+
+#include <ggl/algorithms/overlay/copy_segments.hpp>
+
+#ifdef GGL_DEBUG_INTERSECTION
+#include <ggl/extensions/gis/io/wkt/write_wkt.hpp>
+#endif
+
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersection {
+
+
+const int VISIT_NONE = 0;
+const int VISIT_START = 1;
+const int VISIT_VISITED = 2;
+const int VISIT_FINISH = 3;
+const int VISIT_WITHIN = 4;
+
+
+template
+<
+ typename IntersectionPoint,
+ typename IntersectionInfo
+>
+struct on_direction
+{
+ on_direction(IntersectionPoint const& ip, int direction)
+ : m_ip(ip)
+ , m_direction(direction)
+ {}
+
+ // TEMP: convenient COPY of side
+ template <typename P1, typename P2, typename P>
+ static inline int side(P1 const& p1, P2 const& p2, P const& p)
+ {
+ typedef typename select_coordinate_type<P, P1>::type T;
+
+ T dx = get<0>(p2) - get<0>(p1);
+ T dy = get<1>(p2) - get<1>(p1);
+ T dpx = get<0>(p) - get<0>(p1);
+ T dpy = get<1>(p) - get<1>(p1);
+ T product = dx * dpy - dy * dpx;
+ return product > 0 ? 1 : product < 0 ? -1 : 0;
+ }
+
+ inline bool operator()(IntersectionInfo const& first, IntersectionInfo const& second) const
+ {
+ int dir = side(m_ip, first->other_point, second->other_point);
+ return m_direction == dir;
+ }
+
+private :
+ IntersectionPoint const& m_ip;
+ int m_direction;
+};
+
+
+template
+<
+ typename GeometryOut,
+ typename G1,
+ typename G2,
+ typename IntersectionPoints,
+ typename IntersectionInfo
+>
+inline bool assign_next_ip(G1 const& g1, G2 const& g2, int direction,
+ IntersectionPoints& intersection_points,
+ typename boost::range_iterator<IntersectionPoints>::type & ip,
+ GeometryOut& current_output,
+ IntersectionInfo & info)
+{
+ info.visit_code = VISIT_VISITED;
+
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << " take: " << info << std::endl;
+#endif
+
+ // If there is no next IP on this segment
+ if (info.next_ip_index < 0)
+ {
+ if (info.seg_id.source_index == 0)
+ {
+ ggl::copy_segments(g1, info.seg_id,
+ info.travels_to_vertex_index,
+ current_output);
+ }
+ else
+ {
+ ggl::copy_segments(g2, info.seg_id,
+ info.travels_to_vertex_index,
+ current_output);
+ }
+ ip = boost::begin(intersection_points) + info.travels_to_ip_index;
+ }
+ else
+ {
+ ip = boost::begin(intersection_points) + info.next_ip_index;
+ }
+ current_output.push_back(ip->point);
+
+ return true;
+}
+
+template <typename Info>
+inline bool turning(Info const& info, int direction)
+{
+ // If it is turning in specified direction (RIGHT for intersection,
+ // LEFT for union, and NOT arriving at that point
+ return info.direction == direction
+ && info.arrival != 1
+ //&& (! (info.how == 'a' && info.direction != 0))
+ ;
+}
+
+template
+<
+ typename GeometryOut,
+ typename G1,
+ typename G2,
+ typename IntersectionPoints
+>
+inline bool select_next_ip_trivial(G1 const& g1, G2 const& g2, int direction,
+ IntersectionPoints& intersection_points,
+ typename boost::range_iterator<IntersectionPoints>::type & ip,
+ GeometryOut& current_output)
+{
+ // Check all intersecting segments on this IP:
+ typedef typename boost::range_value<IntersectionPoints>::type ip_type;
+ typedef typename ip_type::traversal_vector tv;
+ typedef typename boost::range_iterator<tv>::type tit_type;
+
+ for (tit_type it = boost::begin(ip->info); it != boost::end(ip->info); ++it)
+ {
+ if (turning(*it, direction))
+ {
+ return assign_next_ip(g1, g2, direction,
+ intersection_points, ip, current_output, *it);
+ }
+ }
+
+ return false;
+}
+
+
+template
+<
+ typename GeometryOut,
+ typename G1,
+ typename G2,
+ typename IntersectionPoints
+>
+inline bool select_next_ip_with_sorting(G1 const& g1, G2 const& g2,
+ int direction,
+ IntersectionPoints& intersection_points,
+ typename boost::range_iterator<IntersectionPoints>::type & ip,
+ GeometryOut& current_output)
+{
+
+ typedef typename boost::range_value<IntersectionPoints>::type ip_type;
+ typedef typename ip_type::traversal_vector tv;
+ typedef typename boost::range_iterator<tv>::type tit_type;
+ typedef typename ip_type::traversal_type info_type;
+
+ std::vector<info_type*> info;
+ for (tit_type it = boost::begin(ip->info); it != boost::end(ip->info); ++it)
+ {
+ if (turning(*it, direction))
+ {
+ info.push_back(&(*it));
+ }
+ }
+
+ // If there are no intersection points, fall-back to collinear cases or
+ // if already in that case, return false.
+ if (boost::size(info) == 0)
+ {
+ return direction == 0
+ ? false
+ : select_next_ip_with_sorting(g1, g2, 0,
+ intersection_points, ip, current_output);
+ }
+
+ // For one IP, it is easy: take that one.
+ if (boost::size(info) == 1)
+ {
+ return assign_next_ip(g1, g2, direction,
+ intersection_points, ip, current_output, *info.front());
+ }
+
+ // In case of direction 0, also take first one
+ // TODO: sort this vector somehow, there are more rows, it is too
+ // arbitrary to take first one (though working well)
+ if (direction == 0)
+ {
+ return assign_next_ip(g1, g2, direction,
+ intersection_points, ip, current_output, *info.front());
+ }
+
+
+ // For more, sort the information on direction, take the most left / right one
+ //std::cout << " " << boost::size(info);
+ std::sort(info.begin(), info.end(), on_direction<ip_type, info_type*>(*ip, direction));
+ return assign_next_ip(g1, g2, direction, intersection_points, ip, current_output, *info.back());
+}
+
+template
+<
+ typename GeometryOut,
+ typename G1,
+ typename G2,
+ typename IntersectionPoints
+>
+inline bool select_next_ip(G1 const& g1, G2 const& g2, int direction,
+ IntersectionPoints& intersection_points,
+ typename boost::range_iterator<IntersectionPoints>::type & ip,
+ GeometryOut& current_output)
+{
+ if (ip->trivial)
+ {
+ return select_next_ip_trivial(g1, g2, direction, intersection_points,
+ ip, current_output);
+ }
+ else
+ {
+ return select_next_ip_with_sorting(g1, g2, direction, intersection_points,
+ ip, current_output);
+ }
+}
+
+
+template<typename IntersectionPoint>
+inline bool is_starting_point(IntersectionPoint const& ip, int direction)
+{
+ for (typename IntersectionPoint::traversal_vector::const_iterator it
+ = boost::begin(ip.info); it != boost::end(ip.info); ++it)
+ {
+ if (it->direction == direction
+ && it->arrival != 1)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+template <typename Container>
+inline void stop_gracefully(Container& container, bool& stop,
+ std::string const& reason)
+{
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "STOPPING: " << reason << std::endl;
+#endif
+
+ stop = true;
+ if (container.size() > 0)
+ {
+ container.push_back(container.front());
+ }
+}
+
+}} // namespace detail::intersection
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+
+
+
+/*!
+ \brief Traverses through intersection points / geometries
+ \ingroup overlay
+ */
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename IntersectionPoints,
+ typename OutputIterator
+>
+inline void traverse(Geometry1 const& geometry1,
+ Geometry2 const& geometry2, int direction,
+ IntersectionPoints& intersection_points,
+ bool trivial,
+ OutputIterator out)
+{
+ typedef typename boost::range_iterator
+ <IntersectionPoints>::type ip_iterator;
+
+ typedef typename boost::range_value<IntersectionPoints>::type ip_type;
+ typedef typename ip_type::traversal_vector tv;
+ typedef typename boost::range_iterator<tv>::type tit_type;
+ typedef typename ip_type::traversal_type info_type;
+
+
+
+ GeometryOut current_output;
+
+
+ // Iterate through all unvisited points
+ for (ip_iterator it = boost::begin(intersection_points);
+ it != boost::end(intersection_points);
+ ++it)
+ {
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "TRY traversal: " << *it;
+#endif
+
+ if (it->visit_code == detail::intersection::VISIT_NONE
+ // UNION may operate on non-starting points, but INTERSECTION may not.
+ // TODO: re-evaluate that
+ && (direction == 1
+ || detail::intersection::is_starting_point(*it, direction)
+ )
+ )
+ {
+ for (tit_type iit = boost::begin(it->info);
+ iit != boost::end(it->info);
+ ++iit)
+ {
+ if (iit->arrival == -1
+ && iit->visit_code == detail::intersection::VISIT_NONE
+ && iit->direction == direction)
+ {
+ it->visit_code = detail::intersection::VISIT_START;
+ iit->visit_code = detail::intersection::VISIT_START;
+
+ current_output.push_back(it->point);
+
+ ip_iterator current = it;
+
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "START traversal: " << *current;
+#endif
+
+ detail::intersection::assign_next_ip(geometry1, geometry2,
+ direction,
+ intersection_points,
+ current, current_output, *iit);
+
+ std::vector<segment_identifier> segments;
+ segments.push_back(iit->seg_id);
+
+ unsigned int i = 0;
+ bool stop = false;
+
+ while (current != it && ! stop)
+ {
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "traverse: " << *current;
+#endif
+
+ // 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.
+ if (! detail::intersection::select_next_ip(geometry1,
+ geometry2, direction,
+ intersection_points,
+ current, current_output))
+ {
+ // 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::intersection::stop_gracefully(
+ current_output, stop, "Dead end");
+ }
+
+ if (current->visit_code == detail::intersection::VISIT_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::intersection::stop_gracefully(
+ current_output, stop, "Visit again");
+ }
+
+
+ if (i++ > intersection_points.size())
+ {
+ // Sanity check: there may be never more loops
+ // than intersection points.
+ detail::intersection::stop_gracefully(
+ current_output, stop, "Endless loop");
+ }
+
+ current->visit_code = detail::intersection::VISIT_VISITED;
+ }
+
+ iit->visit_code = detail::intersection::VISIT_FINISH;
+
+#ifdef GGL_DEBUG_INTERSECTION
+ std::cout << "finish: " << *current;
+ std::cout << ggl::wkt(current_output) << std::endl;
+#endif
+
+ *out = current_output;
+ ++out;
+ current_output.clear();
+ }
+ }
+ it->visit_code = detail::intersection::VISIT_FINISH;
+ }
+ }
+}
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_OVERLAY_TRAVERSE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/perimeter.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/perimeter.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,141 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_PERIMETER_HPP
+#define GGL_ALGORITHMS_PERIMETER_HPP
+
+#include <cmath>
+#include <iterator>
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/algorithms/length.hpp>
+#include <ggl/core/cs.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/strategies/strategies.hpp>
+
+/*!
+\defgroup perimeter perimeter calculation
+The perimeter algorithm is implemented for polygon,box,linear_ring,multi_polygon
+*/
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace perimeter {
+
+template<typename R, typename S>
+struct range_perimeter : detail::length::range_length<R, S>
+{
+};
+
+// might be merged with "range_area" with policy to sum/subtract interior rings
+template<typename Polygon, typename S>
+struct polygon_perimeter
+{
+ static inline double apply(Polygon const& poly, S const& strategy)
+ {
+ typedef typename ring_type<Polygon>::type ring_type;
+ typedef typename boost::range_const_iterator
+ <
+ typename interior_type<Polygon>::type
+ >::type iterator_type;
+
+ double sum = std::abs(range_perimeter<ring_type, S>::apply(exterior_ring(poly), strategy));
+
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly)); it++)
+ {
+ sum += std::abs(range_perimeter<ring_type, S>::apply(*it, strategy));
+ }
+ return sum;
+ }
+};
+
+}} // namespace detail:;perimeter
+#endif // DOXYGEN_NO_DETAIL
+
+
+#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<double, Geometry, Strategy>
+{};
+
+template <typename Geometry, typename Strategy>
+struct perimeter<ring_tag, Geometry, Strategy>
+ : detail::perimeter::range_perimeter<Geometry, Strategy>
+{};
+
+template <typename Geometry, typename Strategy>
+struct perimeter<polygon_tag, Geometry, Strategy>
+ : detail::perimeter::polygon_perimeter<Geometry, 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 ggl::ring, vector, iterator pair, or any other boost compatible range
+ \return the perimeter
+ */
+template<typename Geometry>
+inline double perimeter(Geometry 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 ggl::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 double perimeter(Geometry const& geometry, Strategy const& strategy)
+{
+ return dispatch::perimeter
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Strategy
+ >::apply(geometry, strategy);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_PERIMETER_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/sectionalize.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/sectionalize.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,579 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_SECTIONALIZE_HPP
+#define GGL_ALGORITHMS_SECTIONALIZE_HPP
+
+#include <cstddef>
+#include <vector>
+
+#include <boost/concept_check.hpp>
+#include <boost/concept/requires.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/algorithms/assign.hpp>
+#include <ggl/algorithms/combine.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/exterior_ring.hpp>
+
+#include <ggl/iterators/point_const_iterator.hpp>
+
+#include <ggl/util/assign_box_corner.hpp>
+#include <ggl/util/math.hpp>
+#include <ggl/geometries/segment.hpp>
+
+
+/*!
+\defgroup sectionalize sectionalize: split a geometry (polygon, linestring, etc)
+ into monotonic sections
+
+\par Geometries:
+- LINESTRING:
+- RING:
+- POLYGON:
+- BOX
+*/
+
+namespace ggl
+{
+
+
+/*!
+ \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 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()
+ : 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 =
+ ggl::get<1, Dimension>(seg) - ggl::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 =
+ ggl::get<1, Dimension>(seg) - ggl::get<0, Dimension>(seg);
+
+ if (! ggl::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, ggl::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);
+ ggl::combine(section.bounding_box, *previous);
+ }
+
+ ggl::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)
+{
+ // 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);
+}
+
+
+
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_SECTIONALIZE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/selected.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/selected.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,278 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_SELECTED_HPP
+#define GGL_ALGORITHMS_SELECTED_HPP
+
+#include <cmath>
+#include <cstddef>
+
+#include <boost/concept/requires.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/algorithms/within.hpp>
+#include <ggl/core/access.hpp>
+#include <ggl/core/topological_dimension.hpp>
+#include <ggl/core/concepts/nsphere_concept.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+
+/*!
+\defgroup selected selection: check if a geometry is "selected" by a point
+
+Checks if one geometry is selected by a point lying within or in the neighborhood of that geometry
+
+\par Geometries:
+- POINT: checks if points are CLOSE TO each other (< search_radius)
+- LINESTRING: checks if selection point is CLOSE TO linestring (< search_radius)
+- RING: checks if selection point is INSIDE the ring, search radius is ignored
+- POLYGON: checks if selection point is INSIDE the polygon, but not inside any of its holes
+
+*/
+
+namespace ggl
+{
+
+/*!
+ \ingroup impl
+ */
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace selected {
+
+/*!
+\details Checks, per dimension, if d[I] not larger than search distance. If true for all
+dimensions then returns true. If larger stops immediately and returns false.
+Calculate during this process the sum, which is only valid if returning true
+*/
+template <typename P1, typename P2, typename T, std::size_t D, std::size_t N>
+struct differences_loop
+{
+ static inline bool apply(P1 const& p1, P2 const& p2, T const& distance, T& sum)
+ {
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+
+ coordinate_type const c1 = boost::numeric_cast<coordinate_type>(get<D>(p1));
+ coordinate_type const c2 = boost::numeric_cast<coordinate_type>(get<D>(p2));
+
+ T const d = std::abs(c1 - c2);
+ if (d > distance)
+ {
+ return false;
+ }
+ sum += d * d;
+ return differences_loop<P1, P2, T, D + 1, N>::apply(p1, p2, distance, sum);
+ }
+};
+
+template <typename P1, typename P2, typename T, std::size_t N>
+struct differences_loop<P1, P2, T, N, N>
+{
+ static inline bool apply(P1 const&, P2 const&, T const&, T&)
+ {
+ return true;
+ }
+};
+
+
+
+template <typename S, typename P, typename T, std::size_t D, std::size_t N>
+struct outside_loop
+{
+ static inline bool apply(S const& seg, P const& point, T const& distance)
+ {
+ typedef typename select_coordinate_type<S, P>::type coordinate_type;
+
+ coordinate_type const v = boost::numeric_cast<coordinate_type>(get<D>(point));
+ coordinate_type const s1 = get<0, D>(seg);
+ coordinate_type const s2 = get<1, D>(seg);
+
+ // Out of reach if left/bottom or right/top of both points making up the segment
+ // I know and currently accept that these comparisons/calculations are done twice per point
+
+ if ((v < s1 - distance && v < s2 - distance) || (v > s1 + distance && v > s2 + distance))
+ {
+ return true;
+ }
+ return outside_loop<S, P, T, D + 1, N>::apply(seg, point, distance);
+ }
+};
+
+template <typename S, typename P, typename T, std::size_t N>
+struct outside_loop<S, P, T, N, N>
+{
+ static inline bool apply(S const&, P const&, T const&)
+ {
+ return false;
+ }
+};
+
+
+template <typename P1, typename P2, typename T>
+struct close_to_point
+{
+ static inline bool apply(P1 const& point, P1 const& selection_point, T const& search_radius)
+ {
+ assert_dimension_equal<P1, P2>();
+
+ T sum = 0;
+ if (differences_loop
+ <
+ P1, P2, T, 0, dimension<P1>::type::value
+ >::apply(point, selection_point, search_radius, sum))
+ {
+ return sum <= search_radius * search_radius;
+ }
+
+ return false;
+ }
+};
+
+template <typename S, typename P, typename T>
+struct close_to_segment
+{
+ static inline bool apply(S const& seg, P const& selection_point, T const& search_radius)
+ {
+ assert_dimension_equal<S, P>();
+
+ if (! outside_loop
+ <
+ S, P, T, 0, dimension<P>::type::value
+ >::apply(seg, selection_point, search_radius))
+ {
+ // Not outside, calculate dot product/square distance to segment.
+ // Call corresponding strategy
+ typedef typename strategy_distance_segment
+ <
+ typename cs_tag<P>::type,
+ typename cs_tag<S>::type,
+ P,
+ S
+ >::type strategy_type;
+ typedef typename strategy_type::return_type return_type;
+
+ strategy_type strategy;
+ return_type result = strategy(selection_point, seg);
+ return result < search_radius;
+ }
+
+ return false;
+ }
+};
+
+template <typename R, typename P, typename T>
+struct close_to_range
+{
+ static inline bool apply(R const& range, P const& selection_point, T const& search_radius)
+ {
+ assert_dimension_equal<R, P>();
+
+ std::size_t const n = boost::size(range);
+ if (n == 0)
+ {
+ // Line with zero points, never close
+ return false;
+ }
+
+ typedef typename point_type<R>::type point_type;
+ typedef typename boost::range_const_iterator<R>::type iterator_type;
+
+ iterator_type it = boost::begin(range);
+ if (n == 1)
+ {
+ // Line with one point ==> close to point
+ return close_to_point<P, point_type, T>::apply(*it, selection_point, search_radius);
+ }
+
+ iterator_type previous = it++;
+ while(it != boost::end(range))
+ {
+ typedef segment<const point_type> segment_type;
+ segment_type s(*previous, *it);
+ if (close_to_segment<segment_type, P, T>::apply(s, selection_point, search_radius))
+ {
+ return true;
+ }
+ previous = it++;
+ }
+
+ return false;
+ }
+};
+
+template <typename Tag, typename G, typename P, typename T>
+struct use_within
+{
+ static inline bool apply(G const& geometry, P const& selection_point, T const& search_radius)
+ {
+ // Note the reversion, point-in-poly -> first point, then poly
+ // Selected-at-point -> first geometry, then point
+ return dispatch::within<point_tag, Tag, P, G>::apply(selection_point, geometry);
+ }
+};
+
+}} // namespace detail::selected
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+/*!
+ \tparam TD topological dimension
+ */
+template <typename Tag, typename G, std::size_t D, typename P, typename T>
+struct selected
+{
+};
+
+template <typename P1, typename P2, typename T>
+struct selected<point_tag, P1, 0, P2, T> : detail::selected::close_to_point<P1, P2, T> { };
+
+// SEGMENT, TODO HERE (close_to_segment)
+
+template <typename L, typename P, typename T>
+struct selected<linestring_tag, L, 1, P, T> : detail::selected::close_to_range<L, P, T> { };
+
+template <typename Tag, typename G, typename P, typename T>
+struct selected<Tag, G, 2, P, T> : detail::selected::use_within<Tag, G, P, T> { };
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Checks if one geometry is selected by a point lying within or in the neighborhood of that geometry
+ \ingroup selected
+ \tparam G type of geometry to check
+ \tparam P type of point to check
+ \tparam T type of search radius
+ \param geometry geometry which might be located in the neighborhood
+ \param selection_point point to select the geometry
+ \param search_radius for points/linestrings: defines radius of "neighborhood" to find things in
+ \return true if point is within or close to the other geometry
+
+ */
+template<typename G, typename P, typename T>
+inline bool selected(G const& geometry, P const& selection_point, T const& search_radius)
+{
+ typedef dispatch::selected
+ <
+ typename tag<G>::type,
+ G,
+ topological_dimension<G>::value,
+ P,
+ T
+ > selector_type;
+
+ return selector_type::apply(geometry, selection_point, search_radius);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_SELECTED_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/simplify.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/simplify.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,342 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_SIMPLIFY_HPP
+#define GGL_ALGORITHMS_SIMPLIFY_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/algorithms/distance.hpp>
+#include <ggl/core/cs.hpp>
+#include <ggl/core/ring_type.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+#include <ggl/strategies/agnostic/agn_simplify.hpp>
+
+
+/*!
+\defgroup simplify simplification (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.8 seconds (2.5 seconds or 11.5 seconds in 2 other libraries)
+- 3918 zipcode areas of the Netherlands are simplified in 0.03 seconds (0.1 seconds or 0.45 seconds in 2 other libraries)
+
+
+\par Geometries
+- LINESTRING:
+\image html simplify_linestring.png
+- POLYGON: 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)
+
+*/
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace simplify {
+
+template<typename R, typename OutputIterator, typename S>
+inline void simplify_range_strategy(R const& range, OutputIterator out, double max_distance, S const& strategy)
+{
+ if (boost::begin(range) == boost::end(range) || max_distance < 0)
+ {
+ std::copy(boost::begin(range), boost::end(range), out);
+ }
+ else
+ {
+ typename boost::range_const_iterator<R>::type it = boost::begin(range) + 1;
+ if (it == boost::end(range) || it + 1 == boost::end(range))
+ {
+ std::copy(boost::begin(range), boost::end(range), out);
+ }
+ else
+ {
+ strategy.simplify(range, out, max_distance);
+ }
+ }
+}
+
+template<typename R, typename OutputIterator>
+inline void simplify_range(R const& range, OutputIterator out, double max_distance)
+{
+ // Define default strategy
+ typedef typename point_type<R>::type point_type;
+ typedef typename cs_tag<point_type>::type cs_tag;
+ typedef typename strategy_distance_segment
+ <
+ cs_tag,
+ cs_tag,
+ point_type,
+ segment<const point_type>
+ >::type strategy_type;
+
+ strategy::simplify::douglas_peucker<R, OutputIterator, strategy_type> douglas;
+
+ simplify_range_strategy(range, out, max_distance, douglas);
+}
+
+template<typename R, typename OutputIterator, typename S>
+inline void simplify_ring(R const& r_in, OutputIterator out, double max_distance, S const& strategy)
+{
+ // Call do_container 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(r_in) <= 4 || max_distance < 0)
+ {
+ std::copy(boost::begin(r_in), boost::end(r_in), out);
+ }
+ else
+ {
+ simplify_range_strategy(r_in, out, max_distance, strategy);
+ }
+}
+
+template<typename Y, typename S>
+inline void simplify_polygon(Y const& poly_in, Y& poly_out, double max_distance, S const& strategy)
+{
+ typedef typename boost::range_iterator
+ <typename interior_type<Y>::type>::type iterator_type;
+ typedef typename boost::range_const_iterator
+ <typename interior_type<Y>::type>::type const_iterator_type;
+
+ poly_out.clear();
+
+ // Note that if there are inner rings, and distance is too large, they might intersect with the
+ // outer ring in the output, while it didn't in the input.
+ simplify_ring(exterior_ring(poly_in), std::back_inserter(exterior_ring(poly_out)),
+ max_distance, strategy);
+
+ interior_rings(poly_out).resize(boost::size(interior_rings(poly_in)));
+
+ const_iterator_type it_in = boost::begin(interior_rings(poly_in));
+ iterator_type it_out = boost::begin(interior_rings(poly_out));
+
+ for (; it_in != boost::end(interior_rings(poly_in)); it_in++, it_out++)
+ {
+ simplify_ring(*it_in, std::back_inserter(*it_out), max_distance, strategy);
+ }
+}
+
+template<typename Y>
+inline void simplify_polygon(Y const& poly_in, Y& poly_out, double max_distance)
+{
+ // Define default strategy
+ typedef typename ring_type<Y>::type ring_type;
+ typedef std::back_insert_iterator<ring_type> iterator_type;
+
+ typedef typename point_type<Y>::type point_type;
+ typedef typename cs_tag<point_type>::type cs_tag;
+ typedef typename strategy_distance_segment
+ <
+ cs_tag,
+ cs_tag,
+ point_type,
+ segment<const point_type>
+ >::type strategy_type;
+
+ strategy::simplify::douglas_peucker<ring_type, iterator_type, strategy_type> douglas;
+
+ simplify_polygon(poly_in, poly_out, max_distance, douglas);
+}
+
+}} // namespace detail::simplify
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, typename G>
+struct simplify
+{
+};
+
+// Partial specializations
+template <typename R>
+struct simplify<linestring_tag, R>
+{
+ template<typename OutputIterator, typename S>
+ static inline void apply(R const& range, OutputIterator out, double max_distance, S const& strategy)
+ {
+ strategy.simplify(range, out, max_distance);
+ }
+
+ template<typename OutputIterator>
+ static inline void apply(R const& range, OutputIterator out, double max_distance)
+ {
+ // Define default strategy
+ typedef typename point_type<R>::type point_type;
+ typedef typename cs_tag<point_type>::type cs_tag;
+ typedef typename strategy_distance_segment
+ <
+ cs_tag,
+ cs_tag,
+ point_type,
+ segment<const point_type>
+ >::type strategy_type;
+
+ strategy::simplify::douglas_peucker<R, OutputIterator, strategy_type> douglas;
+
+ detail::simplify::simplify_range_strategy(range, out, max_distance, douglas);
+ }
+};
+
+template <typename R>
+struct simplify<ring_tag, R>
+{
+ /// Simplify a ring, using a strategy
+ template<typename S>
+ static inline void apply(R const& ring_in, R& ring_out, double max_distance, S const& strategy)
+ {
+ using detail::simplify::simplify_ring;
+ simplify_ring(ring_in, std::back_inserter(ring_out), max_distance, strategy);
+ }
+
+ /// Simplify a ring
+ static inline void apply(R const& ring_in, R& ring_out, double max_distance)
+ {
+ // Define default strategy
+ typedef typename point_type<R>::type point_type;
+ typedef typename cs_tag<point_type>::type cs_tag;
+ typedef typename strategy_distance_segment
+ <
+ cs_tag,
+ cs_tag,
+ point_type,
+ segment<const point_type>
+ >::type strategy_type;
+ typedef std::back_insert_iterator<R> iterator_type;
+
+ strategy::simplify::douglas_peucker<R, iterator_type, strategy_type> douglas;
+
+ detail::simplify::simplify_ring(ring_in, std::back_inserter(ring_out), max_distance, douglas);
+ }
+};
+
+template <typename P>
+struct simplify<polygon_tag, P>
+{
+ /// Simplify a polygon, using a strategy
+ template<typename S>
+ static inline void apply(P const& poly_in, P& poly_out, double max_distance, S const& strategy)
+ {
+ detail::simplify::simplify_polygon(poly_in, poly_out, max_distance, strategy);
+ }
+
+ /// Simplify a polygon
+ static inline void apply(P const& poly_in, P& poly_out, double max_distance)
+ {
+ detail::simplify::simplify_polygon(poly_in, poly_out, max_distance);
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+// Model 1, using output iterator
+
+/*!
+ \brief Simplify a geometry
+ \ingroup simplify
+ \details The simplify algorithm removes points, keeping the shape as much as possible.
+ This version of simplify uses an output iterator
+ \param geometry the geometry to be simplified, being a ggl::linestring, vector, iterator pair, or any other boost compatible range
+ \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
+ \par Example:
+ The simplify algorithm can be used as following:
+ \dontinclude doxygen_examples.cpp
+ \skip example_simplify_linestring1
+ \line {
+ \until }
+ */
+template<typename G, typename O>
+inline void simplify(const G& geometry, O out, double max_distance)
+{
+ typedef dispatch::simplify<typename tag<G>::type, G> simplify_type;
+ simplify_type::apply(geometry, out, max_distance);
+}
+
+/*!
+ \brief Simplify a geometry
+ \ingroup simplify
+ \details The simplify algorithm removes points, keeping the shape as much as possible.
+ This version of simplify uses an output iterator and a simplify strategy
+ \param geometry the geometry to be simplified, being a ggl::linestring, vector, iterator pair, or any other boost compatible range
+ \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:
+ The simplify algorithm with strategy can be used as following:
+ \dontinclude doxygen_examples.cpp
+ \skip example_simplify_linestring2
+ \line {
+ \until }
+ */
+template<typename G, typename O, typename S>
+inline void simplify(const G& geometry, O out, double max_distance, S const& strategy)
+{
+ typedef dispatch::simplify<typename tag<G>::type, G> simplify_type;
+ simplify_type::apply(geometry, out, max_distance, strategy);
+}
+
+// Model 2, where output is same type as input
+
+/*!
+ \brief Simplify a geometry
+ \ingroup simplify
+ \details This version of simplify simplifies a geometry using the default strategy (Douglas Peucker),
+ where the output is of the same geometry type as the input.
+ \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
+ */
+template<typename G>
+inline void simplify(const G& geometry, G& out, double max_distance)
+{
+ typedef dispatch::simplify<typename tag<G>::type, G> simplify_type;
+ simplify_type::apply(geometry, out, max_distance);
+}
+
+/*!
+ \brief Simplify a geometry
+ \ingroup simplify
+ \details This version of simplify simplifies a geometry using a specified strategy
+ where the output is of the same geometry type as the input.
+ \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 G, typename S>
+inline void simplify(const G& geometry, G& out, double max_distance, S const& strategy)
+{
+ typedef dispatch::simplify<typename tag<G>::type, G> simplify_type;
+ simplify_type::apply(geometry, out, max_distance, strategy);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_SIMPLIFY_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/transform.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/transform.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,289 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_TRANSFORM_HPP
+#define GGL_ALGORITHMS_TRANSFORM_HPP
+
+#include <cmath>
+#include <iterator>
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/algorithms/clear.hpp>
+#include <ggl/core/cs.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+#include <ggl/core/ring_type.hpp>
+#include <ggl/geometries/segment.hpp>
+#include <ggl/strategies/strategies.hpp>
+
+
+/*!
+\defgroup transform transformations
+\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 ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace transform {
+
+template <typename P1, typename P2>
+struct transform_point
+{
+ template <typename S>
+ static inline bool apply(P1 const& p1, P2& p2, S const& strategy)
+ {
+ return strategy(p1, p2);
+ }
+};
+
+template <typename B1, typename B2>
+struct transform_box
+{
+ template <typename S>
+ static inline bool apply(B1 const& b1, B2& b2, S const& strategy)
+ {
+ typedef typename point_type<B1>::type point_type1;
+ typedef typename point_type<B2>::type point_type2;
+
+ point_type1 lower_left, upper_right;
+ assign_box_corner<min_corner, min_corner>(b1, lower_left);
+ assign_box_corner<max_corner, max_corner>(b1, upper_right);
+
+ point_type2 p1, p2;
+ if (strategy(lower_left, p1) && strategy(upper_right, p2))
+ {
+ // Create a valid box and therefore swap if necessary
+ typedef typename coordinate_type<point_type2>::type coordinate_type;
+ coordinate_type x1 = ggl::get<0>(p1)
+ , y1 = ggl::get<1>(p1)
+ , x2 = ggl::get<0>(p2)
+ , y2 = ggl::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 P, typename OutputIterator, typename R, typename S>
+inline bool transform_range_out(R const& range, OutputIterator out, S const& strategy)
+{
+ P point_out;
+ for(typename boost::range_const_iterator<R>::type it = boost::begin(range);
+ it != boost::end(range); ++it)
+ {
+ if (! transform_point<typename point_type<R>::type, P>::apply(*it, point_out, strategy))
+ {
+ return false;
+ }
+ *out = point_out;
+ ++out;
+ }
+ return true;
+}
+
+template <typename P1, typename P2>
+struct transform_polygon
+{
+ template <typename S>
+ static inline bool apply(const P1& poly1, P2& poly2, S const& strategy)
+ {
+ typedef typename interior_type<P1>::type interior1_type;
+ typedef typename interior_type<P2>::type interior2_type;
+ typedef typename ring_type<P1>::type ring1_type;
+ typedef typename ring_type<P2>::type ring2_type;
+ typedef typename point_type<P2>::type point2_type;
+
+ ggl::clear(poly2);
+
+ if (!transform_range_out<point2_type>(exterior_ring(poly1),
+ std::back_inserter(exterior_ring(poly2)), strategy))
+ {
+ return false;
+ }
+
+ interior_rings(poly2).resize(boost::size(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 P1, typename P2>
+struct select_strategy
+{
+ typedef typename strategy_transform
+ <
+ typename cs_tag<P1>::type,
+ typename cs_tag<P2>::type,
+ typename coordinate_system<P1>::type,
+ typename coordinate_system<P2>::type,
+ dimension<P1>::type::value,
+ dimension<P2>::type::value,
+ typename point_type<P1>::type,
+ typename point_type<P2>::type
+ >::type type;
+};
+
+template <typename R1, typename R2>
+struct transform_range
+{
+ template <typename S>
+ static inline bool apply(R1 const& range1, R2& range2, S const& strategy)
+ {
+ typedef typename point_type<R2>::type point_type;
+
+ ggl::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 G1, typename G2>
+struct transform {};
+
+template <typename P1, typename P2>
+struct transform<point_tag, point_tag, P1, P2>
+ : detail::transform::transform_point<P1, P2>
+{
+};
+
+
+template <typename L1, typename L2>
+struct transform<linestring_tag, linestring_tag, L1, L2>
+ : detail::transform::transform_range<L1, L2>
+{
+};
+
+template <typename R1, typename R2>
+struct transform<ring_tag, ring_tag, R1, R2>
+ : detail::transform::transform_range<R1, R2>
+{
+};
+
+template <typename P1, typename P2>
+struct transform<polygon_tag, polygon_tag, P1, P2>
+ : detail::transform::transform_polygon<P1, P2>
+{
+};
+
+template <typename B1, typename B2>
+struct transform<box_tag, box_tag, B1, B2>
+ : detail::transform::transform_box<B1, B2>
+{
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Transforms from one geometry to another geometry using a strategy
+ \ingroup transform
+ \tparam G1 first geometry type
+ \tparam G2 second geometry type
+ \tparam S strategy
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \param strategy the strategy to be used for transformation
+ */
+template <typename G1, typename G2, typename S>
+inline bool transform(G1 const& geometry1, G2& geometry2, S const& strategy)
+{
+ typedef dispatch::transform
+ <
+ typename tag<G1>::type,
+ typename tag<G2>::type,
+ G1,
+ G2
+ > transform_type;
+
+ return transform_type::apply(geometry1, geometry2, strategy);
+}
+
+/*!
+ \brief Transforms from one geometry to another geometry using a strategy
+ \ingroup transform
+ \tparam G1 first geometry type
+ \tparam G2 second geometry type
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \return true if the transformation could be done
+ */
+template <typename G1, typename G2>
+inline bool transform(G1 const& geometry1, G2& geometry2)
+{
+ typename detail::transform::select_strategy<G1, G2>::type strategy;
+ return transform(geometry1, geometry2, strategy);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_TRANSFORM_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/algorithms/within.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/algorithms/within.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,414 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ALGORITHMS_WITHIN_HPP
+#define GGL_ALGORITHMS_WITHIN_HPP
+
+#include <boost/concept/requires.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/algorithms/distance.hpp>
+#include <ggl/algorithms/make.hpp>
+#include <ggl/core/access.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/core/concepts/nsphere_concept.hpp>
+#include <ggl/core/cs.hpp>
+#include <ggl/strategies/strategies.hpp>
+#include <ggl/util/loop.hpp>
+
+
+
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace within {
+
+
+//-------------------------------------------------------------------------------------------------------
+// Implementation for boxes. Supports boxes in 2 or 3 dimensions, in Euclidian system
+// Todo: implement as strategy
+//-------------------------------------------------------------------------------------------------------
+template <typename P, typename B, size_t D, size_t N>
+struct point_in_box
+{
+ static bool inside(P const& p, B const& b)
+ {
+ if (get<D>(p) <= get<min_corner, D>(b)
+ || get<D>(p) >= get<max_corner, D>(b))
+ {
+ return false;
+ }
+
+ return point_in_box<P, B, D + 1, N>::inside(p, b);
+ }
+};
+
+template <typename P, typename B, size_t N>
+struct point_in_box<P, B, N, N>
+{
+ static bool inside(P const& p, B const& b)
+ {
+ return true;
+ }
+};
+
+//-------------------------------------------------------------------------------------------------------
+// Box-in-box, for 2/3 dimensions
+//-------------------------------------------------------------------------------------------------------
+template <typename B1, typename B2, size_t D, size_t N>
+struct box_in_box
+{
+ static inline bool inside(B1 const& b1, B2 const& b2)
+ {
+ if (get<min_corner, D>(b1) <= get<min_corner, D>(b2)
+ || get<max_corner, D>(b1) >= get<max_corner, D>(b2))
+ {
+ return false;
+ }
+
+ return box_in_box<B1, B2, D + 1, N>::inside(b1, b2);
+ }
+};
+
+template <typename B1, typename B2, size_t N>
+struct box_in_box<B1, B2, N, N>
+{
+ static inline bool inside(B1 const& b1, B2 const& b2)
+ {
+ return true;
+ }
+};
+
+
+//-------------------------------------------------------------------------------------------------------
+// Implementation for n-spheres. Supports circles or spheres, in 2 or 3 dimensions, in Euclidian system
+// Circle center might be of other point-type as geometry
+// Todo: implement as strategy
+//-------------------------------------------------------------------------------------------------------
+template<typename P, typename C>
+inline bool point_in_circle(P const& p, C const& c)
+{
+ assert_dimension<C, 2>();
+
+ typedef typename point_type<C>::type point_type;
+ typedef typename strategy_distance
+ <
+ typename cs_tag<P>::type,
+ typename cs_tag<point_type>::type,
+ P,
+ point_type
+ >::type strategy_type;
+ typedef typename strategy_type::return_type return_type;
+
+ P const center = ggl::make<P>(get<0>(c), get<1>(c));
+ strategy_type distance;
+ return_type const r = distance(p, center);
+ return_type const rad = make_distance_result<return_type>(get_radius<0>(c));
+
+ return r < rad;
+}
+/// 2D version
+template<typename T, typename C>
+inline bool point_in_circle(const T& c1, const T& c2, C const& c)
+{
+ typedef typename point_type<C>::type point_type;
+
+ point_type p = ggl::make<point_type>(c1, c2);
+ return point_in_circle(p, c);
+}
+
+template<typename B, typename C>
+inline bool box_in_circle(B const& b, C const& c)
+{
+ typedef typename point_type<B>::type point_type;
+
+ // Currently only implemented for 2d geometries
+ assert_dimension<point_type, 2>();
+ assert_dimension<C, 2>();
+
+ // Box: all four points must lie within circle
+
+ // Check points lower-left and upper-right, then lower-right and upper-left
+ return point_in_circle(get<min_corner, 0>(b), get<min_corner, 1>(b), c)
+ && point_in_circle(get<max_corner, 0>(b), get<max_corner, 1>(b), c)
+ && point_in_circle(get<min_corner, 0>(b), get<max_corner, 1>(b), c)
+ && point_in_circle(get<max_corner, 0>(b), get<min_corner, 1>(b), c);
+}
+
+// Generic "range-in-circle", true if all points within circle
+template<typename R, typename C>
+inline bool range_in_circle(R const& range, C const& c)
+{
+ assert_dimension<R, 2>();
+ assert_dimension<C, 2>();
+
+ for (typename boost::range_const_iterator<R>::type it = boost::begin(range);
+ it != boost::end(range); ++it)
+ {
+ if (! point_in_circle(*it, c))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+template<typename Y, typename C>
+inline bool polygon_in_circle(Y const& poly, C const& c)
+{
+ return range_in_circle(exterior_ring(poly), c);
+}
+
+template<typename P, typename R, typename S>
+inline bool point_in_ring(P const& p, R const& r, S const& strategy)
+{
+ if (boost::size(r) < 4)
+ {
+ return false;
+ }
+
+ typename S::state_type state(p);
+ if (loop(r, strategy, state))
+ {
+ return state.within();
+ }
+
+ return false;
+}
+
+// Polygon: in exterior ring, and if so, not within interior ring(s)
+template<typename P, typename Y, typename S>
+inline bool point_in_polygon(P const& p, Y const& poly, S const& strategy)
+{
+ if (point_in_ring(p, exterior_ring(poly), strategy))
+ {
+ typedef typename boost::range_const_iterator
+ <typename interior_type<Y>::type>::type iterator_type;
+
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly)); ++it)
+ {
+ if (point_in_ring(p, *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 G1, typename G2>
+struct within {};
+
+template <typename P, typename B>
+struct within<point_tag, box_tag, P, B>
+{
+ static inline bool apply(P const& p, B const& b)
+ {
+ assert_dimension_equal<P, B>();
+
+ return detail::within::point_in_box
+ <
+ P,
+ B,
+ 0,
+ dimension<P>::type::value
+ >::inside(p, b);
+ }
+};
+
+template <typename B1, typename B2>
+struct within<box_tag, box_tag, B1, B2>
+{
+ static inline bool apply(B1 const& b1, B2 const& b2)
+ {
+ assert_dimension_equal<B1, B2>();
+
+ return detail::within::box_in_box
+ <
+ B1,
+ B2,
+ 0,
+ dimension<B1>::type::value
+ >::inside(b1, b2);
+ }
+};
+
+
+template <typename P, typename C>
+struct within<point_tag, nsphere_tag, P, C>
+{
+ static inline bool apply(P const& p, C const& c)
+ {
+ return detail::within::point_in_circle(p, c);
+ }
+};
+
+template <typename B, typename C>
+struct within<box_tag, nsphere_tag, B, C>
+{
+ static inline bool apply(B const& b, C const& c)
+ {
+ return detail::within::box_in_circle(b, c);
+ }
+};
+
+template <typename R, typename C>
+struct within<linestring_tag, nsphere_tag, R, C>
+{
+ static inline bool apply(R const& ln, C const& c)
+ {
+ return detail::within::range_in_circle(ln, c);
+ }
+};
+
+template <typename R, typename C>
+struct within<ring_tag, nsphere_tag, R, C>
+{
+ static inline bool apply(R const& r, C const& c)
+ {
+ return detail::within::range_in_circle(r, c);
+ }
+};
+
+template <typename Y, typename C>
+struct within<polygon_tag, nsphere_tag, Y, C>
+{
+ static inline bool apply(Y const& poly, C const& c)
+ {
+ return detail::within::polygon_in_circle(poly, c);
+ }
+};
+
+template <typename P, typename R>
+struct within<point_tag, ring_tag, P, R>
+{
+ static inline bool apply(P const& p, R const& r)
+ {
+ typedef typename boost::range_value<R>::type point_type;
+ typedef typename strategy_within
+ <
+ typename cs_tag<P>::type,
+ typename cs_tag<point_type>::type,
+ P,
+ point_type
+ >::type strategy_type;
+
+ return detail::within::point_in_ring(p, r, strategy_type());
+ }
+};
+
+template <typename P, typename Y>
+struct within<point_tag, polygon_tag, P, Y>
+{
+ static inline bool apply(P const& point, Y const& poly)
+ {
+ typedef typename point_type<Y>::type point_type;
+ typedef typename strategy_within
+ <
+ typename cs_tag<P>::type,
+ typename cs_tag<point_type>::type,
+ P,
+ point_type
+ >::type strategy_type;
+
+ return detail::within::point_in_polygon(point, poly, strategy_type());
+ }
+
+ template<typename S>
+ static inline bool apply(P const& point, Y const& poly, S const& strategy)
+ {
+ return detail::within::point_in_polygon(point, poly, strategy);
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Within check
+ \details Examine if one geometry is within another geometry (a.o. point in polygon)
+ \ingroup boolean_relations
+ \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
+
+\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.09 seconds (other libraries: 0.14 seconds, 3.0 seconds, 3.8)
+
+\par Example:
+The within algorithm is used as following:
+\dontinclude doxygen_examples.cpp
+\skip example_within
+\line {
+\until }
+\par Geometries:
+- POINT + 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
+- POINT + RING: returns true if point is completely within a ring \image html within_ring.png
+
+ */
+template<typename G1, typename G2>
+inline bool within(G1 const& geometry1, G2 const& geometry2)
+{
+ typedef dispatch::within
+ <
+ typename tag<G1>::type,
+ typename tag<G2>::type,
+ G1,
+ G2
+ > within_type;
+
+ return within_type::apply(geometry1, geometry2);
+}
+
+/*!
+ \brief Within check using a strategy
+ \ingroup boolean_relations
+ \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 G1, typename G2, typename S>
+inline bool within(G1 const& geometry1, G2 const& geometry2, S const& strategy)
+{
+ typedef dispatch::within
+ <
+ typename tag<G1>::type,
+ typename tag<G2>::type,
+ G1,
+ G2
+ > within_type;
+
+ return within_type::apply(geometry1, geometry2, strategy);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_WITHIN_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/arithmetic/arithmetic.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/arithmetic/arithmetic.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,209 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ARITHMETIC_ARITHMETIC_HPP
+#define GGL_ARITHMETIC_ARITHMETIC_HPP
+
+#include <functional>
+
+#include <boost/call_traits.hpp>
+#include <boost/concept/requires.hpp>
+
+#include <ggl/core/coordinate_type.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/util/for_each_coordinate.hpp>
+
+/*!
+\defgroup arithmetic arithmetic: arithmetic operations on points
+*/
+
+namespace ggl
+{
+
+#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(const C& 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(const PointSrc& 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 ggl
+
+#endif // GGL_ARITHMETIC_ARITHMETIC_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/arithmetic/dot_product.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/arithmetic/dot_product.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,70 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ARITHMETIC_DOT_PRODUCT_HPP
+#define GGL_ARITHMETIC_DOT_PRODUCT_HPP
+
+#include <boost/concept/requires.hpp>
+
+#include <ggl/core/concepts/point_concept.hpp>
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename P1, typename P2, std::size_t Dimension, std::size_t DimensionCount>
+struct dot_product_maker
+{
+ static inline typename coordinate_type<P1>::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>
+{
+ static inline typename coordinate_type<P1>::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 of 2 points
+ \ingroup arithmetic
+ \param p1 first point
+ \param p2 second point
+ \return the dot product
+ */
+template <typename P1, typename P2>
+inline typename coordinate_type<P1>::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 ggl
+
+#endif // GGL_ARITHMETIC_DOT_PRODUCT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/access.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/access.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,292 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef GGL_CORE_ACCESS_HPP
+#define GGL_CORE_ACCESS_HPP
+
+#include <cstddef>
+
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/concept_check.hpp>
+
+#include <ggl/core/coordinate_type.hpp>
+#include <ggl/core/point_type.hpp>
+#include <ggl/core/tag.hpp>
+
+namespace ggl
+{
+
+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
+ - n-sphere (circle,sphere) for their center
+ \par Specializations should provide:
+ - static inline T get<I>(const G&)
+ - static inline void set<I>(G&, const T&)
+ \tparam G geometry
+*/
+template <typename G>
+struct access {};
+
+
+/*!
+ \brief Traits class defining "get" and "set" to get and set point coordinate values
+ \tparam G geometry (box, segment)
+ \tparam I index (min_corner/max_corner for box, 0/1 for segment)
+ \tparam D dimension
+ \par Geometries:
+ - box
+ - segment
+ \par Specializations should provide:
+ - static inline T get(const G&)
+ - static inline void set(G&, const T&)
+ \ingroup traits
+*/
+template <typename G, std::size_t I, std::size_t D>
+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 G>
+struct use_std
+{
+ static const bool value = true;
+};
+
+} // namespace traits
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+template <typename Tag, typename G, typename T, std::size_t D>
+struct access
+{
+ //static inline T get(const G& ) {}
+ //static inline void set(G& g, const T& value) {}
+};
+
+template <typename Tag, typename G, typename T, std::size_t I, std::size_t D>
+struct indexed_access
+{
+ //static inline T get(const G& ) {}
+ //static inline void set(G& g, const T& value) {}
+};
+
+template <typename P, typename T, std::size_t D>
+struct access<point_tag, P, T, D>
+{
+ static inline T get(const P& p)
+ {
+ return traits::access<P>::template get<D>(p);
+ }
+ static inline void set(P& p, const T& value)
+ {
+ traits::access<P>::template set<D>(p, value);
+ }
+};
+
+template <typename S, typename T, std::size_t D>
+struct access<nsphere_tag, S, T, D>
+{
+ static inline T get(const S& s)
+ {
+ return traits::access<S>::template get<D>(s);
+ }
+ static inline void set(S& s, const T& value)
+ {
+ traits::access<S>::template set<D>(s, value);
+ }
+};
+
+template <typename B, typename T, std::size_t I, std::size_t D>
+struct indexed_access<box_tag, B, T, I, D>
+{
+ static inline T get(const B& b)
+ {
+ return traits::indexed_access<B, I, D>::get(b);
+ }
+ static inline void set(B& b, const T& value)
+ {
+ traits::indexed_access<B, I, D>::set(b, value);
+ }
+};
+
+template <typename S, typename T, std::size_t I, std::size_t D>
+struct indexed_access<segment_tag, S, T, I, D>
+{
+ static inline T get(const S& segment)
+ {
+ return traits::indexed_access<S, I, D>::get(segment);
+ }
+ static inline void set(S& segment, const T& value)
+ {
+ traits::indexed_access<S, I, D>::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
+
+
+/*!
+ \brief get a coordinate value of a point / nsphere
+ \return coordinate value
+ \ingroup access
+ \tparam D dimension
+ \tparam G geometry
+ \param geometry geometry to get coordinate value from
+ \param dummy does not have to be specified
+*/
+template <std::size_t D, typename G>
+inline typename coordinate_type<G>::type get(const G& geometry,
+ detail::signature_getset_dimension* dummy = 0)
+{
+ boost::ignore_unused_variable_warning(dummy);
+
+ typedef typename boost::remove_const<G>::type ncg_type;
+
+ typedef core_dispatch::access
+ <
+ typename tag<G>::type,
+ ncg_type,
+ typename coordinate_type<ncg_type>::type,
+ D
+ > coord_access_type;
+
+ return coord_access_type::get(geometry);
+}
+
+
+/*!
+ \brief assign coordinate value to a point / sphere
+ \ingroup access
+ \tparam D dimension
+ \tparam G geometry
+ \param geometry geometry to assign coordinate to
+ \param value coordinate value to assign
+ \param dummy does not have to be specified
+*/
+template <std::size_t D, typename G>
+inline void set(G& geometry, const typename coordinate_type<G>::type& value,
+ detail::signature_getset_dimension* dummy = 0)
+{
+ boost::ignore_unused_variable_warning(dummy);
+
+ typedef typename boost::remove_const<G>::type ncg_type;
+
+ typedef core_dispatch::access
+ <
+ typename tag<G>::type,
+ ncg_type,
+ typename coordinate_type<ncg_type>::type,
+ D
+ > coord_access_type;
+
+ coord_access_type::set(geometry, value);
+}
+
+// Note: doxygen needs a construct to distinguish get/set (like the gcc compiler)
+
+/*!
+ \brief get a coordinate value of a box / segment
+ \return coordinate value
+ \ingroup access
+ \tparam I index, for boxes: min_corner or max_corner. For segment: 0 / 1
+ \tparam D dimension
+ \tparam G geometry
+ \param geometry geometry to get coordinate value from
+ \param dummy does not have to be specified
+*/
+template <std::size_t I, std::size_t D, typename G>
+inline typename coordinate_type<G>::type get(const G& geometry,
+ detail::signature_getset_index_dimension* dummy = 0)
+{
+ boost::ignore_unused_variable_warning(dummy);
+
+ typedef typename boost::remove_const<G>::type ncg_type;
+
+ typedef core_dispatch::indexed_access
+ <
+ typename tag<G>::type,
+ ncg_type,
+ typename coordinate_type<ncg_type>::type,
+ I,
+ D
+ > coord_access_type;
+
+ return coord_access_type::get(geometry);
+}
+
+/*!
+ \brief assign a coordinate value of a box / segment
+ \ingroup access
+ \tparam I index, for boxes: min_corner or max_corner. For segment: 0 / 1
+ \tparam D dimension
+ \tparam G geometry
+ \param geometry geometry to assign coordinate to
+ \param value coordinate value to assign
+ \param dummy does not have to be specified
+*/
+template <std::size_t I, std::size_t D, typename G>
+inline void set(G& geometry, const typename coordinate_type<G>::type& value,
+ detail::signature_getset_index_dimension* dummy = 0)
+{
+ boost::ignore_unused_variable_warning(dummy);
+
+ typedef typename boost::remove_const<G>::type ncg_type;
+
+ typedef core_dispatch::indexed_access
+ <
+ typename tag<G>::type, ncg_type,
+ typename coordinate_type<ncg_type>::type,
+ I,
+ D
+ > coord_access_type;
+
+ coord_access_type::set(geometry, value);
+}
+
+} // namespace ggl
+
+#endif // GGL_CORE_ACCESS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/concepts/box_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/concepts/box_concept.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,109 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef GGL_CORE_CONCEPTS_BOX_CONCEPT_HPP
+#define GGL_CORE_CONCEPTS_BOX_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/point_type.hpp>
+
+
+
+namespace ggl { namespace concept {
+
+
+/*!
+ \brief Checks box concept, using Boost Concept Check Library and metafunctions
+ \ingroup concepts
+*/
+template <typename B>
+struct Box
+{
+ private :
+ typedef typename point_type<B>::type P;
+
+ /// Internal structure to check if access is OK for all dimensions
+ template <size_t C, size_t D, size_t N>
+ struct dimension_checker
+ {
+ static void check()
+ {
+ B* b;
+ ggl::set<C, D>(*b, ggl::get<C, D>(*b));
+ dimension_checker<C, D + 1, N>::check();
+ }
+ };
+
+ template <size_t C, size_t N>
+ struct dimension_checker<C, N, N>
+ {
+ static void check() {}
+ };
+
+ public :
+ /// BCCL macro to check the Box concept
+ BOOST_CONCEPT_USAGE(Box)
+ {
+ static const size_t N = dimension<B>::value;
+ dimension_checker<min_corner, 0, N>::check();
+ dimension_checker<max_corner, 0, N>::check();
+ }
+};
+
+
+/*!
+ \brief Checks Box concept (const version)
+ \ingroup concepts
+ \details The ConstBox concept check the same as the Box concept,
+ but does not check write access.
+*/
+template <typename B>
+struct ConstBox
+{
+ private :
+ typedef typename point_type<B>::type P;
+ typedef typename coordinate_type<B>::type T;
+
+ /// Internal structure to check if access is OK for all dimensions
+ template <size_t C, size_t D, size_t N>
+ struct dimension_checker
+ {
+ static void check()
+ {
+ const B* b = 0;
+ T coord(ggl::get<C, D>(*b));
+ boost::ignore_unused_variable_warning(coord);
+ dimension_checker<C, D + 1, N>::check();
+ }
+ };
+
+ template <size_t C, size_t N>
+ struct dimension_checker<C, N, N>
+ {
+ static void check() {}
+ };
+
+ public :
+ /// BCCL macro to check the ConstBox concept
+ BOOST_CONCEPT_USAGE(ConstBox)
+ {
+ static const size_t N = dimension<B>::value;
+ dimension_checker<min_corner, 0, N>::check();
+ dimension_checker<max_corner, 0, N>::check();
+ }
+};
+
+}} // namespace ggl::concept
+
+
+#endif // GGL_CORE_CONCEPTS_BOX_CONCEPT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/concepts/linestring_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/concepts/linestring_concept.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,84 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_CORE_CONCEPTS_LINESTRING_CONCEPT_HPP
+#define GGL_CORE_CONCEPTS_LINESTRING_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+
+#include <ggl/core/concepts/point_concept.hpp>
+
+
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/point_type.hpp>
+
+#include <ggl/algorithms/clear.hpp>
+#include <ggl/algorithms/append.hpp>
+
+
+
+namespace ggl { namespace concept {
+
+
+/*!
+ \brief Checks linestring concept, using Boost Concept Check Library and metafunctions
+ \ingroup concepts
+*/
+template <typename L>
+struct Linestring
+{
+ private :
+ typedef typename point_type<L>::type P;
+
+ BOOST_CONCEPT_ASSERT( (concept::Point<P>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<L>) );
+
+ public :
+ /// BCCL macro to check the Linestring concept
+ BOOST_CONCEPT_USAGE(Linestring)
+ {
+
+ // Check if it can be modified
+ L* ls;
+ clear(*ls);
+ append(*ls, P());
+ }
+};
+
+
+/*!
+ \brief Checks Linestring concept (const version)
+ \ingroup concepts
+ \details The ConstLinestring concept check the same as the Linestring concept,
+ but does not check write access.
+*/
+template <typename L>
+struct ConstLinestring
+{
+ private :
+ typedef typename point_type<L>::type P;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<P>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<L>) );
+
+
+ public :
+ /// BCCL macro to check the ConstLinestring concept
+ BOOST_CONCEPT_USAGE(ConstLinestring)
+ {
+ }
+};
+
+}} // namespace ggl::concept
+
+
+#endif // GGL_CORE_CONCEPTS_LINESTRING_CONCEPT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/concepts/nsphere_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/concepts/nsphere_concept.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,119 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef GGL_CORE_CONCEPTS_NSPHERE_CONCEPT_HPP
+#define GGL_CORE_CONCEPTS_NSPHERE_CONCEPT_HPP
+
+#include <boost/concept_check.hpp>
+
+#include <ggl/core/coordinate_dimension.hpp>
+#include <ggl/core/access.hpp>
+#include <ggl/core/radius.hpp>
+
+namespace ggl { namespace concept {
+
+/*!
+ \brief Checks Nsphere concept (const version)
+ \ingroup concepts
+ \details The ConstNsphere concept check the same as the Nsphere concept,
+ but does not check write access.
+*/
+template <typename S>
+struct ConstNsphere
+{
+ private :
+ typedef typename point_type<S>::type P;
+ typedef typename radius_type<S>::type R;
+
+ /// Internal structure to check if access is OK for all dimensions
+ template <size_t D, size_t N>
+ struct dimension_checker
+ {
+ static void check()
+ {
+ typedef typename coordinate_type<S>::type T;
+ const S* s = 0;
+ T coord(ggl::get<D>(*s));
+ (void)sizeof(coord); // To avoid "unused variable" warnings
+ dimension_checker<D + 1, N>::check();
+ }
+ };
+
+ template <size_t N>
+ struct dimension_checker<N, N>
+ {
+ static void check() {}
+ };
+
+ public :
+ /// BCCL macro to check the ConstNsphere concept
+ BOOST_CONCEPT_USAGE(ConstNsphere)
+ {
+ static const size_t N = dimension<S>::value;
+ dimension_checker<0, N>::check();
+ dimension_checker<0, N>::check();
+
+ // Check radius access
+ const S* s = 0;
+ R coord(ggl::get_radius<0>(*s));
+ (void)sizeof(coord); // To avoid "unused variable" warnings
+ }
+};
+
+
+/*!
+ \brief Checks nsphere concept, using Boost Concept Check Library and metafunctions
+ \ingroup concepts
+*/
+template <typename S>
+struct Nsphere
+{
+ private :
+ BOOST_CONCEPT_ASSERT( (concept::ConstNsphere<S>) );
+
+ typedef typename point_type<S>::type P;
+ typedef typename radius_type<S>::type R;
+
+ /// Internal structure to check if access is OK for all dimensions
+ template <size_t D, size_t N>
+ struct dimension_checker
+ {
+ static void check()
+ {
+ S* s;
+ ggl::set<D>(*s, ggl::get<D>(*s));
+ dimension_checker<D + 1, N>::check();
+ }
+ };
+
+ template <size_t N>
+ struct dimension_checker<N, N>
+ {
+ static void check() {}
+ };
+
+ public :
+ /// BCCL macro to check the Nsphere concept
+ BOOST_CONCEPT_USAGE(Nsphere)
+ {
+ static const size_t N = dimension<S>::value;
+ dimension_checker<0, N>::check();
+ dimension_checker<0, N>::check();
+
+ // Check radius access
+ S* s = 0;
+ set_radius<0>(*s, get_radius<0>(*s));
+
+ }
+};
+
+
+
+}} // namespace ggl::concept
+
+#endif // GGL_CORE_CONCEPTS_NSPHERE_CONCEPT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/concepts/point_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/concepts/point_concept.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,146 @@
+// Generic Geometry Library Point concept
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef GGL_CORE_CONCEPTS_POINT_CONCEPT_HPP
+#define GGL_CORE_CONCEPTS_POINT_CONCEPT_HPP
+
+#include <cstddef>
+
+#include <boost/concept_check.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/coordinate_dimension.hpp>
+#include <ggl/core/coordinate_system.hpp>
+
+
+/*!
+\defgroup concepts concept checking
+Concepts are used to check if pointtypes provide required implementation. Concept checking
+is done using BCCL (Boost Concept Check Library) and MPL (Meta Programming Library)
+*/
+
+namespace ggl { namespace concept {
+
+/*!
+ \brief Checks point concept, using Boost Concept Check Library and metafunctions
+ \ingroup concepts
+ \details The concept is separated into 4 metafunctions:
+ - \ref ggl::traits::coordinate_type "coordinate_type": provides the type of the coordinates of a point
+ - \ref ggl::traits::coordinate_system "coordinate system": provides the coordinate system in which the point is placed
+ - \ref ggl::traits::dimension "dimension": provides the number of coordinates of a point
+ - \ref ggl::traits::access "access": provides access to the coordinates of a point
+
+ In MPL, a metafunction that provides a type must expose is as "type"
+ and a metafunction that provides a value must expose it as "value", so
+ here the same convention are used: coordinate_type<P>::type and
+ dimension<P>::value provide the type and number of coordinates. This
+ makes them compatible with any MPL and Fusion algorithm and
+ metafunction.
+
+ \par Example:
+ First example, using an own pointtype, for example a legacy point, defining the necessary
+ properties outside the pointtype in a traits class
+ \dontinclude doxygen_examples.cpp
+ \skip example_point_1
+ \until //:\\
+ \par Example:
+ Second example, deriving a pointtype from boost::tuple. It defines the necessary properties
+ itself, so a separate traits class is not necessary.
+ \dontinclude doxygen_examples.cpp
+ \skip example_own_point2
+ \line {
+ \until //:\\
+*/
+
+template <typename X>
+struct Point
+{
+private:
+
+ typedef typename coordinate_type<X>::type ctype;
+ typedef typename coordinate_system<X>::type csystem;
+
+ enum { ccount = dimension<X>::value };
+
+ /// Internal structure to check if access is OK for all dimensions
+ template <typename P, std::size_t I, std::size_t Count>
+ struct dimension_checker
+ {
+ static void check()
+ {
+ P* p;
+ ggl::set<I>(*p, ggl::get<I>(*p));
+ dimension_checker<P, I+1, Count>::check();
+ }
+ };
+
+ /// Internal structure to check if access is OK for all dimensions
+ template <typename P, std::size_t Count>
+ struct dimension_checker<P, Count, Count>
+ {
+ static void check() {}
+ };
+
+public:
+
+ /// BCCL macro to check the Point concept
+ BOOST_CONCEPT_USAGE(Point)
+ {
+ dimension_checker<X, 0, ccount>::check();
+ }
+};
+
+
+/*!
+ \brief Checks point concept (const version)
+ \ingroup concepts
+ \details The ConstPoint concept check the same as the Point concept,
+ but does not check write access.
+*/
+template <typename X>
+struct ConstPoint
+{
+private:
+
+ typedef typename coordinate_type<X>::type ctype;
+ typedef typename coordinate_system<X>::type csystem;
+
+ enum { ccount = dimension<X>::value };
+
+ /// Internal structure to check if access is OK for all dimensions
+ template <typename P, std::size_t I, std::size_t Count>
+ struct dimension_checker
+ {
+ static void check()
+ {
+ const P* p = 0;
+ ctype coord(ggl::get<I>(*p));
+ boost::ignore_unused_variable_warning(coord);
+ dimension_checker<P, I+1, Count>::check();
+ }
+ };
+
+ /// Internal structure to check if access is OK for all dimensions
+ template <typename P, std::size_t Count>
+ struct dimension_checker<P, Count, Count>
+ {
+ static void check() {}
+ };
+
+public:
+
+ /// BCCL macro to check the ConstPoint concept
+ BOOST_CONCEPT_USAGE(ConstPoint)
+ {
+ dimension_checker<X, 0, ccount>::check();
+ }
+};
+
+}} // namespace ggl::concept
+
+#endif // GGL_CORE_CONCEPTS_POINT_CONCEPT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/concepts/polygon_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/concepts/polygon_concept.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,120 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_CORE_CONCEPTS_POLYGON_CONCEPT_HPP
+#define GGL_CORE_CONCEPTS_POLYGON_CONCEPT_HPP
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+
+#include <ggl/algorithms/append.hpp>
+#include <ggl/algorithms/clear.hpp>
+#include <ggl/core/access.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+#include <ggl/core/point_type.hpp>
+#include <ggl/core/ring_type.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/core/concepts/ring_concept.hpp>
+
+namespace ggl { namespace concept {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename P>
+struct PolygonChecker
+{
+ typedef typename point_type<P>::type PNT;
+ typedef typename ring_type<P>::type R;
+ typedef typename interior_type<P>::type I;
+
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<I>) );
+
+ void constraints()
+ {
+ P* poly;
+ R& e = exterior_ring(*poly);
+ const R& ce = exterior_ring(*poly);
+
+ I& i = interior_rings(*poly);
+ const I& 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);
+ }
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+/*!
+ \brief Checks polygon concept, using Boost Concept Check Library and metafunctions
+ \ingroup concepts
+*/
+template <typename P>
+struct Polygon : detail::PolygonChecker<P>
+{
+private:
+
+ typedef typename point_type<P>::type PNT;
+ typedef typename ring_type<P>::type R;
+ typedef typename interior_type<P>::type I;
+
+ BOOST_CONCEPT_ASSERT( (concept::Point<PNT>) );
+ BOOST_CONCEPT_ASSERT( (concept::Ring<R>) );
+
+public:
+
+ /// BCCL macro to check the Polygon concept
+ BOOST_CONCEPT_USAGE(Polygon)
+ {
+ // Check if it can be modified
+ P* poly;
+ clear(*poly);
+ append(*poly, PNT());
+
+ this->constraints();
+ }
+};
+
+
+/*!
+ \brief Checks Polygon concept (const version)
+ \ingroup concepts
+ \details The ConstPolygon concept check the same as the Polygon concept,
+ but does not check write access.
+*/
+template <typename P>
+struct ConstPolygon : detail::PolygonChecker<P>
+{
+private:
+
+ typedef typename point_type<P>::type PNT;
+ typedef typename ring_type<P>::type R;
+ typedef typename interior_type<P>::type I;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<PNT>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstRing<R>) );
+
+public:
+
+ /// BCCL macro to check the ConstPolygon concept
+ BOOST_CONCEPT_USAGE(ConstPolygon)
+ {
+ this->constraints();
+ }
+};
+
+}} // namespace ggl::concept
+
+#endif // GGL_CORE_CONCEPTS_POLYGON_CONCEPT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/concepts/ring_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/concepts/ring_concept.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,83 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_CORE_CONCEPTS_RING_CONCEPT_HPP
+#define GGL_CORE_CONCEPTS_RING_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+
+#include <ggl/core/concepts/point_concept.hpp>
+
+
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/point_type.hpp>
+
+#include <ggl/algorithms/clear.hpp>
+#include <ggl/algorithms/append.hpp>
+
+
+
+namespace ggl { namespace concept {
+
+
+/*!
+ \brief Checks (linear) Ring concept, using Boost Concept Check Library and metafunctions
+ \ingroup concepts
+*/
+template <typename R>
+struct Ring
+{
+ private :
+ typedef typename point_type<R>::type P;
+
+ BOOST_CONCEPT_ASSERT( (concept::Point<P>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<R>) );
+
+
+ public :
+ /// BCCL macro to check the Ring concept
+ BOOST_CONCEPT_USAGE(Ring)
+ {
+ // Check if it can be modified
+ R* ls;
+ clear(*ls);
+ append(*ls, P());
+ }
+};
+
+
+/*!
+ \brief Checks (linear) ring concept (const version)
+ \ingroup concepts
+ \details The ConstLinearRing concept check the same as the Ring concept,
+ but does not check write access.
+*/
+template <typename R>
+struct ConstRing
+{
+ private :
+ typedef typename point_type<R>::type P;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<P>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<R>) );
+
+ public :
+ /// BCCL macro to check the ConstLinearRing concept
+ BOOST_CONCEPT_USAGE(ConstRing)
+ {
+ }
+};
+
+}} // namespace ggl::concept
+
+
+#endif // GGL_CORE_CONCEPTS_RING_CONCEPT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/concepts/segment_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/concepts/segment_concept.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,119 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef GGL_CORE_CONCEPTS_SEGMENT_CONCEPT_HPP
+#define GGL_CORE_CONCEPTS_SEGMENT_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+
+#include <ggl/core/concepts/point_concept.hpp>
+
+
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/point_type.hpp>
+
+
+
+namespace ggl { namespace concept {
+
+
+/*!
+ \brief Checks segment concept, using Boost Concept Check Library and metafunctions
+ \ingroup concepts
+*/
+template <typename S>
+struct Segment
+{
+ private :
+ typedef typename point_type<S>::type P;
+
+ BOOST_CONCEPT_ASSERT( (concept::Point<P>) );
+
+
+ /// Internal structure to check if access is OK for all dimensions
+ template <size_t C, size_t D, size_t N>
+ struct dimension_checker
+ {
+ static void check()
+ {
+ S* s;
+ ggl::set<C, D>(*s, ggl::get<C, D>(*s));
+ dimension_checker<C, D + 1, N>::check();
+ }
+ };
+
+ template <size_t C, size_t N>
+ struct dimension_checker<C, N, N>
+ {
+ static void check() {}
+ };
+
+ public :
+ /// BCCL macro to check the Segment concept
+ BOOST_CONCEPT_USAGE(Segment)
+ {
+ static const size_t N = dimension<P>::value;
+ dimension_checker<0, 0, N>::check();
+ dimension_checker<1, 0, N>::check();
+ }
+};
+
+
+/*!
+ \brief Checks Segment concept (const version)
+ \ingroup concepts
+ \details The ConstSegment concept check the same as the Segment concept,
+ but does not check write access.
+*/
+template <typename S>
+struct ConstSegment
+{
+ private :
+ typedef typename point_type<S>::type P;
+ typedef typename coordinate_type<S>::type T;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<P>) );
+
+
+ /// Internal structure to check if access is OK for all dimensions
+ template <size_t C, size_t D, size_t N>
+ struct dimension_checker
+ {
+ static void check()
+ {
+ const S* s = 0;
+ T coord(ggl::get<C, D>(*s));
+ boost::ignore_unused_variable_warning(coord);
+ dimension_checker<C, D + 1, N>::check();
+ }
+ };
+
+ template <size_t C, size_t N>
+ struct dimension_checker<C, N, N>
+ {
+ static void check() {}
+ };
+
+ public :
+ /// BCCL macro to check the ConstSegment concept
+ BOOST_CONCEPT_USAGE(ConstSegment)
+ {
+ static const size_t N = dimension<P>::value;
+ dimension_checker<0, 0, N>::check();
+ dimension_checker<1, 0, N>::check();
+ }
+};
+
+
+}} // namespace ggl::concept
+
+
+#endif // GGL_CORE_CONCEPTS_SEGMENT_CONCEPT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/coordinate_dimension.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/coordinate_dimension.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,111 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef GGL_CORE_COORDINATE_DIMENSION_HPP
+#define GGL_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 <ggl/core/coordinate_dimension.hpp>
+#include <ggl/core/point_type.hpp>
+
+namespace ggl
+{
+
+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
+ <
+ ggl::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 ggl
+
+#endif // GGL_CORE_COORDINATE_DIMENSION_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/coordinate_system.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/coordinate_system.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,79 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef GGL_CORE_COORDINATE_SYSTEM_HPP
+#define GGL_CORE_COORDINATE_SYSTEM_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+#include <ggl/core/point_type.hpp>
+
+
+namespace ggl
+{
+
+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;
+};
+
+}
+
+
+#endif // GGL_CORE_COORDINATE_SYSTEM_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/coordinate_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/coordinate_type.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,72 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef GGL_CORE_COORDINATE_TYPE_HPP
+#define GGL_CORE_COORDINATE_TYPE_HPP
+
+#include <boost/type_traits/remove_const.hpp>
+
+#include <ggl/core/point_type.hpp>
+
+namespace ggl {
+
+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 ggl
+
+#endif // GGL_CORE_COORDINATE_TYPE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/cs.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/cs.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,234 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_CORE_CS_HPP
+#define GGL_CORE_CS_HPP
+
+#include <cstddef>
+
+#include <boost/type_traits.hpp>
+
+#include <ggl/core/coordinate_system.hpp>
+#include <ggl/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 ggl
+{
+
+/*!
+ \brief Unit of plan angles: degrees
+ \ingroup utility
+*/
+class degree {};
+
+
+/*!
+ \brief Unit of plan angles: radians
+ \ingroup utility
+*/
+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 EPSG Cartesian coordinate system
+ \details EPSG (European Petrol Survey Group) has a standard list of projections,
+ each having a code
+ \see
+ \ingroup cs
+ \tparam Code the EPSG code
+ \todo Maybe derive from boost::mpl::int_<EpsgCode>
+*/
+template<std::size_t Code>
+struct epsg
+{
+ static const std::size_t epsg_code = Code;
+};
+
+
+/*!
+ \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
+*/
+template<typename DegreeOrRadian>
+struct geographic
+{
+ typedef DegreeOrRadian units;
+};
+
+/*!
+ \brief Earth Centered, Earth Fixed
+ \details Defines a Cartesian coordinate system x,y,z with the center of the earth as its origin,
+ going through the Greenwich
+ \see http://en.wikipedia.org/wiki/ECEF
+ \see http://en.wikipedia.org/wiki/Geodetic_system
+ \note Also known as "Geocentric", but geocentric is also an astronomic coordinate system
+ \ingroup cs
+*/
+struct ecef
+{
+};
+
+/*!
+ \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 celestial
+{
+
+/*!
+ \brief Ecliptic (celestial) coordinate system
+ \details Defines the astronomical ecliptic coordinate system "that uses the ecliptic for its fundamental plane"
+ It uses Beta and Lambda as its latitude and longitude.
+ \see http://en.wikipedia.org/wiki/Ecliptic_coordinate_system
+ \ingroup cs
+*/
+template<typename DegreeOrRadian>
+struct ecliptic
+{
+ typedef DegreeOrRadian units;
+};
+
+// TODO: More celestial coordinate systems could be defined
+
+} // namespace celestial
+
+} // 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;
+};
+
+template<>
+struct cs_tag<cs::ecef>
+{
+ typedef cartesian_tag type;
+};
+
+template <std::size_t C>
+struct cs_tag<cs::epsg<C> >
+{
+ 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 ggl::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 ggl
+
+#endif // GGL_CORE_CS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/exception.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/exception.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,26 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_CORE_EXCEPTION_HPP
+#define GGL_CORE_EXCEPTION_HPP
+
+#include <exception>
+
+namespace ggl {
+
+/*!
+\brief Base exception class for GGL
+\ingroup core
+*/
+struct exception : public std::exception
+{
+};
+
+} // namespace ggl
+
+#endif // GGL_CORE_EXCEPTION_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/exterior_ring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/exterior_ring.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,100 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_CORE_EXTERIOR_RING_HPP
+#define GGL_CORE_EXTERIOR_RING_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+
+
+#include <ggl/core/ring_type.hpp>
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+
+namespace ggl {
+
+namespace traits {
+
+/*!
+ \brief Traits class defining access to exterior_ring of a polygon
+ \details Should define const and non const access
+ \ingroup traits
+ \tparam G geometry
+ \par Geometries:
+ - polygon
+ \par Specializations should provide:
+ - static inline RING& get(POLY& )
+ - static inline const RING& get(const POLY& )
+*/
+template <typename P>
+struct exterior_ring {};
+
+} // namespace traits
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename T, typename G>
+struct exterior_ring {};
+
+template <typename P>
+struct exterior_ring<polygon_tag, P>
+{
+ static inline typename ring_type<polygon_tag, P>::type& get(P& polygon)
+ {
+ return traits::exterior_ring<P>::get(polygon);
+ }
+
+ static inline const typename ring_type<polygon_tag, P>::type& get(const P& polygon)
+ {
+ return traits::exterior_ring<P>::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 P>
+inline typename ring_type<P>::type& exterior_ring(P& polygon)
+{
+ return core_dispatch::exterior_ring<typename tag<P>::type, P>::get(polygon);
+}
+
+/*!
+ \brief Function to get the exterior ring of a polygon (const version)
+ \ingroup access
+ \note OGC compliance: instead of ExteriorRing
+ \tparam P polygon type
+ \param polygon the polygon to get the exterior ring from
+ \return a const reference to the exterior ring
+*/
+template <typename P>
+inline const typename ring_type<P>::type& exterior_ring(const P& polygon)
+{
+ return core_dispatch::exterior_ring<typename tag<P>::type, P>::get(polygon);
+}
+
+
+} // namespace ggl
+
+
+#endif // GGL_CORE_EXTERIOR_RING_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/geometry_id.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/geometry_id.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,80 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_CORE_GEOMETRY_ID_HPP
+#define GGL_CORE_GEOMETRY_ID_HPP
+
+
+#include <boost/mpl/int.hpp>
+#include <boost/type_traits.hpp>
+
+
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+
+namespace ggl {
+
+
+#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<nsphere_tag> : boost::mpl::int_<91> {};
+
+
+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 ggl
+
+
+#endif // GGL_CORE_GEOMETRY_ID_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/interior_rings.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/interior_rings.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,165 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_CORE_INTERIOR_RINGS_HPP
+#define GGL_CORE_INTERIOR_RINGS_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+namespace ggl
+{
+
+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 CONTAINER<RING<P> > type (e.g. std::vector<linear_ring<P> >)
+ \tparam G geometry
+ */
+ template <typename G>
+ 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 G geometry
+ */
+ template <typename G>
+ struct interior_rings
+ {
+ };
+
+
+} // namespace traits
+
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+ template <typename GeometryTag, typename G> struct interior_type {};
+
+ template <typename P>
+ struct interior_type<polygon_tag, P>
+ {
+ typedef typename traits::interior_type<P>::type type;
+ };
+
+
+
+ template <typename GeometryTag, typename G>
+ struct interior_rings {};
+
+
+ template <typename P>
+ struct interior_rings<polygon_tag, P>
+ {
+ static inline typename interior_type<polygon_tag, P>::type& get(P& polygon)
+ {
+ return traits::interior_rings<P>::get(polygon);
+ }
+
+ static inline const typename interior_type<polygon_tag, P>::type& get(const P& polygon)
+ {
+ return traits::interior_rings<P>::get(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 G>
+struct interior_type
+{
+ typedef typename boost::remove_const<G>::type ncg;
+ typedef typename core_dispatch::interior_type<
+ typename tag<G>::type, ncg>::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 P>
+inline typename interior_type<P>::type& interior_rings(P& polygon)
+{
+ return core_dispatch::interior_rings<typename tag<P>::type, P>::get(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 P>
+inline const typename interior_type<P>::type& interior_rings(const P& polygon)
+{
+ return core_dispatch::interior_rings<typename tag<P>::type, P>::get(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
+ \tparam P polygon type
+ \param polygon the polygon
+ \return the nubmer of interior rings
+*/
+template <typename P>
+inline size_t num_interior_rings(const P& polygon)
+{
+ return boost::size(interior_rings(polygon));
+}
+
+}
+
+
+#endif // GGL_CORE_INTERIOR_RINGS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/is_linear.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/is_linear.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,59 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_CORE_IS_LINEAR_HPP
+#define GGL_CORE_IS_LINEAR_HPP
+
+
+#include <boost/type_traits.hpp>
+
+
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+
+namespace ggl {
+
+
+#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 ggl
+
+
+#endif // GGL_CORE_IS_LINEAR_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/is_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/is_multi.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,49 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_CORE_IS_MULTI_HPP
+#define GGL_CORE_IS_MULTI_HPP
+
+
+#include <boost/type_traits.hpp>
+
+
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+
+namespace ggl {
+
+
+#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 ggl
+
+#endif // GGL_CORE_IS_MULTI_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/point_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/point_type.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,109 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef GGL_CORE_POINT_TYPE_HPP
+#define GGL_CORE_POINT_TYPE_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <ggl/core/ring_type.hpp>
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+namespace ggl {
+
+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 rinsg
+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 ggl
+
+#endif // GGL_CORE_POINT_TYPE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/radian_access.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/radian_access.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,118 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_CORE_RADIAN_ACCESS_HPP
+#define GGL_CORE_RADIAN_ACCESS_HPP
+
+
+#include <cstddef>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/cs.hpp>
+
+
+#include <ggl/util/math.hpp>
+
+
+namespace ggl {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail {
+
+template <std::size_t D, typename G, typename DR>
+struct radian_access
+{
+};
+
+template <std::size_t D, typename G, template<typename> class CS>
+struct radian_access<D, G, CS<radian> >
+{
+ typedef typename coordinate_type<G>::type coordinate_type;
+
+ static inline coordinate_type get(G const& geometry)
+ {
+ return ggl::get<D>(geometry);
+ }
+
+ static inline void set(G& geometry, coordinate_type const& radians)
+ {
+ ggl::set<D>(geometry, radians);
+ }
+};
+
+template <std::size_t D, typename G, template<typename> class CS>
+struct radian_access<D, G, CS<degree> >
+{
+ typedef typename coordinate_type<G>::type coordinate_type;
+
+ static inline coordinate_type get(G const& geometry)
+ {
+ return boost::numeric_cast
+ <
+ coordinate_type
+ >(ggl::get<D>(geometry) * math::d2r);
+ }
+
+ static inline void set(G& geometry, coordinate_type const& radians)
+ {
+ ggl::set<D>(geometry, boost::numeric_cast
+ <
+ coordinate_type
+ >(radians * math::r2d));
+ }
+
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief get a coordinate value of a point, result is in RADIAN
+ \details also if coordinate system was in degree, result is in radian
+ \return coordinate value
+ \ingroup access
+ \tparam D dimension
+ \tparam G geometry
+ \param geometry geometry to get coordinate value from
+*/
+template <std::size_t D, typename G>
+inline typename coordinate_type<G>::type get_as_radian(const G& geometry)
+{
+ return detail::radian_access<D, G,
+ typename coordinate_system<G>::type>::get(geometry);
+}
+
+
+/*!
+ \brief assign coordinate value (which is in radian) to a point
+ \details if coordinate system of point is in degree, will be converted
+ to degree
+ \ingroup access
+ \tparam D dimension
+ \tparam G geometry
+ \param geometry geometry to assign coordinate to
+ \param radians coordinate value to assign
+*/
+template <std::size_t D, typename G>
+inline void set_from_radian(G& geometry,
+ const typename coordinate_type<G>::type& radians)
+{
+ detail::radian_access<D, G,
+ typename coordinate_system<G>::type>::set(geometry, radians);
+}
+
+
+} // namespace ggl
+
+
+#endif // GGL_CORE_RADIAN_ACCESS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/radius.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/radius.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,152 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef GGL_CORE_RADIUS_HPP
+#define GGL_CORE_RADIUS_HPP
+
+
+#include <cstddef>
+
+
+#include <boost/type_traits/remove_const.hpp>
+
+
+#include <ggl/core/tag.hpp>
+
+
+namespace ggl {
+
+namespace traits {
+
+/*!
+ \brief Traits class to get/set radius of a circle/sphere/(ellipse)
+ \details the radius access meta-functions give read/write access to the radius of a circle or a sphere,
+ or to the major/minor axis or an ellipse, or to one of the 3 equatorial radii of an ellipsoid.
+
+ It should be specialized per geometry, in namespace core_dispatch. Those specializations should
+ forward the call via traits to the geometry class, which could be specified by the user.
+
+ There is a corresponding generic radius_get and radius_set function
+ \par Geometries:
+ - n-sphere (circle,sphere)
+ - upcoming ellipse
+ \par Specializations should provide:
+ - inline static T get(const G& geometry)
+ - inline static void set(G& geometry, const T& radius)
+ \ingroup traits
+*/
+template <typename G, typename T, std::size_t D>
+struct radius_access {};
+
+
+/*!
+ \brief Traits class indicating the type (double,float,...) of the radius of a circle or a sphere
+ \par Geometries:
+ - n-sphere (circle,sphere)
+ - upcoming ellipse
+ \par Specializations should provide:
+ - typedef T type (double,float,int,etc)
+ \ingroup traits
+*/
+template <typename G>
+struct radius_type {};
+
+} // namespace traits
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename Tag, typename G>
+struct radius_type
+{
+ //typedef core_dispatch_specialization_required type;
+};
+
+/*!
+ \brief radius access meta-functions, used by concept n-sphere and upcoming ellipse.
+*/
+template <typename Tag, typename G, typename T, std::size_t D>
+struct radius_access
+{
+ //static inline T get(const G& ) {}
+ //static inline void set(G& g, const T& value) {}
+};
+
+template <typename S>
+struct radius_type<nsphere_tag, S>
+{
+ typedef typename traits::radius_type<S>::type type;
+};
+
+template <typename S, typename T, std::size_t D>
+struct radius_access<nsphere_tag, S, T, D>
+{
+ BOOST_STATIC_ASSERT((D == 0));
+ static inline T get(const S& s)
+ {
+ return traits::radius_access<S, T, D>::get(s);
+ }
+ static inline void set(S& s, const T& radius)
+ {
+ traits::radius_access<S, T, D>::set(s, radius);
+ }
+};
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+template <typename G>
+struct radius_type
+{
+ typedef typename boost::remove_const<G>::type rconst;
+ typedef typename core_dispatch::radius_type<typename tag<G>::type, rconst>::type type;
+};
+
+/*!
+ \brief Function to get radius
+ \return radius of a circle / sphere / ellipse
+ \ingroup access
+ \param geometry the geometry to get the radius from
+ \tparam I index, for circle/sphere always zero, for ellipse major/minor axis,
+ for ellipsoid one of the 3 equatorial radii
+*/
+template <std::size_t I, typename G>
+inline typename radius_type<G>::type get_radius(const G& geometry)
+{
+ typedef typename boost::remove_const<G>::type rconst;
+
+ return core_dispatch::radius_access<typename tag<G>::type, rconst,
+ typename radius_type<G>::type, I>::get(geometry);
+}
+
+/*!
+ \brief Function to set the radius of a circle / sphere / (ellipse)
+ \ingroup access
+ \tparam I index, for circle/sphere always zero, for ellipse major/minor axis,
+ for ellipsoid one of the 3 equatorial radii
+ \param geometry the geometry to change
+ \param radius the radius to set
+*/
+template <std::size_t I, typename G>
+inline void set_radius(G& geometry, const typename radius_type<G>::type& radius)
+{
+ typedef typename boost::remove_const<G>::type rconst;
+
+ core_dispatch::radius_access<typename tag<G>::type, G,
+ typename radius_type<G>::type, I>::set(geometry, radius);
+}
+
+
+} // namespace ggl
+
+
+#endif // GGL_RADIUS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/replace_point_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/replace_point_type.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,99 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef GGL_CORE_REPLACE_POINT_TYPE_HPP
+#define GGL_CORE_REPLACE_POINT_TYPE_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+
+
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+#include <ggl/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 <ggl/geometries/point.hpp>
+#include <ggl/geometries/linestring.hpp>
+#include <ggl/geometries/linear_ring.hpp>
+#include <ggl/geometries/polygon.hpp>
+#include <ggl/geometries/segment.hpp>
+#include <ggl/geometries/box.hpp>
+#include <ggl/geometries/nsphere.hpp>
+
+
+namespace ggl {
+
+#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;
+};
+
+template <typename Geometry, typename NewPointType>
+struct replace_point_type<nsphere_tag, Geometry, NewPointType>
+{
+ typedef typename ggl::coordinate_type<Geometry>::type coortype;
+ typedef nsphere<NewPointType, coortype> 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 ggl
+
+#endif // GGL_CORE_REPLACE_POINT_TYPE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/reverse_dispatch.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/reverse_dispatch.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,61 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_CORE_REVERSE_DISPATCH_HPP
+#define GGL_CORE_REVERSE_DISPATCH_HPP
+
+
+#include <boost/type_traits.hpp>
+
+#include <boost/mpl/greater.hpp>
+
+#include <ggl/core/geometry_id.hpp>
+
+
+namespace ggl {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+// Different geometries: reverse_dispatch if second ID < first ID
+// Note: if "boost::mpl::greater is used, with geometry_id instead of geometry_id::type::value,
+// it is not working correctly!!!! TODO: find out why not.
+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 ggl
+
+#endif // GGL_CORE_REVERSE_DISPATCH_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/ring_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/ring_type.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,97 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_CORE_RING_TYPE_HPP
+#define GGL_CORE_RING_TYPE_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+
+
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+
+namespace ggl
+{
+
+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 G geometry
+*/
+template <typename G>
+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<Polygon>::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).
+ The type of those rings is assumed to be equal. This meta function retrieves the type
+ of such rings.
+ \ingroup core
+*/
+template <typename Geometry>
+struct ring_type
+{
+ typedef typename boost::remove_const<Geometry>::type ncg;
+ typedef typename core_dispatch::ring_type
+ <
+ typename tag<Geometry>::type, ncg
+ >::type type;
+};
+
+
+
+
+}
+
+
+#endif // GGL_CORE_RING_TYPE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/tag.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/tag.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,65 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef GGL_CORE_TAG_HPP
+#define GGL_CORE_TAG_HPP
+
+#include <boost/type_traits/remove_const.hpp>
+
+#include <ggl/core/tags.hpp>
+
+/*!
+\defgroup core core: meta-functions for geometry types
+*/
+
+namespace ggl
+{
+
+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 ggl
+
+#endif // GGL_CORE_TAG_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/tags.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/tags.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,64 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_CORE_TAGS_HPP
+#define GGL_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 ggl
+{
+
+// 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 2D (circle) or 3D (sphere) n-sphere identifying tag
+struct nsphere_tag {};
+
+/// Convenience segment (2-points) identifying tag
+struct segment_tag {};
+
+} // namespace ggl
+
+#endif // GGL_CORE_TAGS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/core/topological_dimension.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/core/topological_dimension.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,89 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_CORE_TOPOLOGICAL_DIMENSION_HPP
+#define GGL_CORE_TOPOLOGICAL_DIMENSION_HPP
+
+
+#include <boost/mpl/int.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+
+namespace ggl {
+
+
+#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> {};
+
+
+// nsphere: 2, but there is discussion. Is it CLOSED? Then 2, but
+// then it should be called "disk"...
+template <>
+struct top_dim<nsphere_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 ggl
+
+
+#endif // GGL_CORE_TOPOLOGICAL_DIMENSION_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/detail/wkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/detail/wkt.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,45 @@
+// 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 GGL_IO_WKT_DETAIL_WKT_HPP
+#define GGL_IO_WKT_DETAIL_WKT_HPP
+
+
+
+
+namespace ggl
+{
+
+#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
+
+
+
+} // namescpae ggl
+
+#endif // GGL_IO_WKT_DETAIL_WKT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/detail/wkt_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/detail/wkt_multi.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,51 @@
+// 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 GGL_MULTI_IO_WKT_DETAIL_WKT_HPP
+#define GGL_MULTI_IO_WKT_DETAIL_WKT_HPP
+
+
+#include <ggl/extensions/gis/io/wkt/write_wkt.hpp>
+#include <ggl/multi/core/tags.hpp>
+
+
+namespace ggl
+{
+
+#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
+
+
+
+} // namescpae ggl
+
+#endif // GGL_MULTI_IO_WKT_DETAIL_WKT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/read_wkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/read_wkt.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,624 @@
+// 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 GGL_EXTENSIONS_GIS_IO_WKT_READ_WKT_HPP
+#define GGL_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/concept/requires.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/type_traits.hpp>
+
+
+#include <ggl/algorithms/clear.hpp>
+#include <ggl/core/access.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/core/exception.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+
+#include <ggl/extensions/gis/io/wkt/detail/wkt.hpp>
+
+namespace ggl
+{
+
+
+
+/*!
+\brief Exception showing things wrong with WKT parsing
+\ingroup wkt
+*/
+struct read_wkt_exception : public ggl::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)
+ {
+ ggl::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);
+ }
+ set<min_corner, 0>(box, get<0>(points[0]));
+ set<min_corner, 1>(box, get<1>(points[0]));
+ set<max_corner, 0>(box, get<0>(points[index]));
+ set<max_corner, 1>(box, get<1>(points[index]));
+ }
+};
+
+
+
+}} // 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
+ >
+{
+private :
+ BOOST_CONCEPT_ASSERT( (concept::Point<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>
+{};
+
+
+} // 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_examples.cpp
+\skip example_from_wkt_point
+\line {
+\until }
+\par Example:
+Small example showing how to use read_wkt to build a linestring
+\dontinclude doxygen_examples.cpp
+\skip example_from_wkt_linestring
+\line {
+\until }
+\par Example:
+Small example showing how to use read_wkt to build a polygon
+\dontinclude doxygen_examples.cpp
+\skip example_from_wkt_polygon
+\line {
+\until }
+*/
+template <typename Geometry>
+inline void read_wkt(std::string const& wkt, Geometry& 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_examples.cpp
+\skip example_from_wkt_output_iterator
+\line {
+\until }
+*/
+template <typename P, typename Out>
+inline void read_wkt(std::string const& wkt, Out out)
+{
+ // 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<P>(tokens, tag, wkt, it))
+ {
+ detail::wkt::container_inserter<P>::apply(it, tokens.end(), wkt, out);
+ }
+}
+
+} // namespace ggl
+
+#endif // GGL_EXTENSIONS_GIS_IO_WKT_READ_WKT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/read_wkt_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/read_wkt_multi.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,105 @@
+// 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 GGL_EXTENSIONS_GIS_IO_WKT_READ_WKT_MULTI_HPP
+#define GGL_EXTENSIONS_GIS_IO_WKT_READ_WKT_MULTI_HPP
+
+#include <string>
+
+#include <ggl/multi/core/tags.hpp>
+#include <ggl/multi/core/point_type.hpp>
+
+#include <ggl/extensions/gis/io/wkt/read_wkt.hpp>
+#include <ggl/extensions/gis/io/wkt/detail/wkt_multi.hpp>
+
+
+namespace ggl
+{
+
+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 ggl
+
+#endif // GGL_EXTENSIONS_GIS_IO_WKT_READ_WKT_MULTI_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/stream_wkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/stream_wkt.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,36 @@
+// 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 GGL_EXTENSIONS_GIS_IO_WKT_STREAM_WKT_HPP
+#define GGL_EXTENSIONS_GIS_IO_WKT_STREAM_WKT_HPP
+
+#include <ggl/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 ggl, to enable the library to stream custom geometries which
+// are living outside the namespace ggl
+
+//namespace ggl
+//{
+
+
+/*!
+\brief Streams a geometry as Well-Known Text
+\ingroup wkt
+*/
+template<typename CH, typename TR, typename G>
+inline std::basic_ostream<CH,TR>& operator<<(std::basic_ostream<CH,TR> &os, const G& geometry)
+{
+ os << ggl::wkt(geometry);
+ return os;
+}
+
+//} // namespace ggl
+
+#endif // GGL_EXTENSIONS_GIS_IO_WKT_STREAM_WKT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/wkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/wkt.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,19 @@
+// 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 GGL_EXTENSIONS_GIS_IO_WKT_WKT_HPP
+#define GGL_EXTENSIONS_GIS_IO_WKT_WKT_HPP
+
+
+#include <ggl/extensions/gis/io/wkt/read_wkt.hpp>
+#include <ggl/extensions/gis/io/wkt/write_wkt.hpp>
+
+#include <ggl/extensions/gis/io/wkt/read_wkt_multi.hpp>
+#include <ggl/extensions/gis/io/wkt/write_wkt_multi.hpp>
+
+
+#endif // GGL_EXTENSIONS_GIS_IO_WKT_WKT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/write_wkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/write_wkt.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,360 @@
+// 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 GGL_EXTENSIONS_GIS_IO_WKT_WRITE_WKT_HPP
+#define GGL_EXTENSIONS_GIS_IO_WKT_WRITE_WKT_HPP
+
+#include <iostream>
+#include <string>
+
+#include <boost/concept/assert.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/algorithms/convert.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+#include <ggl/core/ring_type.hpp>
+#include <ggl/geometries/linear_ring.hpp>
+
+#include <ggl/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 ggl
+{
+
+#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 << ")";
+ }
+
+ private:
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point>) );
+};
+
+/*!
+\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, 0, dimension<point>::type::value>::apply(os, *it);
+ first = false;
+ }
+
+ os << SuffixPolicy::apply();
+ }
+
+ private:
+ typedef typename boost::range_value<Range>::type point;
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point>) );
+};
+
+/*!
+\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 << ")";
+ }
+
+ private:
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<typename point_type<Polygon>::type>) );
+};
+
+
+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;
+ ggl::convert(box, ring);
+ os << "POLYGON(";
+ wkt_sequence<ring_type>::apply(os, ring);
+ os << ")";
+ }
+
+ private:
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point_type>) );
+
+ 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_examples.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_examples.cpp
+\skip example_as_wkt_vector
+\line {
+\until }
+*/
+template <typename Geometry>
+inline wkt_manipulator<Geometry> wkt(Geometry const& geometry)
+{
+ return wkt_manipulator<Geometry>(geometry);
+}
+
+
+// Backward compatibility
+template <typename Geometry>
+inline wkt_manipulator<Geometry> make_wkt(Geometry const& geometry)
+{
+ return wkt_manipulator<Geometry>(geometry);
+}
+
+} // namespace ggl
+
+#endif // GGL_EXTENSIONS_GIS_IO_WKT_WRITE_WKT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/write_wkt_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/extensions/gis/io/wkt/write_wkt_multi.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,109 @@
+// 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 GGL_EXTENSIONS_GIS_IO_WKT_WRITE_WKT_MULTI_HPP
+#define GGL_EXTENSIONS_GIS_IO_WKT_WRITE_WKT_MULTI_HPP
+
+
+
+#include <ggl/multi/core/tags.hpp>
+
+#include <ggl/extensions/gis/io/wkt/write_wkt.hpp>
+#include <ggl/extensions/gis/io/wkt/detail/wkt_multi.hpp>
+
+
+namespace ggl
+{
+
+#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
+
+}
+
+#endif // GGL_EXTENSIONS_GIS_IO_WKT_WRITE_WKT_MULTI_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/extensions/io/svg/write_svg.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/extensions/io/svg/write_svg.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,269 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_IO_SVG_WRITE_SVG_HPP
+#define GGL_IO_SVG_WRITE_SVG_HPP
+
+#include <iostream>
+#include <string>
+
+#include <boost/concept/assert.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+#include <ggl/core/ring_type.hpp>
+
+/*!
+\defgroup svg svg: stream SVG (Scalable Vector Graphics)
+*/
+
+namespace ggl
+{
+
+#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 << "\"/>";
+ }
+
+ private:
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point>) );
+};
+
+
+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)
+ {
+ int x = ggl::get<ggl::min_corner, 0>(box);
+ int y = ggl::get<ggl::min_corner, 1>(box);
+ int width = std::abs(ggl::get<ggl::max_corner, 0>(box) - x);
+ int height = std::abs(ggl::get<ggl::max_corner, 1>(box) - y);
+
+ os << "<rect x=\"" << x << "\" y=\"" << y
+ << "\" width=\"" << width << "\" height=\"" << height
+ << "\" style=\"" << style << "\"/>";
+ }
+
+ private:
+ typedef typename ggl::point_type<Box>::type point_type;
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point_type>) );
+};
+
+
+/*!
+\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() << "\"/>";
+ }
+
+ private:
+ typedef typename boost::range_value<Range>::type point;
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point>) );
+};
+
+
+
+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 ggl::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 = ggl::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 ggl::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>";
+
+ }
+
+ private:
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::ConstPoint<typename point_type<Polygon>::type>)
+ );
+};
+
+
+
+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 Object generator to conveniently stream objects without including streamsvg
+\ingroup svg
+\par Example:
+Small example showing how to use the make_svg helper function
+\dontinclude doxygen_examples.cpp
+\skip example_as_svg_vector
+\line {
+\until }
+*/
+template <typename Geometry>
+inline svg_manipulator<Geometry> svg(Geometry const& t, std::string const& style, int size = -1)
+{
+ return svg_manipulator<Geometry>(t, style, size);
+}
+
+} // namespace ggl
+
+#endif // GGL_IO_SVG_WRITE_SVG_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/extensions/io/svg/write_svg_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/extensions/io/svg/write_svg_multi.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,73 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_IO_SVG_WRITE_SVG_MULTI_HPP
+#define GGL_IO_SVG_WRITE_SVG_MULTI_HPP
+
+
+#include <ggl/extensions/io/svg/write_svg.hpp>
+
+
+namespace ggl
+{
+
+#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 ggl
+
+#endif // GGL_IO_SVG_WRITE_SVG_MULTI_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/boost_array_as_linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/boost_array_as_linestring.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,40 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef GGL_ADAPTED_BOOST_ARRAY_AS_LINESTRING_HPP
+#define GGL_ADAPTED_BOOST_ARRAY_AS_LINESTRING_HPP
+
+
+#ifdef _GEOMETRY_ADAPTED_BOOST_ARRAY_RANGE_TAG_DEFINED
+#error Include only one headerfile to register tag for adapted boost::array
+#endif
+
+#define GGL_ADAPTED_BOOST_ARRAY_RANGE_TAG_DEFINED
+
+
+#include <boost/array.hpp>
+
+namespace ggl
+{
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+ template <typename T, size_t N>
+ struct tag< boost::array<T, N> >
+ {
+ typedef linestring_tag type;
+ };
+
+}
+#endif
+}
+
+
+#endif
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/boost_array_as_ring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/boost_array_as_ring.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,40 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef GGL_ADAPTED_BOOST_ARRAY_AS_RING_HPP
+#define GGL_ADAPTED_BOOST_ARRAY_AS_RING_HPP
+
+
+#ifdef _GEOMETRY_ADAPTED_BOOST_ARRAY_RANGE_TAG_DEFINED
+#error Include only one headerfile to register tag for adapted boost::array
+#endif
+
+#define GGL_ADAPTED_BOOST_ARRAY_RANGE_TAG_DEFINED
+
+
+#include <boost/array.hpp>
+
+namespace ggl
+{
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+ template <typename T, size_t N>
+ struct tag< boost::array<T, N> >
+ {
+ typedef ring_tag type;
+ };
+
+}
+#endif
+}
+
+
+#endif
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/c_array.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/c_array.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,88 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef GGL_GEOMETRIES_ADAPTED_C_ARRAY_HPP
+#define GGL_GEOMETRIES_ADAPTED_C_ARRAY_HPP
+
+#include <cstddef>
+
+#include <boost/type_traits/is_arithmetic.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/cs.hpp>
+#include <ggl/core/coordinate_dimension.hpp>
+#include <ggl/core/coordinate_type.hpp>
+#include <ggl/core/tags.hpp>
+
+namespace ggl
+{
+
+#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 T, std::size_t N>
+struct tag<T[N]> : detail::c_array_tag<boost::is_arithmetic<T>::value> {};
+
+template <typename T, std::size_t N>
+struct coordinate_type<T[N]>
+{
+ typedef T type;
+};
+
+template <typename T, std::size_t N>
+struct dimension<T[N]>: boost::mpl::int_<N> {};
+
+template <typename T, std::size_t N>
+struct access<T[N]>
+{
+ template <std::size_t I>
+ static inline T get(const T p[N])
+ {
+ return p[I];
+ }
+
+ template <std::size_t I>
+ static inline void set(T p[N], const T& value)
+ {
+ p[I] = value;
+ }
+};
+
+// The library user has
+// 1) either to specify the coordinate system
+// 2) or include <ggl/geometries/adapted/c_array__at_.hpp> where @=cartesian,geographic,...
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_ADAPTED_C_ARRAY_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/c_array_cartesian.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/c_array_cartesian.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,37 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef GGL_ADAPTED_C_ARRAY_CARTESIAN_HPP
+#define GGL_ADAPTED_C_ARRAY_CARTESIAN_HPP
+
+#ifdef _GEOMETRY_ADAPTED_C_ARRAY_COORDINATE_SYSTEM_DEFINED
+#error Include only one headerfile to register coordinate coordinate_system for adapted c array
+#endif
+
+#define GGL_ADAPTED_C_ARRAY_COORDINATE_SYSTEM_DEFINED
+
+
+#include <ggl/geometries/adapted/c_array.hpp>
+
+
+namespace ggl
+{
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+ template <typename T, int N>
+ struct coordinate_system<T[N]>
+ { typedef cs::cartesian type; };
+
+}
+#endif
+}
+
+
+#endif
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/std_as_linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/std_as_linestring.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,61 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef GGL_ADAPTED_STD_AS_LINESTRING_HPP
+#define GGL_ADAPTED_STD_AS_LINESTRING_HPP
+
+
+#ifdef _GEOMETRY_ADAPTED_STD_RANGE_TAG_DEFINED
+#error Include only one headerfile to register tag for adapted std:: containers or iterator pair
+#endif
+
+#define GGL_ADAPTED_STD_RANGE_TAG_DEFINED
+
+
+#include <vector>
+#include <deque>
+#include <list>
+#include <utility>
+
+
+namespace ggl
+{
+#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 a 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
+}
+
+
+#endif
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/std_as_ring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/std_as_ring.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,43 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef GGL_ADAPTED_STD_AS_RING_HPP
+#define GGL_ADAPTED_STD_AS_RING_HPP
+
+
+#ifdef _GEOMETRY_ADAPTED_STD_RANGE_TAG_DEFINED
+#error Include only one headerfile to register tag for adapted std:: containers or iterator pair
+#endif
+
+#define GGL_ADAPTED_STD_RANGE_TAG_DEFINED
+
+
+#include <vector>
+#include <deque>
+#include <list>
+#include <utility>
+
+namespace ggl
+{
+#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 a 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
+}
+
+
+#endif
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/tuple.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/tuple.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,100 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef GGL_GEOMETRIES_ADAPTED_TUPLE_HPP
+#define GGL_GEOMETRIES_ADAPTED_TUPLE_HPP
+
+#include <boost/tuple/tuple.hpp>
+
+#include <ggl/core/coordinate_dimension.hpp>
+#include <ggl/core/coordinate_type.hpp>
+#include <ggl/core/point_type.hpp>
+#include <ggl/core/tags.hpp>
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+// boost::tuple, 2D
+template <typename T>
+struct coordinate_type<boost::tuple<T, T> >
+{
+ typedef T type;
+};
+
+template <typename T>
+struct dimension<boost::tuple<T, T> > : boost::mpl::int_<2> {};
+
+template <typename T>
+struct access<boost::tuple<T, T> >
+{
+ template <int I>
+ static inline T get(const boost::tuple<T, T>& p)
+ {
+ return p.get<I>();
+ }
+
+ template <int I>
+ static inline void set(boost::tuple<T, T>& p, const T& value)
+ {
+ p.get<I>() = value;
+ }
+};
+
+template <typename T>
+struct tag<boost::tuple<T, T> >
+{
+ typedef point_tag type;
+};
+
+// boost::tuple, 3D
+template <typename T>
+struct coordinate_type<boost::tuple<T, T, T> >
+{
+ typedef T type;
+};
+
+template <typename T>
+struct dimension<boost::tuple<T, T, T> > : boost::mpl::int_<3> {};
+
+template <typename T>
+struct access<boost::tuple<T, T, T> >
+{
+ template <int I>
+ static inline T get(const boost::tuple<T, T, T>& p)
+ {
+ return p.get<I>();
+ }
+
+ template <int I>
+ static inline void set(boost::tuple<T, T, T>& p, const T& value)
+ {
+ p.get<I>() = value;
+ }
+};
+
+template <typename T>
+struct tag<boost::tuple<T, T, T> >
+{
+ typedef point_tag type;
+};
+
+// The library user has
+// 1) either to specify the coordinate system using a traits class
+// 2) or include <ggl/geometries/adapted/tuple__at_.hpp> where @=cartesian,geographic,...
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_ADAPTED_TUPLE_HPP
+
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/tuple_cartesian.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/adapted/tuple_cartesian.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,41 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef GGL_ADAPTED_TUPLE_CARTESIAN_HPP
+#define GGL_ADAPTED_TUPLE_CARTESIAN_HPP
+
+#ifdef _GEOMETRY_ADAPTED_TUPLE_COORDINATE_SYSTEM_DEFINED
+#error Include only one headerfile to register coordinate coordinate_system for adapted tuple
+#endif
+
+#define GGL_ADAPTED_TUPLE_COORDINATE_SYSTEM_DEFINED
+
+
+#include <ggl/geometries/adapted/tuple.hpp>
+
+
+namespace ggl
+{
+#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
+}
+
+
+#endif
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/box.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/box.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,110 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRIES_BOX_HPP
+#define GGL_GEOMETRIES_BOX_HPP
+
+#include <cstddef>
+
+#include <ggl/algorithms/assign.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/util/copy.hpp>
+
+namespace ggl
+{
+
+/*!
+ \brief Class box: defines a box made of two describing points
+ \ingroup Geometry
+ \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 P 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 P>
+class box
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<P>) );
+
+public:
+
+ inline box() {}
+
+ /*!
+ \brief Constructor taking the minimum corner point and the maximum corner point
+ */
+ inline box(P const& min_corner, P const& max_corner)
+ {
+ copy_coordinates(min_corner, m_min_corner);
+ copy_coordinates(max_corner, m_max_corner);
+ }
+
+ inline P const& min_corner() const { return m_min_corner; }
+ inline P const& max_corner() const { return m_max_corner; }
+
+ inline P& min_corner() { return m_min_corner; }
+ inline P& max_corner() { return m_max_corner; }
+
+private:
+
+ P m_min_corner;
+ P m_max_corner;
+};
+
+
+// Traits specializations for box above
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename P>
+struct tag< box<P> >
+{
+ typedef box_tag type;
+};
+
+template <typename P>
+struct point_type<box<P> >
+{
+ typedef P type;
+};
+
+template <typename P, std::size_t C, std::size_t D>
+struct indexed_access<box<P>, C, D>
+{
+ typedef box<P> box_type;
+
+ static inline typename ggl::coordinate_type<box_type>::type get(box_type const& b)
+ {
+ return (C == min_corner ? ggl::get<D>(b.min_corner()) : ggl::get<D>(b.max_corner()));
+ }
+
+ static inline void set(box_type& b, typename ggl::coordinate_type<box_type>::type const& value)
+ {
+ if (C == min_corner)
+ {
+ ggl::set<D>(b.min_corner(), value);
+ }
+ else
+ {
+ ggl::set<D>(b.max_corner(), value);
+ }
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_BOX_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/cartesian2d.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/cartesian2d.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,29 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRIES_CARTESIAN2D_HPP
+#define GGL_GEOMETRIES_CARTESIAN2D_HPP
+
+// Predeclare common Cartesian 2D points for convenience
+
+#include <ggl/geometries/geometries.hpp>
+
+namespace ggl
+{
+
+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;
+typedef nsphere<point_2d, double> circle;
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_CARTESIAN2D_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/cartesian3d.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/cartesian3d.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,28 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_CARTESIAN3D_HPP
+#define GGL_CARTESIAN3D_HPP
+
+// Predeclare common Cartesian 3D points for convenience
+
+#include <ggl/geometries/geometries.hpp>
+
+namespace ggl
+{
+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;
+
+typedef nsphere<point_3d, double> sphere;
+}
+
+
+#endif // GGL_CARTESIAN3D_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/geometries.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/geometries.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,25 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRIES_HPP
+#define GGL_GEOMETRIES_HPP
+
+#include <ggl/geometries/adapted/c_array.hpp>
+#include <ggl/geometries/adapted/tuple.hpp>
+
+#include <ggl/geometries/point.hpp>
+#include <ggl/geometries/point_xy.hpp>
+#include <ggl/geometries/linear_ring.hpp>
+#include <ggl/geometries/linestring.hpp>
+#include <ggl/geometries/polygon.hpp>
+
+#include <ggl/geometries/box.hpp>
+#include <ggl/geometries/nsphere.hpp>
+#include <ggl/geometries/segment.hpp>
+
+#endif // GGL_GEOMETRIES_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/linear_ring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/linear_ring.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,64 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRIES_LINEAR_RING_HPP
+#define GGL_GEOMETRIES_LINEAR_RING_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/assert.hpp>
+
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+#include <ggl/core/concepts/point_concept.hpp>
+
+
+namespace ggl
+{
+
+/*!
+ \brief A linear_ring (linear linear_ring) is a closed line which should not be selfintersecting
+ \ingroup Geometry
+ \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,
+ 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,
+ template<typename> class A
+>
+struct tag< linear_ring<P, V, A> >
+{
+ typedef ring_tag type;
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_LINEAR_RING_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/linestring.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,69 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRIES_LINESTRING_HPP
+#define GGL_GEOMETRIES_LINESTRING_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/assert.hpp>
+#include <boost/range/functions.hpp>
+
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+#include <ggl/core/concepts/point_concept.hpp>
+
+
+namespace ggl
+{
+
+/*!
+ \brief A linestring (named so by OGC) is a collection (default a vector) of points.
+ \ingroup Geometry
+ \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 ggl
+
+#endif // GGL_GEOMETRIES_LINESTRING_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/nsphere.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/nsphere.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,130 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRIES_NSPHERE_HPP
+#define GGL_GEOMETRIES_NSPHERE_HPP
+
+#include <cstddef>
+
+#include <ggl/algorithms/assign.hpp>
+#include <ggl/core/concepts/nsphere_concept.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/util/copy.hpp>
+
+namespace ggl
+{
+
+/*!
+ \brief Class nsphere: defines a circle or a sphere: a point with radius
+ \ingroup Geometry
+ \details The name nsphere is quite funny but the best description of the class. It can be a circle (2D),
+ a sphere (3D), or higher (hypersphere) or lower. According to Wikipedia this name is the most appropriate.
+ It was mentioned on the Boost list.
+ An alternative is the more fancy name "sphercle" but that might be a bit too much an invention.
+ \note Circle is currently used for selections, for example polygon_in_circle. Currently not all
+ algorithms are implemented for n-spheres.
+ \tparam P point type of the center
+ \tparam T number type of the radius
+ */
+template <typename P, typename T>
+class nsphere
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<P>) );
+
+public:
+
+ typedef T radius_type;
+ typedef typename coordinate_type<P>::type coordinate_type;
+
+ nsphere()
+ : m_radius(0)
+ {
+ detail::assign::assign_value(m_center, coordinate_type());
+ }
+
+ nsphere(P const& center, T const& radius)
+ : m_radius(radius)
+ {
+ copy_coordinates(center, m_center);
+ }
+
+ inline P const& center() const { return m_center; }
+ inline T const& radius() const { return m_radius; }
+
+ inline void radius(T const& r) { m_radius = r; }
+ inline P& center() { return m_center; }
+
+private:
+
+ P m_center;
+ T m_radius;
+};
+
+// Traits specializations for n-sphere above
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename P, typename T>
+struct tag< nsphere<P, T> >
+{
+ typedef nsphere_tag type;
+};
+
+template <typename P, typename T>
+struct point_type<nsphere<P, T> >
+{
+ typedef P type;
+};
+
+template <typename P, typename T>
+struct radius_type<nsphere<P, T> >
+{
+ typedef T type;
+};
+
+template <typename P, typename T>
+struct access<nsphere<P, T> >
+{
+ typedef nsphere<P, T> nsphere_type;
+
+ template <std::size_t D>
+ static inline typename ggl::coordinate_type<nsphere_type>::type get(nsphere_type const& s)
+ {
+ return ggl::get<D>(s.center());
+ }
+
+ template <std::size_t D>
+ static inline void set(nsphere_type& s, typename ggl::coordinate_type<nsphere_type>::type const& value)
+ {
+ ggl::set<D>(s.center(), value);
+ }
+};
+
+template <typename P, typename T>
+struct radius_access<nsphere<P, T>, T, 0>
+{
+ typedef nsphere<P, T> nsphere_type;
+
+ static inline T get(nsphere_type const& s)
+ {
+ return s.radius();
+ }
+
+ static inline void set(nsphere_type& s, T const& value)
+ {
+ s.radius(value);
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_NSPHERE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/point.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/point.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,125 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRIES_POINT_HPP
+#define GGL_GEOMETRIES_POINT_HPP
+
+#include <cstddef>
+
+#include <boost/mpl/int.hpp>
+#include <boost/static_assert.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/coordinate_type.hpp>
+#include <ggl/core/coordinate_system.hpp>
+#include <ggl/core/coordinate_dimension.hpp>
+#include <ggl/util/math.hpp>
+
+namespace ggl
+{
+
+/*!
+ \brief Basic point class, having coordinates defined in a neutral way
+ \ingroup Geometry
+ \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 T, std::size_t D, typename C>
+struct tag<point<T, D, C> >
+{
+ typedef point_tag type;
+};
+
+template<typename T, std::size_t D, typename C>
+struct coordinate_type<point<T, D, C> >
+{
+ typedef T type;
+};
+
+template<typename T, std::size_t D, typename C>
+struct coordinate_system<point<T, D, C> >
+{
+ typedef C type;
+};
+
+template<typename T, std::size_t D, typename C>
+struct dimension<point<T, D, C> > : boost::mpl::int_<D> {};
+
+template<typename T, std::size_t D, typename C>
+struct access<point<T, D, C> >
+{
+ template <std::size_t I>
+ static inline T get(point<T, D, C> const& p)
+ {
+ return p.template get<I>();
+ }
+
+ template <std::size_t I>
+ static inline void set(point<T, D, C>& p, T const& value)
+ {
+ p.template set<I>(value);
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_POINT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/point_xy.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/point_xy.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,109 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRIES_POINT_XY_HPP
+#define GGL_GEOMETRIES_POINT_XY_HPP
+
+#include <cstddef>
+
+#include <boost/mpl/int.hpp>
+
+#include <ggl/core/cs.hpp>
+#include <ggl/geometries/point.hpp>
+
+namespace ggl
+{
+
+/*!
+ \brief 2D point in Cartesian coordinate system
+ \ingroup Geometry
+ \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); }
+
+ /// Compare two points
+ inline bool operator<(point_xy const& other) const
+ {
+ return math::equals(x(), other.x()) ? y() < other.y() : x() < other.x();
+ }
+
+};
+
+// Adapt the point_xy to the concept
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename T, typename C>
+struct tag<point_xy<T, C> >
+{
+ typedef point_tag type;
+};
+
+template<typename T, typename C>
+struct coordinate_type<point_xy<T, C> >
+{
+ typedef T type;
+};
+
+template<typename T, typename C>
+struct coordinate_system<point_xy<T, C> >
+{
+ typedef C type;
+};
+
+template<typename T, typename C>
+struct dimension<point_xy<T, C> > : boost::mpl::int_<2> {};
+
+template<typename T, typename C>
+struct access<point_xy<T, C> >
+{
+ template <std::size_t I>
+ static inline T get(point_xy<T, C> const& p)
+ {
+ return p.template get<I>();
+ }
+
+ template <std::size_t I>
+ static inline void set(point_xy<T, C>& p, T const& value)
+ {
+ p.template set<I>(value);
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_POINT_XY_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/polygon.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/polygon.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,179 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRIES_POLYGON_HPP
+#define GGL_GEOMETRIES_POLYGON_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/assert.hpp>
+
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+#include <ggl/core/point_type.hpp>
+#include <ggl/core/ring_type.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/geometries/linear_ring.hpp>
+
+namespace ggl
+{
+
+/*!
+ \brief The \b polygon contains an outer ring and zero or more inner rings.
+ \ingroup Geometry
+ \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 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,
+ 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, 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,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct tag<polygon<Point, PointList, RingList, PointAlloc, RingAlloc> >
+{
+ typedef polygon_tag type;
+};
+
+template
+<
+ typename Point,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct ring_type<polygon<Point, PointList, RingList, PointAlloc, RingAlloc> >
+{
+ typedef typename polygon
+ <
+ Point, PointList, RingList, PointAlloc, RingAlloc
+ >::ring_type type;
+};
+
+template
+<
+ typename Point,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct interior_type< polygon<Point, PointList, RingList, PointAlloc, RingAlloc> >
+{
+ typedef typename polygon
+ <
+ Point, PointList, RingList, PointAlloc, RingAlloc
+ >::inner_container_type type;
+};
+
+template
+<
+ typename Point,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct exterior_ring< polygon<Point, PointList, RingList, PointAlloc, RingAlloc> >
+{
+ typedef polygon<Point, PointList, RingList, 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,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct interior_rings< polygon<Point, PointList, RingList, PointAlloc, RingAlloc> >
+{
+ typedef polygon<Point, PointList, RingList, 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 ggl
+
+#endif // GGL_GEOMETRIES_POLYGON_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/register/box.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/register/box.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,106 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRIES_REGISTER_BOX_HPP
+#define GGL_GEOMETRIES_REGISTER_BOX_HPP
+
+
+#ifndef DOXYGEN_NO_SPECIALIZATIONS
+
+// box based on point
+#define GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS(Box, Point, MinCorner, MaxCorner) \
+template <size_t C, size_t D> \
+struct indexed_access<Box, C, D> \
+{ \
+ static inline typename coordinate_type<Point>::type get(const Box& b) \
+ { \
+ return C == min_corner ? ggl::get<D>(b. MinCorner) : ggl::get<D>(b. MaxCorner); \
+ } \
+ static inline void set(Box& b, const typename coordinate_type<Point>::type& value) \
+ { \
+ if (C == min_corner) ggl::set<D>(b. MinCorner, value); else ggl::set<D>(b. MaxCorner, value); \
+ } \
+};
+
+
+#define GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_TEMPLATIZED(Box, MinCorner, MaxCorner) \
+template <typename P, size_t C, size_t D> \
+struct indexed_access<Box<P>, C, D> \
+{ \
+ static inline typename coordinate_type<P>::type get(const Box<P>& b) \
+ { \
+ return C == min_corner ? ggl::get<D>(b. MinCorner) : ggl::get<D>(b. MaxCorner); \
+ } \
+ static inline void set(Box<P>& b, const typename coordinate_type<P>::type& value) \
+ { \
+ if (C == min_corner) ggl::set<D>(b. MinCorner, value); else ggl::set<D>(b. MaxCorner, value); \
+ } \
+};
+
+
+#define GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_4VALUES(Box, Point, Left, Bottom, Right, Top) \
+template <size_t C, size_t D> \
+struct indexed_access<Box, C, D> \
+{ \
+ static inline typename coordinate_type<Point>::type get(const Box& b) \
+ { \
+ return C == min_corner && D == 0 ? b. Left \
+ : C == min_corner && D == 1 ? b. Bottom \
+ : C == max_corner && D == 0 ? b. Right \
+ : C == max_corner && D == 1 ? b. Top \
+ : 0; \
+ } \
+ static inline void set(Box& b, const typename coordinate_type<Point>::type& value) \
+ { \
+ if (C == min_corner && D == 0) b. Left = value; \
+ else if (C == min_corner && D == 1) b. Bottom = value; \
+ else if (C == max_corner && D == 0) b. Right = value; \
+ else if (C == max_corner && D == 1) b. Top = value; \
+ } \
+};
+
+
+
+#define GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS(Box, PointType) \
+ template<> struct tag<Box > { typedef box_tag type; }; \
+ template<> struct point_type<Box > { typedef PointType type; };
+
+#define 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 GEOMETRY_REGISTER_BOX(Box, PointType, MinCorner, MaxCorner) \
+namespace ggl { namespace traits { \
+ GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS(Box, PointType) \
+ GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS(Box, PointType, MinCorner, MaxCorner) \
+}}
+
+
+#define GEOMETRY_REGISTER_BOX_TEMPLATIZED(Box, MinCorner, MaxCorner) \
+namespace ggl { namespace traits { \
+ GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS_TEMPLATIZED(Box) \
+ GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_TEMPLATIZED(Box, MinCorner, MaxCorner) \
+}}
+
+#define GEOMETRY_REGISTER_BOX_2D_4VALUES(Box, PointType, Left, Bottom, Right, Top) \
+namespace ggl { namespace traits { \
+ GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS(Box, PointType) \
+ GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_4VALUES(Box, PointType, Left, Bottom, Right, Top) \
+}}
+
+
+
+// CONST versions are for boxes probably not that common. Leave this for the moment.
+
+
+#endif // GGL_GEOMETRIES_REGISTER_BOX_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/register/linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/register/linestring.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,25 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRIES_REGISTER_LINESTRING_HPP
+#define GGL_GEOMETRIES_REGISTER_LINESTRING_HPP
+
+
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+
+#define GEOMETRY_REGISTER_LINESTRING(Linestring) \
+namespace ggl { namespace traits { \
+ template<> struct tag<Linestring> { typedef linestring_tag type; }; \
+}}
+
+
+
+#endif // GGL_GEOMETRIES_REGISTER_LINESTRING_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/register/point.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/register/point.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,154 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRIES_REGISTER_POINT_HPP
+#define GGL_GEOMETRIES_REGISTER_POINT_HPP
+
+
+
+// This file implements a "macro party", nevertheless very useful 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 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<int I> struct Point##accessor {};
+
+
+// Non Const version
+#define GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, CoordinateType) \
+ template<> struct access<Point> { \
+ template <int I> \
+ static inline CoordinateType get(const Point& p) { return Point##accessor<I>::get(p); } \
+ template <int I> \
+ static inline void set(Point& p, const CoordinateType& value) { Point##accessor<I>::set(p, value); } \
+ };
+
+// Const version
+#define GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, CoordinateType) \
+ template<> struct access<Point> { \
+ template <int I> \
+ static inline CoordinateType get(const Point& p) { return Point##accessor<I>::get(p); } \
+ };
+
+
+
+
+// Specialize the point-specific-accessor class, declared below, per dimension
+#define GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR(Point, Dim, CoordinateType, Get, Set) \
+ template<> struct Point##accessor< Dim > \
+ { \
+ static inline CoordinateType get(const Point& p) { return p. Get; } \
+ static inline void set(Point& p, const CoordinateType& value) { p. Set = value; } \
+ };
+
+
+// Const version
+#define GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_CONST(Point, Dim, CoordinateType, Get) \
+ template<> struct Point##accessor< Dim > \
+ { \
+ static inline CoordinateType get(const Point& p) { return p. Get; } \
+ };
+
+
+// Get/set version
+#define GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_GET_SET(Point, Dim, CoordinateType, Get, Set) \
+ template<> struct Point##accessor< Dim > \
+ { \
+ static inline CoordinateType get(const Point& p) { return p. Get (); } \
+ static inline void set(Point& p, const CoordinateType& value) { p. Set ( value ); } \
+ };
+
+
+
+#define GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_2D(Point, CoordinateType, Get0, Get1, Set0, Set1) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR(Point, 0, CoordinateType, Get0, Set0) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR(Point, 1, CoordinateType, Get1, Set1)
+
+#define GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_3D(Point, CoordinateType, Get0, Get1, Get2, Set0, Set1, Set2) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR(Point, 0, CoordinateType, Get0, Set0) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR(Point, 1, CoordinateType, Get1, Set1) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR(Point, 2, CoordinateType, Get2, Set2)
+
+// Const versions
+#define GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST_2D(Point, CoordinateType, Get0, Get1) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_CONST(Point, 0, CoordinateType, Get0) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_CONST(Point, 1, CoordinateType, Get1)
+
+#define GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST_3D(Point, CoordinateType, Get0, Get1, Get2) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_CONST(Point, 0, CoordinateType, Get0) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_CONST(Point, 1, CoordinateType, Get1) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_CONST(Point, 2, CoordinateType, Get2)
+
+#endif // DOXYGEN_NO_SPECIALIZATIONS
+
+
+
+// Library user macro to register a custom 2D point
+#define GEOMETRY_REGISTER_POINT_2D(Point, CoordinateType, CoordinateSystem, Field0, Field1) \
+namespace ggl { namespace traits { \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 2, CoordinateType, CoordinateSystem) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, CoordinateType) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_2D(Point, CoordinateType, Field0, Field1, Field0, Field1) \
+}}
+
+// Library user macro to register a custom 3D point
+#define GEOMETRY_REGISTER_POINT_3D(Point, CoordinateType, CoordinateSystem, Field0, Field1, Field2) \
+namespace ggl { namespace traits { \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 3, CoordinateType, CoordinateSystem) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, CoordinateType) \
+ 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 GEOMETRY_REGISTER_POINT_2D_CONST(Point, CoordinateType, CoordinateSystem, Field0, Field1) \
+namespace ggl { namespace traits { \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 2, CoordinateType, CoordinateSystem) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, CoordinateType) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST_2D(Point, CoordinateType, Field0, Field1) \
+}}
+
+// Library user macro to register a custom 3D point (CONST version)
+#define GEOMETRY_REGISTER_POINT_3D_CONST(Point, CoordinateType, CoordinateSystem, Field0, Field1, Field2) \
+namespace ggl { namespace traits { \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 3, CoordinateType, CoordinateSystem) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, CoordinateType) \
+ 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 GEOMETRY_REGISTER_POINT_2D_GET_SET(Point, CoordinateType, CoordinateSystem, Get0, Get1, Set0, Set1) \
+namespace ggl { namespace traits { \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 2, CoordinateType, CoordinateSystem) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, CoordinateType) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_GET_SET(Point, 0, CoordinateType, Get0, Set0) \
+ 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 GEOMETRY_REGISTER_POINT_3D_GET_SET(Point, CoordinateType, CoordinateSystem, Get0, Get1, Get2, Set0, Set1, Set2) \
+namespace ggl { namespace traits { \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 3, CoordinateType, CoordinateSystem) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, CoordinateType) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_GET_SET(Point, 0, CoordinateType, Get0, Set0) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_GET_SET(Point, 1, CoordinateType, Get1, Set1) \
+ GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_GET_SET(Point, 2, CoordinateType, Get2, Set2) \
+}}
+
+
+#endif // GGL_GEOMETRIES_REGISTER_POINT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/register/register_box.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/register/register_box.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,22 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRIES_REGISTER_REGISTER_BOX_HPP
+#define GGL_GEOMETRIES_REGISTER_REGISTER_BOX_HPP
+
+#include <ggl/geometries/register/box.hpp>
+
+#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
+# pragma message ("Warning: This header is deprecated. Please use: ggl/geometries/register/box.hpp")
+#elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
+# warning "This header is deprecated. Please use: ggl/geometries/register/box.hpp")
+#endif
+
+
+#endif // GGL_GEOMETRIES_REGISTER_REGISTER_BOX_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/register/register_point.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/register/register_point.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,22 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRIES_REGISTER_REGISTER_POINT_HPP
+#define GGL_GEOMETRIES_REGISTER_REGISTER_POINT_HPP
+
+#include <ggl/geometries/register/point.hpp>
+
+#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__DMC__)
+# pragma message ("Warning: This header is deprecated. Please use: ggl/geometries/register/point.hpp")
+#elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
+# warning "This header is deprecated. Please use: ggl/geometries/register/point.hpp")
+#endif
+
+
+#endif // GGL_GEOMETRIES_REGISTER_REGISTER_POINT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/register/ring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/register/ring.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,28 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRIES_REGISTER_RING_HPP
+#define GGL_GEOMETRIES_REGISTER_RING_HPP
+
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+#define GEOMETRY_REGISTER_RING(Ring) \
+namespace ggl { namespace traits { \
+ template<> struct tag<Ring> { typedef ring_tag type; }; \
+}}
+
+
+#define GEOMETRY_REGISTER_RING_TEMPLATIZED(Ring) \
+namespace ggl { namespace traits { \
+ template<typename P> struct tag< Ring<P> > { typedef ring_tag type; }; \
+}}
+
+
+#endif // GGL_GEOMETRIES_REGISTER_RING_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/geometries/segment.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/geometries/segment.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,105 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRIES_SEGMENT_HPP
+#define GGL_GEOMETRIES_SEGMENT_HPP
+
+#include <cstddef>
+
+#include <boost/concept/assert.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_const.hpp>
+
+#include <ggl/core/concepts/point_concept.hpp>
+
+namespace ggl
+{
+
+/*!
+\brief Class segment: small containing two (templatized) point references
+\ingroup Geometry
+\details From Wikipedia: In geometry, a line segment is a part of a line that is bounded
+ by two distinct end points, and contains every point on the line between its end points.
+\note The structure is like std::pair, and can often be used interchangeable.
+So points are public available. We cannot derive from std::pair<P&, P&> because of
+reference assignments. Points are not const and might be changed by the algorithm
+(used in intersection_linestring).
+\tparam P point type of the segment
+*/
+template<typename P>
+struct segment
+{
+private:
+
+ BOOST_CONCEPT_ASSERT( (typename boost::mpl::if_
+ <
+ boost::is_const<P>,
+ concept::ConstPoint<P>,
+ concept::Point<P>
+ >
+ ) );
+
+public:
+
+ typedef P point_type;
+
+ P& first;
+ P& second;
+
+ inline segment(P& p1, P& p2)
+ : first(p1), second(p2)
+ {}
+};
+
+// Traits specializations for segment above
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename P>
+struct tag< segment<P> >
+{
+ typedef segment_tag type;
+};
+
+template <typename P>
+struct point_type<segment<P> >
+{
+ typedef P type;
+};
+
+template <typename P, std::size_t I, std::size_t D>
+struct indexed_access<segment<P>, I, D>
+{
+ typedef segment<P> segment_type;
+ typedef typename ggl::coordinate_type<segment_type>::type coordinate_type;
+
+ static inline coordinate_type get(segment_type const& s)
+ {
+ return (I == 0 ? ggl::get<D>(s.first) : ggl::get<D>(s.second));
+ }
+
+ static inline void set(segment_type& s, coordinate_type const& value)
+ {
+ if (I == 0)
+ {
+ ggl::set<D>(s.first, value);
+ }
+ else
+ {
+ ggl::set<D>(s.second, value);
+ }
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_SEGMENT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/ggl.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/ggl.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,72 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GGL_HPP
+#define GGL_GGL_HPP
+
+// Shortcut to include all header files
+
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/core/concepts/ring_concept.hpp>
+#include <ggl/core/concepts/linestring_concept.hpp>
+#include <ggl/core/concepts/polygon_concept.hpp>
+
+#include <ggl/core/concepts/box_concept.hpp>
+#include <ggl/core/concepts/nsphere_concept.hpp>
+#include <ggl/core/concepts/segment_concept.hpp>
+
+#include <ggl/core/cs.hpp>
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/radian_access.hpp>
+#include <ggl/core/topological_dimension.hpp>
+
+#include <ggl/core/replace_point_type.hpp>
+
+#include <ggl/arithmetic/arithmetic.hpp>
+#include <ggl/arithmetic/dot_product.hpp>
+
+#include <ggl/strategies/strategies.hpp>
+
+#include <ggl/algorithms/append.hpp>
+#include <ggl/algorithms/area.hpp>
+#include <ggl/algorithms/assign.hpp>
+#include <ggl/algorithms/buffer.hpp>
+#include <ggl/algorithms/centroid.hpp>
+#include <ggl/algorithms/clear.hpp>
+#include <ggl/algorithms/convert.hpp>
+#include <ggl/algorithms/convex_hull.hpp>
+#include <ggl/algorithms/correct.hpp>
+#include <ggl/algorithms/distance.hpp>
+#include <ggl/algorithms/envelope.hpp>
+#include <ggl/algorithms/for_each.hpp>
+#include <ggl/algorithms/intermediate.hpp>
+#include <ggl/algorithms/intersection.hpp>
+#include <ggl/algorithms/intersects.hpp>
+#include <ggl/algorithms/length.hpp>
+#include <ggl/algorithms/make.hpp>
+#include <ggl/algorithms/num_points.hpp>
+#include <ggl/algorithms/perimeter.hpp>
+#include <ggl/algorithms/sectionalize.hpp>
+#include <ggl/algorithms/selected.hpp>
+#include <ggl/algorithms/simplify.hpp>
+#include <ggl/algorithms/transform.hpp>
+#include <ggl/algorithms/within.hpp>
+
+
+#include <ggl/util/copy.hpp>
+#include <ggl/util/for_each_coordinate.hpp>
+#include <ggl/util/loop.hpp>
+#include <ggl/util/math.hpp>
+#include <ggl/util/select_most_precise.hpp>
+#include <ggl/util/select_coordinate_type.hpp>
+#include <ggl/util/write_dsv.hpp>
+
+#endif // GGL_GGL_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/iterators/base.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/iterators/base.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,55 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ITERATORS_BASE_HPP
+#define GGL_ITERATORS_BASE_HPP
+
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+
+namespace ggl { 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 ggl::detail::iterators
+
+#endif // GGL_ITERATORS_BASE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/iterators/ever_circling_iterator.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/iterators/ever_circling_iterator.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,86 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
+#define GGL_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
+
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+
+#include <ggl/iterators/base.hpp>
+
+namespace ggl
+{
+
+/*!
+ \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)
+ : m_begin(begin)
+ , m_end(end)
+ {
+ this->base_reference() = begin;
+ }
+
+ explicit inline ever_circling_iterator(Iterator begin, Iterator end, Iterator start)
+ : m_begin(begin)
+ , m_end(end)
+ {
+ 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()
+ {
+ (this->base_reference())++;
+ check_end();
+ }
+
+ inline void check_end()
+ {
+ if (this->base() == this->m_end)
+ {
+ this->base_reference() = this->m_begin;
+ }
+ }
+
+ Iterator m_begin;
+ Iterator m_end;
+};
+
+
+} // namespace ggl
+
+#endif // GGL_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/iterators/point_const_iterator.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/iterators/point_const_iterator.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,76 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ITERATORS_POINT_CONST_ITERATOR_HPP
+#define GGL_ITERATORS_POINT_CONST_ITERATOR_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+
+
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+
+#include <boost/range/metafunctions.hpp>
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, typename Geometry>
+struct point_const_iterator
+{
+ // The default: meta-forward this to boost
+ // This enables calling this function using std::vector as well, even if they
+ // are not registered.
+ // It also requires less specializations
+ typedef typename boost::range_const_iterator<Geometry>::type type;
+};
+
+
+template <typename Polygon>
+struct point_const_iterator<polygon_tag, Polygon>
+{
+ typedef typename boost::range_const_iterator
+ <
+ typename ring_type<Polygon>::type
+ >::type type;
+};
+
+
+
+
+} // namespace dispatch
+#endif
+
+
+/*!
+ \brief Meta-function which defines point-const-iterator type
+ \ingroup iterators
+*/
+template <typename Geometry>
+struct point_const_iterator
+{
+ typedef typename boost::remove_const<Geometry>::type ncg;
+ typedef typename dispatch::point_const_iterator<
+ typename tag<Geometry>::type, ncg>::type type;
+};
+
+
+
+
+}
+
+
+#endif // GGL_ITERATORS_POINT_CONST_ITERATOR_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/iterators/segment_iterator.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/iterators/segment_iterator.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,139 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_ITERATORS_SEGMENT_ITERATOR_HPP
+#define GGL_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 <ggl/algorithms/equals.hpp>
+#include <ggl/geometries/segment.hpp>
+
+namespace ggl
+{
+
+template <typename Base, typename Point>
+struct segment_iterator
+{
+ typedef Base base_type;
+ typedef Point point_type;
+ typedef typename ggl::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)
+ {
+ BOOST_ASSERT(ggl::equals(point_type(), m_segment.first));
+ BOOST_ASSERT(ggl::equals(point_type(), m_segment.second));
+ }
+
+ 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 ggl
+
+#endif // GGL_ITERATORS_SEGMENT_ITERATOR_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/area.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/area.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,37 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_ALGORITHMS_AREA_HPP
+#define GGL_MULTI_ALGORITHMS_AREA_HPP
+
+#include <ggl/algorithms/area.hpp>
+#include <ggl/multi/core/point_type.hpp>
+#include <ggl/multi/algorithms/detail/multi_sum.hpp>
+
+namespace ggl {
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+ template <typename MultiGeometry, typename Strategy>
+ struct area<multi_polygon_tag, MultiGeometry, Strategy>
+ : detail::multi_sum<double, MultiGeometry, Strategy,
+ detail::area::polygon_area<
+ typename boost::range_value<MultiGeometry>::type, Strategy> >
+ {};
+
+
+} // namespace dispatch
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_ALGORITHMS_AREA_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/centroid.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/centroid.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,81 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_ALGORITHMS_CENTROID_HPP
+#define GGL_MULTI_ALGORITHMS_CENTROID_HPP
+
+#include <ggl/algorithms/centroid.hpp>
+#include <ggl/multi/core/point_type.hpp>
+#include <ggl/multi/algorithms/detail/multi_sum.hpp>
+
+namespace ggl {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace centroid {
+
+template<typename MultiPolygon, typename Point, typename Strategy>
+struct centroid_multi_polygon
+{
+ static inline void apply(MultiPolygon const& multi, Point& c, Strategy const& strategy)
+ {
+ typedef typename boost::range_const_iterator<MultiPolygon>::type iterator;
+
+ typename Strategy::state_type state;
+
+ for (iterator it = boost::begin(multi); it != boost::end(multi); ++it)
+ {
+// TODO: make THIS the building block!
+ typedef typename boost::range_value<MultiPolygon>::type polygon_type;
+ polygon_type const& poly = *it;
+ if (ring_ok(exterior_ring(poly), c))
+ {
+
+ loop(exterior_ring(poly), strategy, state);
+
+ typedef typename boost::range_const_iterator
+ <
+ typename interior_type<polygon_type>::type
+ >::type iterator_type;
+
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly));
+ ++it)
+ {
+ loop(*it, strategy, state);
+ }
+ }
+ }
+ state.centroid(c);
+ }
+};
+
+
+
+}} // 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_polygon<MultiPolygon, Point, Strategy>
+ {};
+
+
+} // namespace dispatch
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_ALGORITHMS_CENTROID_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/convex_hull.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/convex_hull.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,95 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_ALGORITHMS_CONVEX_HULL_HPP
+#define GGL_MULTI_ALGORITHMS_CONVEX_HULL_HPP
+
+
+#include <ggl/util/as_range.hpp>
+
+#include <ggl/multi/core/tags.hpp>
+#include <ggl/multi/core/is_multi.hpp>
+#include <ggl/multi/core/point_type.hpp>
+
+#include <ggl/algorithms/convex_hull.hpp>
+
+
+namespace ggl {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace convex_hull {
+
+
+template <typename MultiGeometry, typename OutputIterator>
+struct convex_hull_multi
+{
+ static inline OutputIterator apply(MultiGeometry const& multi,
+ OutputIterator out)
+ {
+ using namespace boost;
+
+ typedef typename point_type<MultiGeometry>::type point;
+ typename strategy_convex_hull
+ <
+ typename cs_tag<point>::type,
+ point
+ >::type strategy;
+
+ typedef typename range_const_iterator<MultiGeometry>::type iterator;
+ typedef typename range_value<MultiGeometry>::type single;
+ for(iterator it = begin(multi); it != end(multi); ++it)
+ {
+ strategy.add_range(as_range
+ <typename as_range_type<single>::type>(*it));
+ }
+ strategy.handle_input();
+
+ strategy.get(out);
+ return out;
+ }
+};
+
+
+}} // namespace detail::convex_hull
+
+#endif
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// Specialize for multi's
+template
+<
+ typename MultiTag,
+ typename MultiGeometry,
+ typename OutputIterator
+>
+struct convex_hull<MultiTag, true, MultiGeometry, OutputIterator>
+ : detail::convex_hull::convex_hull_multi<MultiGeometry, OutputIterator>
+{};
+
+
+// Specialize more for point
+template <typename MultiPoint, typename OutputIterator>
+struct convex_hull<multi_point_tag, true, MultiPoint, OutputIterator>
+ : detail::convex_hull::hull<MultiPoint, OutputIterator>
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_ALGORITHMS_CONVEX_HULL_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/correct.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/correct.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,53 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_CORRECT_HPP
+#define GGL_MULTI_CORRECT_HPP
+
+#include <vector>
+
+#include <ggl/algorithms/correct.hpp>
+
+
+//FIX ME it is not yet adapted to tag-dispatching
+
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+ namespace correct
+ {
+ // correct a multi-polygon
+ template <typename O>
+ inline void correct_multi_polygon(O& o)
+ {
+ for (typename O::iterator it = o.begin(); it != o.end(); it++)
+ {
+ correct_polygon(*it);
+ }
+ }
+ }
+}
+#endif
+
+template<typename Y,
+ template<typename,typename> class V, template<typename> class A>
+void correct(multi_polygon<Y, V, A>& mp)
+{
+ detail::correct::correct_multi_polygon(mp);
+}
+
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_CORRECT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/detail/modify_with_predicate.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/detail/modify_with_predicate.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,46 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_ALGORITHMS_DETAIL_MODIFY_WITH_PREDICATE_HPP
+#define GGL_MULTI_ALGORITHMS_DETAIL_MODIFY_WITH_PREDICATE_HPP
+
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+namespace ggl {
+
+
+#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 ggl
+
+
+#endif // GGL_MULTI_ALGORITHMS_DETAIL_MODIFY_WITH_PREDICATE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/detail/multi_sum.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/detail/multi_sum.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,54 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_SUM_HPP
+#define GGL_MULTI_SUM_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+namespace ggl
+{
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template
+<
+ typename T,
+ typename MultiGeometry,
+ typename Strategy,
+ typename Policy
+>
+struct multi_sum
+{
+ static inline T apply(MultiGeometry const& geometry, Strategy const& strategy)
+ {
+ typedef typename boost::range_const_iterator
+ <
+ MultiGeometry
+ >::type iterator_type;
+ T sum = T();
+ for (iterator_type it = boost::begin(geometry);
+ it != boost::end(geometry);
+ ++it)
+ {
+ sum += Policy::apply(*it, strategy);
+ }
+ return sum;
+ }
+};
+
+
+} // namespace detail
+#endif
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_SUM_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/distance.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/distance.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,121 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_ALGORITHMS_DISTANCE_HPP
+#define GGL_MULTI_ALGORITHMS_DISTANCE_HPP
+
+
+#include <boost/numeric/conversion/bounds.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/multi/core/tags.hpp>
+#include <ggl/multi/core/is_multi.hpp>
+#include <ggl/multi/core/geometry_id.hpp>
+#include <ggl/multi/core/point_type.hpp>
+
+#include <ggl/algorithms/distance.hpp>
+
+
+namespace ggl {
+
+#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());
+ typedef typename range_const_iterator<MultiGeometry>::type iterator;
+ for(iterator it = begin(multi); it != end(multi); ++it)
+ {
+ return_type dist = ggl::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 ggl
+
+
+#endif // GGL_MULTI_ALGORITHMS_DISTANCE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/envelope.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/envelope.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,98 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_ENVELOPE_HPP
+#define GGL_MULTI_ENVELOPE_HPP
+
+#include <vector>
+
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/algorithms/envelope.hpp>
+
+#include <ggl/multi/core/point_type.hpp>
+
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+
+namespace detail { namespace envelope {
+
+
+template<typename MultiLinestring, typename Box, typename Strategy>
+struct envelope_multi_linestring
+{
+ static inline void apply(MultiLinestring const& mp, Box& mbr, Strategy const& strategy)
+ {
+ typename Strategy::state_type state(mbr);
+ for (typename boost::range_const_iterator<MultiLinestring>::type
+ it = mp.begin();
+ it != mp.end();
+ ++it)
+ {
+ envelope_range_state(*it, strategy, state);
+ }
+ }
+};
+
+
+// version for multi_polygon: outer linear_ring's of all polygons
+template<typename MultiPolygon, typename Box, typename Strategy>
+struct envelope_multi_polygon
+{
+ static inline void apply(MultiPolygon const& mp, Box& mbr, Strategy const& strategy)
+ {
+ typename Strategy::state_type state(mbr);
+ for (typename boost::range_const_iterator<MultiPolygon>::type
+ it = mp.begin();
+ it != mp.end();
+ ++it)
+ {
+ envelope_range_state(exterior_ring(*it), strategy, state);
+ }
+ }
+};
+
+
+}} // namespace detail::envelope
+
+#endif
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename M, typename B, typename S>
+struct envelope<multi_point_tag, box_tag, M, B, S>
+ : detail::envelope::envelope_range<M, B, S>
+{};
+
+template <typename M, typename B, typename S>
+struct envelope<multi_linestring_tag, box_tag, M, B, S>
+ : detail::envelope::envelope_multi_linestring<M, B, S>
+{};
+
+
+template <typename M, typename B, typename S>
+struct envelope<multi_polygon_tag, box_tag, M, B, S>
+ : detail::envelope::envelope_multi_polygon<M, B, S>
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_ENVELOPE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/foreach.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/foreach.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,222 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_FOREACH_HPP
+#define GGL_MULTI_FOREACH_HPP
+
+#include <vector>
+
+#include <ggl/algorithms/for_each.hpp>
+
+FIX ME it is not yet adapted to tag-dispatching
+
+
+namespace ggl
+{
+
+template<typename MP, typename F>
+inline F for_each_point_multi_point(MP& mp, F f)
+{
+ return (for_each_point_container(mp, f));
+}
+
+template<typename ML, typename F>
+inline F for_each_point_multi_linestring(ML& ml, F f)
+{
+ for (typename ML::iterator it = ml.begin(); it != ml.end(); it++)
+ {
+ f = for_each_point_linestring(*it, f);
+ }
+ return (f);
+}
+
+template<typename MY, typename F>
+inline F for_each_point_multi_polygon(MY& mp, F f)
+{
+ for (typename MY::iterator it = mp.begin(); it != mp.end(); it++)
+ {
+ f = for_each_point_polygon(*it, f);
+ }
+ return (f);
+}
+
+
+
+
+template<typename MP, typename F>
+inline F for_each_point_multi_point(const MP& mp, F f)
+{
+ return (for_each_point_container(mp, f));
+}
+
+
+template<typename ML, typename F>
+inline F for_each_point_multi_linestring(const ML& ml, F f)
+{
+ for (typename ML::const_iterator it = ml.begin(); it != ml.end(); it++)
+ {
+ f = for_each_point_linestring(*it, f);
+ }
+ return (f);
+}
+
+template<typename MY, typename F>
+inline F for_each_point_multi_polygon(const MY& mp, F f)
+{
+ for (typename MY::const_iterator it = mp.begin(); it != mp.end(); it++)
+ {
+ f = for_each_point_polygon(*it, f);
+ }
+ return (f);
+}
+
+
+
+template<typename ML, typename F>
+inline F for_each_segment_multi_linestring(ML& ml, F f)
+{
+ for (typename ML::iterator it = ml.begin(); it != ml.end(); it++)
+ {
+ f = for_each_segment_linestring(*it, f);
+ }
+ return (f);
+}
+
+template<typename MY, typename F>
+inline F for_each_segment_multi_polygon(MY& mp, F f)
+{
+ for (typename MY::iterator it = mp.begin(); it != mp.end(); it++)
+ {
+ f = for_each_segment_polygon(*it, f);
+ }
+ return (f);
+}
+
+
+
+
+
+
+template<typename ML, typename F>
+inline F for_each_segment_multi_linestring(const ML& ml, F f)
+{
+ for (typename ML::const_iterator it = ml.begin(); it != ml.end(); it++)
+ {
+ f = for_each_segment_linestring(*it, f);
+ }
+ return (f);
+}
+
+template<typename MY, typename F>
+inline F for_each_segment_multi_polygon(const MY& mp, F f)
+{
+ for (typename MY::const_iterator it = mp.begin(); it != mp.end(); it++)
+ {
+ f = for_each_segment_polygon(*it, f);
+ }
+ return (f);
+}
+
+
+
+
+
+
+template<typename P,
+ template<typename,typename> class V, template<typename> class A,
+ typename F>
+inline F for_each_point(multi_point<P, V, A>& mp, F f)
+{
+ return (for_each_point_multi_point(mp, f));
+}
+
+template<typename L,
+ template<typename,typename> class V, template<typename> class A,
+ typename F>
+inline F for_each_point(multi_linestring<L, V, A>& ml, F f)
+{
+ return (for_each_point_multi_linestring(ml, f));
+}
+
+template<typename Y,
+ template<typename,typename> class V, template<typename> class A,
+ typename F>
+inline F for_each_point(multi_polygon<Y, V, A>& mp, F f)
+{
+ return (for_each_point_multi_polygon(mp, f));
+}
+
+
+
+
+template<typename P,
+ template<typename,typename> class V, template<typename> class A,
+ typename F>
+inline F for_each_point(const multi_point<P, V, A>& mp, F f)
+{
+ return (for_each_point_multi_point(mp, f));
+}
+
+template<typename L,
+ template<typename,typename> class V, template<typename> class A,
+ typename F>
+inline F for_each_point(const multi_linestring<L, V, A>& ml, F f)
+{
+ return (for_each_point_multi_linestring(ml, f));
+}
+
+
+template<typename Y,
+ template<typename,typename> class V, template<typename> class A,
+ typename F>
+inline F for_each_point(const multi_polygon<Y, V, A>& mp, F f)
+{
+ return (for_each_point_multi_polygon(mp, f));
+}
+
+
+
+
+template<typename L,
+ template<typename,typename> class V, template<typename> class A,
+ typename F>
+inline F for_each_segment(multi_linestring<L, V, A>& ml, F f)
+{
+ return (for_each_segment_multi_linestring(ml, f));
+}
+
+template<typename Y,
+ template<typename,typename> class V, template<typename> class A,
+ typename F>
+inline F for_each_segment(multi_polygon<Y, V, A>& mp, F f)
+{
+ return (for_each_segment_multi_polygon(mp, f));
+}
+
+
+
+
+template<typename L,
+ template<typename,typename> class V, template<typename> class A,
+ typename F>
+inline F for_each_segment(const multi_linestring<L, V, A>& ml, F f)
+{
+ return (for_each_segment_multi_linestring(ml, f));
+}
+
+template<typename Y,
+ template<typename,typename> class V, template<typename> class A,
+ typename F>
+inline F for_each_segment(const multi_polygon<Y, V, A>& mp, F f)
+{
+ return (for_each_segment_multi_polygon(mp, f));
+}
+} // namespace ggl
+
+
+#endif // GGL_MULTI_FOREACH_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/get_section.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/get_section.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,57 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_ALGORITHMS_GET_SECTION_HPP
+#define GGL_MULTI_ALGORITHMS_GET_SECTION_HPP
+
+
+#include <boost/concept/requires.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/multi/core/tags.hpp>
+
+#include <ggl/algorithms/get_section.hpp>
+
+
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename MultiPolygon, typename Section>
+struct get_section<multi_polygon_tag, MultiPolygon, Section>
+{
+ typedef typename ggl::point_const_iterator<MultiPolygon>::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 ggl
+
+#endif // GGL_MULTI_ALGORITHMS_GET_SECTION_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/intersection.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/intersection.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,43 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_ALGORITHMS_INTERSECTION_HPP
+#define GGL_MULTI_ALGORITHMS_INTERSECTION_HPP
+
+#include <vector>
+
+#include <ggl/algorithms/intersection.hpp>
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename MultiPolygon1, typename MultiPolygon2,
+ typename OutputIterator, typename GeometryOut
+>
+struct intersection
+ <
+ multi_polygon_tag, multi_polygon_tag, polygon_tag,
+ MultiPolygon1, MultiPolygon2,
+ OutputIterator, GeometryOut
+ >
+{
+ // todo: implement this
+};
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_ALGORITHMS_INTERSECTION_HPP
+
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/length.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/length.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,32 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_LENGTH_HPP
+#define GGL_MULTI_LENGTH_HPP
+
+#include <ggl/algorithms/length.hpp>
+#include <ggl/multi/algorithms/detail/multi_sum.hpp>
+
+namespace ggl
+{
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+ template <typename MG, typename S>
+ struct length<multi_linestring_tag, MG, S>
+ : detail::multi_sum<double, MG, S,
+ detail::length::range_length<typename boost::range_value<MG>::type, S> > {};
+
+} // namespace dispatch
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_LENGTH_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/num_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/num_points.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,78 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_ALGORITHMS_NUM_POINTS_HPP
+#define GGL_MULTI_ALGORITHMS_NUM_POINTS_HPP
+
+
+#include <ggl/multi/core/tags.hpp>
+#include <ggl/algorithms/num_points.hpp>
+
+
+namespace ggl
+{
+
+#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,
+ ggl::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
+
+
+}
+
+
+#endif // GGL_MULTI_ALGORITHMS_NUM_POINTS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/overlay/copy_segments.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/overlay/copy_segments.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,92 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_ALGORITHMS_OVERLAY_COPY_SEGMENTS_HPP
+#define GGL_MULTI_ALGORITHMS_OVERLAY_COPY_SEGMENTS_HPP
+
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/algorithms/overlay/copy_segments.hpp>
+
+#include <ggl/multi/core/ring_type.hpp>
+#include <ggl/multi/core/tags.hpp>
+
+
+namespace ggl
+{
+
+#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 ggl
+
+#endif // GGL_MULTI_ALGORITHMS_OVERLAY_COPY_SEGMENTS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/overlay/get_intersection_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/overlay/get_intersection_points.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,64 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_ALGORITHMS_GET_INTERSECTION_POINTS_HPP
+#define GGL_MULTI_ALGORITHMS_GET_INTERSECTION_POINTS_HPP
+
+#include <ggl/multi/core/is_multi.hpp>
+
+#include <ggl/multi/algorithms/distance.hpp>
+#include <ggl/multi/algorithms/get_section.hpp>
+#include <ggl/multi/algorithms/sectionalize.hpp>
+
+#include <ggl/multi/iterators/point_const_iterator.hpp>
+
+#include <ggl/algorithms/overlay/get_intersection_points.hpp>
+
+
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename MultiTag1,
+ typename MultiTag2,
+ typename MultiGeometry1,
+ typename MultiGeometry2,
+ typename IntersectionPoints
+>
+struct get_intersection_points
+ <
+ MultiTag1, MultiTag2,
+ true, true,
+ MultiGeometry1, MultiGeometry2,
+ IntersectionPoints
+ >
+ : detail::get_intersection_points::get_ips_generic
+ <
+ MultiGeometry1,
+ MultiGeometry2,
+ IntersectionPoints
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+} // namespace ggl
+
+#endif // GGL_MULTI_ALGORITHMS_GET_INTERSECTION_POINTS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/perimeter.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/perimeter.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,33 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_PERIMETER_HPP
+#define GGL_MULTI_PERIMETER_HPP
+
+#include <ggl/algorithms/perimeter.hpp>
+#include <ggl/multi/algorithms/detail/multi_sum.hpp>
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+ template <typename MG, typename S>
+ struct perimeter<multi_polygon_tag, MG, S>
+ : detail::multi_sum<double, MG, S,
+ detail::perimeter::polygon_perimeter<typename boost::range_value<MG>::type, S> > {};
+
+} // namespace dispatch
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_PERIMETER_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/sectionalize.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/sectionalize.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,86 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_ALGORITHMS_SECTIONALIZE_HPP
+#define GGL_MULTI_ALGORITHMS_SECTIONALIZE_HPP
+
+#include <cstddef>
+#include <vector>
+
+#include <boost/concept/requires.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/algorithms/sectionalize.hpp>
+
+
+
+namespace ggl
+{
+
+
+#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 ggl
+
+#endif // GGL_MULTI_ALGORITHMS_SECTIONALIZE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/simplify.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/simplify.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,69 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_SIMPLIFY_HPP
+#define GGL_MULTI_SIMPLIFY_HPP
+
+#include <vector>
+
+#include <ggl/algorithms/simplify.hpp>
+
+FIX ME it is not yet adapted to tag-dispatching
+
+namespace ggl
+{
+
+
+ template<typename ML>
+ inline void simplify_multi_linestring(const ML& ml_in, ML& ml_out, double max_distance)
+ {
+ ml_out.resize(ml_in.size());
+ typename ML::const_iterator it_in = ml_in.begin();
+ typename ML::iterator it_out = ml_out.begin();
+ for (; it_in != ml_in.end(); it_in++, it_out++)
+ {
+ simplify_linestring(*it_in, *it_out, max_distance);
+ }
+ }
+
+
+ template<typename MY>
+ inline void simplify_multi_polygon(const MY& mp_in, MY& mp_out, double max_distance)
+ {
+ mp_out.resize(mp_in.size());
+ typename MY::const_iterator it_in = mp_in.begin();
+ typename MY::iterator it_out = mp_out.begin();
+ for (; it_in != mp_in.end(); it_in++, it_out++)
+ {
+ simplify(*it_in, *it_out, max_distance);
+ }
+ }
+
+
+
+template<typename L,
+ template<typename,typename> class V, template<typename> class A>
+inline void simplify(const multi_linestring<L, V, A>& ml_in,
+ multi_linestring<L, V, A>& ml_out, double max_distance)
+{
+ simplify_multi_linestring(ml_in, ml_out, max_distance);
+}
+
+template<typename Y,
+ template<typename,typename> class V, template<typename> class A>
+inline void simplify(const multi_polygon<Y, V, A>& mp_in,
+ multi_polygon<Y, V, A>& mp_out, double max_distance)
+{
+ simplify_multi_polygon(mp_in, mp_out, max_distance);
+}
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_SIMPLIFY_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/transform.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/transform.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,87 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_ALGORITHMS_TRANSFORM_HPP
+#define GGL_MULTI_ALGORITHMS_TRANSFORM_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/algorithms/transform.hpp>
+
+#include <ggl/multi/core/tags.hpp>
+
+namespace ggl
+{
+
+#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>
+struct transform<multi_polygon_tag, multi_polygon_tag, Multi1, Multi2>
+ : detail::transform::transform_multi
+ <
+ Multi1,
+ Multi2,
+ detail::transform::transform_polygon
+ <
+ typename boost::range_value<Multi1>::type,
+ typename boost::range_value<Multi2>::type
+ >
+ >
+{};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+} // namespace ggl
+
+#endif // GGL_MULTI_ALGORITHMS_TRANSFORM_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/within.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/algorithms/within.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,104 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_ALGORITHMS_WITHIN_HPP
+#define GGL_MULTI_ALGORITHMS_WITHIN_HPP
+
+#include <vector>
+
+#include <ggl/algorithms/within.hpp>
+#include <ggl/multi/core/tags.hpp>
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace within {
+
+
+template<typename P, typename I, typename S>
+inline bool point_in_multi_polygon(const P& p, const I& m, const S& strategy)
+{
+ for (typename I::const_iterator i = m.begin(); i != m.end(); i++)
+ {
+ // Point within a multi-polygon: true if within one of the polygons
+ if (point_in_polygon(p, *i, strategy))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+template<typename I, typename C>
+inline bool multi_polygon_in_circle(const I& m, const C& c)
+{
+ for (typename I::const_iterator i = m.begin(); i != m.end(); i++)
+ {
+ if (! polygon_in_circle(*i, c))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+}} // namespace detail::within
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+/*
+template <typename M, typename B>
+struct within<multi_polygon_tag, box_tag, M, B>
+{
+ static inline bool apply(const M& m, const B& b)
+ {
+ return detail::within::multi_polygon_in_box(m, b);
+ }
+};
+*/
+
+template <typename M, typename C>
+struct within<multi_polygon_tag, nsphere_tag, M, C>
+{
+ static inline bool apply(const M& m, const C& c)
+ {
+ return detail::within::multi_polygon_in_circle(m, c);
+ }
+};
+
+template <typename P, typename M>
+struct within<point_tag, multi_polygon_tag, P, M>
+{
+ template <typename S>
+ static inline bool apply(const P& p, const M& m, const S& strategy)
+ {
+ return detail::within::point_in_multi_polygon(p, m, strategy);
+ }
+
+ static inline bool apply(const P& p, const M& m)
+ {
+ typedef typename point_type<M>::type PM;
+ typename strategy_within<
+ typename cs_tag<P>::type, typename cs_tag<PM>::type, P, PM
+ >::type strategy;
+ return apply(p, m, strategy);
+ }
+
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+} // namespace ggl
+
+#endif // GGL_MULTI_ALGORITHMS_WITHIN_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/core/geometry_id.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/core/geometry_id.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,51 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_CORE_GEOMETRY_ID_HPP
+#define GGL_MULTI_CORE_GEOMETRY_ID_HPP
+
+
+#include <boost/mpl/int.hpp>
+#include <boost/type_traits.hpp>
+
+
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+#include <ggl/core/geometry_id.hpp>
+#include <ggl/multi/core/tags.hpp>
+
+
+namespace ggl {
+
+
+#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 ggl
+
+
+#endif // GGL_MULTI_CORE_GEOMETRY_ID_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/core/is_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/core/is_multi.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,49 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_CORE_IS_MULTI_HPP
+#define GGL_MULTI_CORE_IS_MULTI_HPP
+
+
+#include <boost/type_traits.hpp>
+
+
+#include <ggl/core/is_multi.hpp>
+#include <ggl/multi/core/tags.hpp>
+
+
+namespace ggl {
+
+
+#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 ggl
+
+
+#endif // GGL_MULTI_CORE_IS_MULTI_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/core/point_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/core/point_type.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,59 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef GGL_MULTI_CORE_POINT_TYPE_HPP
+#define GGL_MULTI_CORE_POINT_TYPE_HPP
+
+
+#include <boost/range/metafunctions.hpp>
+
+
+#include <ggl/core/point_type.hpp>
+#include <ggl/multi/core/tags.hpp>
+
+
+
+namespace ggl {
+
+#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 ggl
+
+#endif // GGL_MULTI_CORE_POINT_TYPE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/core/ring_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/core/ring_type.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,48 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_CORE_RING_TYPE_HPP
+#define GGL_MULTI_CORE_RING_TYPE_HPP
+
+
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/core/ring_type.hpp>
+#include <ggl/multi/core/tags.hpp>
+
+
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename MultiPolygon>
+struct ring_type<multi_polygon_tag, MultiPolygon>
+{
+ typedef typename ggl::ring_type
+ <
+ typename boost::range_value<MultiPolygon>::type
+ >::type type;
+};
+
+
+
+
+} // namespace core_dispatch
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_CORE_RING_TYPE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/core/tags.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/core/tags.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,30 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_CORE_TAGS_HPP
+#define GGL_MULTI_CORE_TAGS_HPP
+
+namespace ggl
+{
+
+/// 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 {};
+
+} // namespace ggl
+
+#endif // GGL_MULTI_CORE_TAGS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/core/topological_dimension.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/core/topological_dimension.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,45 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_TOPOLOGICAL_DIMENSION_HPP
+#define GGL_MULTI_TOPOLOGICAL_DIMENSION_HPP
+
+
+#include <boost/mpl/int.hpp>
+
+
+#include <ggl/core/topological_dimension.hpp>
+#include <ggl/multi/core/tags.hpp>
+
+
+namespace ggl {
+
+#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 ggl
+
+
+#endif
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/geometries/multi_linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/geometries/multi_linestring.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,55 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_LINESTRING_HPP
+#define GGL_MULTI_LINESTRING_HPP
+
+#include <memory>
+#include <vector>
+
+#include <ggl/core/concepts/linestring_concept.hpp>
+#include <ggl/multi/core/tags.hpp>
+
+namespace ggl
+{
+
+// Class: multi_line
+// Purpose: groups lines belonging to each other, e.g. a broken highway
+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 ggl
+
+#endif // GGL_MULTI_LINESTRING_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/geometries/multi_point.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/geometries/multi_point.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,54 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_GEOMETRIES_MULTI_POINT_HPP
+#define GGL_MULTI_GEOMETRIES_MULTI_POINT_HPP
+
+#include <memory>
+#include <vector>
+
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/multi/core/tags.hpp>
+
+namespace ggl
+{
+
+// Class: multi_point
+// Purpose: groups points belonging to each other, e.g. a constellation
+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 ggl
+
+#endif // GGL_MULTI_GEOMETRIES_MULTI_POINT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/geometries/multi_polygon.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/geometries/multi_polygon.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,55 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_GEOMETRIES_MULTI_POLYGON_HPP
+#define GGL_MULTI_GEOMETRIES_MULTI_POLYGON_HPP
+
+#include <memory>
+#include <vector>
+
+#include <ggl/multi/core/tags.hpp>
+#include <ggl/core/concepts/polygon_concept.hpp>
+#include <ggl/multi/core/tags.hpp>
+
+namespace ggl
+{
+
+// Class: multi_polygon
+// Purpose: groups polygons belonging to each other, e.g. Hawaii
+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 ggl
+
+#endif // GGL_MULTI_GEOMETRIES_MULTI_POLYGON_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/multi/iterators/point_const_iterator.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/multi/iterators/point_const_iterator.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,50 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_MULTI_ITERATORS_POINT_CONST_ITERATOR_HPP
+#define GGL_MULTI_ITERATORS_POINT_CONST_ITERATOR_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+
+
+#include <ggl/iterators/point_const_iterator.hpp>
+
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename MultiPolygon>
+struct point_const_iterator<multi_polygon_tag, MultiPolygon>
+{
+ typedef typename boost::range_value<MultiPolygon>::type polygon_type;
+ typedef typename boost::range_const_iterator
+ <
+ typename ring_type<polygon_type>::type
+ >::type type;
+};
+
+
+
+
+} // namespace dispatch
+#endif
+
+
+
+}
+
+
+#endif // GGL_MULTI_ITERATORS_POINT_CONST_ITERATOR_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/policies/relate/de9im.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/policies/relate/de9im.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,184 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRY_POLICIES_RELATE_DE9IM_HPP
+#define GGL_GEOMETRY_POLICIES_RELATE_DE9IM_HPP
+
+
+#include <ggl/strategies/intersection_result.hpp>
+#include <ggl/util/math.hpp>
+#include <ggl/util/select_coordinate_type.hpp>
+
+
+namespace ggl
+{
+
+namespace policies { namespace relate {
+
+
+template <typename S1, typename S2>
+struct segments_de9im
+{
+ typedef de9im_segment return_type;
+ typedef S1 segment_type1;
+ typedef S2 segment_type2;
+ typedef typename select_coordinate_type<S1, S2>::type coordinate_type;
+
+ static inline return_type rays_intersect(bool on_segment,
+ double ra, double rb,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ coordinate_type const& dx2, coordinate_type const& dy2,
+ coordinate_type const& wx, coordinate_type const& wy,
+ S1 const& s1, S2 const& s2)
+ {
+ if(on_segment)
+ {
+ // 0 <= ra <= 1 and 0 <= rb <= 1
+ // Now check if one of them is 0 or 1, these are "touch" cases
+ bool a = math::equals(ra, 0.0) || math::equals(ra, 1.0);
+ bool b = math::equals(rb, 0.0) || math::equals(rb, 1.0);
+ if (a && b)
+ {
+ // Touch boundary/boundary: i-i == -1, i-b == -1, b-b == 0
+ // Opposite: if both are equal they touch in opposite direction
+ return de9im_segment(ra,rb,
+ -1, -1, 1,
+ -1, 0, 0,
+ 1, 0, 2, false, math::equals(ra,rb));
+ }
+ else if (a || b)
+ {
+ // Touch boundary/interior: i-i == -1, i-b == -1 or 0, b-b == -1
+ int A = a ? 0 : -1;
+ int B = b ? 0 : -1;
+ return de9im_segment(ra,rb,
+ -1, B, 1,
+ A, -1, 0,
+ 1, 0, 2);
+ }
+
+ // Intersects: i-i == 0, i-b == -1, i-e == 1
+ return de9im_segment(ra,rb,
+ 0, -1, 1,
+ -1, -1, 0,
+ 1, 0, 2);
+ }
+
+ // Not on segment, disjoint
+ return de9im_segment(ra,rb,
+ -1, -1, 1,
+ -1, -1, 0,
+ 1, 0, 2);
+ }
+
+ static inline return_type collinear_touch(coordinate_type const& x,
+ coordinate_type const& y, bool opposite, char)
+ {
+ return de9im_segment(0,0,
+ -1, -1, 1,
+ -1, 0, 0,
+ 1, 0, 2,
+ true, opposite);
+ }
+
+ template <typename S>
+ static inline return_type collinear_interior_boundary_intersect(S const& s,
+ bool a_within_b, bool opposite)
+ {
+ return a_within_b
+ ? de9im_segment(0,0,
+ 1, -1, -1,
+ 0, 0, -1,
+ 1, 0, 2,
+ true, opposite)
+ : de9im_segment(0,0,
+ 1, 0, 1,
+ -1, 0, 0,
+ -1, -1, 2,
+ true, opposite);
+ }
+
+
+
+ static inline return_type collinear_a_in_b(S1 const& s, bool opposite)
+ {
+ return de9im_segment(0,0,
+ 1, -1, -1,
+ 0, -1, -1,
+ 1, 0, 2,
+ true, opposite);
+ }
+ static inline return_type collinear_b_in_a(const S2& s, bool opposite)
+ {
+ return de9im_segment(0,0,
+ 1, 0, 1,
+ -1, -1, 0,
+ -1, -1, 2,
+ true, opposite);
+ }
+
+ static inline return_type collinear_overlaps(
+ coordinate_type const& x1, coordinate_type const& y1,
+ coordinate_type const& x2, coordinate_type const& y2, bool opposite)
+ {
+ return de9im_segment(0,0,
+ 1, 0, 1,
+ 0, -1, 0,
+ 1, 0, 2,
+ true, opposite);
+ }
+
+ static inline return_type segment_equal(S1 const& s, bool opposite)
+ {
+ return de9im_segment(0,0,
+ 1, -1, -1,
+ -1, 0, -1,
+ -1, -1, 2,
+ true, opposite);
+ }
+
+ static inline return_type degenerate(S1 const& segment, bool a_degenerate)
+ {
+ return a_degenerate
+ ? de9im_segment(0,0,
+ 0, -1, -1,
+ -1, -1, -1,
+ 1, 0, 2,
+ false, false, false, true)
+ : de9im_segment(0,0,
+ 0, -1, 1,
+ -1, -1, 0,
+ -1, -1, 2,
+ false, false, false, true);
+ }
+
+ static inline return_type collinear_disjoint()
+ {
+ return de9im_segment(0,0,
+ -1, -1, 1,
+ -1, -1, 0,
+ 1, 0, 2,
+ true);
+ }
+
+
+ static inline return_type parallel()
+ {
+ return de9im_segment(0,0,
+ -1, -1, 1,
+ -1, -1, 0,
+ 1, 0, 2, false, false, true);
+ }
+};
+
+
+}} // namespace policies::relate
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRY_POLICIES_RELATE_DE9IM_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/policies/relate/direction.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/policies/relate/direction.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,299 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP
+#define GGL_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP
+
+#include <boost/concept_check.hpp>
+
+#include <ggl/util/math.hpp>
+#include <ggl/util/select_coordinate_type.hpp>
+
+
+namespace ggl
+{
+
+
+namespace policies { namespace relate {
+
+struct direction_type
+{
+ inline direction_type(char h,
+ double a = 0, double b = 0,
+ int ha = 0, int hb = 0,
+ int da = 0, int db = 0,
+ bool op = false)
+ : how(h)
+ , opposite(op)
+ , ra(a)
+ , rb(b)
+ , how_a(ha)
+ , how_b(hb)
+ , dir_a(da)
+ , dir_b(db)
+ {
+ }
+
+ inline direction_type(char h, bool op, int ha = 0, int hb = 0)
+ : how(h)
+ , opposite(op)
+ , ra(0)
+ , rb(0)
+ , how_a(ha)
+ , how_b(hb)
+ , dir_a(0)
+ , dir_b(0)
+ {
+ }
+
+
+ // "How" is the intersection formed?
+ char how;
+
+ // Is it opposite (for collinear/equal cases)
+ bool opposite;
+
+ // "Distance information", information on how far lies IP from a/b in ratio [0..1]
+ double ra, rb;
+
+ // 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
+};
+
+
+template <typename S1, typename S2>
+struct segments_direction
+{
+ typedef direction_type return_type;
+ typedef S1 segment_type1;
+ typedef S2 segment_type2;
+ typedef typename select_coordinate_type<S1, S2>::type coordinate_type;
+
+ static inline return_type rays_intersect(bool on_segment,
+ double ra, double rb,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ coordinate_type const& dx2, coordinate_type const& dy2,
+ coordinate_type const& wx, coordinate_type const& wy,
+ S1 const& s1, S2 const& s2)
+ {
+ boost::ignore_unused_variable_warning(dx2);
+ boost::ignore_unused_variable_warning(dy2);
+ boost::ignore_unused_variable_warning(wx);
+ boost::ignore_unused_variable_warning(wy);
+
+ if(on_segment)
+ {
+ // 0 <= ra <= 1 and 0 <= rb <= 1
+ // Check the configuration
+ bool ra0 = math::equals(ra, 0.0);
+ bool ra1 = math::equals(ra, 1.0);
+ bool rb0 = math::equals(rb, 0.0);
+ bool rb1 = math::equals(rb, 1.0);
+
+ return
+ // opposite and same starting point (FROM)
+ ra0 && rb0 ? calculate_side<1>(ra, rb, dx1, dy1, s1, s2, 'f', -1, -1)
+
+ // opposite and point to each other (TO)
+ : ra1 && rb1 ? calculate_side<0>(ra, rb, 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>(ra, rb, 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>(ra, rb, dx1, dy1, s1, s2, 'a', -1, 1)
+
+ // b starts from interior of a
+ : rb0 ? starts_from_middle(ra, rb, dx1, dy1, s1, s2, 'B', 0, -1)
+
+ // a starts from interior of b (#39)
+ : ra0 ? starts_from_middle(ra, rb, dx1, dy1, s1, s2, 'A', -1, 0)
+
+ // b ends at interior of a, calculate direction of A from IP
+ : rb1 ? b_ends_at_middle(ra, rb, dx2, dy2, s1, s2)
+
+ // a ends at interior of b
+ : ra1 ? a_ends_at_middle(ra, rb, dx1, dy1, s1, s2)
+
+ // normal intersection
+ : calculate_side<1>(ra, rb, dx1, dy1, s1, s2, 'i', -1, -1)
+ ;
+ }
+
+ // Not on segment, disjoint
+ return return_type('d');
+ }
+
+ static inline return_type collinear_touch(coordinate_type const& , coordinate_type const& , bool opposite, char how)
+ {
+ // Though this is 'collinear', we handle it as To/From/Angle because it is the same.
+ // It only does NOT have a direction.
+ int const arrive = how == 'T' ? 1 : -1;
+ return
+ ! opposite
+ ? return_type('a', 0, 0, how == 'A' ? 1 : -1, how == 'B' ? 1 : -1)
+ : return_type(how == 'T' ? 't' : 'f', 0, 0, arrive, arrive, 0, 0, true);
+ }
+
+ template <typename S>
+ static inline return_type collinear_interior_boundary_intersect(S const& , bool, bool opposite)
+ {
+ return return_type('c', opposite);
+ }
+
+ static inline return_type collinear_a_in_b(S1 const& , bool opposite)
+ {
+ return return_type('c', opposite);
+ }
+ static inline return_type collinear_b_in_a(S2 const& , bool opposite)
+ {
+ return return_type('c', opposite);
+ }
+
+ static inline return_type collinear_overlaps(
+ coordinate_type const& , coordinate_type const& ,
+ coordinate_type const& , coordinate_type const& , bool opposite)
+ {
+ return return_type('c', opposite);
+ }
+
+ 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');
+ }
+
+ static inline return_type collinear_disjoint()
+ {
+ return return_type('d');
+ }
+
+
+ static inline return_type parallel()
+ {
+ return return_type('p');
+ }
+
+private :
+
+
+ template <std::size_t I>
+ static inline return_type calculate_side(double ra, double rb,
+ 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(how, ra, rb, how_a, how_b, -1, 1)
+ : return_type(how, ra, rb, how_a, how_b, 1, -1);
+ }
+
+ template <std::size_t I>
+ static inline return_type angle(double ra, double rb,
+ 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(how, ra, rb, how_a, how_b, 1, 1)
+ : return_type(how, ra, rb, how_a, how_b, -1, -1);
+ }
+
+
+ static inline return_type starts_from_middle(double ra, double rb,
+ 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('s', ra, rb,
+ how_a,
+ how_b,
+ is_a ? dir : -dir,
+ ! is_a ? dir : -dir);
+ }
+
+
+
+ // To be harmonized
+ static inline return_type a_ends_at_middle(double ra, double rb,
+ 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('m', ra, rb, 1, 0, 1, 1)
+ : return_type('m', ra, rb, 1, 0, -1, -1);
+ }
+
+
+ static inline return_type b_ends_at_middle(double ra, double rb,
+ 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('m', ra, rb, 0, 1, 1, 1)
+ : return_type('m', ra, rb, 0, 1, -1, -1);
+ }
+
+};
+
+}} // namespace policies::relate
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/policies/relate/intersection_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/policies/relate/intersection_points.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,143 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
+#define GGL_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
+
+#include <boost/concept_check.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/util/select_coordinate_type.hpp>
+
+
+namespace ggl
+{
+
+namespace policies { namespace relate {
+
+
+template <typename S1, typename S2, typename ReturnType>
+struct segments_intersection_points
+{
+ typedef ReturnType return_type;
+ typedef S1 segment_type1;
+ typedef S2 segment_type2;
+ typedef typename select_coordinate_type<S1, S2>::type coordinate_type;
+
+ static inline return_type rays_intersect(bool on_segment,
+ double ra, double rb,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ coordinate_type const& dx2, coordinate_type const& dy2,
+ coordinate_type const& wx, coordinate_type const& wy,
+ S1 const& s1, S2 const& s2)
+ {
+ boost::ignore_unused_variable_warning(rb);
+ boost::ignore_unused_variable_warning(dx2);
+ boost::ignore_unused_variable_warning(dy2);
+ boost::ignore_unused_variable_warning(wx);
+ boost::ignore_unused_variable_warning(wy);
+ boost::ignore_unused_variable_warning(s2);
+
+ return_type result;
+
+ if (on_segment)
+ {
+ result.count = 1;
+ set<0>(result.intersections[0],
+ boost::numeric_cast<coordinate_type>(get<0, 0>(s1) + ra * dx1));
+ set<1>(result.intersections[0],
+ boost::numeric_cast<coordinate_type>(get<0, 1>(s1) + ra * 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 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 ggl
+
+#endif // GGL_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/policies/relate/tupled.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/policies/relate/tupled.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,154 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRY_POLICIES_RELATE_TUPLED_HPP
+#define GGL_GEOMETRY_POLICIES_RELATE_TUPLED_HPP
+
+#include <boost/tuple/tuple.hpp>
+#include <ggl/util/select_coordinate_type.hpp>
+
+namespace ggl
+{
+
+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>
+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_coordinate_type
+ <
+ segment_type1,
+ segment_type2
+ >::type coordinate_type;
+
+
+ static inline return_type rays_intersect(bool on_segment,
+ double ra, double rb,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ coordinate_type const& dx2, coordinate_type const& dy2,
+ coordinate_type const& wx, coordinate_type const& wy,
+ segment_type1 const& s1, segment_type2 const& s2)
+ {
+ return boost::make_tuple
+ (
+ Policy1::rays_intersect(on_segment, ra, rb, dx1, dy1, dx2, dy2, wx, wy, s1, s2),
+ Policy2::rays_intersect(on_segment, ra, rb, dx1, dy1, dx2, dy2, wx, wy, s1, s2)
+ );
+ }
+
+ static inline return_type collinear_touch(coordinate_type const& x,
+ coordinate_type const& y, bool opposite, char how)
+ {
+ return boost::make_tuple
+ (
+ Policy1::collinear_touch(x, y, opposite, how),
+ Policy2::collinear_touch(x, y, opposite, how)
+ );
+ }
+
+ template <typename S>
+ static inline return_type collinear_interior_boundary_intersect(S const& segment,
+ bool a_within_b, bool opposite)
+ {
+ return boost::make_tuple
+ (
+ Policy1::collinear_interior_boundary_intersect(segment, a_within_b, opposite),
+ Policy2::collinear_interior_boundary_intersect(segment, a_within_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,
+ bool opposite)
+ {
+ return boost::make_tuple
+ (
+ Policy1::collinear_overlaps(x1, y1, x2, y2, opposite),
+ Policy2::collinear_overlaps(x1, y1, x2, y2, 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 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 ggl
+
+#endif // GGL_GEOMETRY_POLICIES_RELATE_TUPLED_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/agnostic/agn_convex_hull.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/agnostic/agn_convex_hull.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,278 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGIES_AGNOSTIC_CONVEX_HULL_HPP
+#define GGL_STRATEGIES_AGNOSTIC_CONVEX_HULL_HPP
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4101 )
+#endif
+
+#include <cstddef>
+#include <algorithm>
+#include <vector>
+
+#include <boost/range/functions.hpp>
+
+#include <ggl/core/cs.hpp>
+#include <ggl/strategies/strategy_traits.hpp>
+
+// TODO: Temporary, comparing tests, this can be removed in the end
+#if defined(GGL_USE_SMOOTH_SORT)
+# include "SmoothSort.hpp"
+#elif defined(GGL_USE_MERGE_SORT)
+# include "MergeSort.hpp"
+#else
+#endif
+
+namespace ggl
+{
+
+namespace strategy { namespace convex_hull {
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Range, typename RangeIterator, typename Strategy>
+static inline void get_extremes(const Range& range,
+ RangeIterator& min_it, RangeIterator& max_it,
+ const Strategy& strategy)
+{
+ min_it = boost::begin(range);
+ max_it = boost::begin(range);
+
+ for (RangeIterator it = boost::begin(range) + 1; it != boost::end(range); ++it)
+ {
+ if (strategy.smaller(*it, *min_it))
+ {
+ min_it = it;
+ }
+
+ if (strategy.larger(*it, *max_it))
+ {
+ max_it = it;
+ }
+ }
+}
+
+template <typename R>
+static inline void sort(R& range)
+{
+ #if defined(USE_SMOOTH_SORT)
+ smoothsort::sort(boost::begin(range), boost::end(range));
+ #elif defined(USE_MERGE_SORT)
+ comparing::merge_sort<thread_count>(boost::begin(range), boost::end(range), std::less<P>());
+ #else
+ std::sort(boost::begin(range), boost::end(range));
+ #endif
+}
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+// Completely reworked version from source at:
+// http://www.ddj.com/architect/201806315
+// also available at http://marknelson.us/2007/08/22/convex
+template <typename P>
+class graham
+{
+private:
+
+ typedef typename cs_tag<P>::type cs_tag;
+ typedef typename std::vector<P> container;
+ typedef typename std::vector<P>::const_iterator iterator;
+ typedef typename std::vector<P>::const_reverse_iterator rev_iterator;
+
+ container m_lower_hull;
+ container m_upper_hull;
+ container m_copied_input;
+
+
+public:
+
+ // Default constructor, ranges can be added using "add_range" but note they'll be copied
+ inline graham()
+ {
+ }
+
+ // Constructor with a range
+ template <typename Range>
+ inline graham(const Range& range)
+ {
+ handle_range(range);
+ }
+
+
+ template <typename OutputIterator>
+ inline void get(OutputIterator out)
+ {
+ for (iterator it = m_upper_hull.begin(); it != m_upper_hull.end(); ++it, ++out)
+ {
+ *out = *it;
+ }
+
+ // STL Port does not accept iterating from rbegin+1 to rend
+ std::size_t size = m_lower_hull.size();
+ if (size > 0)
+ {
+ rev_iterator it = m_lower_hull.rbegin() + 1;
+ for (std::size_t i = 1; i < size; ++i, ++it, ++out)
+ {
+ *out = *it;
+ }
+ }
+ }
+
+
+ // Note /
+ // TODO:
+ // Consider if it is better to create an iterator over a multi, which is then used here,
+ // instead of copying the range
+ // It makes it slightly more complicated but avoids the copy, which is attractive because
+ // multi-polygons (where it is used for) can be large.
+ template <typename Range>
+ inline void add_range(const Range& range)
+ {
+ std::copy(boost::begin(range), boost::end(range), std::back_inserter(m_copied_input));
+ }
+
+ inline void handle_input()
+ {
+ handle_range(m_copied_input);
+ }
+
+
+private:
+
+ template <typename Range>
+ inline void handle_range(const Range& range)
+ {
+ typedef typename boost::range_const_iterator<Range>::type range_iterator;
+
+ // Polygons with three corners, or closed with 4 points, are always convex
+ if (boost::size(range) <= 3)
+ {
+ for (range_iterator it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ m_upper_hull.push_back(*it);
+ }
+ return;
+ }
+
+ // Get min/max (in most cases left / right) points
+ range_iterator left_it, right_it;
+ typename strategy_compare<cs_tag, P, 0>::type comparing;
+ detail::get_extremes(range, left_it, right_it, comparing);
+
+ // Bounding left/right points
+ container lower_points, upper_points;
+
+ assign_range(range, left_it, right_it, lower_points, upper_points);
+
+ detail::sort(lower_points);
+ detail::sort(upper_points);
+
+ build_half_hull<1>(lower_points, m_lower_hull, *left_it, *right_it);
+ build_half_hull<-1>(upper_points, m_upper_hull, *left_it, *right_it);
+ }
+
+
+
+ template <typename RangeIterator, typename Range>
+ inline void assign_range(const Range& range,
+ const RangeIterator& left_it,
+ const RangeIterator& right_it,
+ container& lower_points,
+ container& upper_points)
+ {
+ typename strategy_side<cs_tag, P>::type side;
+
+ // Put points in one of the two output sequences
+ for (RangeIterator it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ if (it != left_it && it != right_it)
+ {
+ int dir = side.side(*left_it, *right_it, *it);
+ if ( dir < 0 )
+ {
+ upper_points.push_back(*it);
+ }
+ else
+ {
+ lower_points.push_back(*it);
+ }
+ }
+ }
+ }
+
+
+ template <int Factor>
+ inline void build_half_hull(const container& input, container& output,
+ const P& left, const P& 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>
+ inline void add_to_hull(const P& p, container& output)
+ {
+ typename strategy_side<cs_tag, P>::type side;
+
+ output.push_back(p);
+ register std::size_t output_size = output.size();
+ while (output_size >= 3)
+ {
+ rev_iterator rit = output.rbegin();
+ const P& last = *rit++;
+ const P& last2 = *rit++;
+
+ if (Factor * side.side(*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;
+ }
+ }
+ }
+
+
+};
+
+}} // namespace strategy::convex_hull
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename P>
+struct strategy_convex_hull<cartesian_tag, P>
+{
+ typedef strategy::convex_hull::graham<P> type;
+};
+#endif
+
+} // namespace ggl
+
+
+#endif // GGL_STRATEGY_AGNOSTIC_CONVEX_HULL_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/agnostic/agn_simplify.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/agnostic/agn_simplify.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,196 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGY_AGNOSTIC_SIMPLIFY_HPP
+#define GGL_STRATEGY_AGNOSTIC_SIMPLIFY_HPP
+
+#include <boost/range/functions.hpp>
+
+#include <ggl/core/cs.hpp>
+
+
+//#define GL_DEBUG_SIMPLIFY
+
+#ifdef GL_DEBUG_SIMPLIFY
+#include <ggl/extensions/gis/io/wkt/write_wkt.hpp>
+#include <ggl/extensions/gis/io/wkt/stream_wkt.hpp>
+#include <iostream>
+#endif
+
+
+namespace ggl
+{
+namespace strategy
+{
+ namespace simplify
+ {
+ #ifndef DOXYGEN_NO_DETAIL
+ namespace detail
+ {
+
+ /*!
+ \brief Small wrapper around a point, with an extra member "included"
+ \details
+ - We could implement a complete point as well but that is not necessary
+ - We could derive from ggl::point but we need the original later on, including extra members;
+ besides that it is not necessary to copy points during the algorithm
+ \tparam the enclosed point type
+ */
+ template<typename P>
+ struct douglas_peucker_point
+ {
+ const P& p;
+ bool included;
+
+ inline douglas_peucker_point(const P& ap)
+ : p(ap)
+ , included(false)
+ {}
+
+ inline douglas_peucker_point<P> operator=(const douglas_peucker_point<P>& other)
+ {
+ return douglas_peucker_point<P>(*this);
+ }
+ };
+ }
+ #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 R boost range
+ \tparam O_IT output iterator
+ \tparam PSDS 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 R, typename O_IT, typename PSDS>
+ class douglas_peucker
+ {
+ typedef typename point_type<R>::type P;
+ typedef detail::douglas_peucker_point<P> DP;
+ typedef typename std::vector<DP>::iterator DIT;
+
+ typedef typename PSDS::return_type RET;
+
+ inline void consider(DIT begin, DIT end, const RET& max_dist, int& n,
+ const PSDS& ps_distance_strategy) const
+ {
+ size_t size = end - begin;
+ // size must be at least 3 here: we want to consider a candidate point between begin and end
+ if (size <= 2)
+ {
+#ifdef GL_DEBUG_SIMPLIFY
+ if (begin != end)
+ {
+ std::cout << "ignore between " << begin->p << " and " << (end - 1)->p << " size=" << size << std::endl;
+ }
+ std::cout << "return because size=" << size << std::endl;
+#endif
+ return;
+ }
+
+ DIT last = end - 1;
+
+#ifdef GL_DEBUG_SIMPLIFY
+ std::cout << "find between " << begin->p << " and " << last->p << " size=" << size << std::endl;
+#endif
+
+
+ // Find most distance point, compare to the current segment
+ ggl::segment<const P> s(begin->p, last->p);
+ RET md(-1.0); // any value < 0
+ DIT candidate;
+ for(DIT it = begin + 1; it != last; it++)
+ {
+ RET dist = ps_distance_strategy(it->p, s);
+
+#ifdef GL_DEBUG_SIMPLIFY
+ std::cout << "consider " << it->p << " at " << dist.value() << (dist.value() > max_dist.value() ? " 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_SIMPLIFY
+ std::cout << "use " << 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 PSDS distance_strategy_type;
+
+ /*!
+ \brief Call simplification on an iterator pair
+ */
+ inline void simplify(const R& range, O_IT out, double max_distance) const
+ {
+ PSDS strategy;
+ // Init the output, a vector of references to all points
+
+ // Note Geometry Algorithms suggest here
+ // http://geometryalgorithms.com/Archive/algorithm_0205/algorithm_0205.htm
+ // to "STAGE 1: Vertex Reduction within max_distance of prior vertex cluster"
+ // However, that is not correct: a vertex within the specified distance might be
+ // excluded here, but might be a better candidate for final inclusion than the point before.
+
+ std::vector<DP> ref_candidates(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 PSDS::return_type RET;
+
+ consider(boost::begin(ref_candidates), boost::end(ref_candidates),
+ make_distance_result<RET>(max_distance), n, strategy);
+
+ // Copy included elements to the output (might be changed using copy_if)
+ for(typename std::vector<DP>::const_iterator it = boost::begin(ref_candidates);
+ it != boost::end(ref_candidates); it++)
+ {
+ if (it->included)
+ {
+ *out = it->p;
+ out++;
+ }
+ }
+ }
+
+ };
+
+ }
+}
+
+
+} // namespace ggl
+
+#endif // GGL_STRATEGY_AGNOSTIC_SIMPLIFY_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/agnostic/agn_within.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/agnostic/agn_within.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,162 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGY_AGNOSTIC_WITHIN_HPP
+#define GGL_STRATEGY_AGNOSTIC_WITHIN_HPP
+
+
+
+#include <ggl/geometries/segment.hpp>
+
+#include <ggl/strategies/strategy_traits.hpp>
+
+
+
+namespace ggl
+{
+namespace strategy
+{
+ namespace within
+ {
+
+ /*!
+ \brief Within detection using winding rule
+ \tparam P point type of point to examine
+ \tparam PS point type of segments, defaults to P
+ \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 More efficient (less comparisons and no divison) than the cross count algorithm
+ \note Only dependant on "side", -> agnostic, suitable for latlong
+ */
+ template<typename P, typename PS = P>
+ class winding
+ {
+ private :
+ typedef typename coordinate_type<P>::type PT;
+ typedef typename coordinate_type<PS>::type ST;
+
+ /*! subclass to keep state */
+ struct windings
+ {
+ int count;
+ bool touches;
+ const P& p;
+ inline explicit windings(const P& ap)
+ : count(0)
+ , touches(false)
+ , p(ap)
+ {}
+ inline bool within() const
+ {
+ return ! touches && count != 0;
+ }
+ };
+
+ template <size_t D>
+ static inline int check_touch(const segment<const PS>& s, windings& state)
+ {
+ const PT& p = get<D>(state.p);
+ const ST& s1 = get<0, D>(s);
+ const ST& s2 = get<1, D>(s);
+ if ((s1 <= p && s2 >= p) || (s2 <= p && s1 >= p))
+ {
+ state.touches = true;
+ }
+ return 0;
+ }
+
+
+ template <size_t D>
+ static inline int check_segment(const segment<const PS>& s, windings& state)
+ {
+ const PT& p = get<D>(state.p);
+ const ST& s1 = get<0, D>(s);
+ const ST& s2 = get<1, D>(s);
+
+ // 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>(s, state);
+ }
+
+ return
+ eq1 ? (s2 > p ? 1 : -1) // P on level s1, UP/DOWN depending on s2
+ : eq2 ? (s1 > p ? -1 : 1) // idem
+ : s1 < p && s2 > p ? 2 // P between s1 -> s2 --> UP
+ : s2 < p && s1 > p ? -2 // P between s2 -> s1 --> DOWN
+ : 0;
+ }
+
+
+ public :
+
+ typedef windings state_type;
+
+ inline bool operator()(const segment<const PS>& s, state_type& state) const
+ {
+ int cnt = check_segment<1>(s, state);
+ if (cnt != 0)
+ {
+ typedef typename strategy_side<typename cs_tag<P>::type, P, PS>::type SS;
+
+ typename select_coordinate_type<P, PS>::type side = SS::side(s, state.p);
+
+ if (math::equals(side, 0))
+ {
+ // Point is lying on segment
+ state.touches = true;
+ state.count = 0;
+ return false;
+ }
+
+ // Side is NEG for right, POS for left.
+ // CNT 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)
+ int sd = (side > 0 ? 1 : -1) * cnt;
+ if (sd > 0)
+ {
+ state.count += cnt;
+ }
+
+ }
+ return ! state.touches;
+ }
+
+ };
+
+ } // namespace within
+
+} // namespace strategy
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename P, typename PS>
+struct strategy_within<cartesian_tag, cartesian_tag, P, PS>
+{
+ typedef strategy::within::winding<P, PS> type;
+};
+
+template <typename P, typename PS>
+struct strategy_within<geographic_tag, geographic_tag, P, PS>
+{
+ typedef strategy::within::winding<P, PS> type;
+};
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_STRATEGY_AGNOSTIC_WITHIN_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_area.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_area.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,102 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGY_CARTESIAN_AREA_HPP
+#define GGL_STRATEGY_CARTESIAN_AREA_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+#include <ggl/geometries/point_xy.hpp>
+#include <ggl/geometries/segment.hpp>
+
+
+namespace ggl
+{
+namespace strategy
+{
+ namespace area
+ {
+
+ /*!
+ \brief Strategy functor for area calculation on point_xy points
+ \details Calculates area using well-known triangulation algorithm
+ \tparam PS point type of segments
+ \par Concepts for PS:
+ - specialized point_traits class
+ */
+ template<typename PS, 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<PS>::type,
+ double
+ >::type,
+ CalculationType
+ >::type return_type;
+
+
+ private :
+
+ struct summation
+ {
+ return_type sum;
+
+ inline summation() : sum(return_type())
+ {
+ // Currently only 2D areas are supported
+ assert_dimension<PS, 2>();
+ }
+ inline return_type area() const
+ {
+ return_type result = sum;
+ result *= 0.5;
+ return result;
+ }
+ };
+
+ public :
+ typedef summation state_type;
+
+ inline bool operator()(segment<const PS> const& s,
+ state_type& state) const
+ {
+ // SUM += x2 * y1 - x1 * y2;
+ state.sum += get<1, 0>(s) * get<0, 1>(s)
+ - get<0, 0>(s) * get<1, 1>(s);
+ return true;
+ }
+
+ };
+
+ } // namespace area
+} // namespace strategy
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename P>
+struct strategy_area<cartesian_tag, P>
+{
+ typedef strategy::area::by_triangles<P> type;
+};
+#endif
+
+} // namespace ggl
+
+
+#endif // GGL_STRATEGY_CARTESIAN_AREA_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_centroid.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_centroid.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,292 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGY_CARTESIAN_CENTROID_HPP
+#define GGL_STRATEGY_CARTESIAN_CENTROID_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/type_traits.hpp>
+
+#include <ggl/geometries/point_xy.hpp>
+#include <ggl/geometries/segment.hpp>
+
+#include <ggl/algorithms/assign.hpp>
+
+#include <ggl/util/select_coordinate_type.hpp>
+#include <ggl/util/copy.hpp>
+
+
+namespace ggl
+{
+
+namespace strategy
+{
+ namespace centroid
+ {
+ /*!
+ \brief Centroid calculation
+ \details Geolib original version,
+ \par Template parameters and concepts: see bashein_detmer
+ \author Barend and Maarten, 1995/1996
+ \author Revised for templatized library, Barend Gehrels, 2007
+ \note The results are slightly different from Bashein/Detmer, so probably slightly wrong.
+ */
+
+ template<typename PC, typename PS = PC>
+ class geolib1995
+ {
+ private :
+ typedef typename select_most_precise
+ <
+ typename select_coordinate_type<PC, PS>::type,
+ double
+ >::type T;
+
+ /*! subclass to keep state */
+ struct sums
+ {
+ PC sum_ms, sum_m;
+
+ sums()
+ {
+ assign_point(sum_m, T());
+ assign_point(sum_ms, T());
+ }
+ void centroid(PC& point)
+ {
+ point = sum_ms;
+
+ if (get<0>(sum_m) != 0 && get<1>(sum_m) != 0)
+ {
+ multiply_value(point, 0.5);
+ divide_point(point, sum_m);
+ }
+ else
+ {
+ // exception?
+ }
+ }
+ };
+
+ public :
+ typedef sums state_type;
+ inline bool operator()(const segment<const PS>& s, state_type& state) const
+ {
+ /* Algorithm:
+ For each segment:
+ begin
+ dx = x2 - x1;
+ dy = y2 - y1;
+ sx = x2 + x1;
+ sy = y2 + y1;
+ mx = dx * sy;
+ my = sx * dy;
+
+ sum_mx += mx;
+ sum_my += my;
+ sum_msx += mx * sx;
+ sum_msy += my * sy;
+ end;
+ return POINT(0.5 * sum_msx / sum_mx, 0.5 * sum_msy / sum_my);
+ */
+
+ PS diff = s.second, sum = s.second;
+ subtract_point(diff, s.first);
+ add_point(sum, s.first);
+
+ // We might create an arithmatic operation for this.
+ PS m;
+ get<0>(m) = get<0>(diff) * get<1>(sum);
+ get<1>(m) = get<0>(sum) * get<1>(diff);
+
+ add_point(state.sum_m, m);
+ multiply_point(m, sum);
+ add_point(state.sum_ms, m);
+
+ return true;
+ }
+
+ };
+
+
+ /*!
+ \brief Centroid calculation using algorith Bashein / Detmer
+ \details Calculates centroid using triangulation method published by Bashein / Detmer
+ \tparam PC point type of centroid to calculate
+ \tparam PS point type of segments, defaults to PC
+ \par Concepts for PC and PS:
+ - specialized point_traits class
+ \author Adapted from "Centroid of a Polygon" by Gerard Bashein and Paul R. Detmer<em>,
+ in "Graphics Gems IV", Academic Press, 1994</em>
+ \par Research notes
+ The algorithm gives the same results as Oracle and 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 CentroidPointType,
+ typename SegmentPointType = CentroidPointType,
+ 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
+ <
+ CentroidPointType,
+ SegmentPointType
+ >::type,
+ double
+ >::type,
+ CalculationType
+ >::type calc_type;
+
+ /*! subclass to keep state */
+ struct sums
+ {
+ calc_type sum_a2;
+ calc_type sum_x;
+ calc_type sum_y;
+ inline sums()
+ : sum_a2(calc_type())
+ , sum_x(calc_type())
+ , sum_y(calc_type())
+ {
+ typedef calc_type ct;
+ //std::cout << "-> calctype: " << typeid(ct).name()
+ // << " size: " << sizeof(ct)
+ // << " init: " << sum_a2
+ // << std::endl;
+ }
+
+ inline void centroid(CentroidPointType& point)
+ {
+ if (sum_a2 != 0)
+ {
+ calc_type const v3 = 3;
+ calc_type const a3 = v3 * sum_a2;
+
+ typedef typename ggl::coordinate_type
+ <
+ CentroidPointType
+ >::type coordinate_type;
+
+ set<0>(point,
+ boost::numeric_cast<coordinate_type>(sum_x / a3));
+ set<1>(point,
+ boost::numeric_cast<coordinate_type>(sum_y / a3));
+ }
+ else
+ {
+ // exception?
+ }
+ }
+
+ };
+
+ public :
+ typedef sums state_type;
+
+ inline bool operator()(segment<const SegmentPointType> const& s, state_type& state) const
+ {
+ /* Algorithm:
+ For each segment:
+ begin
+ ai = x1 * y2 - x2 * y1;
+ sum_a2 += ai;
+ sum_x += ai * (x1 + x2);
+ sum_y += ai * (y1 + y2);
+ end
+ return POINT(sum_x / (3 * sum_a2), sum_y / (3 * sum_a2) )
+ */
+
+ // Get coordinates and promote them to calc_type
+ calc_type const x1 = boost::numeric_cast<calc_type>(get<0, 0>(s));
+ calc_type const y1 = boost::numeric_cast<calc_type>(get<0, 1>(s));
+ calc_type const x2 = boost::numeric_cast<calc_type>(get<1, 0>(s));
+ calc_type const y2 = boost::numeric_cast<calc_type>(get<1, 1>(s));
+ calc_type const ai = x1 * y2 - x2 * y1;
+ state.sum_a2 += ai;
+ state.sum_x += ai * (x1 + x2);
+ state.sum_y += ai * (y1 + y2);
+
+ return true;
+ }
+
+ };
+ } // namespace centroid
+
+} // namespace strategy
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename P, typename PS>
+struct strategy_centroid<cartesian_tag, P, PS>
+{
+ typedef strategy::centroid::bashein_detmer<P, PS> type;
+};
+#endif
+
+} // namespace ggl
+
+
+#endif // GGL_STRATEGY_CARTESIAN_CENTROID_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_compare.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_compare.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,66 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGY_CARTESIAN_COMPARE_HPP
+#define GGL_STRATEGY_CARTESIAN_COMPARE_HPP
+
+
+#include <ggl/core/cs.hpp>
+#include <ggl/core/access.hpp>
+
+
+#include <ggl/strategies/strategy_traits.hpp>
+
+
+namespace ggl
+{
+namespace strategy
+{
+ namespace compare
+ {
+
+
+ /*!
+ \brief Compare (in one direction) strategy for cartesian coordinates
+ \ingroup util
+ \tparam P point-type
+ \tparam D dimension
+ */
+ template <typename P, size_t D>
+ struct euclidian
+ {
+ static inline bool smaller(const P& p1, const P& p2)
+ {
+ return get<D>(p1) < get<D>(p2);
+ }
+
+ static inline bool larger(const P& p1, const P& p2)
+ {
+ return get<D>(p1) > get<D>(p2);
+ }
+
+ };
+ } // namespace compare
+} // namespace strategy
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+template <typename P, size_t D>
+struct strategy_compare<cartesian_tag, P, D>
+{
+ typedef strategy::compare::euclidian<P, D> type;
+};
+
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_STRATEGY_CARTESIAN_COMPARE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_distance.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_distance.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,246 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGY_CARTESIAN_DISTANCE_HPP
+#define GGL_STRATEGY_CARTESIAN_DISTANCE_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/point_type.hpp>
+
+#include <ggl/arithmetic/arithmetic.hpp>
+#include <ggl/arithmetic/dot_product.hpp>
+
+#include <ggl/strategies/strategy_traits.hpp>
+#include <ggl/strategies/distance_result.hpp>
+
+#include <ggl/util/select_coordinate_type.hpp>
+#include <ggl/util/copy.hpp>
+
+
+// Helper geometry
+#include <ggl/geometries/segment.hpp>
+
+namespace ggl {
+
+namespace strategy { namespace distance {
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename P1, typename P2, size_t I, typename T>
+struct compute_pythagoras
+{
+ static inline T apply(P1 const& p1, P2 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<P1, P2, I-1, T>::apply(p1, p2);
+ }
+};
+
+template <typename P1, typename P2, typename T>
+struct compute_pythagoras<P1, P2, 0, T>
+{
+ static inline T apply(P1 const&, P2 const&)
+ {
+ return boost::numeric_cast<T>(0);
+ }
+};
+
+}
+#endif
+
+/*!
+ \brief Strategy for distance point to point: pythagoras
+ \ingroup distance
+ \tparam P1 first point type
+ \tparam P2 optional, second point type, defaults to first point type
+ \par Concepts for P1 and P2:
+ - specialized point_traits class
+*/
+template
+<
+ typename P1,
+ typename P2 = P1,
+ typename CalculationType = void
+>
+struct pythagoras
+{
+ typedef typename
+ boost::mpl::if_c
+ <
+ boost::is_void<CalculationType>::type::value,
+ typename select_coordinate_type
+ <
+ P1,
+ P2
+ >::type,
+ CalculationType
+ >::type calculation_type;
+
+ typedef cartesian_distance<calculation_type> return_type;
+
+
+ inline return_type operator()(P1 const& p1, P2 const& p2) const
+ {
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<P1>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<P2>) );
+
+ // Calculate distance using Pythagoras
+ // (Leave comment above for Doxygen)
+
+ assert_dimension_equal<P1, P2>();
+
+ return return_type(detail::compute_pythagoras
+ <
+ P1, P2,
+ dimension<P1>::value,
+ calculation_type
+ >::apply(p1, p2));
+ }
+};
+
+
+/*!
+ \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 SEG segment type
+ \tparam S strategy, optional, defaults to pythagoras
+ \par Concepts for S:
+ - cartesian_distance operator(P,P)
+*/
+template
+<
+ typename P,
+ typename Segment,
+ typename Strategy = pythagoras<P, typename point_type<Segment>::type>
+>
+struct xy_point_segment
+{
+ typedef typename select_coordinate_type<P, Segment>::type coordinate_type;
+ typedef cartesian_distance<coordinate_type> return_type;
+ typedef Strategy distance_strategy_type; // OBSOLETE!
+ typedef Strategy point_strategy_type;
+
+
+ inline return_type operator()(P const& p, Segment const& s) const
+ {
+ assert_dimension_equal<P, Segment>();
+
+ /* 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);
+ */
+
+ typedef typename boost::remove_const
+ <
+ typename point_type<Segment>::type
+ >::type segment_point_type;
+
+ segment_point_type v, w;
+
+ // TODO
+ // ASSUMPTION: segment
+ // SOLVE THIS USING OTHER FUNCTIONS using get<,>
+ copy_coordinates(s.second, v);
+ copy_coordinates(p, w);
+ subtract_point(v, s.first);
+ subtract_point(w, s.first);
+
+ Strategy strategy;
+
+ coordinate_type c1 = dot_product(w, v);
+ if (c1 <= 0)
+ {
+ return strategy(p, s.first);
+ }
+ coordinate_type c2 = dot_product(v, v);
+ if (c2 <= c1)
+ {
+ return strategy(p, s.second);
+ }
+
+ // Even in case of char's, we have to turn to a point<double/float>
+ // because of the division.
+ coordinate_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
+ segment_point_type projected;
+ copy_coordinates(s.first, projected);
+ multiply_value(v, b);
+ add_point(projected, v);
+
+ return strategy(p, projected);
+
+ }
+};
+
+}} // namespace strategy::distance
+
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename P1, typename P2>
+struct strategy_distance<cartesian_tag, cartesian_tag, P1, P2>
+{
+ typedef strategy::distance::pythagoras<P1, P2> type;
+};
+
+template <typename Point, typename Segment>
+struct strategy_distance_segment<cartesian_tag, cartesian_tag, Point, Segment>
+{
+ typedef typename point_type<Segment>::type segment_point_type;
+
+ typedef strategy::distance::xy_point_segment
+ <
+ Point,
+ Segment,
+ typename strategy_distance
+ <
+ cartesian_tag, cartesian_tag, Point, segment_point_type
+ >::type
+ > type;
+};
+#endif
+
+
+template <typename P1, typename P2>
+struct strategy_tag<strategy::distance::pythagoras<P1, P2> >
+{
+ typedef strategy_tag_distance_point_point type;
+};
+
+template <typename Point, typename Segment, typename PPStrategy>
+struct strategy_tag<strategy::distance::xy_point_segment<Point, Segment, PPStrategy> >
+{
+ typedef strategy_tag_distance_point_segment type;
+};
+
+
+
+} // namespace ggl
+
+
+#endif // GGL_STRATEGY_CARTESIAN_DISTANCE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_envelope.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_envelope.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,66 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGY_CARTESIAN_ENVELOPE_HPP
+#define GGL_STRATEGY_CARTESIAN_ENVELOPE_HPP
+
+
+
+#include <ggl/geometries/point_xy.hpp>
+#include <ggl/geometries/segment.hpp>
+
+#include <ggl/algorithms/combine.hpp>
+
+
+namespace ggl
+{
+namespace strategy
+{
+ namespace envelope
+ {
+ // envelope calculation strategy for xy-points
+ template <typename P, typename B>
+ struct combine_xy
+ {
+ struct state
+ {
+ B& m_box;
+ state(B& box) : m_box(box)
+ {
+ assign_inverse(m_box);
+ }
+ };
+
+ typedef state state_type;
+
+ void operator()(const P& p, state_type& s) const
+ {
+ ggl::combine(s.m_box, p);
+ }
+ };
+ } // namespace envelope
+
+} // namespace strategy
+
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename P, typename B>
+struct strategy_envelope<cartesian_tag, cartesian_tag, P, B>
+{
+ typedef strategy::envelope::combine_xy<P, B> type;
+};
+
+
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_STRATEGY_CARTESIAN_ENVELOPE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_intersect.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_intersect.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,352 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGY_CARTESIAN_INTERSECTION_HPP
+#define GGL_STRATEGY_CARTESIAN_INTERSECTION_HPP
+
+#include <algorithm>
+
+#include <ggl/core/exception.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/core/concepts/segment_concept.hpp>
+
+#include <ggl/util/select_coordinate_type.hpp>
+
+
+namespace ggl
+{
+
+
+class relate_cartesian_segments_exception : public ggl::exception
+{
+public:
+
+ relate_cartesian_segments_exception() {}
+
+ virtual char const* what() const throw()
+ {
+ return "GGL: Internal error, unexpected case in relate_segment";
+ }
+};
+
+
+namespace strategy { namespace intersection {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename S, size_t D>
+struct segment_interval
+{
+ template <typename T>
+ static inline void arrange(S const& s, T& s_1, T& s_2, bool& swapped)
+ {
+ s_1 = get<0, D>(s);
+ s_2 = get<1, D>(s);
+ if (s_1 > s_2)
+ {
+ std::swap(s_1, s_2);
+ swapped = true;
+ }
+ }
+};
+
+}
+#endif
+
+
+/*!
+ \see http://mathworld.wolfram.com/Line-LineIntersection.html
+ */
+template <typename F>
+struct relate_cartesian_segments
+{
+ typedef typename F::return_type RETURN_TYPE;
+ typedef typename F::segment_type1 S1;
+ typedef typename F::segment_type2 S2;
+
+ typedef typename point_type<S1>::type P;
+ BOOST_CONCEPT_ASSERT( (concept::Point<P>) );
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstSegment<S1>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstSegment<S2>) );
+ typedef typename select_coordinate_type<S1, S2>::type T;
+
+ /// Relate segments a and b
+ static inline RETURN_TYPE relate(S1 const& a, S2 const& b)
+ {
+ T dx_a = get<1, 0>(a) - get<0, 0>(a); // distance in x-dir
+ T dx_b = get<1, 0>(b) - get<0, 0>(b);
+ T dy_a = get<1, 1>(a) - get<0, 1>(a); // distance in y-dir
+ T dy_b = get<1, 1>(b) - get<0, 1>(b);
+ return relate(a, b, dx_a, dy_a, dx_b, dy_b);
+ }
+
+
+ /// Relate segments a and b using precalculated differences. This can save two or four substractions in many cases
+ static inline RETURN_TYPE relate(S1 const& a, S2 const& b,
+ T const& dx_a, T const& dy_a, T const& dx_b, T const& dy_b)
+ {
+ T wx = get<0, 0>(a) - get<0, 0>(b);
+ T wy = get<0, 1>(a) - get<0, 1>(b);
+
+ // Calculate determinants - Cramers rule
+ T d = (dy_b * dx_a) - (dx_b * dy_a);
+ T da = (dx_b * wy) - (dy_b * wx);
+ T db = (dx_a * wy) - (dy_a * wx);
+
+ if(! math::equals(d, 0))
+ {
+ // Determinant d is nonzero. Rays do intersect. This is the normal case.
+ // ra/rb: ratio 0-1 where intersection divides A/B
+
+ // Maybe:
+ // The ra/rb calculation can probably also be avoided, only necessary to calculate the points themselves
+ // On segment: 0 <= r <= 1
+ // where: r==0 and r==1 are special cases
+ // --> r=0 if and only if da==0 (d != 0) [this is also checked below]
+ // --> r=1 da==d
+ // --> da/d > 0 if da==positive and d==positive OR da==neg and d==neg
+ // --> da/d < 1 if (both positive) da < d or (negative) da > d, e.g. -2 > -4
+ // --> it would save a division but makes it complexer
+
+ double ra = double(da) / double(d);
+ double rb = double(db) / double(d);
+
+ return F::rays_intersect(ra >= 0 && ra <= 1 && rb >= 0 && rb <= 1, ra, rb,
+ dx_a, dy_a, dx_b, dy_b, wx, wy, a, b);
+ }
+
+ if(math::equals(da, 0) && math::equals(db, 0))
+ {
+ // Both da & db are zero. Segments are collinear. We'll find out how.
+ return relate_collinear(a, b, dx_a, dy_a, dx_b, dy_b);
+ }
+
+ // Segments are parallel (might still be opposite but this is probably never interesting)
+ return F::parallel();
+ }
+
+private :
+
+
+ /// Relate segments known collinear
+ static inline RETURN_TYPE relate_collinear(S1 const& a, S2 const& b,
+ T const& dx_a, T const& dy_a,
+ T const& dx_b, T const& dy_b)
+ {
+ // All ca. 200 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
+ // We arrange 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
+ T a_1, a_2, b_1, b_2;
+ bool a_swapped = false, b_swapped = false;
+ if (math::equals(dx_b, 0))
+ {
+ // Vertical -> Check y-direction
+ detail::segment_interval<S1, 1>::arrange(a, a_1, a_2, a_swapped);
+ detail::segment_interval<S1, 1>::arrange(b, b_1, b_2, b_swapped);
+ }
+ else
+ {
+ // Check x-direction
+ detail::segment_interval<S1, 0>::arrange(a, a_1, a_2, a_swapped);
+ detail::segment_interval<S1, 0>::arrange(b, b_1, b_2, b_swapped);
+ }
+
+ // First handle "disjoint", probably common case.
+ // 2 cases: a_1----------a_2 b_1-------b_2 or B left of A
+ if (a_2 < b_1 || a_1 > b_2)
+ {
+ return F::collinear_disjoint();
+ }
+
+ // Then handle "equal", in polygon neighbourhood comparisons also a common case
+
+ // Check if segments are equal...
+ bool a1_eq_b1 = math::equals(get<0, 0>(a), get<0, 0>(b))
+ && math::equals(get<0, 1>(a), get<0, 1>(b));
+ bool 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 F::segment_equal(a, false);
+ }
+
+ // ... or opposite equal
+ bool a1_eq_b2 = math::equals(get<0, 0>(a), get<1, 0>(b))
+ && math::equals(get<0, 1>(a), get<1, 1>(b));
+ bool 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 F::segment_equal(a, true);
+ }
+
+
+ // Degenerate cases: segments of single point, lying on other segment, non disjoint
+ if (math::equals(dx_a, 0) && math::equals(dy_a, 0))
+ {
+ return F::degenerate(a, true);
+ }
+ if (math::equals(dx_b, 0) && math::equals(dy_b, 0))
+ {
+ return F::degenerate(b, false);
+ }
+
+
+ // 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 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" first)
+ // 2: a2<----a1 b2<---b1 ("b" first)
+ // 3: a1---->a2 b2<---b1 ("t": to)
+ // 4: a2<----a1 b1--->b2 ("f": from)
+ // 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 F::collinear_touch(get<1, 0>(a), get<1, 1>(a), false, 'A');
+ if (a2_eq_b2) return F::collinear_touch(get<1, 0>(a), get<1, 1>(a), true, 'T');
+ if (a1_eq_b2) return F::collinear_touch(get<0, 0>(a), get<0, 1>(a), false, 'B');
+ if (a1_eq_b1) return F::collinear_touch(get<0, 0>(a), get<0, 1>(a), true, 'F');
+ }
+
+
+ // "Touch/within" -> there are common points and also an intersection of interiors:
+ // Corresponds to many cases:
+ // Case 1: a1------->a2 Case 5: a1-->a2 Case 9: a1--->a2
+ // b1--->b2 b1------->b2 b1---------b2
+ // Case 2: a2<-------a1
+ // b1----b2 Et cetera
+ // Case 3: a1------->a2
+ // b2<---b1
+ // Case 4: a2<-------a1
+ // b2<---b1
+
+ // 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 a_in_b = (b_1 < a_1 && a_1 < b_2) || (b_1 < a_2 && a_2 < b_2);
+ if (a2_eq_b2) return F::collinear_interior_boundary_intersect(a_in_b ? a : b, a_in_b, false);
+ if (a1_eq_b2) return F::collinear_interior_boundary_intersect(a_in_b ? a : b, a_in_b, true);
+ if (a2_eq_b1) return F::collinear_interior_boundary_intersect(a_in_b ? a : b, a_in_b, true);
+ if (a1_eq_b1) return F::collinear_interior_boundary_intersect(a_in_b ? a : b, a_in_b, false);
+ }
+
+ bool 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 F::collinear_a_in_b(a, opposite);
+ }
+ if (b_1 > a_1 && b_2 < a_2)
+ {
+ // B within A
+ return F::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
+ // Case 1: a1--------->a2 a_1---------a_2
+ // b1----->b2 b_1------b_2
+ // Case 2: a2<---------a1 a_1---------a_2 a_swapped
+ // b1----->b2 b_1------b_2
+ // Case 3: a1--------->a2 a_1---------a_2
+ // b2<-----b1 b_1------b_2 b_swapped
+ // Case 4: a2<-------->a1 a_1---------a_2 a_swapped
+ // b2<-----b1 b_1------b_2 b_swapped
+
+ // Case 5: a1--------->a2 a_1---------a_2
+ // b1----->b2 b1--------b2
+ // Case 6: a2<---------a1
+ // b1----->b2
+ // Case 7: a1--------->a2
+ // b2<-----b1
+ // Case 8: a2<-------->a1
+ // b2<-----b1
+
+ if (a_1 < b_1 && b_1 < a_2)
+ {
+ // Case 4,2,3,1
+ return
+ a_swapped && b_swapped ? F::collinear_overlaps(get<0, 0>(a), get<0, 1>(a), get<1, 0>(b), get<1, 1>(b), opposite)
+ : a_swapped ? F::collinear_overlaps(get<0, 0>(a), get<0, 1>(a), get<0, 0>(b), get<0, 1>(b), opposite)
+ : b_swapped ? F::collinear_overlaps(get<1, 0>(a), get<1, 1>(a), get<1, 0>(b), get<1, 1>(b), opposite)
+ : F::collinear_overlaps(get<1, 0>(a), get<1, 1>(a), get<0, 0>(b), get<0, 1>(b), opposite)
+ ;
+ }
+ if (b_1 < a_1 && a_1 < b_2)
+ {
+ // Case 8, 6, 7, 5
+ return
+ a_swapped && b_swapped ? F::collinear_overlaps(get<1, 0>(a), get<1, 1>(a), get<0, 0>(b), get<0, 1>(b), opposite)
+ : a_swapped ? F::collinear_overlaps(get<1, 0>(a), get<1, 1>(a), get<1, 0>(b), get<1, 1>(b), opposite)
+ : b_swapped ? F::collinear_overlaps(get<0, 0>(a), get<0, 1>(a), get<0, 0>(b), get<0, 1>(b), opposite)
+ : F::collinear_overlaps(get<0, 0>(a), get<0, 1>(a), get<1, 0>(b), get<1, 1>(b), opposite)
+ ;
+ }
+
+ // Nothing should goes through. If any we have made an error
+ // TODO: proper exception
+ throw relate_cartesian_segments_exception();
+ }
+};
+
+
+}} // namespace strategy::intersection
+
+
+
+} // namespace ggl
+
+
+#endif // GGL_STRATEGY_CARTESIAN_INTERSECTION_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_side.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_side.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,71 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGY_CARTESIAN_SIDE_HPP
+#define GGL_STRATEGY_CARTESIAN_SIDE_HPP
+
+
+
+#include <ggl/geometries/point_xy.hpp>
+#include <ggl/geometries/segment.hpp>
+
+#include <ggl/util/select_coordinate_type.hpp>
+
+
+
+namespace ggl
+{
+namespace strategy
+{
+ namespace side
+ {
+
+ template <typename P, typename PS>
+ struct xy_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
+ static inline typename select_coordinate_type<P, PS>::type
+ side(const segment<const PS>& s, const P& p)
+ {
+ typedef typename select_coordinate_type<P, PS>::type T;
+
+ // Todo: might be changed to subtract_point
+ T dx = get<1, 0>(s) - get<0, 0>(s);
+ T dy = get<1, 1>(s) - get<0, 1>(s);
+ T dpx = get<0>(p) - get<0, 0>(s);
+ T dpy = get<1>(p) - get<0, 1>(s);
+ return dx * dpy - dy * dpx;
+ }
+
+
+ static inline int side(const P& p0, const P& p1, const P& p2)
+ {
+ typename coordinate_type<P>::type s = side(segment<const P>(p0, p1), p2);
+ return s > 0 ? 1 : s < 0 ? -1 : 0;
+ }
+ };
+
+ } // namespace side
+} // namespace strategy
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename P, typename PS>
+struct strategy_side<cartesian_tag, P, PS>
+{
+ typedef strategy::side::xy_side<P, PS> type;
+};
+#endif
+
+} // namespace ggl
+
+
+#endif // GGL_STRATEGY_CARTESIAN_SIDE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_within.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/cartesian/cart_within.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,100 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGY_CARTESIAN_WITHIN_HPP
+#define GGL_STRATEGY_CARTESIAN_WITHIN_HPP
+
+
+
+#include <ggl/geometries/segment.hpp>
+
+
+
+namespace ggl
+{
+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 P, typename PS = P>
+ struct franklin
+ {
+ private :
+ /*! subclass to keep state */
+ struct crossings
+ {
+ P p;
+ bool crosses;
+ explicit crossings(const P& ap)
+ : p(ap)
+ , crosses(false)
+ {}
+ bool within() const
+ {
+ return crosses;
+ }
+ };
+
+ public :
+
+ typedef crossings state_type;
+
+ inline bool operator()(const segment<const PS>& s, state_type& state) const
+ {
+ /* Algorithm:
+ if (
+ ( (y2 <= py && py < y1)
+ || (y1 <= py && py < y2) )
+ && (px < (x1 - x2)
+ * (py - y2)
+ / (y1 - y2) + x2)
+ )
+ crosses = ! crosses
+ */
+
+
+ if (
+ ((get<1, 1>(s) <= get<1>(state.p) && get<1>(state.p) < get<0, 1>(s))
+ || (get<0, 1>(s) <= get<1>(state.p) && get<1>(state.p) < get<1, 1>(s)))
+ && (get<0>(state.p) < (get<0, 0>(s) - get<1, 0>(s))
+ * (get<1>(state.p) - get<1, 1>(s))
+ / (get<0, 1>(s) - get<1, 1>(s)) + get<1, 0>(s))
+ )
+ {
+ state.crosses = ! state.crosses;
+ }
+ return true;
+ }
+ };
+
+
+
+ } // namespace within
+
+
+
+} // namespace strategy
+
+
+
+
+
+} // namespace ggl
+
+
+#endif // GGL_STRATEGY_CARTESIAN_WITHIN_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/distance_result.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/distance_result.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,265 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRY_STRATEGIES_DISTANCE_RESULT_HPP
+#define GGL_GEOMETRY_STRATEGIES_DISTANCE_RESULT_HPP
+
+#include <utility>
+#include <cmath>
+#include <limits>
+#include <iostream>
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+namespace ggl {
+
+/*!
+ \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
+ \note It might be templatized with a T
+*/
+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
+ {
+#if defined(NUMERIC_ADAPTOR_INCLUDED)
+ return boost::sqrt(m_squared_distance);
+#else
+ return std::sqrt((long double)m_squared_distance);
+#endif
+ }
+
+ // 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 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 << ggl::distance( )
+ template <typename CH, typename TR>
+ inline friend std::basic_ostream<CH, TR>& operator<<(std::basic_ostream<CH, TR>& 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<ggl::cartesian_distance<R>, T>
+ {
+ static inline ggl::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<ggl::cartesian_distance<T> >
+ {
+ static inline bool apply(ggl::cartesian_distance<T> const& value)
+ {
+ return value.very_small();
+ }
+ };
+
+
+ }
+}
+#endif
+
+
+/*!
+ \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);
+}
+
+} // namespace ggl
+
+
+#endif // GGL_GEOMETRY_STRATEGIES_DISTANCE_RESULT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/intersection_result.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/intersection_result.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,167 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_INTERSECTION_RESULT_HPP
+#define GGL_INTERSECTION_RESULT_HPP
+
+#if defined(HAVE_MATRIX_AS_STRING)
+#include <string>
+#endif
+
+namespace ggl
+{
+
+/*!
+ \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 P>
+struct segment_intersection_points
+{
+ int count;
+ P intersections[2];
+
+ segment_intersection_points()
+ : count(0)
+ {}
+};
+
+} // namespace ggl
+
+
+#endif // GGL_INTERSECTION_RESULT_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/spherical/haversine.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/spherical/haversine.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,257 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGY_SPHERICAL_DISTANCE_HPP
+#define GGL_STRATEGY_SPHERICAL_DISTANCE_HPP
+
+
+#include <ggl/core/cs.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/core/access.hpp>
+#include <ggl/core/radian_access.hpp>
+
+
+#include <ggl/strategies/strategy_traits.hpp>
+
+#include <ggl/strategies/distance_result.hpp>
+
+#include <ggl/util/get_cs_as_radian.hpp>
+
+
+
+namespace ggl
+{
+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 P1, typename P2 = P1>
+ class haversine
+ {
+ public :
+ //typedef spherical_distance return_type;
+ typedef double return_type;
+
+ inline haversine(double r = constants::average_earth_radius)
+ : m_radius(r)
+ {}
+
+ inline return_type operator()(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 :
+ double m_radius;
+ typedef typename coordinate_type<P1>::type T1;
+ typedef typename coordinate_type<P2>::type T2;
+
+ inline return_type calc(const T1& lon1, const T1& lat1, const T2& lon2, const T2& 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);
+ }
+ };
+
+
+
+ /*!
+ \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
+ \tparam P point type
+ \tparam S segment type
+ */
+ template <typename P, typename S>
+ class ll_point_segment
+ {
+ public :
+ typedef double return_type;
+
+ inline ll_point_segment(double r = constants::average_earth_radius) : m_radius(r)
+ {}
+
+ inline return_type operator()(P const& p, S const& s) const
+ {
+ PR pr, ps1, ps2;
+
+ // Select transformation strategy and transform to radians (if necessary)
+ typename strategy_transform<
+ typename cs_tag<P>::type,
+ typename cs_tag<PR>::type,
+ typename coordinate_system<P>::type,
+ typename coordinate_system<PR>::type,
+ dimension<P>::value,
+ dimension<PR>::value,
+ P, PR>::type transform_strategy;
+
+
+ // TODO
+ // ASSUMPTION: segment
+ // SOLVE THIS USING OTHER FUNCTIONS using get<,>
+ transform_strategy(p, pr);
+ transform_strategy(s.first, ps1);
+ transform_strategy(s.second, ps2);
+ return calc(pr, ps1, ps2);
+ }
+
+ private :
+ typedef point
+ <
+ typename coordinate_type<P>::type,
+ ggl::dimension<P>::type::value,
+ typename ggl::detail::get_cs_as_radian
+ <
+ typename coordinate_system<P>::type
+ >::type
+ > PR;
+ double m_radius;
+
+ /// Calculate course (bearing) between two points. Might be moved to a "course formula" ...
+ inline double course(PR const& p1, PR const& p2) const
+ {
+ /***
+ Course between points
+
+ We obtain the initial course, tc1, (at point 1) from point 1 to point 2 by the following. The formula fails if the initial point is a pole. We can special case this with:
+
+ IF (cos(lat1) < EPS) // EPS a small number ~ machine precision
+ IF (lat1 > 0): tc1= pi // starting from N pole
+ ELSE: tc1= 2*pi // starting from S pole
+ ENDIF
+ ENDIF
+
+ For starting points other than the poles:
+ IF sin(lon2-lon1)<0: tc1=acos((sin(lat2)-sin(lat1)*cos(d))/(sin(d)*cos(lat1)))
+ ELSE: tc1=2*pi-acos((sin(lat2)-sin(lat1)*cos(d))/(sin(d)*cos(lat1)))
+ ENDIF
+
+ An alternative formula, not requiring the pre-computation of d, the distance between the points, is:
+ tc1=mod(atan2(sin(lon1-lon2)*cos(lat2),
+ cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(lon1-lon2))
+ , 2*pi)
+ ***/
+ double dlon = get<0>(p2) - get<0>(p1);
+ double cos_p2lat = cos(get<1>(p2));
+ return atan2(sin(dlon) * cos_p2lat,
+ cos(get<1>(p1)) * sin(get<1>(p2))
+ - sin(get<1>(p1)) * cos_p2lat * cos(dlon));
+ }
+
+ inline return_type calc(PR const& p, PR const& sp1, PR const& sp2) const
+ {
+ /***
+ Cross track error:
+ Suppose you are proceeding on a great circle route from A to B (course =crs_AB) and end up at D, perhaps off course.
+ (We presume that A is ot a pole!) You can calculate the course from A to D (crs_AD) and the distance from A to D (dist_AD)
+ using the formulae above. In shifteds of these the cross track error, XTD, (distance off course) is given by
+
+ XTD =asin(sin(dist_AD)*sin(crs_AD-crs_AB))
+
+ (positive XTD means right of course, negative means left)
+ (If the point A is the N. or S. Pole replace crs_AD-crs_AB with
+ lon_D-lon_B or lon_B-lon_D, respectively.)
+ ***/
+
+ // Calculate distances, in radians, on the unit sphere
+ // It seems not useful to let this strategy be templatized, it should be in radians and on the unit sphere
+ strategy::distance::haversine<PR, PR> strategy(1.0);
+ double d1 = strategy(sp1, p);
+
+ // Actually, calculation of d2 not necessary if we know that the projected point is on the great circle...
+ double d2 = strategy(sp2, p);
+
+ // Source: http://williams.best.vwh.net/avform.htm
+
+ double crs_AD = course(sp1, p);
+ double crs_AB = course(sp1, sp2);
+ double XTD = fabs(asin(sin(d1) * sin(crs_AD - crs_AB)));
+
+ // Return shortest distance, either to projected point on segment sp1-sp2, or to sp1, or to sp2
+ return return_type(m_radius * (std::min)((std::min)(d1, d2), XTD));
+ }
+ };
+
+
+
+
+
+ } // namespace distance
+
+
+
+
+} // namespace strategy
+
+
+#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 Point, typename Segment>
+struct strategy_distance_segment<spherical_tag, spherical_tag, Point, Segment>
+{
+ typedef strategy::distance::ll_point_segment<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::ll_point_segment<Point, Segment> type;
+};
+
+
+
+
+template <typename P1, typename P2>
+struct strategy_tag<strategy::distance::haversine<P1, P2> >
+{
+ typedef strategy_tag_distance_point_point type;
+};
+
+template <typename Point, typename Segment>
+struct strategy_tag<strategy::distance::ll_point_segment<Point, Segment> >
+{
+ typedef strategy_tag_distance_point_segment type;
+};
+
+
+
+#endif
+
+
+
+
+
+
+} // namespace ggl
+
+
+#endif // GGL_STRATEGY_SPHERICAL_DISTANCE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/spherical/sph_area.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/spherical/sph_area.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,167 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRY_STRATEGIES_SPHERICAL_SPH_AREA_HPP
+#define GGL_GEOMETRY_STRATEGIES_SPHERICAL_SPH_AREA_HPP
+
+#include <ggl/geometries/segment.hpp>
+#include <ggl/strategies/spherical/haversine.hpp>
+#include <ggl/strategies/strategy_transform.hpp>
+
+#include <ggl/util/get_cs_as_radian.hpp>
+
+namespace ggl
+{
+namespace strategy
+{
+ namespace area
+ {
+
+
+
+ /*!
+ \brief Area calculation by spherical excess
+ \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 P>
+ class by_spherical_excess
+ {
+ private :
+ struct excess_sum
+ {
+ double m_sum;
+ double m_radius;
+
+ // TODO: make this 1.0 & implement other construct to let user specify
+ inline excess_sum(double radius = constants::average_earth_radius)
+ : m_sum(0)
+ , m_radius(radius)
+ {}
+ inline double area() const
+ {
+ return - m_sum * m_radius * m_radius;
+ //constants::average_earth_radius * constants::average_earth_radius;
+ }
+ };
+
+ // Distances are calculated on unit sphere here
+ strategy::distance::haversine<P, P> m_unit_sphere;
+ double m_radius;
+
+ public :
+ typedef double return_type;
+ typedef excess_sum state_type;
+
+ by_spherical_excess(double radius = 1.0)
+ : m_unit_sphere(1)
+ , m_radius(radius)
+ {}
+
+ inline bool operator()(segment<const P> const& segment, state_type& state) const
+ {
+ if (get<0>(segment.first) != get<0>(segment.second))
+ {
+ typedef point
+ <
+ typename coordinate_type<P>::type,
+ 2,
+ typename ggl::detail::get_cs_as_radian
+ <
+ typename coordinate_system<P>::type
+ >::type
+ > PR;
+ PR p1, p2;
+
+ // Select transformation strategy and transform to radians (if necessary)
+ typename strategy_transform<
+ typename cs_tag<P>::type,
+ typename cs_tag<PR>::type,
+ typename coordinate_system<P>::type,
+ typename coordinate_system<PR>::type,
+ dimension<P>::value,
+ dimension<PR>::value,
+ P, PR>::type transform_strategy;
+
+ transform_strategy(segment.first, p1);
+ transform_strategy(segment.second, p2);
+
+ // Distance p1 p2
+ double a = m_unit_sphere(segment.first, segment.second);
+ // Sides on unit sphere to south pole
+ double b = 0.5 * math::pi - ggl::get<1>(p2);
+ double c = 0.5 * math::pi - ggl::get<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(fabs(tan(s / 2)
+ * tan((s - a) / 2)
+ * tan((s - b) / 2)
+ * tan((s - c) / 2))));
+
+ E = fabs(E);
+
+ // In right direction: positive, add area. In left direction: negative, subtract area.
+ // Longitude comparisons are not so obvious. If one is negative, other is positive,
+ // we have to take the date into account.
+ // TODO: check this / enhance this, should be more robust. See also the "grow" for ll
+ // TODO: use minmax or "smaller"/"compare" strategy for this
+ double lon1 = ggl::get<0>(p1) < 0
+ ? ggl::get<0>(p1) + math::two_pi
+ : ggl::get<0>(p1);
+ double lon2 = ggl::get<0>(p2) < 0
+ ? ggl::get<0>(p2) + math::two_pi
+ : ggl::get<0>(p2);
+
+ if (lon2 < lon1)
+ {
+ E= -E;
+ }
+
+ state.m_sum += E;
+ }
+ return true;
+ }
+ };
+
+ } // namespace area
+
+} // namespace strategy
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename LL>
+struct strategy_area<spherical_tag, LL>
+{
+ typedef strategy::area::by_spherical_excess<LL> type;
+};
+
+template <typename LL>
+struct strategy_area<geographic_tag, LL>
+{
+ typedef strategy::area::by_spherical_excess<LL> type;
+};
+#endif
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRY_STRATEGIES_SPHERICAL_SPH_AREA_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/spherical/sph_envelope.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/spherical/sph_envelope.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,176 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_GEOMETRY_STRATEGIES_SPHERICAL_SPH_ENVELOPE_HPP
+#define GGL_GEOMETRY_STRATEGIES_SPHERICAL_SPH_ENVELOPE_HPP
+
+#include <boost/numeric/conversion/bounds.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+// NOTE: maybe evaluate/rework this using new "compare" strategy
+// - implement "compare" for latlong (e.g. return true if distance-difference < 90 deg, so 170 < -170 but 90 > -180)
+
+#include <ggl/strategies/spherical/haversine.hpp>
+
+namespace ggl
+{
+namespace strategy
+{
+ namespace envelope
+ {
+ // envelope calculation strategy for latlong-points
+ namespace shift
+ {
+ template <typename D>
+ struct shifted
+ {
+ };
+
+ template<>
+ struct shifted<radian>
+ {
+ inline static double shift() { return math::two_pi; }
+ };
+ template<>
+ struct shifted<degree>
+ {
+ inline static double shift() { return 360.0; }
+ };
+
+ }
+
+ /*!
+ \par Algorithm:
+ The envelope of latlong-points cannot be implemented as for xy-points. Suppose the
+ envelope of the Aleutian Islands must be calculated. The span from 170E to 170W, from -170 to 170.
+ Of course the real envelope is not -170..170 but 170..-170.
+ On the other hand, there might be geometries that indeed span from -170 to 170. If there are
+ two points, it is not known. If there are points in between, we probably should take the shorter
+ range. So we do that for the moment.
+ We shift coordinates and do as if we live in a world with longitude coordinates from 0 - 360,
+ where 0 is still at Greenwich. Longitude ranges are then calculated twice: one for real world,
+ one for the shifted world.
+ The shortest range is taken for the bounding box. This might have coordinates > 180
+ */
+
+ template <typename P, typename B>
+ struct grow_ll
+ {
+
+ struct state
+ {
+ typedef typename coordinate_type<B>::type T;
+ bool has_west;
+ T min_lat, max_lat;
+ T min_lon1, min_lon2, max_lon1, max_lon2;
+ B& mbr;
+
+ state(B& b)
+ : mbr(b)
+ , has_west(false)
+ , min_lat(boost::numeric::bounds<T>::highest())
+ , min_lon1(boost::numeric::bounds<T>::highest())
+ , min_lon2(boost::numeric::bounds<T>::highest())
+ , max_lat(boost::numeric::bounds<T>::lowest())
+ , max_lon1(boost::numeric::bounds<T>::lowest())
+ , max_lon2(boost::numeric::bounds<T>::lowest())
+ {}
+
+ template <typename T>
+ void take_minmax(const T& value, T& min_value, T& max_value)
+ {
+ if (value < min_value)
+ {
+ min_value = value;
+ }
+ if (value > max_value)
+ {
+ max_value = value;
+ }
+ }
+
+ void grow(const P& p)
+ {
+ // For latitude, we can take the min/max
+ take_minmax(get<1>(p), min_lat, max_lat);
+
+
+ // For longitude, we do the same...
+ take_minmax(get<0>(p), min_lon1, max_lon1);
+
+ // But we also add 360 (2pi) if it is negative
+ T value = get<0>(p);
+ while(value < 0)
+ {
+ has_west = true;
+ value += shift::shifted<typename coordinate_system<P>::type::units>::shift();
+ }
+ while (value > math::two_pi)
+ {
+ value -= shift::shifted<typename coordinate_system<P>::type::units>::shift();
+ }
+ take_minmax(value, min_lon2, max_lon2);
+ }
+
+ ~state()
+ //void envelope(box<PB>& mbr)
+ {
+ // For latitude it is easy
+ set<min_corner, 1>(mbr, min_lat);
+ set<max_corner, 1>(mbr, max_lat);
+
+ if (! has_west)
+ {
+ set<min_corner, 0>(mbr, min_lon1);
+ set<max_corner, 0>(mbr, max_lon1);
+ }
+ else
+ {
+ // Get both ranges
+ T diff1 = max_lon1 - min_lon1;
+ T diff2 = max_lon2 - min_lon2;
+
+ //std::cout << "range 1: " << min_lon1 * math::r2d << ".." << max_lon1 * math::r2d << std::endl;
+ //std::cout << "range 2: " << min_lon2 * math::r2d << ".." << max_lon2 * math::r2d << std::endl;
+
+ if (diff1 <= diff2)
+ {
+ set<min_corner, 0>(mbr, min_lon1);
+ set<max_corner, 0>(mbr, max_lon1);
+ }
+ else
+ {
+ set<min_corner, 0>(mbr, min_lon2);
+ set<max_corner, 0>(mbr, max_lon2);
+ }
+ }
+ }
+ };
+
+ typedef state state_type;
+
+ void operator()(const P& p, state_type& s) const
+ {
+ s.grow(p);
+ }
+ };
+ } // namespace envelope
+} // namespace strategy
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename P, typename B>
+struct strategy_envelope<geographic_tag, geographic_tag, P, B>
+{
+ typedef strategy::envelope::grow_ll<P, B> type;
+};
+#endif
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRY_STRATEGIES_SPHERICAL_SPH_ENVELOPE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/strategies.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/strategies.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,38 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGIES_HPP
+#define GGL_STRATEGIES_HPP
+
+
+#include <ggl/strategies/strategy_traits.hpp>
+
+#include <ggl/strategies/cartesian/cart_area.hpp>
+#include <ggl/strategies/cartesian/cart_centroid.hpp>
+#include <ggl/strategies/cartesian/cart_compare.hpp>
+#include <ggl/strategies/cartesian/cart_distance.hpp>
+#include <ggl/strategies/cartesian/cart_envelope.hpp>
+#include <ggl/strategies/cartesian/cart_side.hpp>
+#include <ggl/strategies/cartesian/cart_within.hpp>
+
+#include <ggl/strategies/spherical/sph_area.hpp>
+#include <ggl/strategies/spherical/haversine.hpp>
+#include <ggl/strategies/spherical/sph_envelope.hpp>
+
+#include <ggl/strategies/agnostic/agn_convex_hull.hpp>
+#include <ggl/strategies/agnostic/agn_simplify.hpp>
+#include <ggl/strategies/agnostic/agn_within.hpp>
+
+#include <ggl/strategies/strategy_transform.hpp>
+
+#include <ggl/strategies/transform/matrix_transformers.hpp>
+#include <ggl/strategies/transform/map_transformer.hpp>
+#include <ggl/strategies/transform/inverse_transformer.hpp>
+
+
+#endif // GGL_STRATEGIES_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/strategy_traits.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/strategy_traits.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,231 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGIES_STRATEGY_TRAITS_HPP
+#define GGL_STRATEGIES_STRATEGY_TRAITS_HPP
+
+#include <ggl/core/cs.hpp>
+#include <ggl/strategies/distance_result.hpp>
+
+// File containing strategy traits classes, to be specialized in other files
+// (This file might be splitted resulting into several small files)
+
+namespace ggl
+{
+
+namespace strategy
+{
+ /*!
+ \brief Indicate compiler/library user that strategy is not implemented.
+ \details The strategy_traits class define strategies for point types or for point type
+ combinations. If there is no implementation for that specific point type, or point type
+ combination, the calculation cannot be done. To indicate this, this not_implemented
+ class is used as a typedef stub.
+
+ */
+ struct not_implemented {};
+}
+
+
+/*!
+ \brief Traits class binding an area strategy to a coordinate system
+ \ingroup area
+ \tparam T tag of coordinate system
+ \tparam P point-type
+*/
+template <typename T, typename P>
+struct strategy_area
+{
+ typedef strategy::not_implemented type;
+};
+
+/*!
+ \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;
+};
+
+
+/*!
+ \brief Traits class binding a centroid calculation strategy to a coordinate system
+ \ingroup centroid
+ \tparam T tag of coordinate system
+ \tparam P point-type
+ \tparam PS segment point-type
+*/
+template <typename T, typename P, typename PS>
+struct strategy_centroid
+{
+ typedef strategy::not_implemented type;
+};
+
+
+/*!
+ \brief Traits class binding envelope strategy to a coordinate system
+ \ingroup envelope
+ \tparam TP tag of coordinate system of point
+ \tparam TB tag of coordinate system of box, usually same as TP
+ \tparam P point-type
+ \tparam B box-type
+*/
+template <typename TP, typename TB, typename P, typename B>
+struct strategy_envelope
+{
+ typedef strategy::not_implemented type;
+};
+
+
+/*!
+ \brief Traits class binding a convex hull calculation strategy to a coordinate system
+ \ingroup convex_hull
+ \tparam T tag of coordinate system
+ \tparam P point-type of input points
+*/
+template <typename T, typename P>
+struct strategy_convex_hull
+{
+ typedef strategy::not_implemented type;
+};
+
+
+/*!
+ \brief Traits class binding a within determination strategy to a coordinate system
+ \ingroup within
+ \tparam TP tag of coordinate system of point-type
+ \tparam TS tag of coordinate system of segment-type
+ \tparam P point-type of input points
+ \tparam PS point-type of input segment-points
+*/
+template <typename TP, typename TS, typename P, typename PS>
+struct strategy_within
+{
+ typedef strategy::not_implemented type;
+};
+
+
+/*!
+ \brief Traits class binding a side determination strategy to a coordinate system
+ \ingroup util
+ \tparam T tag of coordinate system of point-type
+ \tparam P point-type of input points
+ \tparam PS point-type of input points
+*/
+template <typename T, typename P, typename PS = P>
+struct strategy_side
+{
+ typedef strategy::not_implemented type;
+};
+
+
+
+/*!
+ \brief Traits class binding a comparing strategy to a coordinate system
+ \ingroup util
+ \tparam T tag of coordinate system of point-type
+ \tparam P point-type
+ \tparam D dimension to compare
+*/
+template <typename T, typename P, size_t D>
+struct strategy_compare
+{
+ typedef strategy::not_implemented type;
+};
+
+
+/*!
+ \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 CS_TAG 1,2 coordinate system tags
+ \tparam CS 1,2 coordinate system
+ \tparam D 1, 2 dimension
+ \tparam P 1, 2 point type
+ */
+template <typename CS_TAG1, typename CS_TAG2,
+ typename CS1, typename CS2,
+ size_t D1, size_t D2,
+ typename P1, typename P2>
+struct strategy_transform
+{
+ typedef strategy::not_implemented type;
+};
+
+
+/*!
+ \brief Traits class binding a parsing strategy to a coordinate system
+ \ingroup parse
+ \tparam T tag of coordinate system of point-type
+ \tparam CS coordinate system
+*/
+template <typename T, typename CS>
+struct strategy_parse
+{
+ typedef strategy::not_implemented type;
+};
+
+
+
+
+/*!
+ \brief Shortcut to define return type of distance strategy
+ \ingroup distance
+ \tparam G1 first geometry
+ \tparam G2 second geometry
+ */
+template <typename G1, typename G2 = G1>
+struct distance_result
+{
+ typedef typename point_type<G1>::type P1;
+ typedef typename point_type<G2>::type P2;
+ typedef typename strategy_distance<
+ typename cs_tag<P1>::type,
+ typename cs_tag<P2>::type, P1, P2>::type S;
+ typedef typename S::return_type type;
+};
+
+
+
+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 ggl
+
+#endif // GGL_STRATEGIES_STRATEGY_TRAITS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/strategy_transform.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/strategy_transform.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,358 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGY_TRANSFORM_HPP
+#define GGL_STRATEGY_TRANSFORM_HPP
+
+#include <cstddef>
+#include <cmath>
+#include <functional>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <ggl/arithmetic/arithmetic.hpp>
+#include <ggl/core/access.hpp>
+#include <ggl/core/coordinate_dimension.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/util/copy.hpp>
+#include <ggl/util/math.hpp>
+#include <ggl/util/select_coordinate_type.hpp>
+
+namespace ggl
+{
+
+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(const Src& 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(const Src& 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 operator()(const P& 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 operator()(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 operator()(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 operator()(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 operator()(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 operator()(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 operator()(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 operator()(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 ggl
+
+#endif // GGL_STRATEGY_TRANSFORM_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/transform/inverse_transformer.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/transform/inverse_transformer.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,65 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP
+#define GGL_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP
+
+#include <boost/numeric/ublas/lu.hpp>
+#include <boost/numeric/ublas/io.hpp>
+#include <ggl/strategies/transform/matrix_transformers.hpp>
+
+namespace ggl
+{
+
+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 ggl
+
+#endif // GGL_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/transform/map_transformer.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/transform/map_transformer.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,145 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP
+#define GGL_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP
+
+
+#include <ggl/strategies/transform/matrix_transformers.hpp>
+
+
+namespace ggl
+{
+
+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;
+
+
+ // Calculate appropriate scale, take min because whole box must fit
+ // Scale is in PIXELS/MAPUNITS (meters)
+ double sx = (px2 - px1) / (wx2 - wx1);
+ double sy = (py2 - py1) / (wy2 - wy1);
+
+ if (SameScale)
+ {
+ double scale = (std::min)(sx, sy);
+ sx = scale;
+ sy = scale;
+ }
+
+ // Calculate centerpoints
+ double wmx = (wx1 + wx2) / 2.0;
+ double wmy = (wy1 + wy2) / 2.0;
+ double pmx = (px1 + px2) / 2.0;
+ double pmy = (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 ggl
+
+
+#endif // GGL_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/strategies/transform/matrix_transformers.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/strategies/transform/matrix_transformers.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,357 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_STRATEGIES_MATRIX_TRANSFORMERS_HPP
+#define GGL_STRATEGIES_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 <ggl/core/coordinate_dimension.hpp>
+
+
+namespace ggl
+{
+
+
+namespace strategy { namespace transform {
+
+
+/*!
+ \brief Transformation strategy to do an affine matrix transformation in Cartesian system
+ \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,
+ 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()
+ : m_matrix(3, 3)
+ {
+ }
+
+
+ inline bool operator()(const P1& p1, P2& p2) const
+ {
+ assert_dimension_greater_equal<P1, 2>();
+ assert_dimension_greater_equal<P2, 2>();
+
+ const coordinate_type& c1 = get<0>(p1);
+ const coordinate_type& c2 = get<1>(p1);
+
+ typedef typename ggl::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;
+ }
+
+ const matrix_type& 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 operator()(const P1& p1, P2& p2) const
+ {
+ const coordinate_type& c1 = get<0>(p1);
+ const coordinate_type& c2 = get<1>(p1);
+ const coordinate_type& c3 = get<2>(p1);
+
+ typedef typename ggl::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;
+ }
+
+ const matrix_type& matrix() const { return m_matrix; }
+};
+
+
+
+
+/*!
+ \brief Transformation strategy to translate in Cartesian system
+ \ingroup transform
+ \see http://www.devmaster.net/wiki/Transformation_matrices
+ \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 = ggl::dimension<P1>::type::value,
+ std::size_t Dimension2 = ggl::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 Transformation strategy to scale in Cartesian system
+ \ingroup transform
+ \see http://www.devmaster.net/wiki/Transformation_matrices
+ \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 = ggl::dimension<P1>::type::value,
+ std::size_t Dimension2 = ggl::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)
+ {}
+};
+
+
+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)
+ {}
+};
+
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail {
+
+template <typename DegreeOrRadian>
+struct as_radian {};
+
+template <>
+struct as_radian<radian>
+{
+ static inline double get(double const& value)
+ {
+ return value;
+ }
+};
+
+template <>
+struct as_radian<degree>
+{
+ static inline double get(double const& value)
+ {
+ return value * math::d2r;
+ }
+
+};
+
+
+template
+<
+ typename P1, typename P2,
+ std::size_t Dimension1 = ggl::dimension<P1>::type::value,
+ std::size_t Dimension2 = ggl::dimension<P2>::type::value
+>
+struct rad_rotate_transformer
+ : ublas_transformer<P1, P2, Dimension1, Dimension2>
+{
+ inline rad_rotate_transformer(double const& angle)
+ : ublas_transformer<P1, P2, Dimension1, Dimension2>(
+ cos(angle), sin(angle), 0,
+ -sin(angle), cos(angle), 0,
+ 0, 0, 1)
+ {}
+};
+
+}
+#endif
+
+
+/*!
+ \brief Transformation strategy to rotate in Cartesian system
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ \tparam DegreeOrRadian degree/or/radian, type of rotation angle specification
+ \note Not yet in 3D, the 3D version requires special things to allow for
+ rotation around X, Y, Z or arbitrary axis
+ \see http://www.devmaster.net/wiki/Transformation_matrices
+ \note The 3D version will not compile
+ */
+template <typename P1, typename P2, typename DegreeOrRadian>
+struct rotate_transformer : detail::rad_rotate_transformer<P1, P2>
+{
+ inline rotate_transformer(double const& angle)
+ : detail::rad_rotate_transformer
+ <
+ P1, P2
+ >(detail::as_radian<DegreeOrRadian>::get(angle))
+ {}
+
+};
+
+
+}} // namespace strategy::transform
+
+} // namespace ggl
+
+#endif // GGL_STRATEGIES_MATRIX_TRANSFORMERS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/util/as_range.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/util/as_range.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,95 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_UTIL_AS_RANGE_HPP
+#define GGL_UTIL_AS_RANGE_HPP
+
+#include <boost/type_traits.hpp>
+
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/ring_type.hpp>
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+namespace ggl {
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename GeometryTag, typename Geometry>
+struct as_range_type
+{
+ typedef Geometry type;
+};
+
+template <typename Geometry>
+struct as_range_type<polygon_tag, Geometry>
+{
+ typedef typename ring_type<Geometry>::type type;
+};
+
+
+
+template <typename GeometryTag, typename Geometry, typename Range>
+struct as_range
+{
+ static inline Range const& get(Geometry const& input)
+ {
+ return input;
+ }
+};
+
+template <typename Geometry, typename Range>
+struct as_range<polygon_tag, Geometry, Range>
+{
+ static inline Range const& get(Geometry const& input)
+ {
+ return exterior_ring(input);
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Meta-function utility returning either type itself, or outer ring
+ \details Utility to handle polygon's outer ring as a range
+\ingroup utility
+*/
+template <typename Geometry>
+struct as_range_type
+{
+ typedef typename dispatch::as_range_type
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::type type;
+};
+
+/*!
+\brief Function getting either the range (ring, linestring) itself
+or the outer ring
+ \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
+ >::get(input);
+}
+
+} // namespace ggl
+
+#endif // GGL_UTIL_AS_RANGE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/util/assign_box_corner.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/util/assign_box_corner.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,59 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_UTIL_ASSIGN_BOX_CORNER_HPP
+#define GGL_UTIL_ASSIGN_BOX_CORNER_HPP
+
+#include <cstddef>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <ggl/core/coordinate_dimension.hpp>
+
+// TODO: merge with "assign"
+
+namespace ggl
+{
+
+/*!
+ \brief Assign one point of a 2D box
+ \ingroup assign
+ \todo will be merged with assign
+*/
+template <std::size_t C1, std::size_t C2, typename B, typename P>
+inline void assign_box_corner(B const& box, P& point)
+{
+ // Be sure both are 2-Dimensional
+ assert_dimension<B, 2>();
+ assert_dimension<P, 2>();
+
+ // Copy coordinates
+ typedef typename coordinate_type<P>::type coordinate_type;
+
+ set<0>(point, boost::numeric_cast<coordinate_type>(get<C1, 0>(box)));
+ set<1>(point, boost::numeric_cast<coordinate_type>(get<C2, 1>(box)));
+}
+
+/*!
+ \brief Assign the 4 points of a 2D box
+ \ingroup assign
+ \todo will be merged with assign
+ \note The order can be crucial. Most logical is LOWER, UPPER and sub-order LEFT, RIGHT
+*/
+template <typename B, typename P>
+inline void assign_box_corners(B const& box, P& lower_left, P& lower_right, P& upper_left, P& upper_right)
+{
+ assign_box_corner<min_corner, min_corner>(box, lower_left);
+ assign_box_corner<max_corner, min_corner>(box, lower_right);
+ assign_box_corner<min_corner, max_corner>(box, upper_left);
+ assign_box_corner<max_corner, max_corner>(box, upper_right);
+}
+
+} // namespace
+
+#endif // GGL_UTIL_ASSIGN_BOX_CORNER_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/util/copy.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/util/copy.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,76 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_UTIL_COPY_HPP
+#define GGL_UTIL_COPY_HPP
+
+#include <cstddef>
+
+#include <boost/concept/requires.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/concept_check.hpp>
+
+#include <ggl/core/concepts/point_concept.hpp>
+
+
+
+namespace ggl
+{
+
+#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(const Src& 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(const Src& source, Dst& dest)
+ {
+ boost::ignore_unused_variable_warning(source);
+ boost::ignore_unused_variable_warning(dest);
+ }
+};
+
+}} // 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(const Src& 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>::value>::copy(source, dest);
+}
+
+} // namespace ggl
+
+#endif // GGL_UTIL_COPY_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/util/for_each_coordinate.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/util/for_each_coordinate.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,64 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_UTIL_FOR_EACH_COORDINATE_HPP
+#define GGL_UTIL_FOR_EACH_COORDINATE_HPP
+
+#include <boost/concept/requires.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+
+namespace ggl
+{
+
+#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 ggl
+
+#endif // GGL_UTIL_FOR_EACH_COORDINATE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/util/get_cs_as_radian.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/util/get_cs_as_radian.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,46 @@
+// Generic Geometry Library
+//
+// Copyright Bruno Lalande 2008, 2009
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef GGL_UTIL_GET_CS_AS_RADIAN_HPP
+#define GGL_UTIL_GET_CS_AS_RADIAN_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+
+
+
+
+namespace ggl {
+
+namespace detail {
+
+ template <typename CoordinateSystem>
+ struct get_cs_as_radian {};
+
+ template <typename Units>
+ struct get_cs_as_radian<cs::geographic<Units> >
+ {
+ typedef cs::geographic<radian> type;
+ };
+
+ template <typename Units>
+ struct get_cs_as_radian<cs::spherical<Units> >
+ {
+ typedef cs::spherical<radian> type;
+ };
+
+}
+
+
+
+
+
+} // namespace ggl
+
+#endif // GGL_UTIL_GET_CS_AS_RADIAN_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/util/less.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/util/less.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,64 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_UTIL_LESS_HPP
+#define GGL_UTIL_LESS_HPP
+
+
+namespace ggl
+{
+
+/*!
+ \brief Less predicate for usage in e.g. std::map
+*/
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename P, std::size_t Dimension, std::size_t DimensionCount>
+struct less
+{
+ static inline bool apply(P const& left, P const& right)
+ {
+ typedef typename ggl::coordinate_type<P>::type coordinate_type;
+ coordinate_type const cleft = ggl::get<Dimension>(left);
+ coordinate_type const cright = ggl::get<Dimension>(right);
+
+ return ggl::math::equals(cleft, cright)
+ ? less<P, Dimension + 1, DimensionCount>::apply(left, right)
+ : cleft < cright;
+ ;
+ }
+};
+
+template <typename P, std::size_t DimensionCount>
+struct less<P, DimensionCount, DimensionCount>
+{
+ static inline bool apply(P const&, P const&)
+ {
+ return false;
+ }
+};
+
+}
+#endif
+
+template <typename P>
+struct less
+{
+ inline bool operator()(P const& left, P const& right) const
+ {
+ return detail::less<P, 0,
+ ggl::dimension<P>::type::value>::apply(left, right);
+ }
+};
+
+} // namespace ggl
+
+#endif // GGL_UTIL_LESS_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/util/loop.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/util/loop.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,85 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_UTIL_LOOP_HPP
+#define GGL_UTIL_LOOP_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/geometries/segment.hpp>
+
+namespace ggl
+{
+
+/*!
+ \brief Loops through segments of a container and call specified functor for all segments.
+ \ingroup loop
+ \details for_each like implementation to:
+ - walk over const segments of a linestring/polygon
+ - be able to break out the loop (if the functor returns false)
+ - have a const functor and keep state in separate state-object
+ - we still keep the "functor" here so it might be a function or an object, at this place
+ - in most algorithms the typename F::state_type is used; in those places it must be an object
+
+ \tparam R range type, for example a vector, linestring, linear_ring
+ \tparam F functor type, class or function, not modified by the algorithm
+ \tparam S state type, might be modified
+ \param range range (linestring iterator pair,vector,list,deque) containing points
+ \param functor functor which is called at each const segment
+ \param state state, specified separately from the strategy functor
+ \return false if the functor returns false, otherwise true
+ \par Concepts
+ - \a V
+ - const_iterator begin()
+ - const_iterator end()
+ - value_type
+ - \a F
+ - <em>if it is a function functor</em>: bool \b function (const segment&, state&)
+ - <em>if it is a class functor</em>: bool operator()(const segment&, state&) const
+ - \a S
+ - no specific requirements here, requirments given by F
+ \note Some algorithms from the Generic Geometry Library, for example within, centroid,
+ use this method.
+ \par Examples:
+ First example, using a class functor
+ \dontinclude doxygen_examples.cpp
+ \skip example_loop1
+ \line {
+ \until //:\\
+ Second example, using a function functor and latlong coordinates
+ \dontinclude doxygen_examples.cpp
+ \skip example_loop2
+ \line {
+ \until //:\\
+*/
+template<typename R, typename F, typename S>
+inline bool loop(R const& range, F const& functor, S& state)
+{
+ typedef typename boost::range_const_iterator<R>::type iterator_type;
+
+ iterator_type it = boost::begin(range);
+ if (it != boost::end(range))
+ {
+ iterator_type previous = it++;
+ while(it != boost::end(range))
+ {
+ segment<const typename boost::range_value<R>::type> s(*previous, *it);
+ if (! functor(s, state))
+ {
+ return false;
+ }
+ previous = it++;
+ }
+ }
+ return true;
+}
+
+} // namespace ggl
+
+#endif // GGL_UTIL_LOOP_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/util/math.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/util/math.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,98 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_UTIL_MATH_HPP
+#define GGL_UTIL_MATH_HPP
+
+#include <cmath>
+#include <limits>
+
+#include <boost/math/constants/constants.hpp>
+
+#include <ggl/util/select_most_precise.hpp>
+
+namespace ggl
+{
+
+namespace math
+{
+
+// Maybe replace this by boost equals or boost ublas numeric equals or so
+
+/*!
+ \brief returns true if both arguments are equal.
+
+ equals returns true if both arguments are equal.
+ \param a first argument
+ \param b second argument
+ \return true if a == b
+ \note If both a and b are of an integral type, comparison is done by ==. If one of the types
+ is floating point, comparison is done by abs and comparing with epsilon.
+*/
+
+template <typename T1, typename T2>
+inline bool equals(T1 const& a, T2 const& b)
+{
+ typedef typename select_most_precise<T1, T2>::type select_type;
+
+ // TODO: select on is_fundemental. Otherwise (non-fundamental), take == operator
+ if (std::numeric_limits<select_type>::is_exact)
+ {
+ return a == b;
+ }
+ else
+ {
+ return std::abs(a - b) < std::numeric_limits<select_type>::epsilon();
+ }
+}
+
+
+
+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
+ \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
+
+\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
+
+// To be moved somewhere.
+namespace constants
+{
+
+double const average_earth_radius = 6372795.0;
+
+} // namespace constants
+
+} // namespace ggl
+
+#endif // GGL_UTIL_MATH_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/util/select_coordinate_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/util/select_coordinate_type.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,40 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_UTIL_SELECT_COORDINATE_TYPE_HPP
+#define GGL_UTIL_SELECT_COORDINATE_TYPE_HPP
+
+
+#include <ggl/core/coordinate_type.hpp>
+#include <ggl/util/select_most_precise.hpp>
+
+/*!
+\defgroup utility utility: utilities
+*/
+
+namespace ggl
+{
+
+
+/*!
+ \brief Utility 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 ggl
+
+#endif // GGL_UTIL_SELECT_COORDINATE_TYPE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/util/select_most_precise.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/util/select_most_precise.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,160 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_UTIL_SELECT_MOST_PRECISE_HPP
+#define GGL_UTIL_SELECT_MOST_PRECISE_HPP
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+
+/*!
+\defgroup utility utility: utilities
+*/
+
+namespace ggl
+{
+
+#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 Traits class 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 (small) library in 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 ggl
+
+#endif // GGL_UTIL_SELECT_MOST_PRECISE_HPP
Added: sandbox/ggl/formal_review_request/boost/ggl/util/write_dsv.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review_request/boost/ggl/util/write_dsv.hpp 2009-10-12 08:58:16 EDT (Mon, 12 Oct 2009)
@@ -0,0 +1,375 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. 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 GGL_UTIL_WRITE_DSV_HPP
+#define GGL_UTIL_WRITE_DSV_HPP
+
+#include <iostream>
+#include <string>
+
+#include <boost/concept/assert.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/algorithms/convert.hpp>
+#include <ggl/core/concepts/point_concept.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+#include <ggl/core/ring_type.hpp>
+#include <ggl/core/is_multi.hpp>
+#include <ggl/geometries/linear_ring.hpp>
+
+
+
+namespace ggl
+{
+
+#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)
+ {}
+};
+
+template <typename P, int Dimension, int Count>
+struct stream_coordinate
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os, P const& p,
+ dsv_settings const& settings)
+ {
+ os << (Dimension > 0 ? settings.coordinate_separator : "")
+ << get<Dimension>(p);
+ stream_coordinate<P, Dimension + 1, Count>::apply(os, p, settings);
+ }
+};
+
+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&,
+ dsv_settings const& settings)
+ {}
+};
+
+
+template <typename P, int Index, int Dimension, int Count>
+struct stream_box_corner
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os, P const& p,
+ dsv_settings const& settings)
+ {
+ os << (Dimension > 0 ? settings.coordinate_separator : "")
+ << get<Index, Dimension>(p);
+ stream_box_corner<P, Index, Dimension + 1, Count>::apply(os, p, settings);
+ }
+};
+
+template <typename P, int Index, int Count>
+struct stream_box_corner<P, Index, Count, Count>
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>&, P const&,
+ dsv_settings const& settings)
+ {}
+};
+
+
+
+
+
+/*!
+\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;
+ }
+
+ private:
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point>) );
+};
+
+/*!
+\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;
+
+ // TODO: check EMPTY here
+
+ for (iterator_type it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ os << (first ? "" : settings.point_separator)
+ << settings.point_open;
+
+ stream_coordinate
+ <
+ point, 0, dimension<point>::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;
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point>) );
+};
+
+/*!
+\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;
+
+ os << settings.list_open;
+
+ dsv_range<ring>::apply(os, exterior_ring(poly), settings);
+ for (iterator 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;
+ }
+
+ private:
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<typename point_type<Polygon>::type>) );
+};
+
+template <typename Box, std::size_t Index>
+struct dsv_box_corner
+{
+ 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,
+ dsv_settings const& settings)
+ {
+ os << settings.point_open;
+ stream_box_corner
+ <
+ Box, Index, 0, dimension<Box>::type::value
+ >::apply(os, box, settings);
+ os << settings.point_close;
+ }
+};
+
+
+template <typename Box>
+struct dsv_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,
+ dsv_settings const& settings)
+ {
+ os << settings.list_open;
+ dsv_box_corner<Box, 0>::apply(os, box, settings);
+ os << settings.point_separator;
+ dsv_box_corner<Box, 1>::apply(os, box, 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>
+{};
+
+
+/*!
+\brief Specialization to stream a box as DSV
+*/
+template <typename Box>
+struct dsv<box_tag, false, Box>
+ : detail::dsv::dsv_box<Box>
+{};
+
+
+/*!
+\brief Specialization to stream a ring as DSV
+*/
+template <typename Ring>
+struct dsv<ring_tag, false, Ring>
+ : detail::dsv::dsv_range<Ring>
+{};
+
+
+/*!
+\brief Specialization to stream polygon as DSV
+*/
+template <typename Polygon>
+struct dsv<polygon_tag, false, Polygon>
+ : detail::dsv::dsv_poly<Polygon>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Generic geometry template manipulator class, takes corresponding output class from traits class
+\ingroup dsv
+\details Stream manipulator, streams geometry classes as \ref DSV streams
+\par Example:
+Small example showing how to use the dsv class
+\dontinclude doxygen_examples.cpp
+\skip example_as_dsv_point
+\line {
+\until }
+\note the template parameter must be specified. If that is inconvient, users might use streamdsv
+which streams geometries as manipulators, or the object generator make_dsv
+*/
+template <typename Geometry>
+class dsv_manipulator
+{
+public:
+
+ inline dsv_manipulator(Geometry const& g,
+ detail::dsv::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;
+ detail::dsv::dsv_settings m_settings;
+};
+
+/*!
+\brief Main DSV-streaming function
+\ingroup dsv
+*/
+template <typename Geometry>
+inline 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 = ", "
+ )
+{
+ return dsv_manipulator<Geometry>(geometry,
+ detail::dsv::dsv_settings(coordinate_separator,
+ point_open, point_close, point_separator,
+ list_open, list_close, list_separator));
+}
+
+
+
+} // namespace ggl
+
+#endif // GGL_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