Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r57364 - in sandbox/ggl/formal_review/boost/ggl: . algorithms algorithms/detail algorithms/overlay arithmetic core extensions extensions/gis extensions/gis/geographic extensions/gis/geographic/detail extensions/gis/geographic/strategies extensions/gis/io extensions/gis/io/wkb extensions/gis/io/wkb/detail extensions/gis/io/wkt extensions/gis/io/wkt/detail extensions/io extensions/io/svg geometries geometries/adapted geometries/concepts geometries/concepts/detail geometries/register iterators multi multi/algorithms multi/algorithms/detail multi/algorithms/overlay multi/core multi/geometries multi/geometries/concepts multi/iterators multi/strategies multi/strategies/cartesian multi/util policies policies/relate strategies strategies/agnostic strategies/cartesian strategies/concepts strategies/spherical strategies/transform util
From: barend.gehrels_at_[hidden]
Date: 2009-11-04 12:10:24


Author: barendgehrels
Date: 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
New Revision: 57364
URL: http://svn.boost.org/trac/boost/changeset/57364

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

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/append.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/append.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_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 <ggl/core/access.hpp>
+#include <ggl/core/point_type.hpp>
+#include <ggl/core/tags.hpp>
+
+#include <ggl/geometries/concepts/check.hpp>
+
+#include <ggl/util/copy.hpp>
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace append {
+
+template <typename Geometry, typename Point, bool UseStd>
+struct append_point {};
+
+template <typename Geometry, typename Point>
+struct append_point<Geometry, Point, true>
+{
+ static inline void apply(Geometry& geometry, Point const& point, int , int )
+ {
+ typename point_type<Geometry>::type point_type;
+
+ copy_coordinates(point, point_type);
+ geometry.push_back(point_type);
+ }
+};
+
+template <typename Geometry, typename Point>
+struct append_point<Geometry, Point, false>
+{
+ static inline void apply(Geometry& geometry, Point const& point,
+ int ring_index, int multi_index)
+ {
+ traits::append_point<Geometry, Point>::apply(geometry, point,
+ ring_index, multi_index);
+ }
+};
+
+template <typename Geometry, typename Range, bool UseStd>
+struct append_range
+{
+ typedef typename boost::range_value<Range>::type point_type;
+
+ static inline void apply(Geometry& geometry, Range const& range,
+ int ring_index, int multi_index)
+ {
+ for (typename boost::range_const_iterator<Range>::type
+ it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ append_point<Geometry, point_type, UseStd>::apply(geometry, *it,
+ ring_index, multi_index);
+ }
+ }
+};
+
+template <typename Polygon, typename Point, bool Std>
+struct point_to_poly
+{
+ typedef typename ring_type<Polygon>::type range_type;
+
+ static inline void apply(Polygon& polygon, Point const& point,
+ int ring_index, int )
+ {
+ if (ring_index == -1)
+ {
+ append_point<range_type, Point, Std>::apply(
+ exterior_ring(polygon), point, -1, -1);
+ }
+ else if (ring_index < int(num_interior_rings(polygon)))
+ {
+ append_point<range_type, Point, Std>::apply(
+ interior_rings(polygon)[ring_index], point, -1, -1);
+ }
+ }
+};
+
+template <typename Polygon, typename Range, bool Std>
+struct range_to_poly
+{
+ typedef typename ring_type<Polygon>::type ring_type;
+
+ static inline void apply(Polygon& polygon, Range const& range,
+ int ring_index, int )
+ {
+ if (ring_index == -1)
+ {
+ append_range<ring_type, Range, Std>::apply(
+ exterior_ring(polygon), range, -1, -1);
+ }
+ else if (ring_index < int(num_interior_rings(polygon)))
+ {
+ append_range<ring_type, Range, Std>::apply(
+ interior_rings(polygon)[ring_index], range, -1, -1);
+ }
+ }
+};
+
+}} // namespace detail::append
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// (RoP = range or point, Std = use std library)
+
+// Default case (where RoP will be range/array/etc)
+template <typename Tag, typename TagRoP, typename G, typename RoP, bool Std>
+struct append : detail::append::append_range<G, RoP, Std> {};
+
+// Append a point to any geometry
+template <typename Tag, typename G, typename P, bool Std>
+struct append<Tag, point_tag, G, P, Std>
+ : detail::append::append_point<G, P, Std> {};
+
+// Never possible to append anything to a point/box/n-sphere
+template <typename TagRoP, typename Point, typename RoP, bool Std>
+struct append<point_tag, TagRoP, Point, RoP, Std> {};
+
+template <typename TagRoP, typename Box, typename RoP, bool Std>
+struct append<box_tag, TagRoP, Box, RoP, Std> {};
+
+
+template <typename Polygon, typename TagRange, typename Range, bool Std>
+struct append<polygon_tag, TagRange, Polygon, Range, Std>
+ : detail::append::range_to_poly<Polygon, Range, Std> {};
+
+template <typename Polygon, typename Point, bool Std>
+struct append<polygon_tag, point_tag, Polygon, Point, Std>
+ : detail::append::point_to_poly<Polygon, Point, Std> {};
+
+// Multi-linestring and multi-polygon might either implement traits
+// or use standard...
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Appends one or more points to a linestring, ring, polygon, multi
+ \ingroup access
+ \param geometry a geometry
+ \param range_or_point the point or range to add
+ \param ring_index the index of the ring in case of a polygon:
+ exterior ring (-1, the default) or interior ring index
+ \param multi_index reserved for multi polygons
+ */
+template <typename Geometry, typename RoP>
+inline void append(Geometry& geometry, RoP const& range_or_point,
+ int ring_index = -1, int multi_index = 0)
+{
+ concept::check<Geometry>();
+
+ typedef typename boost::remove_const<Geometry>::type ncg_type;
+
+ dispatch::append
+ <
+ typename tag<Geometry>::type,
+ typename tag<RoP>::type,
+ ncg_type,
+ RoP,
+ traits::use_std<ncg_type>::value
+ >::apply(geometry, range_or_point, ring_index, multi_index);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_APPEND_HPP

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

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/assign.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/assign.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,522 @@
+// 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/tags.hpp>
+
+#include <ggl/geometries/concepts/check.hpp>
+
+
+#include <ggl/util/copy.hpp>
+#include <ggl/util/for_each_coordinate.hpp>
+
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace assign {
+
+template <typename CoordinateType>
+struct assign_operation
+{
+ inline assign_operation(CoordinateType const& value)
+ : m_value(value)
+ {}
+
+ template <typename P, std::size_t I>
+ inline void apply(P& point) const
+ {
+ set<I>(point, m_value);
+ }
+
+private:
+
+ CoordinateType m_value;
+};
+
+
+/*!
+ \brief Assigns all coordinates of a specific point to a value
+ \ingroup access
+ \details
+ \param p Point
+ \param value Value which is assigned to all coordinates of point p
+ */
+template <typename Point>
+inline void assign_value(Point& p,
+ typename coordinate_type<Point>::type const& value)
+{
+ for_each_coordinate(p,
+ assign_operation<typename coordinate_type<Point>::type>(value));
+}
+
+
+
+template
+<
+ typename Box, std::size_t Index,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct initialize
+{
+ typedef typename coordinate_type<Box>::type coordinate_type;
+
+ static inline void apply(Box& box, coordinate_type const& value)
+ {
+ set<Index, Dimension>(box, value);
+ initialize<Box, Index, Dimension + 1, DimensionCount>::apply(box, value);
+ }
+};
+
+
+template <typename Box, std::size_t Index, std::size_t DimensionCount>
+struct initialize<Box, Index, DimensionCount, DimensionCount>
+{
+ typedef typename coordinate_type<Box>::type coordinate_type;
+
+ static inline void apply(Box&, coordinate_type const& )
+ {}
+};
+
+
+template <typename Point>
+struct assign_zero_point
+{
+ static inline void apply(Point& point)
+ {
+ typedef typename coordinate_type<Point>::type coordinate_type;
+ assign_value(point, 0);
+ }
+};
+
+
+template <typename Box>
+struct assign_inverse_box
+{
+ typedef typename point_type<Box>::type point_type;
+
+ static inline void apply(Box& box)
+ {
+ typedef typename coordinate_type<point_type>::type coordinate_type;
+
+ 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());
+ }
+};
+
+
+template
+<
+ std::size_t Corner1, std::size_t Corner2,
+ typename Box, typename Point
+>
+inline void assign_box_2d_corner(Box const& box, Point& point)
+{
+ // Be sure both are 2-Dimensional
+ assert_dimension<Box, 2>();
+ assert_dimension<Point, 2>();
+
+ // Copy coordinates
+ typedef typename coordinate_type<Point>::type coordinate_type;
+
+ set<0>(point, boost::numeric_cast<coordinate_type>(get<Corner1, 0>(box)));
+ set<1>(point, boost::numeric_cast<coordinate_type>(get<Corner2, 1>(box)));
+}
+
+
+
+template
+<
+ typename Geometry, typename Point,
+ std::size_t Index,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct assign_point_to_index
+{
+
+ static inline void apply(Point const& point, Geometry& geometry)
+ {
+ ggl::set<Index, Dimension>(geometry, boost::numeric_cast
+ <
+ typename coordinate_type<Geometry>::type
+ >(ggl::get<Dimension>(point)));
+
+ assign_point_to_index
+ <
+ Geometry, Point, Index, Dimension + 1, DimensionCount
+ >::apply(point, geometry);
+ }
+};
+
+template
+<
+ typename Geometry, typename Point,
+ std::size_t Index,
+ std::size_t DimensionCount
+>
+struct assign_point_to_index
+ <
+ Geometry, Point,
+ Index,
+ DimensionCount, DimensionCount
+ >
+{
+ static inline void apply(Point const& , Geometry& )
+ {
+ }
+};
+
+
+template
+<
+ typename Geometry, typename Point,
+ std::size_t Index,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct assign_point_from_index
+{
+
+ static inline void apply(Geometry const& geometry, Point& point)
+ {
+ ggl::set<Dimension>( point, boost::numeric_cast
+ <
+ typename coordinate_type<Geometry>::type
+ >(ggl::get<Index, Dimension>(geometry)));
+
+ assign_point_from_index
+ <
+ Geometry, Point, Index, Dimension + 1, DimensionCount
+ >::apply(geometry, point);
+ }
+};
+
+template
+<
+ typename Geometry, typename Point,
+ std::size_t Index,
+ std::size_t DimensionCount
+>
+struct assign_point_from_index
+ <
+ Geometry, Point,
+ Index,
+ DimensionCount, DimensionCount
+ >
+{
+ static inline void apply(Geometry const&, Point&)
+ {
+ }
+};
+
+
+
+}} // namespace detail::assign
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename GeometryTag, typename Geometry, std::size_t DimensionCount>
+struct assign {};
+
+template <typename Point>
+struct assign<point_tag, Point, 2>
+{
+ typedef typename coordinate_type<Point>::type coordinate_type;
+
+ template <typename T>
+ static inline void apply(Point& point, T const& c1, T const& c2)
+ {
+ set<0>(point, boost::numeric_cast<coordinate_type>(c1));
+ set<1>(point, boost::numeric_cast<coordinate_type>(c2));
+ }
+};
+
+template <typename Point>
+struct assign<point_tag, Point, 3>
+{
+ typedef typename coordinate_type<Point>::type coordinate_type;
+
+ template <typename T>
+ static inline void apply(Point& point, T const& c1, T const& c2, T const& c3)
+ {
+ set<0>(point, boost::numeric_cast<coordinate_type>(c1));
+ set<1>(point, boost::numeric_cast<coordinate_type>(c2));
+ set<2>(point, boost::numeric_cast<coordinate_type>(c3));
+ }
+};
+
+template <typename Box>
+struct assign<box_tag, Box, 2>
+{
+ typedef typename coordinate_type<Box>::type coordinate_type;
+
+ // Here we assign 4 coordinates to a box.
+ // -> Most logical is: x1,y1,x2,y2
+ // In case the user reverses x1/x2 or y1/y2, we could reverse them (THAT IS NOT IMPLEMENTED)
+
+ // Note also comment in util/assign_box_corner ->
+ // ("Most logical is LOWER, UPPER and sub-order LEFT, RIGHT")
+ // (That is assigning 4 points from a box. So lower-left, lower-right, upper-left, upper-right)
+ template <typename T>
+ static inline void apply(Box& box,
+ T const& x1, T const& y1, T const& x2, T const& y2)
+ {
+ set<min_corner, 0>(box, boost::numeric_cast<coordinate_type>(x1));
+ set<min_corner, 1>(box, boost::numeric_cast<coordinate_type>(y1));
+ set<max_corner, 0>(box, boost::numeric_cast<coordinate_type>(x2));
+ set<max_corner, 1>(box, boost::numeric_cast<coordinate_type>(y2));
+ }
+};
+
+
+
+template <typename GeometryTag, typename Geometry>
+struct assign_zero {};
+
+
+template <typename Point>
+struct assign_zero<point_tag, Point>
+ : detail::assign::assign_zero_point<Point>
+{};
+
+template <typename Box>
+struct assign_zero<box_tag, Box>
+ : detail::assign::assign_zero_box<Box>
+{};
+
+
+template <typename GeometryTag, typename Geometry>
+struct assign_inverse {};
+
+template <typename Box>
+struct assign_inverse<box_tag, Box>
+ : detail::assign::assign_inverse_box<Box>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief assign two values to a 2D point
+ \ingroup access
+ */
+template <typename Geometry, typename Type>
+inline void assign(Geometry& geometry, Type const& c1, Type const& c2)
+{
+ concept::check<Geometry>();
+
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ ggl::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2);
+}
+
+/*!
+ \brief assign three values to a 3D point [or the center + radius to a circle]
+ \ingroup access
+ */
+template <typename Geometry, typename Type>
+inline void assign(Geometry& geometry,
+ Type const& c1, Type const& c2, Type const& c3)
+{
+ concept::check<Geometry>();
+
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ ggl::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2, c3);
+}
+
+/*!
+ \brief assign center + radius to a sphere [for extension]
+ \ingroup access
+ */
+template <typename Geometry, typename Type>
+inline void assign(Geometry& geometry,
+ Type const& c1, Type const& c2, Type const& c3, Type const& c4)
+{
+ concept::check<Geometry>();
+
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ ggl::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2, c3, c4);
+}
+
+
+/*!
+ \brief assign a range of points to a linestring, ring or polygon
+ \note The point-type of the range might be different from the point-type of the geometry
+ \ingroup access
+ */
+template <typename Geometry, typename Range>
+inline void assign(Geometry& geometry, Range const& range)
+{
+ concept::check<Geometry>();
+
+ clear(geometry);
+ 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 Geometry>
+inline void assign_inverse(Geometry& geometry)
+{
+ concept::check<Geometry>();
+
+ dispatch::assign_inverse
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::apply(geometry);
+}
+
+/*!
+ \brief assign zero values to a box, point
+ \ingroup access
+ \details The assign_zero function initializes a 2D or 3D point or box with coordinates of zero
+ \tparam Geometry the geometry type
+ */
+template <typename Geometry>
+inline void assign_zero(Geometry& geometry)
+{
+ concept::check<Geometry>();
+
+ dispatch::assign_zero
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::apply(geometry);
+}
+
+
+/*!
+ \brief Assign the 4 points of a 2D box
+ \ingroup access
+ \note The order is crucial. Most logical is LOWER, UPPER and sub-order LEFT, RIGHT
+ so this is how it is implemented.
+*/
+template <typename Box, typename Point>
+inline void assign_box_corners(Box const& box,
+ Point& lower_left, Point& lower_right,
+ Point& upper_left, Point& upper_right)
+{
+ concept::check<const Box>();
+ concept::check<Point>();
+
+ detail::assign::assign_box_2d_corner
+ <min_corner, min_corner>(box, lower_left);
+ detail::assign::assign_box_2d_corner
+ <max_corner, min_corner>(box, lower_right);
+ detail::assign::assign_box_2d_corner
+ <min_corner, max_corner>(box, upper_left);
+ detail::assign::assign_box_2d_corner
+ <max_corner, max_corner>(box, upper_right);
+}
+
+
+
+/*!
+ \brief Assign a box or segment with the value of a point
+ \ingroup access
+ \tparam Index indicates which box-corner, min_corner (0) or max_corner (1)
+ or which point of segment (0/1)
+*/
+template <std::size_t Index, typename Geometry, typename Point>
+inline void assign_point_to_index(Point const& point, Geometry& geometry)
+{
+ concept::check<const Point>();
+ concept::check<Geometry>();
+
+ detail::assign::assign_point_to_index
+ <
+ Geometry, Point, Index, 0, dimension<Geometry>::type::value
+ >::apply(point, geometry);
+}
+
+
+/*!
+ \brief Assign a point with a point of a box or segment
+ \ingroup access
+ \tparam Index indicates which box-corner, min_corner (0) or max_corner (1)
+ or which point of segment (0/1)
+*/
+template <std::size_t Index, typename Point, typename Geometry>
+inline void assign_point_from_index(Geometry const& geometry, Point& point)
+{
+ concept::check<const Geometry>();
+ concept::check<Point>();
+
+ detail::assign::assign_point_from_index
+ <
+ Geometry, Point, Index, 0, dimension<Geometry>::type::value
+ >::apply(geometry, point);
+}
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_ASSIGN_HPP

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

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/clear.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/clear.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_CLEAR_HPP
+#define GGL_ALGORITHMS_CLEAR_HPP
+
+#include <boost/type_traits/remove_const.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+
+#include <ggl/geometries/concepts/check.hpp>
+
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace clear {
+
+template <typename Geometry>
+struct use_std_clear
+{
+ static inline void apply(Geometry& geometry)
+ {
+ geometry.clear();
+ }
+};
+
+template <typename Geometry>
+struct use_traits_clear
+{
+ static inline void apply(Geometry& geometry)
+ {
+ traits::clear<Geometry>::apply(geometry);
+ }
+};
+
+template <typename Polygon>
+struct polygon_clear
+{
+ static inline void apply(Polygon& polygon)
+ {
+ interior_rings(polygon).clear();
+ exterior_ring(polygon).clear();
+ }
+};
+
+template <typename Geometry>
+struct no_action
+{
+ static inline void apply(Geometry& geometry)
+ {
+ }
+};
+
+}} // namespace detail::clear
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, bool UseStd, typename Geometry>
+struct clear
+{};
+
+// True (default for all geometry types, unless otherwise implemented in traits)
+// uses std::clear
+template <typename Tag, typename Geometry>
+struct clear<Tag, true, Geometry>
+ : detail::clear::use_std_clear<Geometry>
+{};
+
+// If any geometry specializes use_std<Geometry> to false, specialize to use the traits clear.
+template <typename Tag, typename Geometry>
+struct clear<Tag, false, Geometry>
+ : detail::clear::use_traits_clear<Geometry>
+{};
+
+// Point/box/segment do not have clear. So specialize to do nothing.
+template <typename Geometry>
+struct clear<point_tag, true, Geometry>
+ : detail::clear::no_action<Geometry>
+{};
+
+template <typename Geometry>
+struct clear<box_tag, true, Geometry>
+ : detail::clear::no_action<Geometry>
+{};
+
+template <typename Geometry>
+struct clear<segment_tag, true, Geometry>
+ : detail::clear::no_action<Geometry>
+{};
+
+
+
+
+// Polygon can (indirectly) use std for clear
+template <typename Polygon>
+struct clear<polygon_tag, true, Polygon>
+ : detail::clear::polygon_clear<Polygon>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Clears a linestring, linear ring or polygon (exterior+interiors) or multi*
+ \details Generic function to clear a geometry
+ \ingroup access
+ \note points and boxes cannot be cleared, instead they can be set to zero by "assign_zero"
+*/
+template <typename Geometry>
+inline void clear(Geometry& geometry)
+{
+ concept::check<Geometry>();
+
+ dispatch::clear
+ <
+ typename tag<Geometry>::type,
+ traits::use_std
+ <
+ typename boost::remove_const<Geometry>::type
+ >::value,
+ Geometry
+ >::apply(geometry);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_CLEAR_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/combine.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/combine.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,321 @@
+// 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/core/coordinate_dimension.hpp>
+#include <ggl/geometries/concepts/check.hpp>
+
+#include <ggl/util/select_coordinate_type.hpp>
+
+#include <ggl/strategies/compare.hpp>
+#include <ggl/policies/compare.hpp>
+
+
+/*!
+\defgroup combine combine: add a geometry to a bounding box
+\par Geometries:
+- \b box + \b box -> \b box: the box will be combined with the other box
+ \image html combine_box_box.png
+ \note Also if the input box is incorrect, the box will correctly updated
+- \b box + \b point -> \b box: the box will combined with the point
+ \image html combine_box_point.png
+- \b box + \b segment -> \b box
+*/
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace combine {
+
+
+template
+<
+ typename Box, typename Point,
+ typename StrategyLess, typename StrategyGreater,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct point_loop
+{
+ typedef typename strategy::compare::detail::select_strategy
+ <
+ StrategyLess, 1, Point, Dimension
+ >::type less_type;
+
+ typedef typename strategy::compare::detail::select_strategy
+ <
+ StrategyGreater, -1, Point, Dimension
+ >::type greater_type;
+
+ typedef typename select_coordinate_type<Point, Box>::type coordinate_type;
+
+ static inline void apply(Box& box, Point const& source)
+ {
+ less_type less;
+ greater_type greater;
+
+ coordinate_type const coord = get<Dimension>(source);
+
+ if (less(coord, get<min_corner, Dimension>(box)))
+ {
+ set<min_corner, Dimension>(box, coord);
+ }
+
+ if (greater(coord, get<max_corner, Dimension>(box)))
+ {
+ set<max_corner, Dimension>(box, coord);
+ }
+
+ point_loop
+ <
+ Box, Point,
+ StrategyLess, StrategyGreater,
+ Dimension + 1, DimensionCount
+ >::apply(box, source);
+ }
+};
+
+
+template
+<
+ typename Box, typename Point,
+ typename StrategyLess, typename StrategyGreater,
+ std::size_t DimensionCount
+>
+struct point_loop
+ <
+ Box, Point,
+ StrategyLess, StrategyGreater,
+ DimensionCount, DimensionCount
+ >
+{
+ static inline void apply(Box&, Point const&) {}
+};
+
+
+template
+<
+ typename Box, typename Geometry,
+ typename StrategyLess, typename StrategyGreater,
+ std::size_t Index,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct indexed_loop
+{
+ typedef typename strategy::compare::detail::select_strategy
+ <
+ StrategyLess, 1, Box, Dimension
+ >::type less_type;
+
+ typedef typename strategy::compare::detail::select_strategy
+ <
+ StrategyGreater, -1, Box, Dimension
+ >::type greater_type;
+
+ typedef typename select_coordinate_type
+ <
+ Box,
+ Geometry
+ >::type coordinate_type;
+
+
+ static inline void apply(Box& box, Geometry const& source)
+ {
+ less_type less;
+ greater_type greater;
+
+ coordinate_type const coord = get<Index, Dimension>(source);
+
+ if (less(coord, get<min_corner, Dimension>(box)))
+ {
+ set<min_corner, Dimension>(box, coord);
+ }
+
+ if (greater(coord, get<max_corner, Dimension>(box)))
+ {
+ set<max_corner, Dimension>(box, coord);
+ }
+
+ indexed_loop
+ <
+ Box, Geometry,
+ StrategyLess, StrategyGreater,
+ Index, Dimension + 1, DimensionCount
+ >::apply(box, source);
+ }
+};
+
+
+template
+<
+ typename Box, typename Geometry,
+ typename StrategyLess, typename StrategyGreater,
+ std::size_t Index, std::size_t DimensionCount
+>
+struct indexed_loop
+ <
+ Box, Geometry,
+ StrategyLess, StrategyGreater,
+ Index, DimensionCount, DimensionCount
+ >
+{
+ static inline void apply(Box&, Geometry const&) {}
+};
+
+
+
+// Changes a box such that the other box is also contained by the box
+template
+<
+ typename Box, typename Geometry,
+ typename StrategyLess, typename StrategyGreater
+>
+struct combine_indexed
+{
+ static inline void apply(Box& box, Geometry const& geometry)
+ {
+ indexed_loop
+ <
+ Box, Geometry,
+ StrategyLess, StrategyGreater,
+ 0, 0, dimension<Geometry>::type::value
+ >::apply(box, geometry);
+
+ indexed_loop
+ <
+ Box, Geometry,
+ StrategyLess, StrategyGreater,
+ 1, 0, dimension<Geometry>::type::value
+ >::apply(box, geometry);
+ }
+};
+
+}} // namespace detail::combine
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag,
+ typename BoxOut, typename Geometry,
+ typename StrategyLess, typename StrategyGreater
+>
+struct combine
+{};
+
+
+// Box + point -> new box containing also point
+template
+<
+ typename BoxOut, typename Point,
+ typename StrategyLess, typename StrategyGreater
+>
+struct combine<point_tag, BoxOut, Point, StrategyLess, StrategyGreater>
+ : detail::combine::point_loop
+ <
+ BoxOut, Point,
+ StrategyLess, StrategyGreater,
+ 0, dimension<Point>::type::value
+ >
+{};
+
+
+// Box + box -> new box containing two input boxes
+template
+<
+ typename BoxOut, typename BoxIn,
+ typename StrategyLess, typename StrategyGreater
+>
+struct combine<box_tag, BoxOut, BoxIn, StrategyLess, StrategyGreater>
+ : detail::combine::combine_indexed
+ <BoxOut, BoxIn, StrategyLess, StrategyGreater>
+{};
+
+template
+<
+ typename Box, typename Segment,
+ typename StrategyLess, typename StrategyGreater
+>
+struct combine<segment_tag, Box, Segment, StrategyLess, StrategyGreater>
+ : detail::combine::combine_indexed
+ <Box, Segment, StrategyLess, StrategyGreater>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/***
+*!
+ \brief Combines a box with another geometry (box, point)
+ \ingroup combine
+ \tparam Box type of the box
+ \tparam Geometry of second geometry, to be combined with the box
+ \param box box to combine another geometry with, might be changed
+ \param geometry other geometry
+ \param strategy_less
+ \param strategy_greater
+ \note Strategy is currently ignored
+ \todo Handle strategy
+ *
+template
+<
+ typename Box, typename Geometry,
+ typename StrategyLess, typename StrategyGreater
+>
+inline void combine(Box& box, Geometry const& geometry,
+ StrategyLess const& strategy_less,
+ StrategyGreater const& strategy_greater)
+{
+ concept::check_concepts_and_equal_dimensions<Box, const Geometry>();
+
+ dispatch::combine
+ <
+ typename tag<Geometry>::type,
+ Box,
+ Geometry,
+ StrategyLess, StrategyGreater
+ >::apply(box, geometry);
+}
+***/
+
+
+/*!
+ \brief Combines a box with another geometry (box, point)
+ \ingroup combine
+ \tparam Box type of the box
+ \tparam Geometry of second geometry, to be combined with the box
+ \param box box to combine another geometry with, might be changed
+ \param geometry other geometry
+ */
+template <typename Box, typename Geometry>
+inline void combine(Box& box, Geometry const& geometry)
+{
+ concept::check_concepts_and_equal_dimensions<Box, const Geometry>();
+
+ dispatch::combine
+ <
+ typename tag<Geometry>::type,
+ Box, Geometry,
+ strategy::compare::default_strategy,
+ strategy::compare::default_strategy
+ >::apply(box, geometry);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_COMBINE_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/convert.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/convert.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_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/assign.hpp>
+#include <ggl/algorithms/for_each.hpp>
+
+#include <ggl/core/cs.hpp>
+#include <ggl/geometries/concepts/check.hpp>
+
+
+/*!
+\defgroup convert convert: convert geometries from one type to another
+\details Convert from one geometry type to another type,
+ for example from BOX to POLYGON
+\par Geometries:
+- \b point to \b box -> a zero-area box of a point
+- \b box to \b ring -> a rectangular ring
+- \b box to \b polygon -> a rectangular polygon
+- \b ring to \b polygon -> polygon with an exterior ring (the input ring)
+- \b polygon to \b ring -> ring, interior rings (if any) are ignored
+*/
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace convert {
+
+template
+<
+ typename Point,
+ typename Box,
+ std::size_t Index,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct point_to_box
+{
+ static inline void apply(Point const& point, Box& box)
+ {
+ typedef typename coordinate_type<Box>::type coordinate_type;
+
+ set<Index, Dimension>(box,
+ boost::numeric_cast<coordinate_type>(get<Dimension>(point)));
+ point_to_box
+ <
+ Point, Box,
+ Index, Dimension + 1, DimensionCount
+ >::apply(point, box);
+ }
+};
+
+
+template
+<
+ typename Point,
+ typename Box,
+ std::size_t Index,
+ std::size_t DimensionCount
+>
+struct point_to_box<Point, Box, Index, DimensionCount, DimensionCount>
+{
+ static inline void apply(Point const& point, Box& box)
+ {}
+};
+
+
+}} // namespace detail::convert
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag1, typename Tag2,
+ std::size_t Dimensions,
+ typename Geometry1, typename Geometry2
+>
+struct convert
+{
+};
+
+
+template
+<
+ typename Tag,
+ std::size_t Dimensions,
+ typename Geometry1, typename Geometry2
+>
+struct convert<Tag, Tag, Dimensions, Geometry1, Geometry2>
+{
+ // Same geometry type -> copy coordinates from G1 to G2
+ // Actually: we try now to just copy it
+ static inline void apply(Geometry1 const& source, Geometry2& destination)
+ {
+ destination = source;
+ }
+};
+
+
+template <typename Tag, std::size_t Dimensions, typename Geometry>
+struct convert<Tag, Tag, Dimensions, Geometry, Geometry>
+{
+ // Same geometry -> can be copied (if copyable)
+ static inline void apply(Geometry const& source, Geometry& destination)
+ {
+ destination = source;
+ }
+};
+
+
+// Partial specializations
+template <typename Box, typename Ring>
+struct convert<box_tag, ring_tag, 2, Box, Ring>
+{
+ static inline void apply(Box const& box, Ring& ring)
+ {
+ // go from box to ring -> add coordinates in correct order
+ ring.clear();
+ typename point_type<Box>::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 Box, typename Polygon>
+struct convert<box_tag, polygon_tag, 2, Box, Polygon>
+{
+ static inline void apply(Box const& box, Polygon& polygon)
+ {
+ typedef typename ring_type<Polygon>::type ring_type;
+
+ convert
+ <
+ box_tag, ring_tag,
+ 2, Box, ring_type
+ >::apply(box, exterior_ring(polygon));
+ }
+};
+
+
+template <typename Point, std::size_t Dimensions, typename Box>
+struct convert<point_tag, box_tag, Dimensions, Point, Box>
+{
+ static inline void apply(Point const& point, Box& box)
+ {
+ detail::convert::point_to_box
+ <
+ Point, Box, min_corner, 0, Dimensions
+ >::apply(point, box);
+ detail::convert::point_to_box
+ <
+ Point, Box, max_corner, 0, Dimensions
+ >::apply(point, box);
+ }
+};
+
+
+template <typename Ring, typename Polygon>
+struct convert<ring_tag, polygon_tag, 2, Ring, Polygon>
+{
+ static inline void apply(Ring const& ring, Polygon& polygon)
+ {
+ typedef typename ring_type<Polygon>::type ring_type;
+ convert
+ <
+ ring_tag, ring_tag, 2,
+ Ring, ring_type
+ >::apply(ring, exterior_ring(polygon));
+ }
+};
+
+
+template <typename Polygon, typename Ring>
+struct convert<polygon_tag, ring_tag, 2, Polygon, Ring>
+{
+ static inline void apply(Polygon const& polygon, Ring& ring)
+ {
+ typedef typename ring_type<Polygon>::type ring_type;
+
+ convert
+ <
+ ring_tag, ring_tag, 2,
+ ring_type, Ring
+ >::apply(exterior_ring(polygon), ring);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+/*!
+ \brief Converts one geometry to another geometry
+ \details The convert algorithm converts one geometry, e.g. a BOX, to another geometry, e.g. a RING. This only
+ if it is possible and applicable.
+ \ingroup convert
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \param geometry1 first geometry (source)
+ \param geometry2 second geometry (target)
+ */
+template <typename Geometry1, typename Geometry2>
+inline void convert(Geometry1 const& geometry1, Geometry2& geometry2)
+{
+ concept::check_concepts_and_equal_dimensions<const Geometry1, Geometry2>();
+
+ dispatch::convert
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ dimension<Geometry1>::type::value,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_CONVERT_HPP

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

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/correct.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/correct.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,192 @@
+// 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 <cstddef>
+#include <algorithm>
+#include <functional>
+
+#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/geometries/concepts/check.hpp>
+
+#include <ggl/algorithms/area.hpp>
+#include <ggl/algorithms/disjoint.hpp>
+
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace correct {
+
+
+template <typename Box, std::size_t Dimension, std::size_t DimensionCount>
+struct correct_box_loop
+{
+ typedef typename coordinate_type<Box>::type coordinate_type;
+
+ static inline void apply(Box& box)
+ {
+ if (get<min_corner, Dimension>(box) > get<max_corner, Dimension>(box))
+ {
+ // Swap the coordinates
+ coordinate_type max_value = get<min_corner, Dimension>(box);
+ coordinate_type min_value = get<max_corner, Dimension>(box);
+ set<min_corner, Dimension>(box, min_value);
+ set<max_corner, Dimension>(box, max_value);
+ }
+
+ correct_box_loop
+ <
+ Box, Dimension + 1, DimensionCount
+ >::apply(box);
+ }
+};
+
+
+
+template <typename Box, std::size_t DimensionCount>
+struct correct_box_loop<Box, DimensionCount, DimensionCount>
+{
+ static inline void apply(Box& box)
+ {}
+
+};
+
+
+// correct an box: make min/max are correct
+template <typename Box>
+struct correct_box
+{
+
+ static inline void apply(Box& box)
+ {
+ // Currently only for Cartesian coordinates
+ // TODO: adapt using strategies
+ correct_box_loop
+ <
+ Box, 0, dimension<Box>::type::value
+ >::apply(box);
+ }
+};
+
+
+// close a linear_ring, if not closed
+template <typename Ring, typename Predicate>
+struct correct_ring
+{
+ typedef typename point_type<Ring>::type point_type;
+
+ typedef typename strategy_area
+ <
+ typename cs_tag<point_type>::type,
+ point_type
+ >::type strategy_type;
+
+ typedef detail::area::ring_area
+ <
+ Ring,
+ ggl::point_order<Ring>::value,
+ strategy_type
+ > ring_area_type;
+
+
+ static inline void apply(Ring& r)
+ {
+ // Check close-ness
+ if (boost::size(r) > 2)
+ {
+ // check if closed, if not, close it
+ if (ggl::disjoint(r.front(), r.back()))
+ {
+ r.push_back(r.front());
+ }
+ }
+ // Check area
+ Predicate predicate;
+ if (predicate(ring_area_type::apply(r, strategy_type()), 0))
+ {
+ std::reverse(boost::begin(r), boost::end(r));
+ }
+ }
+};
+
+// correct a polygon: normalizes all rings, sets outer linear_ring clockwise, sets all
+// inner rings counter clockwise
+template <typename Polygon>
+struct correct_polygon
+{
+ typedef typename ring_type<Polygon>::type ring_type;
+
+ static inline void apply(Polygon& poly)
+ {
+ correct_ring<ring_type, std::less<double> >::apply(exterior_ring(poly));
+
+ typedef typename boost::range_iterator
+ <
+ typename interior_type<Polygon>::type
+ >::type iterator_type;
+
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly)); ++it)
+ {
+ correct_ring<ring_type, std::greater<double> >::apply(*it);
+ }
+ }
+};
+
+
+}} // namespace detail::correct
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, typename Geometry>
+struct correct {};
+
+template <typename Box>
+struct correct<box_tag, Box>
+ : detail::correct::correct_box<Box>
+{};
+
+template <typename Ring>
+struct correct<ring_tag, Ring>
+ : detail::correct::correct_ring<Ring, std::less<double> >
+{};
+
+template <typename Polygon>
+struct correct<polygon_tag, Polygon>
+ : detail::correct::correct_polygon<Polygon>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+template <typename Geometry>
+inline void correct(Geometry& geometry)
+{
+ concept::check<const Geometry>();
+
+ dispatch::correct<typename tag<Geometry>::type, Geometry>::apply(geometry);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_CORRECT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/detail/calculate_null.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/detail/calculate_null.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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 ReturnType, typename Geometry, typename Strategy>
+struct calculate_null
+{
+ static inline ReturnType apply(Geometry const& , Strategy const&)
+ {
+ return ReturnType();
+ }
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/detail/calculate_sum.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/detail/calculate_sum.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,51 @@
+// Generic Geometry Library
+//
+// 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_DETAIL_CALCULATE_SUM_HPP
+#define GGL_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template
+<
+ typename ReturnType,
+ typename Polygon,
+ typename Strategy,
+ typename Policy
+>
+struct calculate_polygon_sum
+{
+ static inline ReturnType apply(Polygon const& poly, Strategy const& strategy)
+ {
+ ReturnType sum = Policy::apply(exterior_ring(poly), strategy);
+
+ for (typename boost::range_const_iterator
+ <
+ typename interior_type<Polygon>::type
+ >::type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly));
+ ++it)
+ {
+ sum += Policy::apply(*it, strategy);
+ }
+ return sum;
+ }
+};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/detail/disjoint.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/detail/disjoint.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,194 @@
+// 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_DISJOINT_HPP
+#define GGL_ALGORITHMS_DETAIL_DISJOINT_HPP
+
+// Note: contrary to most files, the ggl::detail::disjoint namespace
+// is partly implemented in a separate file, to avoid circular references
+// disjoint -> get_intersection_points -> disjoint
+
+
+#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>
+
+
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace disjoint {
+
+
+template
+<
+ typename Point1, typename Point2,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct point_point
+{
+ static inline bool apply(Point1 const& p1, Point2 const& p2)
+ {
+ if (! ggl::math::equals(get<Dimension>(p1), get<Dimension>(p2)))
+ {
+ return true;
+ }
+ return point_point
+ <
+ Point1, Point2,
+ Dimension + 1, DimensionCount
+ >::apply(p1, p2);
+ }
+};
+
+
+template <typename Point1, typename Point2, std::size_t DimensionCount>
+struct point_point<Point1, Point2, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Point1 const& , Point2 const& )
+ {
+ return false;
+ }
+};
+
+
+template
+<
+ typename Point, typename Box,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct point_box
+{
+ static inline bool apply(Point const& point, Box const& box)
+ {
+ if (get<Dimension>(point) < get<min_corner, Dimension>(box)
+ || get<Dimension>(point) > get<max_corner, Dimension>(box))
+ {
+ return true;
+ }
+ return point_box
+ <
+ Point, Box,
+ Dimension + 1, DimensionCount
+ >::apply(point, box);
+ }
+};
+
+
+template <typename Point, typename Box, std::size_t DimensionCount>
+struct point_box<Point, Box, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Point const& , Box const& )
+ {
+ return false;
+ }
+};
+
+
+template
+<
+ typename Box1, typename Box2,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct box_box
+{
+ static inline bool apply(Box1 const& box1, Box2 const& box2)
+ {
+ if (get<max_corner, Dimension>(box1) < get<min_corner, Dimension>(box2))
+ {
+ return true;
+ }
+ if (get<min_corner, Dimension>(box1) > get<max_corner, Dimension>(box2))
+ {
+ return true;
+ }
+ return box_box
+ <
+ Box1, Box2,
+ Dimension + 1, DimensionCount
+ >::apply(box1, box2);
+ }
+};
+
+
+template <typename Box1, typename Box2, std::size_t DimensionCount>
+struct box_box<Box1, Box2, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Box1 const& , Box2 const& )
+ {
+ return false;
+ }
+};
+
+
+
+/*!
+ \brief Internal utility function to detect of boxes are disjoint
+ \note Is used from other algorithms, declared separately
+ to avoid circular references
+ */
+template <typename Box1, typename Box2>
+inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2)
+{
+ return box_box
+ <
+ Box1, Box2,
+ 0, dimension<Box1>::type::value
+ >::apply(box1, box2);
+}
+
+
+
+/*!
+ \brief Internal utility function to detect of points are disjoint
+ \note To avoid circular references
+ */
+template <typename Point1, typename Point2>
+inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2)
+{
+ return point_point
+ <
+ Point1, Point2,
+ 0, dimension<Point1>::type::value
+ >::apply(point1, point2);
+}
+
+
+
+
+}} // namespace detail::disjoint
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace equals {
+
+/*!
+ \brief Internal utility function to detect of points are disjoint
+ \note To avoid circular references
+ */
+template <typename Point1, typename Point2>
+inline bool equals_point_point(Point1 const& point1, Point2 const& point2)
+{
+ return ! detail::disjoint::disjoint_point_point(point1, point2);
+}
+
+
+}} // namespace detail::equals
+#endif // DOXYGEN_NO_DETAIL
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_DETAIL_DISJOINT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/detail/not.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/detail/not.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/algorithms/detail/point_on_border.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/detail/point_on_border.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,173 @@
+// Generic Geometry Library
+//
+// 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_DETAIL_POINT_ON_BORDER_HPP
+#define GGL_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
+
+
+#include <boost/range/functions.hpp>
+
+#include <ggl/core/point_type.hpp>
+#include <ggl/core/ring_type.hpp>
+
+#include <ggl/geometries/concepts/check.hpp>
+
+#include <ggl/algorithms/assign.hpp>
+
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace point_on_border {
+
+template
+<
+ typename Range,
+ typename Point
+>
+struct point_on_range
+{
+ static inline bool apply(Range const& range, Point& point)
+ {
+ if (boost::size(range) > 0)
+ {
+ point = *boost::begin(range);
+ return true;
+ }
+ return false;
+ }
+};
+
+
+template
+<
+ typename Polygon,
+ typename Point
+>
+struct point_on_polygon
+{
+ static inline bool apply(Polygon const& polygon, Point& point)
+ {
+ return point_on_range
+ <
+ typename ring_type<Polygon>::type,
+ Point
+ >::apply(exterior_ring(polygon), point);
+ }
+};
+
+
+template
+<
+ typename Box,
+ typename Point
+>
+struct point_on_box
+{
+ static inline bool apply(Box const& box, Point& point)
+ {
+ detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, point);
+ return true;
+ }
+};
+
+
+}} // namespace detail::point_on_border
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename GeometryTag,
+ typename Geometry,
+ typename Point
+
+>
+struct point_on_border
+{
+};
+
+
+template<typename Point>
+struct point_on_border
+ <
+ point_tag, Point, Point
+ >
+{
+ static inline bool apply(Point const& source, Point& destination)
+ {
+ destination = source;
+ return true;
+ }
+};
+
+
+template<typename Linestring, typename Point>
+struct point_on_border<linestring_tag, Linestring, Point>
+ : detail::point_on_border::point_on_range<Linestring, Point>
+{};
+
+
+template<typename Ring, typename Point>
+struct point_on_border<ring_tag, Ring, Point>
+ : detail::point_on_border::point_on_range<Ring, Point>
+{};
+
+
+template<typename Polygon, typename Point>
+struct point_on_border<polygon_tag, Polygon, Point>
+ : detail::point_on_border::point_on_polygon<Polygon, Point>
+{};
+
+
+template<typename Box, typename Point>
+struct point_on_border<box_tag, Box, Point>
+ : detail::point_on_border::point_on_box<Box, Point>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Take point on a border
+ \ingroup utility
+ \tparam Geometry geometry type
+ \param geometry geometry to take point from
+ \param point
+ \return TRUE if successful, else false.
+ It is only false if polygon/line have no points
+ \note for a polygon, it is always a point on the exterior ring
+ */
+template <typename Geometry>
+inline bool point_on_border(Geometry const& geometry,
+ typename point_type<Geometry>::type& point)
+{
+ typedef typename point_type<Geometry>::type point_type;
+
+ concept::check<const Geometry>();
+ concept::check<point_type>();
+
+ return dispatch::point_on_border
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ point_type
+ >::apply(geometry, point);
+}
+
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/disjoint.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/disjoint.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,215 @@
+// 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
+
+
+/*!
+\defgroup disjoint disjoint: detect if geometries are not spatially related
+\details disjoint means spatially disjoint, there is no overlap of interiors
+ and boundaries, the intersection of interiors or boundaries is empty.
+
+\par Geometries:
+- \b point + \b point (= ! equals)
+- \b point + \b box (= not within or on border)
+- \b box + \b box
+- \b ring + \b box
+- \b polygon + \b box
+- \b polygon + \b ring
+- \b polygon + \b polygon
+
+*/
+
+#include <deque>
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/static_assert.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/coordinate_dimension.hpp>
+#include <ggl/core/is_multi.hpp>
+#include <ggl/core/reverse_dispatch.hpp>
+
+#include <ggl/algorithms/detail/disjoint.hpp>
+#include <ggl/algorithms/detail/point_on_border.hpp>
+#include <ggl/algorithms/overlay/get_intersection_points.hpp>
+#include <ggl/algorithms/within.hpp>
+
+#include <ggl/geometries/concepts/check.hpp>
+
+#include <ggl/util/math.hpp>
+
+
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace disjoint {
+
+
+template <typename Geometry1, typename Geometry2>
+struct general
+{
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ {
+
+ typedef typename ggl::point_type<Geometry1>::type point_type;
+ typedef detail::intersection::intersection_point<point_type> ip_type;
+ std::deque<ip_type> ips; // intersection points
+
+ // Get any intersection
+ ggl::get_intersection_points(geometry1, geometry2, ips);
+ if (ips.size() > 0)
+ {
+ return false;
+ }
+ // If there is no intersection of segments, they might ly
+ // inside each other
+ point_type p1;
+ ggl::point_on_border(geometry1, p1);
+ if (ggl::within(p1, geometry2))
+ {
+ return false;
+ }
+
+ typename ggl::point_type<Geometry1>::type p2;
+ ggl::point_on_border(geometry2, p2);
+ if (ggl::within(p2, geometry1))
+ {
+ return false;
+ }
+
+ return true;
+ }
+};
+
+
+}} // namespace detail::disjoint
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2,
+ typename Geometry1, typename Geometry2,
+ bool IsMulti1, bool IsMulti2,
+ std::size_t DimensionCount
+>
+struct disjoint
+ : detail::disjoint::general<Geometry1, Geometry2>
+{};
+
+
+template <typename Point1, typename Point2, std::size_t DimensionCount>
+struct disjoint<point_tag, point_tag, Point1, Point2, false, false, DimensionCount>
+ : detail::disjoint::point_point<Point1, Point2, 0, DimensionCount>
+{};
+
+
+template <typename Box1, typename Box2, std::size_t DimensionCount>
+struct disjoint<box_tag, box_tag, Box1, Box2, false, false, DimensionCount>
+ : detail::disjoint::box_box<Box1, Box2, 0, DimensionCount>
+{};
+
+
+template <typename Point, typename Box, std::size_t DimensionCount>
+struct disjoint<point_tag, box_tag, Point, Box, false, false, DimensionCount>
+ : detail::disjoint::point_box<Point, Box, 0, DimensionCount>
+{};
+
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2,
+ typename G1, typename G2,
+ bool IsMulti1, bool IsMulti2,
+ std::size_t DimensionCount
+>
+struct disjoint_reversed
+{
+ static inline bool apply(G1 const& g1, G2 const& g2)
+ {
+ return disjoint
+ <
+ GeometryTag2, GeometryTag1,
+ G2, G1,
+ IsMulti2, IsMulti1,
+ DimensionCount
+ >::apply(g2, g1);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+/*!
+ \brief Calculate if two geometries are disjoint
+ \ingroup disjoint
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \return true if disjoint, else false
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool disjoint(const Geometry1& geometry1,
+ const Geometry2& geometry2)
+{
+ concept::check_concepts_and_equal_dimensions
+ <
+ const Geometry1,
+ const Geometry2
+ >();
+
+ typedef typename boost::remove_const<Geometry1>::type ncg1_type;
+ typedef typename boost::remove_const<Geometry2>::type ncg2_type;
+
+ return boost::mpl::if_c
+ <
+ reverse_dispatch<Geometry1, Geometry2>::type::value,
+ dispatch::disjoint_reversed
+ <
+ typename tag<ncg1_type>::type,
+ typename tag<ncg2_type>::type,
+ ncg1_type,
+ ncg2_type,
+ is_multi<ncg1_type>::type::value,
+ is_multi<ncg2_type>::type::value,
+ dimension<ncg1_type>::type::value
+ >,
+ dispatch::disjoint
+ <
+ typename tag<ncg1_type>::type,
+ typename tag<ncg2_type>::type,
+ ncg1_type,
+ ncg2_type,
+ is_multi<ncg1_type>::type::value,
+ is_multi<ncg2_type>::type::value,
+ dimension<ncg1_type>::type::value
+ >
+ >::type::apply(geometry1, geometry2);
+}
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_DISJOINT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/distance.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/distance.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,366 @@
+// 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/geometries/concepts/check.hpp>
+
+#include <ggl/strategies/distance.hpp>
+#include <ggl/strategies/distance_result.hpp>
+
+/*!
+\defgroup distance distance: calculate distance between two geometries
+The distance algorithm returns the distance between two geometries.
+\par Coordinate systems and strategies:
+With help of strategies the distance function returns the appropriate distance.
+If the input is in cartesian coordinates, the Euclidian distance (Pythagoras) is calculated.
+If the input is in spherical coordinates (either degree or radian), the distance over the sphere is returned.
+If the input is in geographic coordinates, distance is calculated over the globe and returned in meters.
+
+\par Distance result:
+Depending on calculation type the distance result is either a structure, convertable
+to a double, or a double value. In case of Pythagoras it makes sense to not draw the square root in the
+strategy itself. Taking a square root is relative expensive and is not necessary when comparing distances.
+
+\par Geometries:
+Currently implemented, for both cartesian and spherical/geographic:
+- POINT - POINT
+- POINT - SEGMENT and v.v.
+- POINT - LINESTRING and v.v.
+
+Not yet implemented:
+- POINT - RING etc, note that it will return a zero if the point is anywhere within the ring
+
+\par Example:
+Example showing distance calculation of two points, in xy and in latlong coordinates
+\dontinclude doxygen_1.cpp
+\skip example_distance_point_point
+\line {
+\until }
+*/
+
+namespace 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.apply(p1, p2);
+ }
+};
+
+
+template<typename Point, typename Segment, typename Strategy>
+struct point_to_segment
+{
+ static inline typename Strategy::return_type apply(Point const& point,
+ Segment const& segment, Strategy const& strategy)
+ {
+ typename strategy_distance_segment
+ <
+ typename cs_tag<Point>::type,
+ typename cs_tag<Segment>::type,
+ Point,
+ typename point_type<Segment>::type
+ >::type segment_strategy;
+
+ return segment_strategy.apply(point, segment.first, segment.second);
+ }
+};
+
+
+template<typename P, typename L, typename PPStrategy, typename PSStrategy>
+struct point_to_linestring
+{
+ typedef typename PPStrategy::return_type return_type;
+
+ static inline return_type apply(P const& point, L const& linestring,
+ PPStrategy const& pp_strategy, PSStrategy const& ps_strategy)
+ {
+ typedef segment<const typename point_type<L>::type> segment_type;
+
+ if (boost::begin(linestring) == boost::end(linestring))
+ {
+ return return_type(0);
+ }
+
+ // line of one point: return point square_distance
+ typedef typename boost::range_const_iterator<L>::type iterator_type;
+ iterator_type it = boost::begin(linestring);
+ iterator_type prev = it++;
+ if (it == boost::end(linestring))
+ {
+ return pp_strategy.apply(point, *boost::begin(linestring));
+ }
+
+
+ // start with first segment distance
+ return_type d = ps_strategy.apply(point, *prev, *it);
+
+ // check if other segments are closer
+ prev = it++;
+ while(it != boost::end(linestring))
+ {
+ return_type ds = ps_strategy.apply(point, *prev, *it);
+ if (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 > segment_type;
+ typedef typename ggl::strategy_distance_segment
+ <
+ typename cs_tag<Point>::type,
+ typename cs_tag<Linestring>::type,
+ Point,
+ typename point_type<Linestring>::type
+ >::type ps_strategy_type;
+
+ return detail::distance::point_to_linestring
+ <
+ Point, Linestring, Strategy, ps_strategy_type
+ >::apply(point, linestring, strategy, ps_strategy_type());
+ }
+};
+
+
+/// Point-line version 2, where point-segment strategy is specified
+template <typename Point, typename Linestring, typename Strategy>
+struct distance
+<
+ point_tag, linestring_tag,
+ Point, Linestring,
+ strategy_tag_distance_point_segment, Strategy,
+ false, false
+>
+{
+ static inline typename Strategy::return_type apply(Point const& point,
+ Linestring const& linestring,
+ Strategy const& strategy)
+ {
+ typedef typename Strategy::point_strategy_type pp_strategy_type;
+ return detail::distance::point_to_linestring
+ <
+ Point, Linestring, pp_strategy_type, Strategy
+ >::apply(point, linestring, pp_strategy_type(), strategy);
+ }
+};
+
+
+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_1.cpp
+ \skip example_distance_point_point_strategy
+ \line {
+ \until }
+ */
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline typename Strategy::return_type distance(Geometry1 const& geometry1,
+ Geometry2 const& geometry2, Strategy const& strategy)
+{
+ typedef typename boost::remove_const<Geometry1>::type ncg1_type;
+ typedef typename boost::remove_const<Geometry2>::type ncg2_type;
+
+ return boost::mpl::if_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)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ typedef typename point_type<Geometry1>::type point1_type;
+ typedef typename point_type<Geometry2>::type point2_type;
+
+ // Define a point-point-distance-strategy
+ // for either the normal case, either the reversed case
+ typedef typename boost::mpl::if_c
+ <
+ 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/boost/ggl/algorithms/envelope.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/envelope.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,282 @@
+// 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/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/geometries/concepts/check.hpp>
+
+/*!
+\defgroup envelope envelope: calculate envelope (minimum bounding rectangle) of a geometry
+\par Source descriptions:
+- OGC: Envelope (): Geometry - The minimum bounding rectangle (MBR) for this
+ Geometry,
+returned as a Geometry. The polygon is defined by the corner points of the
+ bounding box
+ [(MINX, MINY), (MAXX, MINY), (MAXX, MAXY), (MINX, MAXY), (MINX, MINY)].
+
+\note Implemented in the Generic Geometry Library: The minimum bounding box,
+ always as a box, having min <= max
+
+The envelope algorithm calculates the bounding box, or envelope, of a geometry.
+There are two versions:
+- envelope, taking a reference to a box as second parameter
+- make_envelope, returning a newly constructed box (type as a template parameter
+ in the function call)
+
+\par Geometries:
+- \b point: a box with zero area, the maximum and the minimum point of the box are
+set to the point itself.
+- \b linestring, \b ring or \b range is the smallest box that contains all points of the
+ specified point sequence.
+If the linestring is empty, the envelope is the inverse infinite box, that is,
+ the minimum point is very large (max infinite) and the maximum point is
+ very small (min infinite).
+- \b polygon, the envelope of the outer ring
+\image html envelope_polygon.png
+
+\par Example:
+Example showing envelope calculation
+\dontinclude doxygen_1.cpp
+\skip example_envelope_linestring
+\line {
+\until }
+*/
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace envelope {
+
+
+/// Calculate envelope of an 2D or 3D segment
+template<typename Geometry, typename Box>
+struct envelope_combine_one
+{
+ static inline void apply(Geometry const& geometry, Box& mbr)
+ {
+ assign_inverse(mbr);
+ ggl::combine(mbr, geometry);
+ }
+};
+
+
+/// Iterate through range (also used in multi*)
+template<typename Range, typename Box>
+inline void envelope_range_additional(Range const& range, Box& mbr)
+{
+ typedef typename boost::range_const_iterator<Range>::type iterator_type;
+
+ for (iterator_type it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ ggl::combine(mbr, *it);
+ }
+}
+
+
+
+/// Generic range dispatching struct
+template <typename Range, typename Box>
+struct envelope_range
+{
+ /// Calculate envelope of range using a strategy
+ static inline void apply(Range const& range, Box& mbr)
+ {
+ assign_inverse(mbr);
+ envelope_range_additional(range, mbr);
+ }
+};
+
+}} // namespace detail::envelope
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+// Note, the strategy is for future use (less/greater -> compare spherical
+// using other methods), defaults are OK for now.
+// However, they are already in the template methods
+
+template
+<
+ typename Tag1, typename Tag2,
+ typename Geometry, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope {};
+
+
+template
+<
+ typename Point, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope
+ <
+ point_tag, box_tag,
+ Point, Box,
+ StrategyLess, StrategyGreater
+ >
+ : detail::envelope::envelope_combine_one<Point, Box>
+{};
+
+
+template
+<
+ typename BoxIn, typename BoxOut,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope
+ <
+ box_tag, box_tag,
+ BoxIn, BoxOut,
+ StrategyLess, StrategyGreater
+ >
+ : detail::envelope::envelope_combine_one<BoxIn, BoxOut>
+{};
+
+
+template
+<
+ typename Segment, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope
+ <
+ segment_tag, box_tag,
+ Segment, Box,
+ StrategyLess, StrategyGreater
+ >
+ : detail::envelope::envelope_combine_one<Segment, Box>
+{};
+
+
+template
+<
+ typename Linestring, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope
+ <
+ linestring_tag, box_tag,
+ Linestring, Box,
+ StrategyLess, StrategyGreater
+ >
+ : detail::envelope::envelope_range<Linestring, Box>
+{};
+
+
+template
+<
+ typename Ring, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope
+ <
+ ring_tag, box_tag,
+ Ring, Box,
+ StrategyLess, StrategyGreater
+ >
+ : detail::envelope::envelope_range<Ring, Box>
+{};
+
+
+template
+<
+ typename Polygon, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope
+ <
+ polygon_tag, box_tag,
+ Polygon, Box,
+ StrategyLess, StrategyGreater
+ >
+{
+ static inline void apply(Polygon const& poly, Box& mbr)
+ {
+ // For polygon, inspecting outer ring is sufficient
+
+ detail::envelope::envelope_range
+ <
+ typename ring_type<Polygon>::type,
+ Box
+ >::apply(exterior_ring(poly), mbr);
+ }
+
+};
+
+
+} // namespace dispatch
+#endif
+
+
+/*!
+\brief Calculate envelope of a geometry
+\ingroup envelope
+\param geometry the geometry
+\param mbr the box receiving the envelope
+\par Example:
+Example showing envelope calculation, using point_ll latlong points
+\dontinclude doxygen_1.cpp
+\skip example_envelope_polygon
+\line {
+\until }
+*/
+template<typename Geometry, typename Box>
+inline void envelope(Geometry const& geometry, Box& mbr)
+{
+ concept::check<const Geometry>();
+ concept::check<Box>();
+
+ dispatch::envelope
+ <
+ typename tag<Geometry>::type, typename tag<Box>::type,
+ Geometry, Box,
+ void, void
+ >::apply(geometry, mbr);
+}
+
+
+/*!
+\brief Calculate and return envelope of a geometry
+\ingroup envelope
+\param geometry the geometry
+*/
+template<typename Box, typename Geometry>
+inline Box make_envelope(Geometry const& geometry)
+{
+ concept::check<const Geometry>();
+ concept::check<Box>();
+
+ Box mbr;
+ dispatch::envelope
+ <
+ typename tag<Geometry>::type, typename tag<Box>::type,
+ Geometry, Box,
+ void, void
+ >::apply(geometry, mbr);
+ return mbr;
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_ENVELOPE_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/equals.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/equals.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,319 @@
+// 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
+
+/*!
+\defgroup equals equals: detect if two geometries are spatially equal
+\par Geometries:
+- \b point + \b point
+- \b box + \b box
+
+*/
+
+
+#include <cstddef>
+#include <deque>
+
+#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/core/interior_rings.hpp>
+
+#include <ggl/algorithms/detail/disjoint.hpp>
+#include <ggl/algorithms/detail/not.hpp>
+#include <ggl/algorithms/area.hpp>
+#include <ggl/algorithms/overlay/get_intersection_points.hpp>
+#include <ggl/algorithms/overlay/merge_intersection_points.hpp>
+#include <ggl/geometries/concepts/check.hpp>
+#include <ggl/util/math.hpp>
+
+
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace equals {
+
+
+template
+<
+ typename Box1,
+ typename Box2,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct box_box
+{
+ static inline bool apply(Box1 const& box1, Box2 const& box2)
+ {
+ if (!ggl::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2))
+ || !ggl::math::equals(get<max_corner, Dimension>(box1), get<max_corner, Dimension>(box2)))
+ {
+ return false;
+ }
+ return box_box<Box1, Box2, Dimension + 1, DimensionCount>::apply(box1, box2);
+ }
+};
+
+template <typename Box1, typename Box2, std::size_t DimensionCount>
+struct box_box<Box1, Box2, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Box1 const& , Box2 const& )
+ {
+ return true;
+ }
+};
+
+
+template <typename Ring1, typename Ring2>
+struct ring_ring
+{
+ static inline bool apply(Ring1 const& ring1, Ring2 const& ring2, bool check_area = true)
+ {
+ // Note: this implementation makes use of getting interections
+ // and merge them. If all IP's disappear, the ring should be the same
+ // (because merging removes collinear or non-collinear
+ // IP's following the same path)
+ // However, this implementation should be redone using
+ // a linear time algorithm (getting left-most points of both
+ // and follow them using circular iterator and distance/side)
+
+ // obvious check, area's should be the same.
+ if (check_area && ggl::area(ring1) != ggl::area(ring2))
+ {
+ return false;
+ }
+ // We could check more (perimeter,centroid,envelope)
+ // For now we go directly to intersection points
+
+ typedef typename ggl::point_type<Ring1>::type point_type;
+ typedef detail::intersection::intersection_point<point_type> ip_type;
+ typedef std::deque<ip_type> container_type;
+
+ container_type ips;
+
+
+ bool trivial = ggl::get_intersection_points(ring1, ring2, ips);
+ if (trivial || ips.size() == 0)
+ {
+ return false;
+ }
+ ggl::merge_intersection_points(ips);
+ if (ips.size() == 0)
+ {
+ // All IP's are merged. Meaning collinear / path can be followed
+ return true;
+ }
+
+ return false;
+ }
+};
+
+
+template <typename Polygon1, typename Polygon2>
+struct polygon_polygon
+{
+
+ struct sortable
+ {
+ int index;
+ double area;
+ bool counterpart_found;
+ inline sortable(int i, double a)
+ : index(i)
+ , area(a)
+ , counterpart_found(false)
+ {}
+
+ inline bool operator<(sortable const& other) const
+ {
+ return area < other.area;
+ }
+ };
+
+
+ template <typename Poly>
+ static inline void fill_sortable(Poly const& polygon, std::vector<sortable>& v)
+ {
+ int i = 0;
+ for (typename boost::range_const_iterator
+ <
+ typename interior_type<Poly>::type
+ >::type it = boost::begin(interior_rings(polygon));
+ it != boost::end(interior_rings(polygon));
+ ++it, ++i)
+ {
+ v.push_back(sortable(i, ggl::area(*it)));
+ }
+ std::sort(v.begin(), v.end());
+
+ /***
+ for (typename std::vector<sortable>::iterator it = v.begin();
+ it != v.end();
+ ++it)
+ {
+ std::cout << "Ring: " << it->index << " area: " << it->area << std::endl;
+ }
+ ***/
+ }
+
+ static inline bool apply(Polygon1 const& polygon1, Polygon2 const& polygon2)
+ {
+ // Check number of rings (area check is done in exterior ring check)
+ if (ggl::num_interior_rings(polygon1) != ggl::num_interior_rings(polygon2))
+ {
+ return false;
+ }
+
+ typedef typename ggl::ring_type<Polygon1>::type ring_type1;
+ typedef typename ggl::ring_type<Polygon2>::type ring_type2;
+ typedef ring_ring<ring_type1, ring_type2> compare;
+
+ // Check exterior ring
+ if (! compare::apply(exterior_ring(polygon1), exterior_ring(polygon2)))
+ {
+ return false;
+ }
+
+ // Check interior rings -> first sort them on area ,
+ // for performance reasons (area is not re-calculated in ring-compare)
+ std::vector<sortable> int1, int2;
+
+ fill_sortable(polygon1, int1);
+ fill_sortable(polygon2, int2);
+
+ std::size_t n = 0;
+
+ typename interior_type<Polygon1>::type const& rings1
+ = interior_rings(polygon1);
+ typename interior_type<Polygon2>::type const& rings2
+ = interior_rings(polygon2);
+
+ // Compare all rings (having equal area)
+ for (typename std::vector<sortable>::iterator it1 = int1.begin();
+ it1 != int1.end();
+ ++it1)
+ {
+ for (typename std::vector<sortable>::iterator it2 = int2.begin();
+ ! it1->counterpart_found
+ && it2 != int2.end()
+ && it2->area <= it1->area; //+epsilon
+ ++it2)
+ {
+ if (! it2->counterpart_found
+ && ggl::math::equals(it1->area, it2->area))
+ {
+ if (compare::apply(rings1[it1->index],
+ rings2[it2->index], false))
+ {
+ it1->counterpart_found = true;
+ it2->counterpart_found = true;
+ n++;
+ }
+ }
+ }
+ }
+
+ return n == ggl::num_interior_rings(polygon1);
+ }
+};
+
+
+}} // namespace detail::equals
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag1, typename Tag2,
+ bool IsMulti1, bool IsMulti2,
+ typename Geometry1,
+ typename Geometry2,
+ std::size_t DimensionCount
+>
+struct equals
+{};
+
+
+template <typename P1, typename P2, std::size_t DimensionCount>
+struct equals<point_tag, point_tag, false, false, P1, P2, DimensionCount>
+ : ggl::detail::not_
+ <
+ P1,
+ P2,
+ detail::disjoint::point_point<P1, P2, 0, DimensionCount>
+ >
+{};
+
+
+template <typename Box1, typename Box2, std::size_t DimensionCount>
+struct equals<box_tag, box_tag, false, false, Box1, Box2, DimensionCount>
+ : detail::equals::box_box<Box1, Box2, 0, DimensionCount>
+{};
+
+
+template <typename Ring1, typename Ring2>
+struct equals<ring_tag, ring_tag, false, false, Ring1, Ring2, 2>
+ : detail::equals::ring_ring<Ring1, Ring2>
+{};
+
+template <typename Polygon1, typename Polygon2>
+struct equals<polygon_tag, polygon_tag, false, false, Polygon1, Polygon2, 2>
+ : detail::equals::polygon_polygon<Polygon1, Polygon2>
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Detect if two geometries are spatially equal
+ \ingroup equals
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \return true if geometries are spatially equal, else false
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concept::check_concepts_and_equal_dimensions
+ <
+ const Geometry1,
+ const Geometry2
+ >();
+
+
+ return dispatch::equals
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ is_multi<Geometry1>::type::value,
+ is_multi<Geometry2>::type::value,
+ Geometry1,
+ Geometry2,
+ dimension<Geometry1>::type::value
+ >::apply(geometry1, geometry2);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_EQUALS_HPP
+

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/for_each.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/for_each.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_ALGORITHMS_FOR_EACH_HPP
+#define GGL_ALGORITHMS_FOR_EACH_HPP
+
+/*!
+\defgroup for_each for_each: apply a functor to each point or segment of a geometry
+\details There are two algorithms provided which walk through the points or segments
+of linestrings and polygons. They are called for_each_point, for_each_segment,
+after the standard library
+\note For both for_each algorithms there is a \b const and a non-const version provided.
+*/
+
+#include <algorithm>
+
+
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+#include <ggl/core/is_multi.hpp>
+
+#include <ggl/geometries/concepts/check.hpp>
+
+#include <ggl/geometries/segment.hpp>
+
+#include <ggl/util/add_const_if_c.hpp>
+#include <ggl/util/range_iterator_const_if_c.hpp>
+
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace for_each {
+
+
+template <typename Point, typename Functor, bool IsConst>
+struct fe_point_per_point
+{
+ static inline Functor apply(
+ typename add_const_if_c<IsConst, Point>::type& point, Functor f)
+ {
+ f(point);
+ return f;
+ }
+};
+
+
+template <typename Point, typename Functor, bool IsConst>
+struct fe_point_per_segment
+{
+ static inline Functor apply(
+ typename add_const_if_c<IsConst, Point>::type& point, Functor f)
+ {
+ return f;
+ }
+};
+
+
+template <typename Range, typename Functor, bool IsConst>
+struct fe_range_per_point
+{
+ static inline Functor apply(
+ typename add_const_if_c<IsConst, Range>::type& range,
+ Functor f)
+ {
+ return (std::for_each(boost::begin(range), boost::end(range), f));
+ }
+};
+
+
+template <typename Range, typename Functor, bool IsConst>
+struct fe_range_per_segment
+{
+ static inline Functor apply(
+ typename add_const_if_c<IsConst, Range>::type& range,
+ Functor f)
+ {
+ typedef typename range_iterator_const_if_c
+ <
+ IsConst,
+ Range
+ >::type iterator_type;
+
+ typedef typename add_const_if_c
+ <
+ IsConst,
+ typename point_type<Range>::type
+ >::type point_type;
+
+ iterator_type it = boost::begin(range);
+ iterator_type previous = it++;
+ while(it != boost::end(range))
+ {
+ segment<point_type> s(*previous, *it);
+ f(s);
+ previous = it++;
+ }
+
+ return f;
+ }
+};
+
+
+template <typename Polygon, typename Functor, bool IsConst>
+struct fe_polygon_per_point
+{
+ static inline Functor apply(
+ typename add_const_if_c<IsConst, Polygon>::type& poly,
+ Functor f)
+ {
+ typedef typename range_iterator_const_if_c
+ <
+ IsConst,
+ typename interior_type<Polygon>::type
+ >::type iterator_type;
+
+ typedef fe_range_per_point
+ <
+ typename ring_type<Polygon>::type,
+ Functor,
+ IsConst
+ > per_ring;
+
+ f = per_ring::apply(exterior_ring(poly), f);
+
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly));
+ ++it)
+ {
+ f = per_ring::apply(*it, f);
+ }
+
+ return f;
+ }
+
+};
+
+
+template <typename Polygon, typename Functor, bool IsConst>
+struct fe_polygon_per_segment
+{
+ static inline Functor apply(
+ typename add_const_if_c<IsConst, Polygon>::type& poly,
+ Functor f)
+ {
+ typedef typename range_iterator_const_if_c
+ <
+ IsConst,
+ typename interior_type<Polygon>::type
+ >::type iterator_type;
+
+ typedef fe_range_per_segment
+ <
+ typename ring_type<Polygon>::type,
+ Functor,
+ IsConst
+ > per_ring;
+
+ f = per_ring::apply(exterior_ring(poly), f);
+
+ for (iterator_type it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly));
+ ++it)
+ {
+ f = per_ring::apply(*it, f);
+ }
+
+ return f;
+ }
+
+};
+
+
+}} // namespace detail::for_each
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag,
+ bool IsMulti,
+ typename Geometry,
+ typename Functor,
+ bool IsConst
+>
+struct for_each_point {};
+
+
+template <typename Point, typename Functor, bool IsConst>
+struct for_each_point<point_tag, false, Point, Functor, IsConst>
+ : detail::for_each::fe_point_per_point<Point, Functor, IsConst>
+{};
+
+
+template <typename Linestring, typename Functor, bool IsConst>
+struct for_each_point<linestring_tag, false, Linestring, Functor, IsConst>
+ : detail::for_each::fe_range_per_point<Linestring, Functor, IsConst>
+{};
+
+
+template <typename Ring, typename Functor, bool IsConst>
+struct for_each_point<ring_tag, false, Ring, Functor, IsConst>
+ : detail::for_each::fe_range_per_point<Ring, Functor, IsConst>
+{};
+
+
+template <typename Polygon, typename Functor, bool IsConst>
+struct for_each_point<polygon_tag, false, Polygon, Functor, IsConst>
+ : detail::for_each::fe_polygon_per_point<Polygon, Functor, IsConst>
+{};
+
+
+template
+<
+ typename Tag,
+ bool IsMulti,
+ typename Geometry,
+ typename Functor,
+ bool IsConst
+>
+struct for_each_segment {};
+
+template <typename Point, typename Functor, bool IsConst>
+struct for_each_segment<point_tag, false, Point, Functor, IsConst>
+ : detail::for_each::fe_point_per_segment<Point, Functor, IsConst>
+{};
+
+
+template <typename Linestring, typename Functor, bool IsConst>
+struct for_each_segment<linestring_tag, false, Linestring, Functor, IsConst>
+ : detail::for_each::fe_range_per_segment<Linestring, Functor, IsConst>
+{};
+
+
+template <typename Ring, typename Functor, bool IsConst>
+struct for_each_segment<ring_tag, false, Ring, Functor, IsConst>
+ : detail::for_each::fe_range_per_segment<Ring, Functor, IsConst>
+{};
+
+
+template <typename Polygon, typename Functor, bool IsConst>
+struct for_each_segment<polygon_tag, false, Polygon, Functor, IsConst>
+ : detail::for_each::fe_polygon_per_segment<Polygon, Functor, IsConst>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Calls functor for geometry
+ \ingroup loop
+ \param geometry geometry to loop through
+ \param f functor to use
+ \details Calls the functor the specified \b const geometry
+*/
+template<typename Geometry, typename Functor>
+inline Functor for_each_point(Geometry const& geometry, Functor f)
+{
+ concept::check<const Geometry>();
+
+ return dispatch::for_each_point
+ <
+ typename tag<Geometry>::type,
+ is_multi<Geometry>::type::value,
+ Geometry,
+ Functor,
+ true
+ >::apply(geometry, f);
+}
+
+
+/*!
+ \brief Calls functor for geometry
+ \ingroup loop
+ \param geometry geometry to loop through
+ \param f functor to use
+ \details Calls the functor for the specified geometry
+*/
+template<typename Geometry, typename Functor>
+inline Functor for_each_point(Geometry& geometry, Functor f)
+{
+ concept::check<Geometry>();
+
+ return dispatch::for_each_point
+ <
+ typename tag<Geometry>::type,
+ is_multi<Geometry>::type::value,
+ Geometry,
+ Functor,
+ false
+ >::apply(geometry, f);
+}
+
+
+/*!
+ \brief Calls functor for segments on linestrings, rings, polygons, ...
+ \ingroup 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 Geometry, typename Functor>
+inline Functor for_each_segment(Geometry const& geometry, Functor f)
+{
+ concept::check<const Geometry>();
+
+ return dispatch::for_each_segment
+ <
+ typename tag<Geometry>::type,
+ is_multi<Geometry>::type::value,
+ Geometry,
+ Functor,
+ true
+ >::apply(geometry, f);
+}
+
+
+/*!
+ \brief Calls functor for segments on linestrings, rings, polygons, ...
+ \ingroup loop
+ \param geometry geometry to loop through
+ \param f functor to use
+ \details Calls the functor all segments of the specified geometry
+*/
+template<typename Geometry, typename Functor>
+inline Functor for_each_segment(Geometry& geometry, Functor f)
+{
+ concept::check<Geometry>();
+
+ return dispatch::for_each_segment
+ <
+ typename tag<Geometry>::type,
+ is_multi<Geometry>::type::value,
+ Geometry,
+ Functor,
+ false
+ >::apply(geometry, f);
+}
+
+
+} // namespace ggl
+
+
+#endif // GGL_ALGORITHMS_FOR_EACH_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/get_section.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/get_section.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,116 @@
+// 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/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/range_type.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 boost::range_const_iterator
+ <
+ typename ggl::range_type<Geometry>::type
+ >::type iterator_type;
+
+ static inline void apply(Geometry const& geometry, Section const& section,
+ iterator_type& begin, iterator_type& end)
+ {
+ begin = boost::begin(geometry) + section.begin_index;
+ end = boost::begin(geometry) + section.end_index + 1;
+ }
+};
+
+template <typename Polygon, typename Section>
+struct get_section<polygon_tag, Polygon, Section>
+{
+ typedef typename boost::range_const_iterator
+ <
+ typename ggl::range_type<Polygon>::type
+ >::type iterator_type;
+
+ static inline void apply(Polygon const& polygon, Section const& section,
+ iterator_type& begin, iterator_type& end)
+ {
+ typedef typename 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 boost::range_const_iterator
+ <
+ typename ggl::range_type<Geometry>::type
+ >::type& begin,
+ typename boost::range_const_iterator
+ <
+ typename ggl::range_type<Geometry>::type
+ >::type& end)
+{
+ concept::check<const Geometry>();
+
+ dispatch::get_section
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Section
+ >::apply(geometry, section, begin, end);
+}
+
+
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_GET_SECTION_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/intersection.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/intersection.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_ALGORITHMS_INTERSECTION_HPP
+#define GGL_ALGORITHMS_INTERSECTION_HPP
+
+
+#include <boost/mpl/if.hpp>
+
+#include <ggl/core/reverse_dispatch.hpp>
+#include <ggl/geometries/concepts/check.hpp>
+#include <ggl/algorithms/overlay/clip_linestring.hpp>
+#include <ggl/algorithms/overlay/assemble.hpp>
+
+
+
+/*!
+\defgroup intersection intersection: calculate new geometry containing geometries A and B
+\details The intersection of two geometries A and B is the geometry containing
+ all points of A also belonging to B, but no other elements. The so-called
+ clip is an intersection of a geometry with a box.
+\par Source description:
+- OGC: Returns a geometric object that represents the Point set intersection of
+ this geometric object with another Geometry.
+\see http://en.wikipedia.org/wiki/Intersection_(set_theory)
+\note Any intersection can result in no geometry at all
+
+\par Performance
+- 2776 counties of US are intersected with a 100-points ellipse in 1.1 seconds
+(http://trac.osgeo.org/ggl/wiki/Performance#Interesection)
+- 2776 counties of US are clipped in 0.2 seconds
+(http://trac.osgeo.org/ggl/wiki/Performance#Clip)
+
+
+\par Geometries:
+- \b polygon + \b box (clip) -> \b polygon(s)
+\image html svg_intersection_polygon_box.png
+\image html svg_intersection_countries.png
+- \b ring + \b box (clip) -> \b polygon(s)
+\image html svg_intersection_ring_box.png
+- \b ring + \b ring -> \b polygon(s)
+\image html svg_intersection_ring_ring.png
+- \b polygon + \b ring -> \b polygon(s)
+\image html svg_intersection_polygon_ring.png
+- combinations above -> \b ring(s).
+ <i>If the output is an ouput iterator of rings, holes are omitted</i>
+- \b linestring + \b box (clip)
+\image html svg_intersection_roads.png
+
+\par Example:
+Example showing clipping of linestring with box
+\dontinclude doxygen_1.cpp
+\skip example_clip_linestring1
+\line {
+\until }
+\par Example:
+Example showing clipping of vector, outputting vectors, with box
+\dontinclude doxygen_1.cpp
+\skip example_clip_linestring2
+\line {
+\until }
+\par Example:
+Example showing clipping of polygon with box
+\dontinclude doxygen_1.cpp
+\skip example_intersection_polygon1
+\line {
+\until }
+*/
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay {
+
+
+
+// Specializations for "take_one" for intersection
+// "one" should be the inner one
+
+// for ring and box
+template
+<
+ typename Tag1, typename Geometry1,
+ typename Tag2, typename Geometry2,
+ typename GeometryOut
+>
+struct take_if_1_is_in_2<Tag1, Geometry1, Tag2, Geometry2, GeometryOut, -1>
+{
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& out
+ )
+ {
+ ggl::convert(geometry1, out);
+ }
+};
+
+
+template
+<
+ typename Geometry1,
+ typename Tag2, typename Geometry2,
+ typename GeometryOut
+>
+struct take_if_1_is_in_2<polygon_tag, Geometry1, Tag2, Geometry2, GeometryOut, -1>
+{
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& out
+ )
+ {
+ ggl::convert(exterior_ring(geometry1), out);
+ }
+};
+
+
+template
+<
+ typename Geometry, typename GeometryOut, typename Container
+>
+struct add_holes<polygon_tag, Geometry, GeometryOut, Container, -1>
+{
+
+ static inline void apply(Geometry const& geometry,
+ GeometryOut& out,
+ Container const& holes
+ )
+ {
+ std::vector<sortable> v;
+ sort_interior_rings(holes, v, -1);
+
+ // For an intersection, if a ring is containing an inner ring,
+ // take the outer
+
+ std::size_t const n = boost::size(v);
+
+ for (std::size_t i = 0; i < n; i++)
+ {
+ // So, only if no inners:
+ if (v[i].index_of_parent == -1)
+ {
+ typename ggl::point_type<GeometryOut>::type point;
+ ggl::point_on_border(holes[v[i].index], point);
+ if (ggl::within(point, geometry))
+ {
+ typename ring_type<GeometryOut>::type hole;
+ ggl::convert(holes[v[i].index], hole);
+ ggl::interior_rings(out).push_back(hole);
+ }
+ }
+ }
+ }
+};
+
+
+}} // namespace detail::overlay
+#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_inserter {};
+
+
+template
+<
+ typename Segment1, typename Segment2,
+ typename OutputIterator, typename GeometryOut
+>
+struct intersection_inserter
+ <
+ 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_inserter
+ <
+ 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_inserter
+ <
+ polygon_tag, polygon_tag, polygon_tag,
+ Polygon1, Polygon2,
+ OutputIterator, GeometryOut
+ >
+ : detail::overlay::overlay_and_assemble
+ <Polygon1, Polygon2, OutputIterator, GeometryOut, -1>
+{};
+
+
+
+template
+<
+ typename Polygon, typename Box,
+ typename OutputIterator, typename GeometryOut
+>
+struct intersection_inserter
+<
+ polygon_tag, box_tag, polygon_tag,
+ Polygon, Box,
+ OutputIterator, GeometryOut
+>
+ : detail::overlay::overlay_and_assemble
+ <Polygon, Box, OutputIterator, GeometryOut, -1>
+{};
+
+
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2, typename GeometryTag3,
+ typename Geometry1, typename Geometry2,
+ typename OutputIterator, typename GeometryOut
+>
+struct intersection_inserter_reversed
+{
+ static inline OutputIterator apply(Geometry1 const& g1,
+ Geometry2 const& g2, OutputIterator out)
+ {
+ return intersection_inserter
+ <
+ GeometryTag2, GeometryTag1, GeometryTag3,
+ Geometry2, Geometry1,
+ OutputIterator, GeometryOut
+ >::apply(g2, g1, out);
+ }
+};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+/*!
+ \brief Intersects two geometries
+ \ingroup intersection
+ \details The two input geometries are intersected and the resulting linestring(s),
+ ring(s) or polygon(s) are sent to the specified output operator.
+ \tparam GeometryOut output geometry type, must be specified
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \tparam OutputIterator output iterator
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \param out the output iterator, outputting linestrings or polygons
+ \return the output iterator
+*/
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename OutputIterator
+>
+inline OutputIterator intersection_inserter(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ OutputIterator out)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ return boost::mpl::if_c
+ <
+ reverse_dispatch<Geometry1, Geometry2>::type::value,
+ dispatch::intersection_inserter_reversed
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ typename tag<GeometryOut>::type,
+ Geometry1,
+ Geometry2,
+ OutputIterator, GeometryOut
+ >,
+ dispatch::intersection_inserter
+ <
+ 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/boost/ggl/algorithms/intersects.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/intersects.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_ALGORITHMS_INTERSECTS_HPP
+#define GGL_ALGORITHMS_INTERSECTS_HPP
+
+
+/*!
+\defgroup intersects intersects: detect if a geometry self-intersects or if two geometries intersect
+\par Source descriptions:
+- OGC description: Returns 1 (TRUE) if this geometric object spatially
+ intersects anotherGeometry.
+- OGC: a.Intersects(b) <=> ! a.Disjoint(b)
+\note There are two overloaded versions:
+- with one geometry, detecting self-intersections
+- with two geometries, deferring to disjoint, returning !disjoint
+
+\par Geometries:
+- \b ring
+- \b polygon
+- for two geometries: same is disjoint
+
+\note if one geometry is completely within another geometry, it "intersects"
+
+*/
+
+
+#include <ggl/geometries/concepts/check.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/disjoint.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 intersects
+ \tparam Geometry geometry type
+ \param geometry geometry
+ \return true if there are intersections, else false
+ */
+template <typename Geometry>
+inline bool intersects(Geometry const& geometry)
+{
+ concept::check<const Geometry>();
+
+ typedef typename boost::remove_const<Geometry>::type ncg_type;
+
+ typedef 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;
+}
+
+
+/*!
+ \brief Determine if there is at least one intersection
+ \ingroup intersects
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \return true if there are intersection(s), else false
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool intersects(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ return ! ggl::disjoint(geometry1, geometry2);
+}
+
+
+
+} // ggl
+
+#endif //GGL_ALGORITHMS_INTERSECTS_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/length.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/length.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,212 @@
+// 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/core/cs.hpp>
+
+#include <ggl/geometries/concepts/check.hpp>
+
+#include <ggl/algorithms/assign.hpp>
+#include <ggl/algorithms/detail/calculate_null.hpp>
+
+#include <ggl/strategies/distance.hpp>
+#include <ggl/strategies/length_result.hpp>
+
+/*!
+\defgroup length length: calculate length of a linear geometry
+The length algorithm is implemented for the linestring and the multi_linestring
+geometry and results in the length of the linestring. If the points of
+a linestring have coordinates expressed in kilometers,
+the length of the line is expressed in kilometers as well.
+\par Example:
+Example showing length calculation
+\dontinclude doxygen_1.cpp
+\skip example_length_linestring_iterators1
+\line {
+\until }
+*/
+
+namespace ggl
+{
+
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace length {
+
+
+template<typename Segment, typename Strategy>
+struct segment_length
+{
+ static inline typename length_result<Segment>::type apply(
+ Segment const& segment, Strategy const& strategy)
+ {
+ typedef typename point_type<Segment>::type point_type;
+ point_type p1, p2;
+ assign_point_from_index<0>(segment, p1);
+ assign_point_from_index<1>(segment, p2);
+ return strategy.apply(p1, p2);
+ }
+};
+
+/*!
+\brief Internal, calculates length of a linestring using iterator pairs and
+ specified strategy
+\note for_each could be used here, now that point_type is changed by boost
+ range iterator
+*/
+template<typename Range, typename Strategy>
+struct range_length
+{
+ typedef typename length_result<Range>::type return_type;
+
+ static inline return_type apply(
+ Range const& range, Strategy const& strategy)
+ {
+ return_type sum = return_type();
+
+ typedef typename boost::range_const_iterator<Range>::type iterator_type;
+ iterator_type it = boost::begin(range);
+ if (it != boost::end(range))
+ {
+ iterator_type previous = it++;
+ while(it != boost::end(range))
+ {
+ // Add point-point distance using the return type belonging
+ // to strategy
+ sum += strategy.apply(*previous, *it);
+ previous = it++;
+ }
+ }
+
+ return sum;
+ }
+};
+
+}} // namespace detail::length
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Tag, typename Geometry, typename Strategy>
+struct length : detail::calculate_null
+ <
+ typename length_result<Geometry>::type,
+ Geometry,
+ Strategy
+ >
+{};
+
+
+template <typename Geometry, typename Strategy>
+struct length<linestring_tag, Geometry, Strategy>
+ : detail::length::range_length<Geometry, Strategy>
+{};
+
+
+// RING: length is currently 0; it might be argued that it is the "perimeter"
+
+
+template <typename Geometry, typename Strategy>
+struct length<segment_tag, Geometry, Strategy>
+ : detail::length::segment_length<Geometry, Strategy>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Calculate length of a geometry
+ \ingroup length
+ \details The function length returns the length of a geometry, using the
+ default distance-calculation-strategy
+ \param geometry the geometry, being a ggl::linestring, vector,
+ iterator pair, or any other boost compatible range
+ \return the length
+ Example showing length calculation on a vector
+ \dontinclude doxygen_1.cpp
+ \skip example_length_linestring_iterators2
+ \line {
+ \until }
+ */
+template<typename Geometry>
+inline typename length_result<Geometry>::type length(
+ Geometry const& geometry)
+{
+ concept::check<const Geometry>();
+
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename cs_tag<point_type>::type cs_tag;
+ typedef typename strategy_distance
+ <
+ cs_tag,
+ cs_tag,
+ point_type,
+ point_type
+ >::type strategy_type;
+
+ return dispatch::length
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ strategy_type
+ >::apply(geometry, strategy_type());
+}
+
+
+/*!
+ \brief Calculate length of a geometry
+ \ingroup length
+ \details The function length returns the length of a geometry,
+ using specified strategy
+ \param geometry the geometry, being a 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_1.cpp
+ \skip example_length_linestring_iterators3
+ \line {
+ \until }
+ */
+template<typename Geometry, typename Strategy>
+inline typename length_result<Geometry>::type length(
+ Geometry const& geometry, Strategy const& strategy)
+{
+ concept::check<const Geometry>();
+
+ return dispatch::length
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Strategy
+ >::apply(geometry, strategy);
+}
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_LENGTH_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/make.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/make.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,138 @@
+// 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>
+
+#include <ggl/geometries/concepts/check.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.
+ \note It does not work with array-point types, like int[2]
+ \tparam G the geometry type
+ \tparam T the coordinate type
+ \return the geometry
+ */
+template <typename Geometry, typename T>
+inline Geometry make(T const& c1, T const& c2)
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ ggl::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2);
+ return geometry;
+}
+
+/*!
+ \brief Make a geometry
+ \ingroup access
+ \return a 3D point
+ */
+template <typename Geometry, typename T>
+inline Geometry make(T const& c1, T const& c2, T const& c3)
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ ggl::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2, c3);
+ return geometry;
+}
+
+template <typename Geometry, typename T>
+inline Geometry make(T const& c1, T const& c2, T const& c3, T const& c4)
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ ggl::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2, c3, c4);
+ return geometry;
+}
+
+
+
+template <typename Geometry, typename Range>
+inline Geometry make(Range const& range)
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ append(geometry, range);
+ return geometry;
+}
+
+
+/*!
+ \brief Create a box with inverse infinite coordinates
+ \ingroup access
+ \details The make_inverse function initialize a 2D or 3D box with large coordinates, the
+ min corner is very large, the max corner is very small
+ \tparam Geometry the geometry type
+ \return the box
+ */
+template <typename Geometry>
+inline Geometry make_inverse()
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ dispatch::assign_inverse
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::apply(geometry);
+ return geometry;
+}
+
+/*!
+ \brief Create a geometry with "zero" coordinates
+ \ingroup access
+ \details The make_zero function initializes a 2D or 3D point or box with coordinates of zero
+ \tparam Geometry the geometry type
+ \return the geometry
+ */
+template <typename Geometry>
+inline Geometry make_zero()
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ dispatch::assign_zero
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::apply(geometry);
+ return geometry;
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_MAKE_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/num_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/num_points.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,146 @@
+// 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>
+
+#include <ggl/geometries/concepts/check.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<polygon_tag, false, Geometry>
+ : detail::num_points::polygon_count<Geometry>
+{
+};
+
+} // namespace dispatch
+#endif
+
+
+/*!
+ \brief get number of points
+ \ingroup access
+ \tparam Geometry geometry type
+ \param geometry the geometry to get number of points from
+ \return number of points
+ \note For linestrings/rings also boost::size or .size() could be used, however,
+ for polygons this is less obvious. So this function is provided. Besides that
+ it is described by OGC (numPoints)
+*/
+template <typename Geometry>
+inline std::size_t num_points(Geometry const& geometry)
+{
+ concept::check<const Geometry>();
+
+ typedef typename boost::remove_const<Geometry>::type ncg_type;
+
+ return dispatch::num_points
+ <
+ typename tag<Geometry>::type,
+ is_linear<ncg_type>::value,
+ ncg_type
+ >::apply(geometry);
+}
+
+}
+
+
+#endif // GGL_ALGORITHMS_NUM_POINTS_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/overlaps.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/overlaps.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,193 @@
+// 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
+
+/*!
+\defgroup overlaps overlaps: detect overlap between two geometries
+\par Source descriptions:
+- Egenhofer: Two objects overlap if they have common interior faces and the bounding faces have common parts
+with the opposite interior faces.
+
+\par Geometries:
+- \b box + \b box
+
+*/
+
+
+#include <ggl/core/access.hpp>
+
+#include <ggl/geometries/concepts/check.hpp>
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlaps {
+
+template
+<
+ typename Box1,
+ typename Box2,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct box_box_loop
+{
+ static inline void apply(Box1 const& b1, Box2 const& b2,
+ bool& overlaps, bool& one_in_two, bool& two_in_one)
+ {
+ assert_dimension_equal<Box1, Box2>();
+
+ typedef typename coordinate_type<Box1>::type coordinate_type1;
+ typedef typename coordinate_type<Box2>::type coordinate_type2;
+
+ coordinate_type1 const& min1 = get<min_corner, Dimension>(b1);
+ coordinate_type1 const& max1 = get<max_corner, Dimension>(b1);
+ coordinate_type2 const& min2 = get<min_corner, Dimension>(b2);
+ coordinate_type2 const& max2 = get<max_corner, Dimension>(b2);
+
+ // We might use the (not yet accepted) Boost.Interval
+ // submission in the future
+
+ // If:
+ // B1: |-------|
+ // B2: |------|
+ // in any dimension -> no overlap
+ if (max1 <= min2 || min1 >= max2)
+ {
+ overlaps = false;
+ return;
+ }
+
+ // If:
+ // B1: |--------------------|
+ // B2: |-------------|
+ // in all dimensions -> within, then no overlap
+ // B1: |--------------------|
+ // B2: |-------------|
+ // this is "within-touch" -> then no overlap. So use < and >
+ if (min1 < min2 || max1 > max2)
+ {
+ one_in_two = false;
+ }
+ // Same other way round
+ if (min2 < min1 || max2 > max1)
+ {
+ two_in_one = false;
+ }
+
+ box_box_loop
+ <
+ Box1,
+ Box2,
+ Dimension + 1,
+ DimensionCount
+ >::apply(b1, b2, overlaps, one_in_two, two_in_one);
+ }
+};
+
+template
+<
+ typename Box1,
+ typename Box2,
+ std::size_t DimensionCount
+>
+struct box_box_loop<Box1, Box2, DimensionCount, DimensionCount>
+{
+ static inline void apply(Box1 const& , Box2 const&, bool&, bool&, bool&)
+ {
+ }
+};
+
+template
+<
+ typename Box1,
+ typename Box2
+>
+struct box_box
+{
+ static inline bool apply(Box1 const& b1, Box2 const& b2)
+ {
+ bool overlaps = true;
+ bool within1 = true;
+ bool within2 = true;
+ box_box_loop
+ <
+ Box1,
+ Box2,
+ 0,
+ dimension<Box1>::type::value
+ >::apply(b1, b2, overlaps, within1, within2);
+
+ /*
+ \see http://docs.codehaus.org/display/GEOTDOC/02+Geometry+Relationships#02GeometryRelationships-Overlaps
+ where is stated that "inside" is not an "overlap",
+ this is true and is implemented as such.
+ */
+ return overlaps && ! within1 && ! within2;
+ }
+};
+
+
+
+}} // namespace detail::overlaps
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag1,
+ typename Tag2,
+ typename Geometry1,
+ typename Geometry2
+>
+struct overlaps
+{};
+
+
+template <typename Box1, typename Box2>
+struct overlaps<box_tag, box_tag, Box1, Box2>
+ : detail::overlaps::box_box<Box1, Box2>
+{};
+
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Determines overlap between two geometries
+ \ingroup overlaps
+ \return true if there is overlap
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ return dispatch::overlaps
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_OVERLAPS_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/adapt_turns.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/adapt_turns.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,549 @@
+// 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_ADAPT_TURNS_HPP
+#define GGL_ALGORITHMS_OVERLAY_ADAPT_TURNS_HPP
+
+#include <algorithm>
+
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <ggl/core/coordinate_type.hpp>
+
+#include <ggl/strategies/side.hpp>
+
+#include <ggl/algorithms/equals.hpp>
+
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersection {
+
+
+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)
+ {
+ typedef typename strategy_side
+ <
+ typename cs_tag<Point>::type
+ >::type side;
+
+
+ int dir_q = side::apply(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;
+ }
+ }
+ }
+ }
+
+ typedef typename strategy_side
+ <
+ typename cs_tag<ip_type>::type
+ >::type side;
+
+
+ int dir_p = side::apply(p.first, it->point, p.second);
+ int dir_q = side::apply(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_ALGORITHMS_OVERLAY_ADAPT_TURNS_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/assemble.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/assemble.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,471 @@
+// 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_ASSEMBLE_HPP
+#define GGL_ALGORITHMS_OVERLAY_ASSEMBLE_HPP
+
+
+#include <deque>
+
+#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/overlay/sort_interior_rings.hpp>
+
+
+#include <ggl/algorithms/convert.hpp>
+#include <ggl/algorithms/num_points.hpp>
+#include <ggl/algorithms/within.hpp>
+
+#include <ggl/algorithms/detail/point_on_border.hpp>
+
+#include <ggl/iterators/range_type.hpp>
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay {
+
+
+// Utility function
+template <typename GeometryOut, typename Geometry, typename OutputIterator>
+void convert_and_output(Geometry const& geometry, OutputIterator& out)
+{
+ // 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 result;
+ ggl::convert(geometry, result);
+ *out = result;
+ out++;
+}
+
+
+
+
+template
+<
+ typename Tag1, typename Geometry1,
+ typename Tag2, typename Geometry2, typename GeometryOut,
+ int Direction
+>
+struct take_if_1_is_in_2
+{};
+
+
+template
+<
+ int Direction,
+ typename Geometry1, typename Geometry2, typename GeometryOut
+>
+inline bool take_one(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& out
+ )
+{
+ typename ggl::point_type<Geometry1>::type point;
+ ggl::point_on_border(geometry1, point);
+ if (ggl::within(point, geometry2))
+ {
+ take_if_1_is_in_2
+ <
+ typename tag<Geometry1>::type, Geometry1,
+ typename tag<Geometry2>::type, Geometry2,
+ GeometryOut, Direction
+ >::apply(geometry1, geometry2, out);
+ return true;
+ }
+ return false;
+}
+
+
+template
+<
+ typename TagOut,
+ typename Geometry, typename GeometryOut,
+ typename Container,
+ int Direction
+>
+struct add_holes
+{
+ static inline void apply(Geometry const&, GeometryOut&, Container const& holes)
+ {}
+};
+
+
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename OutputIterator, typename GeometryOut,
+ int Direction
+>
+struct take_none_or_both
+{
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ OutputIterator out
+ )
+ {
+ }
+
+};
+
+
+template
+<
+ typename Tag, typename GeometryOut,
+ typename Container, int Direction
+>
+struct assemble_rings
+{
+ template <typename OutputIterator>
+ static inline void apply(Container const& rings,
+ Container const& ni_holes,
+ OutputIterator out)
+ {}
+};
+
+
+template
+<
+ typename GeometryOut, typename Container, int Direction
+>
+struct assemble_rings<polygon_tag, GeometryOut, Container, Direction>
+{
+ typedef typename boost::range_value<Container>::type ring_type;
+ typedef typename ggl::point_type<ring_type>::type point_type;
+
+ template <typename OutputIterator>
+ static inline void apply(Container const& rings,
+ Container const& ni_holes,
+ OutputIterator out)
+ {
+ std::vector<sortable> sorted_rings;
+ sort_interior_rings(rings, sorted_rings, 1);
+
+ // Add polygons, and holes
+ for (std::vector<sortable>::const_iterator
+ rit = boost::begin(sorted_rings);
+ rit != boost::end(sorted_rings);
+ ++rit)
+ {
+ if (rit->index_of_parent == -1)
+ {
+ GeometryOut result;
+ ggl::convert(rings[rit->index], result);
+
+ // Add holes (direction is OK, so no reverse)
+ std::vector<int> const& holes = rit->index_of_holes;
+ for (std::vector<int>::const_iterator hit = holes.begin();
+ hit != holes.end();
+ ++hit)
+ {
+ interior_rings(result).push_back(rings[*hit]);
+ }
+
+ // Add also all non-intersecting-inner-holes
+ add_holes
+ <
+ polygon_tag,
+ ring_type, GeometryOut, Container,
+ Direction
+ >::apply(rings[rit->index], result, ni_holes);
+
+ *out = result;
+ out++;
+ }
+ }
+ }
+};
+
+
+template
+<
+ typename GeometryOut, typename Container, int Direction
+>
+struct assemble_rings<ring_tag, GeometryOut, Container, Direction>
+{
+ typedef typename boost::range_value<Container>::type ring_type;
+ typedef typename ggl::point_type<ring_type>::type point_type;
+
+ template <typename OutputIterator>
+ static inline void apply(Container const& rings,
+ Container const& ni_holes,
+ OutputIterator out)
+ {
+ // Add positive rings, ignore all holes
+ for (typename boost::range_const_iterator<Container>::type
+ it = boost::begin(rings);
+ it != boost::end(rings);
+ ++it)
+ {
+ if (ggl::area(*it) > 0)
+ {
+ convert_and_output<GeometryOut>(*it, out);
+ }
+ }
+ }
+};
+
+
+
+template<typename Tag>
+struct get_not_intersecting_holes
+{
+ template
+ <
+ typename Polygon,
+ typename IpContainer, typename HoleContainer
+ >
+ static inline void apply(Polygon const&, int,
+ IpContainer const&, HoleContainer& )
+ {
+ }
+};
+
+
+template<>
+struct get_not_intersecting_holes<polygon_tag>
+{
+ template
+ <
+ typename Polygon,
+ typename IpContainer, typename HoleContainer
+ >
+ static inline void apply(Polygon const& polygon, int source_index,
+ IpContainer const& ips,
+ HoleContainer& holes)
+ {
+ typedef typename boost::range_value<IpContainer>::type ip_type;
+ typedef typename boost::range_const_iterator<IpContainer>::type iterator_type;
+ typedef typename ip_type::traversal_vector vector_type;
+ typedef typename boost::range_const_iterator<vector_type>::type tvit_type;
+
+ // Declare vector, fill with false
+ int const n = num_interior_rings(polygon);
+ std::vector<bool> intersecting(n, false);
+
+
+ // Check all IP's and set corresponding inner rings to "intersecting"
+ for (iterator_type it = boost::begin(ips);
+ it != boost::end(ips);
+ ++it)
+ {
+ for (tvit_type tvit = boost::begin(it->info);
+ tvit != boost::end(it->info);
+ ++tvit)
+ {
+ if (tvit->seg_id.source_index == source_index)
+ {
+ int const r = tvit->seg_id.ring_index;
+ if (r >= 0 && r < n)
+ {
+ intersecting[r] = true;
+ }
+ }
+ }
+ }
+
+ typename boost::range_const_iterator
+ <
+ typename interior_type<Polygon>::type
+ >::type rit = boost::begin(interior_rings(polygon));
+ std::vector<bool>::const_iterator iit = boost::begin(intersecting);
+
+ for (;
+ rit != boost::end(interior_rings(polygon))
+ && iit != boost::end(intersecting);
+ ++rit, ++iit)
+ {
+ if (! (*iit))
+ {
+ // Don't pushback, it might be of different type.
+ holes.resize(holes.size() + 1);
+ ggl::convert(*rit, holes.back());
+ }
+ }
+ }
+};
+
+
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename OutputIterator, typename GeometryOut,
+ int Direction
+>
+struct overlay_and_assemble
+{
+ typedef typename ggl::tag<Geometry1>::type tag1;
+ typedef typename ggl::tag<Geometry2>::type tag2;
+ typedef typename ggl::tag<GeometryOut>::type tag_out;
+
+ static inline OutputIterator apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2, OutputIterator out)
+ {
+ if (ggl::num_points(geometry1) == 0
+ || ggl::num_points(geometry2) == 0)
+ {
+ return out;
+ }
+
+
+ typedef typename ggl::point_type<GeometryOut>::type point_type;
+ typedef detail::intersection::intersection_point<point_type> ip_type;
+ typedef std::deque<ip_type> container_type;
+
+ // "Abuse" rangetype for ringtype: for polygon, it is the type of the
+ // exterior ring. For ring, it is the ring itself. That is what is
+ // wished here as well.
+ typedef typename ggl::range_type<GeometryOut>::type ring_type;
+
+ container_type ips; // intersection points
+
+ bool trivial = ggl::get_intersection_points(geometry1, geometry2, ips);
+
+ // If there are no IP-s, check if one point is in other geometry
+ // (both geometries have points, see check above)
+ // If yes, take the correct one
+
+ // (which depends on intersection/union)
+ // If both are unrelated, take none (intersection) or both (union)
+
+ // If there are disjoint or containing holes:
+ // - Hole of A can be within hole of B
+ // - for union: take hole of A
+ // - for intersection: take hole of B
+ // - Hole of A can be disjoint from B
+ // - for union: remove those holes
+ // - for intersection: take all those holes
+ // -> generic procedure
+ // - Collect all holes in one vector
+ // - Sort them on decreasing area
+ // - Check if one is within a larger one,
+ // - if yes, take one of them
+ // - if no, take all, or none of them
+
+ // Gather non-intersecting holes
+ typedef std::vector<ring_type> hole_vector_type;
+ hole_vector_type ni_holes;
+ get_not_intersecting_holes<tag1>::apply(geometry1, 0, ips, ni_holes);
+ get_not_intersecting_holes<tag2>::apply(geometry2, 1, ips, ni_holes);
+
+ if (ips.size() <= 0)
+ {
+ GeometryOut result;
+ if (take_one<Direction>(geometry1, geometry2, result))
+ {
+ add_holes
+ <
+ tag_out, Geometry1, GeometryOut, hole_vector_type,
+ Direction
+ >::apply(geometry1, result, ni_holes);
+ *out = result;
+ out++;
+ }
+ else if (take_one<Direction>(geometry2, geometry1, result))
+ {
+ add_holes
+ <
+ tag_out,
+ Geometry2, GeometryOut, hole_vector_type,
+ Direction
+ >::apply(geometry2, result, ni_holes);
+ *out = result;
+ out++;
+ }
+ else
+ {
+ take_none_or_both
+ <
+ Geometry1, Geometry2,
+ OutputIterator, GeometryOut,
+ Direction
+ >::apply(geometry1, geometry2, out);
+ }
+ }
+ else
+ {
+ if (! trivial)
+ {
+ ggl::merge_intersection_points(ips);
+
+ // If all IP's are removed, they are all collinear or forming
+ // an angle which each other.
+ // In that case, the inputs are EQUAL.
+ // For both intersection and union, just output one.
+ if (ips.size() == 0)
+ {
+ convert_and_output<GeometryOut>(geometry1, out);
+ return out;
+ }
+
+ ggl::adapt_turns(ips);
+ }
+
+ ggl::enrich_intersection_points(ips, trivial);
+
+
+ std::vector<ring_type> v;
+ ggl::traverse<ring_type>
+ (
+ geometry1,
+ geometry2,
+ Direction,
+ ips,
+ trivial,
+ std::back_inserter(v)
+ );
+
+ switch (boost::size(v))
+ {
+ case 0 : break;
+ case 1 :
+ //convert_and_output<GeometryOut>(v.front(), out);
+ {
+ GeometryOut result;
+ ggl::convert(v.front(), result);
+ add_holes
+ <
+ tag_out,
+ ring_type, GeometryOut, hole_vector_type,
+ Direction
+ >::apply(v.front(), result, ni_holes);
+ *out = result;
+ out++;
+ }
+ break;
+ default :
+ assemble_rings
+ <
+ tag_out, GeometryOut,
+ hole_vector_type, Direction
+ >::apply(v, ni_holes, out);
+ }
+ }
+
+ return out;
+ }
+};
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+} // ggl
+
+#endif //GGL_ALGORITHMS_OVERLAY_ASSEMBLE_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/clip_linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/clip_linestring.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,238 @@
+// 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_CLIP_LINESTRING_HPP
+#define GGL_ALGORITHMS_OVERLAY_CLIP_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
+ \note Though it is implemented in namespace strategy, and theoretically another
+ strategy could be used, it is not (yet) updated to the general strategy concepts,
+ and not (yet) splitted into a file in folder strategies
+ \author Barend Gehrels, and the following recourses
+ - A tutorial: http://www.skytopia.com/project/articles/compsci/clipping.html
+ - a German applet (link broken): http://ls7-www.cs.uni-dortmund.de/students/projectgroups/acit/lineclip.shtml
+*/
+template<typename Box, typename Point>
+class liang_barsky
+{
+private:
+ typedef ggl::segment<Point> segment_type;
+
+ inline bool check_edge(double const& p, double const& q, double& t1, double& t2) const
+ {
+ bool visible = true;
+
+ if(p < 0)
+ {
+ 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:
+
+ inline bool clip_segment(Box const& b, segment_type& s, bool& sp1_clipped, bool& sp2_clipped) const
+ {
+ typedef typename select_coordinate_type<Box, Point>::type coordinate_type;
+
+ 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;
+
+ if (sp2_clipped)
+ {
+ set<1, 0>(s, get<0, 0>(s) + t2 * dx);
+ set<1, 1>(s, get<0, 1>(s) + t2 * dy);
+ }
+
+ if(sp1_clipped)
+ {
+ set<0, 0>(s, get<0, 0>(s) + t1 * dx);
+ set<0, 1>(s, get<0, 1>(s) + t1 * dy);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ template<typename Linestring, typename OutputIterator>
+ inline void apply(Linestring& line_out, OutputIterator out) const
+ {
+ if (!boost::empty(line_out))
+ {
+ *out = line_out;
+ ++out;
+ 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 "apply"
+*/
+template
+<
+ typename OutputLinestring,
+ typename OutputIterator,
+ typename Linestring,
+ typename Box,
+ typename Strategy
+>
+OutputIterator clip_linestring_with_box(Box const& b, Linestring const& linestring,
+ OutputIterator out, Strategy const& strategy)
+{
+ if (boost::begin(linestring) == boost::end(linestring))
+ {
+ return out;
+ }
+
+ typedef typename point_type<OutputLinestring>::type point_type;
+
+ OutputLinestring line_out;
+
+ typedef typename boost::range_const_iterator<Linestring>::type iterator_type;
+ iterator_type vertex = boost::begin(linestring);
+ for(iterator_type previous = vertex++;
+ vertex != boost::end(linestring);
+ previous = vertex++)
+ {
+ point_type p1, p2;
+ copy_coordinates(*previous, p1);
+ copy_coordinates(*vertex, p2);
+
+ // Clip the segment. Five situations:
+ // 1. Segment is invisible, finish line if any (shouldn't occur)
+ // 2. Segment is completely visible. Add (p1)-p2 to line
+ // 3. Point 1 is invisible (clipped), point 2 is visible. Start new line from p1-p2...
+ // 4. Point 1 is visible, point 2 is invisible (clipped). End the line with ...p2
+ // 5. Point 1 and point 2 are both invisible (clipped). Start/finish an independant line p1-p2
+ //
+ // This results in:
+ // a. if p1 is clipped, start new line
+ // b. if segment is partly or completely visible, add the segment
+ // c. if p2 is clipped, end the line
+
+ bool c1 = false;
+ bool c2 = false;
+ segment<point_type> s(p1, p2);
+
+ if (!strategy.clip_segment(b, s, c1, c2))
+ {
+ strategy.apply(line_out, out);
+ }
+ else
+ {
+ // a. If necessary, finish the line and add a start a new one
+ if (c1)
+ {
+ strategy.apply(line_out, out);
+ }
+
+ // b. Add p1 only if it is the first point, then add p2
+ if (boost::empty(line_out))
+ {
+ ggl::append(line_out, p1);
+ }
+ ggl::append(line_out, p2);
+
+ // c. If c2 is clipped, finish the line
+ if (c2)
+ {
+ strategy.apply(line_out, out);
+ }
+ }
+
+ }
+
+ // Add last part
+ strategy.apply(line_out, out);
+ return out;
+}
+
+}} // namespace detail::intersection
+#endif // DOXYGEN_NO_DETAIL
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_OVERLAY_CLIP_LINESTRING_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/copy_segments.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/copy_segments.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,216 @@
+// 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/geometries/concepts/check.hpp>
+
+#include <ggl/algorithms/overlay/intersection_point.hpp>
+
+#include <ggl/iterators/ever_circling_iterator.hpp>
+
+#include <ggl/iterators/range_type.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 boost::range_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)
+{
+ concept::check<const Geometry>();
+
+ 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/boost/ggl/algorithms/overlay/enrich_intersection_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/enrich_intersection_points.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_OVERLAY_ENRICH_INTERSECTION_POINTS_HPP
+#define GGL_ALGORITHMS_OVERLAY_ENRICH_INTERSECTION_POINTS_HPP
+
+#include <cstddef>
+#include <algorithm>
+#include <map>
+#include <vector>
+#ifdef GGL_DEBUG_INTERSECTION
+#include <iostream>
+#endif
+
+#include <boost/assert.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_OVERLAY_ENRICH_INTERSECTION_POINTS_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/get_intersection_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/get_intersection_points.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,792 @@
+// 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_GET_INTERSECTION_POINTS_HPP
+#define GGL_ALGORITHMS_OVERLAY_GET_INTERSECTION_POINTS_HPP
+
+/*!
+\defgroup overlay overlay helper operations (getting intersection points, etc)
+*/
+
+
+#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/geometries/concepts/check.hpp>
+
+#include <ggl/util/math.hpp>
+
+#include <ggl/geometries/box.hpp>
+
+#include <ggl/iterators/range_type.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/detail/disjoint.hpp>
+
+#include <ggl/algorithms/distance.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 boost::range_const_iterator
+ <
+ typename ggl::range_type<Geometry1>::type
+ >::type range1_iterator;
+ typedef typename boost::range_const_iterator
+ <
+ typename ggl::range_type<Geometry2>::type
+ >::type range2_iterator;
+
+ int const dir1 = sec1.directions[0];
+ int const dir2 = sec2.directions[0];
+ int index1 = sec1.begin_index;
+ int ndi1 = sec1.non_duplicate_index;
+
+ bool const same_source =
+ source_id1 == source_id2
+ && sec1.multi_index == sec2.multi_index
+ && sec1.ring_index == sec2.ring_index;
+
+ // Note that it is NOT possible to have section-iterators here
+ // because of the logistics of "index" (the section-iterator automatically
+ // skips to the begin-point, we loose the index or have to recalculate it)
+ // So we mimic it here
+ range1_iterator it1, end1;
+ get_section(geometry1, sec1, it1, end1);
+
+ // Mimic 1: Skip to point such that section interects other box
+ range1_iterator prev1 = it1++;
+ for(; it1 != end1 && preceding<0>(dir1, *it1, sec2.bounding_box);
+ prev1 = it1++, index1++, ndi1++)
+ {
+ }
+ // Go back one step because we want to start completely preceding
+ it1 = prev1;
+
+ // Walk through section and stop if we exceed the other box
+ for (prev1 = it1++;
+ it1 != end1 && ! exceeding<0>(dir1, *prev1, sec2.bounding_box);
+ prev1 = it1++, index1++, ndi1++)
+ {
+ segment1_type s1(*prev1, *it1);
+
+ int index2 = sec2.begin_index;
+ int ndi2 = sec2.non_duplicate_index;
+
+ range2_iterator it2, end2;
+ get_section(geometry2, sec2, it2, end2);
+
+ range2_iterator prev2 = it2++;
+
+ // Mimic 2:
+ for(; it2 != end2 && preceding<0>(dir2, *it2, sec1.bounding_box);
+ prev2 = it2++, index2++, ndi2++)
+ {
+ }
+ it2 = prev2;
+
+ for (prev2 = it2++;
+ it2 != end2 && ! exceeding<0>(dir2, *prev2, sec1.bounding_box);
+ prev2 = it2++, index2++, ndi2++)
+ {
+ bool skip = same_source;
+ if (skip)
+ {
+ // If sources are the same (possibly self-intersecting):
+ // check if it is a neighbouring sement.
+ // (including first-last segment
+ // and two segments with one or more degenerate/duplicate
+ // (zero-length) segments in between)
+
+ // Also skip if index1 < index2 to avoid getting all
+ // intersections twice (only do this on same source!)
+
+ // About n-2:
+ // (square: range_count=5, indices 0,1,2,3
+ // -> 0-3 are adjacent)
+ skip = index2 >= index1
+ || ndi1 == ndi2 + 1
+ || (index2 == 0 && index1 >= int(sec1.range_count) - 2)
+ ;
+ }
+
+ if (! skip)
+ {
+ if (relate<segment1_type, segment2_type, IntersectionPoints>
+ ::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::detail::disjoint::disjoint_box_box(
+ 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)
+ )
+ )*/
+ if (true)
+ {
+ segment_identifier seg_id(source_id1,
+ multi_index, ring_index, index);
+
+ typedef relate
+ <
+ segment_type, box_segment_type, IntersectionPoints
+ > relater;
+
+ // Depending on code some relations can be left out
+ relater::apply(segment, left, seg_id,
+ segment_identifier(source_id2, -1, -1, 0),
+ intersection_points, trivial);
+ relater::apply(segment, top, seg_id,
+ segment_identifier(source_id2, -1, -1, 1),
+ intersection_points, trivial);
+ relater::apply(segment, right, seg_id,
+ segment_identifier(source_id2, -1, -1, 2),
+ intersection_points, trivial);
+ relater::apply(segment, bottom, seg_id,
+ segment_identifier(source_id2, -1, -1, 3),
+ intersection_points, trivial);
+
+ }
+ }
+ }
+
+private:
+ template<std::size_t Index, typename Point>
+ static inline int get_side(Box const& box, Point const& point)
+ {
+ // Inside -> 0
+ // Outside -> -1 (left/below) or 1 (right/above)
+ // On border -> -2 (left/lower) or 2 (right/upper)
+ // The only purpose of the value is to not be the same,
+ // and to denote if it is inside (0)
+
+ typename coordinate_type<Point>::type const& c = get<Index>(point);
+ typename coordinate_type<Box>::type const& left = get<min_corner, Index>(box);
+ typename coordinate_type<Box>::type const& right = get<max_corner, Index>(box);
+
+ if (ggl::math::equals(c, left)) return -2;
+ else if (ggl::math::equals(c, right)) return 2;
+ else if (c < left) return -1;
+ else if (c > right) return 1;
+ else return 0;
+ }
+
+
+};
+
+
+}} // namespace detail::get_intersection_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2,
+ bool IsMulti1, bool IsMulti2,
+ typename Geometry1, typename Geometry2,
+ typename IntersectionPoints
+
+>
+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 Ring, typename Box, typename IntersectionPoints>
+struct get_intersection_points
+ <
+ ring_tag, box_tag, false, false,
+ Ring, Box,
+ IntersectionPoints
+ >
+{
+ static inline bool apply(
+ std::size_t source_id1, Ring const& ring,
+ std::size_t source_id2, Box const& box,
+ IntersectionPoints& intersection_points)
+ {
+ typedef typename boost::range_const_iterator
+ <
+ Ring
+ >::type iterator_type;
+
+ typedef detail::get_intersection_points::get_ips_cs
+ <Ring, Box, IntersectionPoints> intersector_type;
+
+ bool trivial = true;
+ intersector_type::apply(
+ source_id1, ring, -1, -1,
+ source_id2, box,
+ intersection_points, trivial);
+
+ return trivial;
+ }
+};
+
+
+template<typename Ring1, typename Ring2, typename IntersectionPoints>
+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 Polygon, typename Ring, typename IntersectionPoints>
+struct get_intersection_points
+ <
+ polygon_tag, ring_tag, false, false,
+ Polygon, Ring,
+ IntersectionPoints
+ >
+ : detail::get_intersection_points::get_ips_generic
+ <
+ Polygon,
+ Ring,
+ 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)
+{
+ concept::check_concepts_and_equal_dimensions<const Geometry1, const Geometry2>();
+
+ typedef typename boost::remove_const<Geometry1>::type ncg1_type;
+ typedef typename boost::remove_const<Geometry2>::type ncg2_type;
+
+ return boost::mpl::if_c
+ <
+ reverse_dispatch<Geometry1, Geometry2>::type::value,
+ dispatch::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_OVERLAY_GET_INTERSECTION_POINTS_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/intersection_point.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/intersection_point.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,259 @@
+// 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.hpp>
+#include <ggl/strategies/distance_result.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);
+ }
+ if (info.flagged)
+ {
+ os << " FLAGGED";
+ }
+ 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, std::size_t Dimension>
+ struct access<ggl::detail::intersection::intersection_point<P>, Dimension>
+ {
+ static inline typename coordinate_type<P>::type get(
+ ggl::detail::intersection::intersection_point<P> const& p)
+ {
+ return ggl::get<Dimension>(p.point);
+ }
+
+ static inline void set(ggl::detail::intersection::intersection_point<P>& p,
+ typename coordinate_type<P>::type const& value)
+ {
+ ggl::set<Dimension>(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/boost/ggl/algorithms/overlay/merge_intersection_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/merge_intersection_points.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_ALGORITHMS_OVERLAY_MERGE_INTERSECTION_POINTS_HPP
+#define GGL_ALGORITHMS_OVERLAY_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/detail/disjoint.hpp>
+#include <ggl/algorithms/overlay/intersection_point.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 ggl::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
+ 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;
+ }
+
+ // Some cases will be normal (neutral) case now,
+ // so to continue traversal.
+ if (it->info.size() == 2)
+ {
+ // Case: previously forming an 'angle' (test #19)
+ if (it->info.front().how == 'a'
+ && it->info.back().how == 'a')
+ {
+ it->info.front().direction = 1;
+ it->info.back().direction = 1;
+ }
+ // Case: both arrive there, they can continue,
+ // change in departure
+ if (it->info.front().how == 't'
+ && it->info.back().how == 't')
+ {
+ it->info.front().arrival = -1;
+ it->info.back().arrival = -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::detail::equals::equals_point_point(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_OVERLAY_MERGE_INTERSECTION_POINTS_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/segment_identifier.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/segment_identifier.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_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>
+
+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/boost/ggl/algorithms/overlay/self_intersection_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/self_intersection_points.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,173 @@
+// 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_SELF_INTERSECTION_POINTS_HPP
+#define GGL_ALGORITHMS_OVERLAY_SELF_INTERSECTION_POINTS_HPP
+
+#include <cstddef>
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/coordinate_dimension.hpp>
+#include <ggl/core/is_multi.hpp>
+
+#include <ggl/geometries/concepts/check.hpp>
+
+#include <ggl/algorithms/detail/disjoint.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::detail::disjoint::disjoint_box_box(
+ 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)
+{
+ concept::check<Geometry>();
+
+ 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_OVERLAY_SELF_INTERSECTION_POINTS_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/sort_interior_rings.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/sort_interior_rings.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,128 @@
+// 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_SORT_INTERIOR_RINGS_HPP
+#define GGL_ALGORITHMS_OVERLAY_SORT_INTERIOR_RINGS_HPP
+
+#include <algorithm>
+#include <vector>
+
+#include <ggl/algorithms/area.hpp>
+#include <ggl/algorithms/within.hpp>
+#include <ggl/algorithms/detail/point_on_border.hpp>
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay {
+
+struct sortable
+{
+ int index; // zero-based (ZB) index to ring in rings
+ double area;
+ int index_of_parent; // ZB index to parent-ring
+ std::vector<int> index_of_holes; // ZB index to holes
+
+ inline sortable(int i, double a)
+ : index(i)
+ , area(a)
+ , index_of_parent(-1)
+ {}
+
+ inline bool operator<(sortable const& other) const
+ {
+ // sort in reverse order
+ return area > other.area;
+ }
+};
+
+
+
+template<typename Container>
+void sort_interior_rings(Container const& rings, std::vector<sortable>& sorted_rings, int factor)
+{
+ typedef typename boost::range_value<Container>::type ring_type;
+ typedef typename ggl::point_type<ring_type>::type point_type;
+
+ // Because of the whole followed procedure, the orientations (cw or ccw)
+ // of parents and holes are OK, and their areas are positive (parents)
+ // or negative (children)
+
+ // Create a copy (without copying geometries), with area (and envelope)
+ std::size_t n = 0;
+ for (typename boost::range_const_iterator<Container>::type
+ it = boost::begin(rings);
+ it != boost::end(rings);
+ ++it, ++n)
+ {
+ sorted_rings.push_back(sortable(n, factor * ggl::area(*it)));
+ }
+
+ // Sort in reverse order -> largest rings first, holes (neg. area) last
+ std::sort(sorted_rings.begin(), sorted_rings.end());
+
+ // Check which holes are in which polygons
+ for (std::size_t hole = 1; hole < n; hole++)
+ {
+ // It is a hole if its area is negative
+ if (sorted_rings[hole].area < 0 || factor < 0)
+ {
+ // So check if it is lying in one of the earlier rings
+ bool parent_found = false;
+ for (std::size_t parent = 0;
+ parent < hole
+ && ! parent_found
+ && sorted_rings[parent].area > 0;
+ parent++)
+ {
+ // note that "hole" is indexed in sorted rings,
+ // so make new "h" that is indexed in original rings
+ int const h = sorted_rings[hole].index;
+ int const p = sorted_rings[parent].index;
+
+ point_type point;
+ ggl::point_on_border(rings[h], point);
+ if (ggl::within(point, rings[p]))
+ {
+ // Update registration
+ sorted_rings[hole].index_of_parent = p;
+ sorted_rings[parent].index_of_holes.push_back(h);
+ parent_found = true;
+ }
+ }
+ }
+ }
+
+ /***
+ for (std::size_t i = 0; i < n; i++)
+ {
+ std::cout << "i: " << i
+ << " area: " << sorted_rings[i].area
+ << " count: " << rings[sorted_rings[i].index].size()
+ << " parent: " << sorted_rings[i].index_of_parent
+ << " holes: ";
+ for (int j = 0; j < boost::size(sorted_rings[i].index_of_holes); j++)
+ {
+ std::cout << " " << sorted_rings[i].index_of_holes[j];
+ }
+ std::cout << std::endl;
+ }
+ ***/
+}
+
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_OVERLAY_SORT_INTERIOR_RINGS_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/traverse.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/overlay/traverse.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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>
+
+#include <ggl/strategies/side.hpp>
+
+#include <ggl/geometries/concepts/check.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
+{
+ typedef typename strategy_side
+ <
+ typename cs_tag<IntersectionPoint>::type
+ >::type side;
+
+ inline on_direction(IntersectionPoint const& ip, int direction)
+ : m_ip(ip)
+ , m_direction(direction)
+ {}
+
+
+ inline bool operator()(IntersectionInfo const& first, IntersectionInfo const& second) const
+ {
+ int dir = side::apply(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)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+
+ 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/boost/ggl/algorithms/parse.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/parse.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,122 @@
+// 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_PARSE_HPP
+#define GGL_ALGORITHMS_PARSE_HPP
+
+#include <string>
+
+
+#include <ggl/core/tags.hpp>
+#include <ggl/strategies/parse.hpp>
+
+#include <ggl/geometries/concepts/check.hpp>
+
+// TODO: remove used EXTENSION here (result should be part of parsing strategy)
+#include <ggl/extensions/gis/geographic/strategies/dms_parser.hpp>
+
+/*!
+\defgroup parse parse and assign string values
+*/
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+template <typename Tag, typename G>
+struct parsing
+{
+};
+
+template <typename Point>
+struct parsing<point_tag, Point>
+{
+ template <typename S>
+ static inline void parse(Point& point, std::string const& c1, std::string const& c2, S const& strategy)
+ {
+ assert_dimension<Point, 2>();
+ dms_result r1 = strategy(c1.c_str());
+ dms_result r2 = strategy(c2.c_str());
+
+ if (0 == r1.axis())
+ set<0>(point, r1);
+ else
+ set<1>(point, r1);
+
+ if (0 == r2.axis())
+ set<0>(point, r2);
+ else
+ set<1>(point, r2);
+ }
+
+ static inline void parse(Point& point, std::string const& c1, std::string const& c2)
+ {
+ // strategy-parser corresponding to degree/radian
+ typename strategy_parse
+ <
+ typename cs_tag<Point>::type,
+ typename coordinate_system<Point>::type
+ >::type strategy;
+
+ parse(point, c1, c2, strategy);
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief parse two strings to a spherical/geographic point, using W/E/N/S
+ \ingroup parse
+ */
+template <typename Geometry>
+inline void parse(Geometry& geometry, std::string const& c1, std::string const& c2)
+{
+ concept::check<Geometry>();
+ dispatch::parsing<typename tag<Geometry>::type, Geometry>::parse(geometry, c1, c2);
+}
+
+/*!
+ \brief parse two strings to a spherical/geographic point, using a specified strategy
+ \details user can use N/E/S/O or N/O/Z/W or other formats
+ \ingroup parse
+ */
+template <typename Geometry, typename S>
+inline void parse(Geometry& geometry, std::string const& c1,
+ std::string const& c2, S const& strategy)
+{
+ concept::check<Geometry>();
+ dispatch::parsing<typename tag<Geometry>::type, Geometry>::parse(geometry, c1, c2, strategy);
+}
+
+// There will be a parsing function with three arguments (ANGLE,ANGLE,RADIUS)
+
+template <typename Geometry>
+inline Geometry parse(std::string const& c1, std::string const& c2)
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ dispatch::parsing<typename tag<Geometry>::type, Geometry>::parse(geometry, c1, c2);
+ return geometry;
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_PARSE_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/perimeter.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/perimeter.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,137 @@
+// 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 <ggl/core/cs.hpp>
+
+#include <ggl/geometries/concepts/check.hpp>
+
+#include <ggl/strategies/length_result.hpp>
+
+#include <ggl/algorithms/length.hpp>
+#include <ggl/algorithms/detail/calculate_null.hpp>
+#include <ggl/algorithms/detail/calculate_sum.hpp>
+
+
+/*!
+\defgroup perimeter perimeter: calculate perimeter of a geometry
+\par Geometries:
+- \b polygon
+- \b box
+- \b linear_ring
+- \b multi_polygon
+*/
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// Default perimeter is 0.0, specializations implement calculated values
+template <typename Tag, typename Geometry, typename Strategy>
+struct perimeter : detail::calculate_null
+ <
+ typename length_result<Geometry>::type,
+ Geometry,
+ Strategy
+ >
+{};
+
+template <typename Geometry, typename Strategy>
+struct perimeter<ring_tag, Geometry, Strategy>
+ : detail::length::range_length<Geometry, Strategy>
+{};
+
+template <typename Polygon, typename Strategy>
+struct perimeter<polygon_tag, Polygon, Strategy>
+ : detail::calculate_polygon_sum
+ <
+ typename length_result<Polygon>::type,
+ Polygon,
+ Strategy,
+ detail::length::range_length
+ <
+ typename ring_type<Polygon>::type,
+ Strategy
+ >
+ >
+{};
+
+
+// box,n-sphere: to be implemented
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Calculate perimeter of a geometry
+ \ingroup perimeter
+ \details The function perimeter returns the perimeter of a geometry,
+ using the default distance-calculation-strategy
+ \param geometry the geometry, be it a ggl::ring, vector, iterator pair,
+ or any other boost compatible range
+ \return the perimeter
+ */
+template<typename Geometry>
+inline typename length_result<Geometry>::type perimeter(
+ Geometry const& geometry)
+{
+ concept::check<const Geometry>();
+
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename cs_tag<point_type>::type cs_tag;
+ typedef typename strategy_distance
+ <
+ cs_tag,
+ cs_tag,
+ point_type,
+ point_type
+ >::type strategy_type;
+
+ return dispatch::perimeter
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ strategy_type
+ >::apply(geometry, strategy_type());
+}
+
+/*!
+ \brief Calculate perimeter of a geometry
+ \ingroup perimeter
+ \details The function perimeter returns the perimeter of a geometry,
+ using specified strategy
+ \param geometry the geometry, be it a 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 typename length_result<Geometry>::type perimeter(
+ Geometry const& geometry, Strategy const& strategy)
+{
+ concept::check<const Geometry>();
+
+ return dispatch::perimeter
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Strategy
+ >::apply(geometry, strategy);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_PERIMETER_HPP
+

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/sectionalize.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/sectionalize.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,581 @@
+// 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/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/geometries/concepts/check.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)
+{
+ concept::check<const Geometry>();
+
+ // A maximum of 10 segments per section seems to give the fastest results
+ static const std::size_t max_segments_per_section = 10;
+ typedef dispatch::sectionalize
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Sections,
+ Sections::value,
+ max_segments_per_section
+ > sectionalizer_type;
+
+ sections.clear();
+ sectionalizer_type::apply(geometry, sections);
+}
+
+
+
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_SECTIONALIZE_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/simplify.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/simplify.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,409 @@
+// 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/core/cs.hpp>
+#include <ggl/core/ring_type.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+
+#include <ggl/geometries/concepts/check.hpp>
+
+#include <ggl/strategies/agnostic/simplify_douglas_peucker.hpp>
+#include <ggl/strategies/concepts/simplify_concept.hpp>
+
+#include <ggl/algorithms/clear.hpp>
+
+
+
+/*!
+\defgroup simplify simplify: remove points from a geometry, keeping shape (simplification or generalization)
+\par Source description:
+- Wikipedia: given a 'curve' composed of line segments to find a curve
+ not too dissimilar but that has fewer points
+
+\see http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
+
+\par Performance
+- Performance is measured on simplification of a collection of rings,
+ such that 10% of the points is kept.
+- 2776 counties of US are simplified in 0.7 seconds
+(http://trac.osgeo.org/ggl/wiki/Performance#Simplify1)
+
+\par Geometries
+- \b linestring:
+\image html svg_simplify_road.png
+This US Road originally contained 34 points, the simplified version contains 7 points
+
+- \b polygon:
+\image html svg_simplify_country.png
+This country (Belgium) originally contained 55 points, the simplified version contains 24 points
+
+\note simplifying a valid simple polygon (which never intersects itself)
+ might result in an invalid polygon, where the simplified rings intersect
+ themselves or one of the other outer or inner rings.
+Efficient simplification of a ring/polygon is still an "Open Problem"
+(http://maven.smith.edu/~orourke/TOPP/P24.html#Problem.24)
+
+- \b multi_linestring
+- \b multi_polygon
+
+
+*/
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace simplify {
+
+template<typename Range, typename Strategy>
+struct simplify_range_inserter
+{
+ template <typename OutputIterator>
+ static inline void apply(Range const& range, OutputIterator out,
+ double max_distance, Strategy const& strategy)
+ {
+ if (boost::size(range) <= 2 || max_distance < 0)
+ {
+ std::copy(boost::begin(range), boost::end(range), out);
+ }
+ else
+ {
+ strategy.apply(range, out, max_distance);
+ }
+ }
+};
+
+
+template<typename Range, typename Strategy>
+struct simplify_copy
+{
+ static inline void apply(Range const& range, Range& out,
+ double max_distance, Strategy const& strategy)
+ {
+ std::copy
+ (
+ boost::begin(range), boost::end(range), std::back_inserter(out)
+ );
+ }
+};
+
+
+template<typename Range, typename Strategy, std::size_t Minimum>
+struct simplify_range
+{
+ static inline void apply(Range const& range, Range& out,
+ double max_distance, Strategy const& strategy)
+ {
+ // Call do_container for a linestring / ring
+
+ /* For a RING:
+ The first/last point (the closing point of the ring) should maybe
+ be excluded because it lies on a line with second/one but last.
+ Here it is never excluded.
+
+ Note also that, especially if max_distance is too large,
+ the output ring might be self intersecting while the input ring is
+ not, although chances are low in normal polygons
+
+ Finally the inputring might have 4 points (=correct),
+ the output < 4(=wrong)
+ */
+
+ if (boost::size(range) <= int(Minimum) || max_distance < 0.0)
+ {
+ simplify_copy<Range, Strategy>::apply
+ (
+ range, out, max_distance, strategy
+ );
+ }
+ else
+ {
+ simplify_range_inserter<Range, Strategy>::apply
+ (
+ range, std::back_inserter(out), max_distance, strategy
+ );
+ }
+ }
+};
+
+template<typename Polygon, typename Strategy>
+struct simplify_polygon
+{
+ static inline void apply(Polygon const& poly_in, Polygon& poly_out,
+ double max_distance, Strategy const& strategy)
+ {
+ typedef typename ring_type<Polygon>::type ring_type;
+
+ typedef typename boost::range_iterator
+ <typename interior_type<Polygon>::type>::type iterator_type;
+ typedef typename boost::range_const_iterator
+ <typename interior_type<Polygon>::type>::type const_iterator_type;
+
+ // Note that if there are inner rings, and distance is too large,
+ // they might intersect with the outer ring in the output,
+ // while it didn't in the input.
+ simplify_range<ring_type, Strategy, 4>::apply(exterior_ring(poly_in),
+ exterior_ring(poly_out),
+ max_distance, strategy);
+
+ // Note: here a resizeable container is assumed.
+ // Maybe we should make this part of the concept.
+ interior_rings(poly_out).resize(num_interior_rings(poly_in));
+
+ iterator_type it_out = boost::begin(interior_rings(poly_out));
+
+ for (const_iterator_type it_in = boost::begin(interior_rings(poly_in));
+ it_in != boost::end(interior_rings(poly_in));
+ ++it_in, ++it_out)
+ {
+ simplify_range<ring_type, Strategy, 4>::apply(*it_in,
+ *it_out, max_distance, strategy);
+ }
+ }
+};
+
+
+}} // namespace detail::simplify
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, typename Geometry, typename Strategy>
+struct simplify
+{
+};
+
+template <typename Point, typename Strategy>
+struct simplify<point_tag, Point, Strategy>
+{
+ static inline void apply(Point const& point, Point& out,
+ double max_distance, Strategy const& strategy)
+ {
+ copy_coordinates(point, out);
+ }
+};
+
+
+template <typename Linestring, typename Strategy>
+struct simplify<linestring_tag, Linestring, Strategy>
+ : detail::simplify::simplify_range
+ <
+ Linestring,
+ Strategy,
+ 2
+ >
+{};
+
+template <typename Ring, typename Strategy>
+struct simplify<ring_tag, Ring, Strategy>
+ : detail::simplify::simplify_range
+ <
+ Ring,
+ Strategy,
+ 4
+ >
+{};
+
+template <typename Polygon, typename Strategy>
+struct simplify<polygon_tag, Polygon, Strategy>
+ : detail::simplify::simplify_polygon
+ <
+ Polygon,
+ Strategy
+ >
+{};
+
+
+template <typename Tag, typename Geometry, typename Strategy>
+struct simplify_inserter
+{
+};
+
+
+template <typename Linestring, typename Strategy>
+struct simplify_inserter<linestring_tag, Linestring, Strategy>
+ : detail::simplify::simplify_range_inserter
+ <
+ Linestring,
+ Strategy
+ >
+{};
+
+template <typename Ring, typename Strategy>
+struct simplify_inserter<ring_tag, Ring, Strategy>
+ : detail::simplify::simplify_range_inserter
+ <
+ Ring,
+ Strategy
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Simplify a geometry using a specified strategy
+ \ingroup simplify
+ \param geometry input geometry, to be simplified
+ \param out output geometry, simplified version of the input geometry
+ \param max_distance distance (in units of input coordinates) of a vertex
+ to other segments to be removed
+ \param strategy simplify strategy to be used for simplification, might
+ include point-distance strategy
+ */
+template<typename Geometry, typename Strategy>
+inline void simplify(Geometry const& geometry, Geometry& out,
+ double max_distance, Strategy const& strategy)
+{
+ concept::check<Geometry>();
+
+ BOOST_CONCEPT_ASSERT( (ggl::concept::SimplifyStrategy<Strategy>) );
+
+ ggl::clear(out);
+
+ dispatch::simplify
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Strategy
+ >::apply(geometry, out, max_distance, strategy);
+}
+
+
+
+
+/*!
+ \brief Simplify a geometry
+ \ingroup simplify
+ \note This version of simplify simplifies a geometry using the default
+ strategy (Douglas Peucker),
+ \param geometry input geometry, to be simplified
+ \param out output geometry, simplified version of the input geometry
+ \param max_distance distance (in units of input coordinates) of a vertex
+ to other segments to be removed
+ \par Example:
+ The simplify algorithm can be used as following:
+ \dontinclude doxygen_1.cpp
+ \skip example_simplify_linestring1
+ \line {
+ \until }
+ */
+template<typename Geometry>
+inline void simplify(Geometry const& geometry, Geometry& out,
+ double max_distance)
+{
+ concept::check<Geometry>();
+
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename cs_tag<point_type>::type cs_tag;
+ typedef typename strategy_distance_segment
+ <
+ cs_tag,
+ cs_tag,
+ point_type,
+ point_type
+ >::type ds_strategy_type;
+
+ typedef strategy::simplify::douglas_peucker
+ <
+ point_type, ds_strategy_type
+ > strategy_type;
+
+ simplify(geometry, out, max_distance, strategy_type());
+}
+
+
+/*!
+ \brief Simplify a geometry, using an output iterator
+ and a specified strategy
+ \ingroup simplify
+ \param geometry input geometry, to be simplified
+ \param out output iterator, outputs all simplified points
+ \param max_distance distance (in units of input coordinates) of a vertex
+ to other segments to be removed
+ \param strategy simplify strategy to be used for simplification,
+ might include point-distance strategy
+ \par Example:
+ simplify_inserter with strategy is used as following:
+ \dontinclude doxygen_1.cpp
+ \skip example_simplify_linestring2
+ \line {
+ \until }
+ */
+template<typename Geometry, typename OutputIterator, typename Strategy>
+inline void simplify_inserter(Geometry const& geometry, OutputIterator out,
+ double max_distance, Strategy const& strategy)
+{
+ concept::check<const Geometry>();
+ BOOST_CONCEPT_ASSERT( (ggl::concept::SimplifyStrategy<Strategy>) );
+
+ dispatch::simplify_inserter
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Strategy
+ >::apply(geometry, out, max_distance, strategy);
+}
+
+/*!
+ \brief Simplify a geometry, using an output iterator
+ \ingroup simplify
+ \param geometry input geometry, to be simplified
+ \param out output iterator, outputs all simplified points
+ \param max_distance distance (in units of input coordinates) of a vertex
+ to other segments to be removed
+ */
+template<typename Geometry, typename OutputIterator>
+inline void simplify_inserter(Geometry const& geometry, OutputIterator out,
+ double max_distance)
+{
+ typedef typename point_type<Geometry>::type point_type;
+
+ // Concept: output point type = point type of input geometry
+ concept::check<const Geometry>();
+ concept::check<point_type>();
+
+ typedef typename cs_tag<point_type>::type cs_tag;
+ typedef typename strategy_distance_segment
+ <
+ cs_tag,
+ cs_tag,
+ point_type,
+ point_type
+ >::type ds_strategy_type;
+
+ typedef strategy::simplify::douglas_peucker
+ <
+ point_type, ds_strategy_type
+ > strategy_type;
+
+ dispatch::simplify_inserter
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ strategy_type
+ >::apply(geometry, out, max_distance, strategy_type());
+}
+
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_SIMPLIFY_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/transform.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/transform.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,335 @@
+// 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/algorithms/assign.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/concepts/check.hpp>
+
+#include <ggl/strategies/transform.hpp>
+
+
+/*!
+\defgroup transform transform: apply transformations on geometries
+\brief Transforms from one geometry to another geometry, optionally using a strategy
+\details The transform algorithm automatically transforms from one coordinate system to another coordinate system.
+If the coordinate system of both geometries are the same, the geometry is copied. All point(s of the geometry)
+are transformed.
+
+There is a version without a strategy, transforming automatically, and there is a version with a strategy.
+
+This function has a lot of appliances, for example
+- transform from spherical coordinates to cartesian coordinates, and back
+- transform from geographic coordinates to cartesian coordinates (projections) and back
+- transform from degree to radian, and back
+- transform from and to cartesian coordinates (mapping, translations, etc)
+
+The automatic transformations look to the coordinate system family, and dimensions, of the point type and by this
+apply the strategy (internally bounded by traits classes).
+
+\par Examples:
+The example below shows automatic transformations to go from one coordinate system to another one:
+\dontinclude doxygen_2.cpp
+\skip example_for_transform()
+\skipline XYZ
+\until endl;
+
+The next example takes another approach and transforms from Cartesian to Cartesian:
+\skipline XY
+\until endl;
+
+\note Not every possibility is yet worked out, e.g. polar coordinate system is ignored until now
+\note This "transform" is broader then geodetic datum transformations, those are currently not worked out
+
+*/
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace transform {
+
+template <typename Point1, typename Point2, typename Strategy>
+struct transform_point
+{
+ static inline bool apply(Point1 const& p1, Point2& p2,
+ Strategy const& strategy)
+ {
+ return strategy(p1, p2);
+ }
+};
+
+template <typename Box1, typename Box2, typename Strategy>
+struct transform_box
+{
+ static inline bool apply(Box1 const& b1, Box2& b2,
+ Strategy const& strategy)
+ {
+ typedef typename point_type<Box1>::type point_type1;
+ typedef typename point_type<Box2>::type point_type2;
+
+ point_type1 lower_left, upper_right;
+ detail::assign::assign_box_2d_corner<min_corner, min_corner>(
+ b1, lower_left);
+ detail::assign::assign_box_2d_corner<max_corner, max_corner>(
+ b1, upper_right);
+
+ point_type2 p1, p2;
+ if (strategy(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 PointOut,
+ typename OutputIterator,
+ typename Range,
+ typename Strategy
+>
+inline bool transform_range_out(Range const& range,
+ OutputIterator out, Strategy const& strategy)
+{
+ PointOut point_out;
+ for(typename boost::range_const_iterator<Range>::type
+ it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ if (! transform_point
+ <
+ typename point_type<Range>::type,
+ PointOut,
+ Strategy
+ >::apply(*it, point_out, strategy))
+ {
+ return false;
+ }
+ *out = point_out;
+ ++out;
+ }
+ return true;
+}
+
+template <typename Polygon1, typename Polygon2, typename Strategy>
+struct transform_polygon
+{
+ static inline bool apply(const Polygon1& poly1, Polygon2& poly2,
+ Strategy const& strategy)
+ {
+ typedef typename interior_type<Polygon1>::type interior1_type;
+ typedef typename interior_type<Polygon2>::type interior2_type;
+ typedef typename ring_type<Polygon1>::type ring1_type;
+ typedef typename ring_type<Polygon2>::type ring2_type;
+ typedef typename point_type<Polygon2>::type point2_type;
+
+ 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(num_interior_rings(poly1));
+
+ typedef typename boost::range_const_iterator
+ <
+ interior1_type
+ >::type iterator1_type;
+ typedef typename boost::range_iterator
+ <
+ interior2_type
+ >::type iterator2_type;
+
+ iterator1_type it1 = boost::begin(interior_rings(poly1));
+ iterator2_type it2 = boost::begin(interior_rings(poly2));
+ for ( ; it1 != boost::end(interior_rings(poly1));
+ ++it1, ++it2)
+ {
+ if (!transform_range_out<point2_type>(*it1,
+ std::back_inserter(*it2), strategy))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+};
+
+
+template <typename Point1, typename Point2>
+struct select_strategy
+{
+ typedef typename strategy_transform
+ <
+ typename cs_tag<Point1>::type,
+ typename cs_tag<Point2>::type,
+ typename coordinate_system<Point1>::type,
+ typename coordinate_system<Point2>::type,
+ dimension<Point1>::type::value,
+ dimension<Point2>::type::value,
+ typename point_type<Point1>::type,
+ typename point_type<Point2>::type
+ >::type type;
+};
+
+template <typename Range1, typename Range2, typename Strategy>
+struct transform_range
+{
+ static inline bool apply(Range1 const& range1,
+ Range2& range2, Strategy const& strategy)
+ {
+ typedef typename point_type<Range2>::type point_type;
+
+ 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 Geometry1, typename Geometry2,
+ typename Strategy
+>
+struct transform {};
+
+template <typename Point1, typename Point2, typename Strategy>
+struct transform<point_tag, point_tag, Point1, Point2, Strategy>
+ : detail::transform::transform_point<Point1, Point2, Strategy>
+{
+};
+
+
+template <typename Linestring1, typename Linestring2, typename Strategy>
+struct transform
+ <
+ linestring_tag, linestring_tag,
+ Linestring1, Linestring2, Strategy
+ >
+ : detail::transform::transform_range<Linestring1, Linestring2, Strategy>
+{
+};
+
+template <typename Range1, typename Range2, typename Strategy>
+struct transform<ring_tag, ring_tag, Range1, Range2, Strategy>
+ : detail::transform::transform_range<Range1, Range2, Strategy>
+{
+};
+
+template <typename Polygon1, typename Polygon2, typename Strategy>
+struct transform<polygon_tag, polygon_tag, Polygon1, Polygon2, Strategy>
+ : detail::transform::transform_polygon<Polygon1, Polygon2, Strategy>
+{
+};
+
+template <typename Box1, typename Box2, typename Strategy>
+struct transform<box_tag, box_tag, Box1, Box2, Strategy>
+ : detail::transform::transform_box<Box1, Box2, Strategy>
+{
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Transforms from one geometry to another geometry using a strategy
+ \ingroup transform
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \tparam Strategy strategy
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \param strategy the strategy to be used for transformation
+ */
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2,
+ Strategy const& strategy)
+{
+ concept::check<const Geometry1>();
+ concept::check<Geometry2>();
+
+ typedef dispatch::transform
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ Geometry1,
+ Geometry2,
+ Strategy
+ > transform_type;
+
+ return transform_type::apply(geometry1, geometry2, strategy);
+}
+
+/*!
+ \brief Transforms from one geometry to another geometry using a strategy
+ \ingroup transform
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \return true if the transformation could be done
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2)
+{
+ concept::check<const Geometry1>();
+ concept::check<Geometry2>();
+
+ typename detail::transform::select_strategy<Geometry1, Geometry2>::type strategy;
+ return transform(geometry1, geometry2, strategy);
+}
+
+} // namespace ggl
+
+#endif // GGL_ALGORITHMS_TRANSFORM_HPP

Added: sandbox/ggl/formal_review/boost/ggl/algorithms/union.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/algorithms/union.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,263 @@
+// 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_UNION_HPP
+#define GGL_ALGORITHMS_UNION_HPP
+
+
+#include <boost/mpl/if.hpp>
+
+#include <ggl/core/interior_rings.hpp>
+#include <ggl/core/reverse_dispatch.hpp>
+#include <ggl/geometries/concepts/check.hpp>
+#include <ggl/algorithms/overlay/assemble.hpp>
+#include <ggl/algorithms/overlay/sort_interior_rings.hpp>
+#include <ggl/algorithms/within.hpp>
+
+
+
+/*!
+\defgroup union union: calculate new geometry containing geometries A or B
+\details The union of two geometries A and B is the geometry containing
+ all points belong to either of A or B, but no other elements.
+\par Source description:
+- OGC: Returns a geometric object that represents the Point set union of
+ this geometric object with another Geometry.
+\see http://en.wikipedia.org/wiki/Union_(set_theory)
+\note A union of two rings can result in a polygon having a hole
+
+\par Geometries:
+- \b polygon + \b box -> \b polygon(s)
+\image html svg_union_polygon_box.png
+- \b ring + \b box -> \b polygon(s)
+\image html svg_union_ring_box.png
+- \b ring + \b ring -> \b polygon(s)
+\image html svg_union_ring_ring.png
+- \b polygon + \b ring -> \b polygon(s)
+\image html svg_union_polygon_ring.png
+- combinations above -> \b ring(s).
+ <i>If the output is an ouput iterator of rings, holes are omitted</i>
+
+*/
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay {
+
+
+// Specializations for "take_one" for union
+// "one" should be the outer one, containing the inner one
+
+// for ring and box
+template
+<
+ typename Tag1, typename Geometry1,
+ typename Tag2, typename Geometry2,
+ typename GeometryOut
+>
+struct take_if_1_is_in_2<Tag1, Geometry1, Tag2, Geometry2, GeometryOut, 1>
+{
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& out
+ )
+ {
+ ggl::convert(geometry2, out);
+ }
+};
+
+
+// spcialize more for polygons
+template
+<
+ typename Tag1, typename Geometry1,
+ typename Geometry2,
+ typename GeometryOut
+>
+struct take_if_1_is_in_2<Tag1, Geometry1, polygon_tag, Geometry2, GeometryOut, 1>
+{
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& out
+ )
+ {
+ ggl::convert(exterior_ring(geometry2), out);
+ }
+};
+
+
+template
+<
+ typename Geometry, typename GeometryOut, typename Container
+>
+struct add_holes<polygon_tag, Geometry, GeometryOut, Container, 1>
+{
+ static inline void apply(Geometry const& geometry,
+ GeometryOut& out,
+ Container const& holes
+ )
+ {
+ std::vector<sortable> v;
+ sort_interior_rings(holes, v, -1);
+
+ // For a union, if a ring is containing an inner ring, don't take the outer
+ // but leave to the inners.
+ // If the inner is lying in geometry2, don't add it
+
+ std::size_t const n = boost::size(v);
+
+ for (std::size_t i = 0; i < n; i++)
+ {
+ // So, only if no inners:
+ if (boost::size(v[i].index_of_holes) == 0)
+ {
+ bool add = v[i].index_of_parent >= 0;
+ if (! add)
+ {
+ typename ggl::point_type<GeometryOut>::type point;
+ ggl::point_on_border(holes[v[i].index], point);
+ add = ! ggl::within(point, geometry);
+ }
+ if (add)
+ {
+ typename ring_type<GeometryOut>::type hole;
+ ggl::convert(holes[v[i].index], hole);
+ ggl::interior_rings(out).push_back(hole);
+ }
+ }
+ }
+ }
+};
+
+
+
+// "none or both" should be both
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename OutputIterator, typename GeometryOut
+>
+struct take_none_or_both<Geometry1, Geometry2, OutputIterator, GeometryOut, 1>
+{
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ OutputIterator out
+ )
+ {
+ convert_and_output<GeometryOut>(geometry1, out);
+ convert_and_output<GeometryOut>(geometry2, out);
+ }
+};
+
+
+}} // namespace detail::overlay
+#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 union_inserter
+ : detail::overlay::overlay_and_assemble
+ <G1, G2, OutputIterator, GeometryOut, 1>
+{
+};
+
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2, typename GeometryTag3,
+ typename Geometry1, typename Geometry2,
+ typename OutputIterator, typename GeometryOut
+>
+struct union_inserter_reversed
+{
+ static inline OutputIterator apply(Geometry1 const& g1,
+ Geometry2 const& g2, OutputIterator out)
+ {
+ return union_inserter
+ <
+ GeometryTag2, GeometryTag1, GeometryTag3,
+ Geometry2, Geometry1,
+ OutputIterator, GeometryOut
+ >::apply(g2, g1, out);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Combines two geometries which each other
+ \ingroup union
+ \tparam GeometryOut output geometry type, must be specified
+ \tparam Geometry1 first geometry type
+ \tparam Geometry2 second geometry type
+ \tparam OutputIterator output iterator
+ \param geometry1 first geometry
+ \param geometry2 second geometry
+ \param out the output iterator, outputting polygons
+ \return the output iterator
+*/
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename OutputIterator
+>
+inline OutputIterator union_inserter(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ OutputIterator out)
+{
+ concept::check<const Geometry1>();
+ concept::check<const Geometry2>();
+
+ return boost::mpl::if_c
+ <
+ reverse_dispatch<Geometry1, Geometry2>::type::value,
+ dispatch::union_inserter_reversed
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ typename tag<GeometryOut>::type,
+ Geometry1,
+ Geometry2,
+ OutputIterator, GeometryOut
+ >,
+ dispatch::union_inserter
+ <
+ 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_UNION_HPP

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

Added: sandbox/ggl/formal_review/boost/ggl/arithmetic/arithmetic.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/arithmetic/arithmetic.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/geometries/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(C const &value)
+ : m_value(value)
+ {}
+
+ template <typename P, int I>
+ inline void apply(P& point) const
+ {
+ set<I>(point, Function<C>()(get<I>(point), m_value));
+ }
+};
+
+template <typename PointSrc, template <typename> class Function>
+struct point_operation
+{
+ typedef typename coordinate_type<PointSrc>::type coordinate_type;
+ PointSrc const& m_source_point;
+
+ inline point_operation(PointSrc const& point)
+ : m_source_point(point)
+ {}
+
+ template <typename PointDst, int I>
+ inline void apply(PointDst& dest_point) const
+ {
+ set<I>(dest_point,
+ Function<coordinate_type>()(get<I>(dest_point), get<I>(m_source_point)));
+ }
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+/*!
+ \brief Adds a value to each coordinate of a point
+ \ingroup arithmetic
+ \details
+ \param p point
+ \param value value to add
+ */
+template <typename Point>
+inline void add_value(Point& p, typename detail::param<Point>::type value)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+ for_each_coordinate(p, detail::value_operation<typename coordinate_type<Point>::type, std::plus>(value));
+}
+
+/*!
+ \brief Adds a point to another
+ \ingroup arithmetic
+ \details The coordinates of the second point will be added to those of the first point.
+ The second point is not modified.
+ \param p1 first point
+ \param p2 second point
+ */
+template <typename Point1, typename Point2>
+inline void add_point(Point1& p1, Point2 const& p2)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point2>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
+
+ for_each_coordinate(p1, detail::point_operation<Point2, std::plus>(p2));
+}
+
+/*!
+ \brief Subtracts a value to each coordinate of a point
+ \ingroup arithmetic
+ \details
+ \param p point
+ \param value value to subtract
+ */
+template <typename Point>
+inline void subtract_value(Point& p, typename detail::param<Point>::type value)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+ for_each_coordinate(p, detail::value_operation<typename coordinate_type<Point>::type, std::minus>(value));
+}
+
+/*!
+ \brief Subtracts a point to another
+ \ingroup arithmetic
+ \details The coordinates of the second point will be subtracted to those of the first point.
+ The second point is not modified.
+ \param p1 first point
+ \param p2 second point
+ */
+template <typename Point1, typename Point2>
+inline void subtract_point(Point1& p1, Point2 const& p2)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point2>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
+
+ for_each_coordinate(p1, detail::point_operation<Point2, std::minus>(p2));
+}
+
+/*!
+ \brief Multiplies each coordinate of a point by a value
+ \ingroup arithmetic
+ \details
+ \param p point
+ \param value value to multiply by
+ */
+template <typename Point>
+inline void multiply_value(Point& p, typename detail::param<Point>::type value)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+ for_each_coordinate(p, detail::value_operation<typename coordinate_type<Point>::type, std::multiplies>(value));
+}
+
+/*!
+ \brief Multiplies a point by another
+ \ingroup arithmetic
+ \details The coordinates of the second point will be multiplied by those of the first point.
+ The second point is not modified.
+ \param p1 first point
+ \param p2 second point
+ \note This is *not* a dot, cross or wedge product. It is a mere field-by-field multiplication.
+ */
+template <typename Point1, typename Point2>
+inline void multiply_point(Point1& p1, Point2 const& p2)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point2>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
+
+ for_each_coordinate(p1, detail::point_operation<Point2, std::multiplies>(p2));
+}
+
+/*!
+ \brief Divides each coordinate of a point by a value
+ \ingroup arithmetic
+ \details
+ \param p point
+ \param value value to divide by
+ */
+template <typename Point>
+inline void divide_value(Point& p, typename detail::param<Point>::type value)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+ for_each_coordinate(p, detail::value_operation<typename coordinate_type<Point>::type, std::divides>(value));
+}
+
+/*!
+ \brief Divides a point by another
+ \ingroup arithmetic
+ \details The coordinates of the second point will be divided by those of the first point.
+ The second point is not modified.
+ \param p1 first point
+ \param p2 second point
+ */
+template <typename Point1, typename Point2>
+inline void divide_point(Point1& p1, Point2 const& p2)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point2>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
+
+ for_each_coordinate(p1, detail::point_operation<Point2, std::divides>(p2));
+}
+
+} // namespace ggl
+
+#endif // GGL_ARITHMETIC_ARITHMETIC_HPP

Added: sandbox/ggl/formal_review/boost/ggl/arithmetic/dot_product.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/arithmetic/dot_product.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,74 @@
+// 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/geometries/concepts/point_concept.hpp>
+#include <ggl/util/select_coordinate_type.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
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+
+ static inline coordinate_type apply(P1 const& p1, P2 const& p2)
+ {
+ return get<Dimension>(p1) * get<Dimension>(p2)
+ + dot_product_maker<P1, P2, Dimension+1, DimensionCount>::apply(p1, p2);
+ }
+};
+
+template <typename P1, typename P2, std::size_t DimensionCount>
+struct dot_product_maker<P1, P2, DimensionCount, DimensionCount>
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+
+ static inline coordinate_type apply(P1 const& p1, P2 const& p2)
+ {
+ return get<DimensionCount>(p1) * get<DimensionCount>(p2);
+ }
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief Computes the dot product of 2 points
+ \ingroup arithmetic
+ \param p1 first point
+ \param p2 second point
+ \return the dot product
+ */
+template <typename P1, typename P2>
+inline typename select_coordinate_type<P1, P2>::type dot_product(
+ P1 const& p1, P2 const& p2)
+{
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<P1>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<P2>) );
+
+ return detail::dot_product_maker
+ <
+ P1, P2,
+ 0, dimension<P1>::type::value - 1
+ >::apply(p1, p2);
+}
+
+} // namespace ggl
+
+#endif // GGL_ARITHMETIC_DOT_PRODUCT_HPP

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

Added: sandbox/ggl/formal_review/boost/ggl/core/coordinate_dimension.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/coordinate_dimension.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/core/coordinate_system.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/coordinate_system.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/core/coordinate_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/coordinate_type.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/core/cs.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/cs.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,186 @@
+// 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 plane angle: Degrees
+ \ingroup cs
+*/
+class degree {};
+
+
+/*!
+ \brief Unit of plane angle: Radians
+ \ingroup cs
+*/
+class radian {};
+
+
+namespace cs
+{
+
+/*!
+ \brief Cartesian coordinate system
+ \details Defines the Cartesian or rectangular coordinate system
+ where points are defined in 2 or 3 (or more)
+ dimensions and usually (but not always) known as x,y,z
+ \see http://en.wikipedia.org/wiki/Cartesian_coordinate_system
+ \ingroup cs
+*/
+struct cartesian {};
+
+
+
+
+/*!
+ \brief Geographic coordinate system, in degree or in radian
+ \details Defines the geographic coordinate system where points
+ are defined in two angles and usually
+ known as lat,long or lo,la or phi,lambda
+ \see http://en.wikipedia.org/wiki/Geographic_coordinate_system
+ \ingroup cs
+ \note might be moved to extensions/gis/geographic
+*/
+template<typename DegreeOrRadian>
+struct geographic
+{
+ typedef DegreeOrRadian units;
+};
+
+
+
+/*!
+ \brief Spherical coordinate system, in degree or in radian
+ \details Defines the spherical coordinate system where points are
+ defined in two angles
+ and an optional radius usually known as r, theta, phi
+ \par Coordinates:
+ - coordinate 0:
+ 0 <= phi < 2pi is the angle between the positive x-axis and the
+ line from the origin to the P projected onto the xy-plane.
+ - coordinate 1:
+ 0 <= theta <= pi is the angle between the positive z-axis and the
+ line formed between the origin and P.
+ - coordinate 2 (if specified):
+ r >= 0 is the distance from the origin to a given point P.
+
+ \see http://en.wikipedia.org/wiki/Spherical_coordinates
+ \ingroup cs
+*/
+template<typename DegreeOrRadian>
+struct spherical
+{
+ typedef DegreeOrRadian units;
+};
+
+/*!
+ \brief Polar coordinate system
+ \details Defines the polar coordinate system "in which each point
+ on a plane is determined by an angle and a distance"
+ \see http://en.wikipedia.org/wiki/Polar_coordinates
+ \ingroup cs
+*/
+template<typename DegreeOrRadian>
+struct polar
+{
+ typedef DegreeOrRadian units;
+};
+
+
+} // namespace cs
+
+namespace traits
+{
+/*!
+ \brief Traits class defining coordinate system tag, bound to coordinate system
+ \ingroup traits
+ \tparam CoordinateSystem coordinate system
+*/
+template <typename CoordinateSystem>
+struct cs_tag
+{
+};
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+template<typename DegreeOrRadian>
+struct cs_tag<cs::geographic<DegreeOrRadian> >
+{
+ typedef geographic_tag type;
+};
+
+template<typename DegreeOrRadian>
+struct cs_tag<cs::spherical<DegreeOrRadian> >
+{
+ typedef spherical_tag type;
+};
+
+template<>
+struct cs_tag<cs::cartesian>
+{
+ typedef cartesian_tag type;
+};
+
+
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+} // namespace traits
+
+/*!
+ \brief Meta-function returning coordinate system tag (cs family) of any geometry
+ \ingroup core
+*/
+template <typename G>
+struct cs_tag
+{
+ typedef typename traits::cs_tag
+ <
+ typename 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/boost/ggl/core/exception.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/exception.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/core/exterior_ring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/exterior_ring.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,128 @@
+// 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>
+#include <ggl/util/add_const_if_c.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 Polygon the polygon type
+ \par Geometries:
+ - polygon
+ \par Specializations should provide:
+ - static inline RING& get(POLY& )
+ - static inline const RING& get(const POLY& )
+*/
+template <typename Polygon>
+struct exterior_ring
+{};
+
+
+} // namespace traits
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+
+template <typename Tag, typename Geometry, bool IsConst>
+struct exterior_ring {};
+
+
+template <typename Polygon, bool IsConst>
+struct exterior_ring<polygon_tag, Polygon, IsConst>
+{
+ static inline typename add_const_if_c
+ <
+ IsConst,
+ typename ggl::ring_type
+ <
+ Polygon
+ >::type
+ >::type& apply(typename add_const_if_c
+ <
+ IsConst,
+ Polygon
+ >::type& polygon)
+ {
+ return traits::exterior_ring
+ <
+ typename boost::remove_const<Polygon>::type
+ >::get(polygon);
+ }
+};
+
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Function to get the exterior_ring ring of a polygon
+ \ingroup access
+ \note OGC compliance: instead of ExteriorRing
+ \tparam P polygon type
+ \param polygon the polygon to get the exterior ring from
+ \return a reference to the exterior ring
+*/
+template <typename Polygon>
+inline typename ring_type<Polygon>::type& exterior_ring(Polygon& polygon)
+{
+ return core_dispatch::exterior_ring
+ <
+ typename tag<Polygon>::type,
+ Polygon,
+ false
+ >::apply(polygon);
+}
+
+
+/*!
+ \brief Function to get the exterior ring of a polygon (const version)
+ \ingroup access
+ \note OGC compliance: instead of ExteriorRing
+ \tparam Polygon polygon type
+ \param polygon the polygon to get the exterior ring from
+ \return a const reference to the exterior ring
+*/
+template <typename Polygon>
+inline const typename ring_type<Polygon>::type& exterior_ring(
+ Polygon const& polygon)
+{
+ return core_dispatch::exterior_ring
+ <
+ typename tag<Polygon>::type,
+ Polygon,
+ true
+ >::apply(polygon);
+}
+
+
+} // namespace ggl
+
+
+#endif // GGL_CORE_EXTERIOR_RING_HPP

Added: sandbox/ggl/formal_review/boost/ggl/core/geometry_id.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/geometry_id.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_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<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/boost/ggl/core/interior_rings.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/interior_rings.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,235 @@
+// 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 <cstddef>
+
+#include <boost/range/functions.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+#include <ggl/util/add_const_if_c.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 X type ( e.g. std::vector&lt;myring&lt;P&gt;&gt; )
+ \tparam Geometry geometry
+*/
+template <typename Geometry>
+struct interior_type
+{};
+
+
+/*!
+ \brief Traits class defining access to interior_rings of a polygon
+ \details defines access (const and non const) to interior ring
+ \ingroup traits
+ \par Geometries:
+ - polygon
+ \par Specializations should provide:
+ - static inline INTERIOR& get(POLY&)
+ - static inline const INTERIOR& get(const POLY&)
+ \tparam Geometry geometry
+*/
+template <typename Geometry>
+struct interior_rings
+{};
+
+
+} // namespace traits
+
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+
+template <typename GeometryTag, typename Geometry>
+struct interior_type
+{};
+
+
+template <typename Polygon>
+struct interior_type<polygon_tag, Polygon>
+{
+ typedef typename traits::interior_type
+ <
+ typename boost::remove_const<Polygon>::type
+ >::type type;
+};
+
+
+template
+<
+ typename GeometryTag,
+ typename Geometry,
+ bool IsConst
+>
+struct interior_rings {};
+
+
+template <typename Polygon, bool IsConst>
+struct interior_rings<polygon_tag, Polygon, IsConst>
+{
+ static inline typename add_const_if_c
+ <
+ IsConst,
+ typename interior_type
+ <
+ polygon_tag,
+ Polygon
+ >::type
+ >::type& apply(typename add_const_if_c
+ <
+ IsConst,
+ Polygon
+ >::type& polygon)
+ {
+ return traits::interior_rings
+ <
+ typename boost::remove_const<Polygon>::type
+ >::get(polygon);
+ }
+};
+
+
+template <typename Tag, typename Geometry>
+struct num_interior_rings
+{
+ static inline std::size_t apply(Geometry const&)
+ {
+ return 0;
+ }
+
+};
+
+
+template <typename Polygon>
+struct num_interior_rings<polygon_tag, Polygon>
+{
+ static inline std::size_t apply(Polygon const& polygon)
+ {
+ return boost::size(interior_rings
+ <
+ polygon_tag, Polygon, true
+ >::apply(polygon));
+ }
+
+};
+
+
+} // namespace core_dispatch
+#endif
+
+
+/*!
+ \brief Meta-function defining container type
+ of inner rings of (multi)polygon geometriy
+ \details the interior rings should be organized as a container
+ (std::vector, std::deque, boost::array) with
+ boost range support. This meta function defines the type
+ of that container.
+ \ingroup core
+*/
+template <typename Geometry>
+struct interior_type
+{
+ typedef typename core_dispatch::interior_type
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::type type;
+};
+
+
+/*!
+ \brief Function to get the interior rings of a polygon (non const version)
+ \ingroup access
+ \note OGC compliance: instead of InteriorRingN
+ \tparam P polygon type
+ \param polygon the polygon to get the interior rings from
+ \return a reference to the interior rings
+*/
+template <typename Polygon>
+inline typename interior_type<Polygon>::type& interior_rings(Polygon& polygon)
+{
+ return core_dispatch::interior_rings
+ <
+ typename tag<Polygon>::type,
+ Polygon,
+ false
+ >::apply(polygon);
+}
+
+
+/*!
+ \brief Function to get the interior rings of a polygon (const version)
+ \ingroup access
+ \note OGC compliance: instead of InteriorRingN
+ \tparam P polygon type
+ \param polygon the polygon to get the interior rings from
+ \return a const reference to the interior rings
+*/
+template <typename Polygon>
+inline const typename interior_type<Polygon>::type& interior_rings(
+ Polygon const& polygon)
+{
+ return core_dispatch::interior_rings
+ <
+ typename tag<Polygon>::type,
+ Polygon,
+ true
+ >::apply(polygon);
+}
+
+
+
+/*!
+ \brief Function to get the number of interior rings of a polygon
+ \ingroup access
+ \note Defined by OGC as "numInteriorRing". To be consistent with "numPoints"
+ letter "s" is appended
+ \note Can be used for any geometry, returning 0 for geometries not having
+ interior rings
+ \tparam Geometry geometry type
+ \param geometry the polygon or other geometry
+ \return the number of interior rings of the geometry
+*/
+template <typename Geometry>
+inline std::size_t num_interior_rings(Geometry const& geometry)
+{
+ return core_dispatch::num_interior_rings
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::apply(geometry);
+}
+
+
+}
+
+
+#endif // GGL_CORE_INTERIOR_RINGS_HPP

Added: sandbox/ggl/formal_review/boost/ggl/core/is_linear.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/is_linear.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/core/is_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/is_multi.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/core/point_order.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/point_order.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,98 @@
+// Generic Geometry Library
+//
+// 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_ORDER_HPP
+#define GGL_CORE_POINT_ORDER_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 {
+
+
+enum order_selector { clockwise = 1, counterclockwise = 2, order_undetermined = 0 };
+
+namespace traits {
+
+/*!
+ \brief Traits class indicating the order of contained points within a
+ ring or (multi)polygon, clockwise, counter clockwise or not known.
+ \ingroup traits
+ \par Geometries:
+ - ring
+ - polygon
+ - multi polygon
+ \par Specializations should provide:
+ - typedef P type (where P should fulfil the Point concept)
+ \tparam G geometry
+*/
+template <typename G>
+struct point_order
+{
+ static const order_selector value = clockwise;
+};
+
+
+} // namespace traits
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename Tag, typename Geometry>
+struct point_order
+{
+ static const order_selector value = clockwise;
+};
+
+
+
+template <typename Ring>
+struct point_order<ring_tag, Ring>
+{
+ static const order_selector value = ggl::traits::point_order<Ring>::value;
+};
+
+// Specialization for polygon: the order is the order of its rings
+template <typename Polygon>
+struct point_order<polygon_tag, Polygon>
+{
+ static const order_selector value = core_dispatch::point_order
+ <
+ ring_tag,
+ typename ring_type<polygon_tag, Polygon>::type
+ >::value ;
+};
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Meta-function which defines point type of any geometry
+ \ingroup core
+*/
+template <typename Geometry>
+struct point_order
+{
+ typedef typename boost::remove_const<Geometry>::type ncg;
+ static const order_selector value = core_dispatch::point_order
+ <
+ typename tag<Geometry>::type,
+ ncg
+ >::value;
+};
+
+} // namespace ggl
+
+#endif // GGL_CORE_POINT_ORDER_HPP

Added: sandbox/ggl/formal_review/boost/ggl/core/point_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/point_type.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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 rings
+template <typename Polygon>
+struct point_type<polygon_tag, Polygon>
+{
+ typedef typename point_type
+ <
+ ring_tag,
+ typename ring_type<polygon_tag, Polygon>::type
+ >::type type;
+};
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Meta-function which defines point type of any geometry
+ \ingroup core
+*/
+template <typename Geometry>
+struct point_type
+{
+ typedef typename boost::remove_const<Geometry>::type ncg;
+ typedef typename core_dispatch::point_type<
+ typename tag<Geometry>::type, ncg>::type type;
+
+
+
+
+};
+
+} // namespace ggl
+
+#endif // GGL_CORE_POINT_TYPE_HPP

Added: sandbox/ggl/formal_review/boost/ggl/core/radian_access.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/radian_access.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,133 @@
+// 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 Dimension, typename Geometry, typename DegreeOrRadian>
+struct radian_access
+{
+};
+
+template
+<
+ std::size_t Dimension,
+ typename Geometry,
+ template<typename> class CoordinateSystem
+>
+struct radian_access<Dimension, Geometry, CoordinateSystem<radian> >
+{
+ typedef typename coordinate_type<Geometry>::type coordinate_type;
+
+ static inline coordinate_type get(Geometry const& geometry)
+ {
+ return ggl::get<Dimension>(geometry);
+ }
+
+ static inline void set(Geometry& geometry, coordinate_type const& radians)
+ {
+ ggl::set<Dimension>(geometry, radians);
+ }
+};
+
+template
+<
+ std::size_t Dimension,
+ typename Geometry,
+ template<typename> class CoordinateSystem
+>
+struct radian_access<Dimension, Geometry, CoordinateSystem<degree> >
+{
+ typedef typename coordinate_type<Geometry>::type coordinate_type;
+
+ static inline coordinate_type get(Geometry const& geometry)
+ {
+ return boost::numeric_cast
+ <
+ coordinate_type
+ >(ggl::get<Dimension>(geometry) * ggl::math::d2r);
+ }
+
+ static inline void set(Geometry& geometry, coordinate_type const& radians)
+ {
+ ggl::set<Dimension>(geometry, boost::numeric_cast
+ <
+ coordinate_type
+ >(radians * ggl::math::r2d));
+ }
+
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief get coordinate value of a point, result is in Radian
+ \details Result is in Radian, even if source coordinate system
+ is in Degrees
+ \return coordinate value
+ \ingroup access
+ \tparam Dimension dimension
+ \tparam Geometry geometry
+ \param geometry geometry to get coordinate value from
+ \note Only applicable to coordinate systems templatized by units,
+ e.g. spherical or geographic coordinate systems
+*/
+template <std::size_t Dimension, typename Geometry>
+inline typename coordinate_type<Geometry>::type get_as_radian(const Geometry& geometry)
+{
+ return detail::radian_access<Dimension, Geometry,
+ typename coordinate_system<Geometry>::type>::get(geometry);
+}
+
+
+/*!
+ \brief set coordinate value (in radian) to a point
+ \details Coordinate value will be set correctly, if coordinate system of
+ point is in Degree, Radian value will be converted to Degree
+ \ingroup access
+ \tparam Dimension dimension
+ \tparam Geometry geometry
+ \param geometry geometry to assign coordinate to
+ \param radians coordinate value to assign
+ \note Only applicable to coordinate systems templatized by units,
+ e.g. spherical or geographic coordinate systems
+*/
+template <std::size_t Dimension, typename Geometry>
+inline void set_from_radian(Geometry& geometry,
+ const typename coordinate_type<Geometry>::type& radians)
+{
+ detail::radian_access<Dimension, Geometry,
+ typename coordinate_system<Geometry>::type>::set(geometry, radians);
+}
+
+
+} // namespace ggl
+
+
+#endif // GGL_CORE_RADIAN_ACCESS_HPP

Added: sandbox/ggl/formal_review/boost/ggl/core/replace_point_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/replace_point_type.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,92 @@
+// 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>
+
+
+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;
+};
+
+
+} // 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/boost/ggl/core/reverse_dispatch.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/reverse_dispatch.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_REVERSE_DISPATCH_HPP
+#define GGL_CORE_REVERSE_DISPATCH_HPP
+
+
+#include <boost/type_traits.hpp>
+#include <boost/mpl/if.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
+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/boost/ggl/core/ring_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/ring_type.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_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 Geometry geometry
+*/
+template <typename Geometry>
+struct ring_type
+{
+ // should define type
+};
+
+
+} // namespace traits
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+
+template <typename GeometryTag, typename Geometry>
+struct ring_type
+{};
+
+
+template <typename Polygon>
+struct ring_type<polygon_tag, Polygon>
+{
+ typedef typename traits::ring_type
+ <
+ typename boost::remove_const<Polygon>::type
+ >::type type;
+
+};
+
+
+} // namespace core_dispatch
+#endif
+
+
+/*!
+ \brief Meta-function which defines ring type of (multi)polygon geometry
+ \details a polygon contains one exterior ring
+ and zero or more interior rings (holes).
+ This meta function retrieves the type of the rings
+ \note Exterior ring and interior rings must have the same ring-type.
+ \ingroup core
+*/
+template <typename Geometry>
+struct ring_type
+{
+ typedef typename core_dispatch::ring_type
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::type type;
+};
+
+
+}
+
+
+#endif // GGL_CORE_RING_TYPE_HPP

Added: sandbox/ggl/formal_review/boost/ggl/core/tag.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/tag.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/core/tags.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/tags.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_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 segment (2-points) identifying tag
+struct segment_tag {};
+
+} // namespace ggl
+
+#endif // GGL_CORE_TAGS_HPP

Added: sandbox/ggl/formal_review/boost/ggl/core/topological_dimension.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/core/topological_dimension.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,82 @@
+// 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> {};
+
+
+
+} // 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/boost/ggl/extensions/gis/geographic/detail/ellipsoid.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/extensions/gis/geographic/detail/ellipsoid.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,58 @@
+// 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_EXTENSIONS_GIS_GEOGRAPHIC_DETAIL_ELLIPSOID_HPP
+#define GGL_EXTENSIONS_GIS_GEOGRAPHIC_DETAIL_ELLIPSOID_HPP
+
+
+namespace ggl { namespace detail {
+
+
+/*!
+ \brief Defines ellipsoid values for use in distance calculations
+ \details They have a constructor with the earth radius
+ \note Will be moved / merged with projections
+ \todo Optionally specify earth model, defaulting to WGS84
+ - See http://en.wikipedia.org/wiki/Figure_of_the_Earth
+ - and http://en.wikipedia.org/wiki/World_Geodetic_System#A_new_World_Geodetic_System:_WGS84
+ \note
+*/
+class ellipsoid
+{
+ public :
+ ellipsoid(double a, double b)
+ : m_a(a)
+ , m_b(b)
+ , m_f((a - b) / a)
+ {}
+ ellipsoid()
+ : m_a(6378137.0)
+ , m_b(6356752.314245)
+ , m_f((m_a - m_b) / m_a)
+ {}
+ // Unit sphere
+ ellipsoid(double f)
+ : m_a(1.0)
+ , m_f(f)
+ {}
+
+ double a() const { return m_a; }
+ double b() const { return m_b; }
+ double f() const { return m_f; }
+
+ private :
+ double m_a, m_b, m_f; // equatorial radius, polar radius, flattening
+};
+
+
+
+
+}} // namespace ggl::detail
+
+
+#endif // GGL_EXTENSIONS_GIS_GEOGRAPHIC_DETAIL_ELLIPSOID_HPP

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

Added: sandbox/ggl/formal_review/boost/ggl/extensions/gis/geographic/strategies/area_huiller_earth.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/extensions/gis/geographic/strategies/area_huiller_earth.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,60 @@
+// 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_EXTENSIONS_GIS_GEOGRAPHIC_STRATEGIES_AREA_HUILLER_EARTH_HPP
+#define GGL_EXTENSIONS_GIS_GEOGRAPHIC_STRATEGIES_AREA_HUILLER_EARTH_HPP
+
+
+
+#include <ggl/strategies/spherical/area_huiller.hpp>
+
+
+namespace ggl
+{
+
+namespace strategy { namespace area {
+
+
+
+template
+<
+ typename PointOfSegment,
+ typename CalculationType = void
+>
+class huiller_earth
+ : public huiller<PointOfSegment, CalculationType>
+{
+public :
+ // By default the average earth radius.
+ // Uses can specify another radius.
+ // Note that the earth is still spherical
+ inline huiller_earth(double radius = 6372795.0)
+ : huiller<PointOfSegment, CalculationType>(radius)
+ {}
+};
+
+
+
+}} // namespace strategy::area
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+template <typename Point>
+struct strategy_area<geographic_tag, Point>
+{
+ typedef strategy::area::huiller_earth<Point> type;
+};
+
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_EXTENSIONS_GIS_GEOGRAPHIC_STRATEGIES_AREA_HUILLER_EARTH_HPP

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

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

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

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

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

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

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

Added: sandbox/ggl/formal_review/boost/ggl/extensions/gis/io/wkt/detail/wkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/extensions/gis/io/wkt/detail/wkt.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/extensions/gis/io/wkt/detail/wkt_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/extensions/gis/io/wkt/detail/wkt_multi.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/extensions/gis/io/wkt/read_wkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/extensions/gis/io/wkt/read_wkt.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,681 @@
+// 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/mpl/if.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/type_traits.hpp>
+
+
+#include <ggl/algorithms/assign.hpp>
+#include <ggl/algorithms/clear.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/coordinate_dimension.hpp>
+#include <ggl/core/exception.hpp>
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+
+#include <ggl/geometries/concepts/check.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);
+ }
+
+ assign_point_to_index<min_corner>(points.front(), box);
+ assign_point_to_index<max_corner>(points[index], box);
+ }
+};
+
+
+/*!
+\brief Supports segment parsing
+\note OGC does not define the segment, and WKT does not support segmentes.
+ However, it is useful to implement it, also for testing purposes
+\tparam Segment the segment
+*/
+template <typename Segment>
+struct segment_parser
+{
+ static inline void apply(std::string const& wkt, Segment& segment)
+ {
+ tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
+ tokenizer::iterator it = tokens.begin();
+ tokenizer::iterator end = tokens.end();
+ if (it != end &&
+ (boost::iequals(*it, "SEGMENT")
+ || boost::iequals(*it, "LINESTRING") ))
+ {
+ ++it;
+ }
+ else
+ {
+ throw read_wkt_exception("Should start with 'LINESTRING' or 'SEGMENT'", wkt);
+ }
+
+ typedef typename point_type<Segment>::type point_type;
+ std::vector<point_type> points;
+ container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points));
+
+ check_end(it, end, wkt);
+
+ if (boost::size(points) == 2)
+ {
+ assign_point_to_index<0>(points.front(), segment);
+ assign_point_to_index<1>(points.back(), segment);
+ }
+ else
+ {
+ throw read_wkt_exception("Segment should have 2 points", wkt);
+ }
+
+ }
+};
+
+
+
+}} // namespace detail::wkt
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, typename Geometry>
+struct read_wkt {};
+
+
+template <typename Point>
+struct read_wkt<point_tag, Point>
+ : detail::wkt::geometry_parser
+ <
+ Point,
+ detail::wkt::point_parser,
+ detail::wkt::prefix_point
+ >
+{};
+
+
+template <typename L>
+struct read_wkt<linestring_tag, L>
+ : detail::wkt::geometry_parser
+ <
+ L,
+ detail::wkt::linestring_parser,
+ detail::wkt::prefix_linestring
+ >
+{};
+
+template <typename Ring>
+struct read_wkt<ring_tag, Ring>
+ : detail::wkt::geometry_parser
+ <
+ Ring,
+ detail::wkt::ring_parser,
+ detail::wkt::prefix_polygon
+ >
+{};
+
+template <typename Geometry>
+struct read_wkt<polygon_tag, Geometry>
+ : detail::wkt::geometry_parser
+ <
+ Geometry,
+ detail::wkt::polygon_parser,
+ detail::wkt::prefix_polygon
+ >
+{};
+
+
+// Box (Non-OGC)
+template <typename Box>
+struct read_wkt<box_tag, Box>
+ : detail::wkt::box_parser<Box>
+{};
+
+// Segment (Non-OGC)
+template <typename Segment>
+struct read_wkt<segment_tag, Segment>
+ : detail::wkt::segment_parser<Segment>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Parses OGC Well-Known Text (\ref WKT) into a geometry (any geometry)
+\ingroup wkt
+\param wkt string containing \ref WKT
+\param geometry output geometry
+\par Example:
+\note It is case insensitive and can have the WKT forms "point", "point m", "point z", "point zm", "point mz"
+\note Empty sequences can have forms as "LINESTRING ()" or "POLYGON(())"
+Small example showing how to use read_wkt to build a point
+\dontinclude doxygen_1.cpp
+\skip example_from_wkt_point
+\line {
+\until }
+\par Example:
+Small example showing how to use read_wkt to build a linestring
+\dontinclude doxygen_1.cpp
+\skip example_from_wkt_linestring
+\line {
+\until }
+\par Example:
+Small example showing how to use read_wkt to build a polygon
+\dontinclude doxygen_1.cpp
+\skip example_from_wkt_polygon
+\line {
+\until }
+*/
+template <typename Geometry>
+inline void read_wkt(std::string const& wkt, Geometry& geometry)
+{
+ ggl::concept::check<Geometry>();
+ dispatch::read_wkt<typename tag<Geometry>::type, Geometry>::apply(wkt, geometry);
+}
+
+/*!
+\brief Parses OGC Well-Known Text (\ref WKT) and outputs using an output iterator
+\ingroup wkt
+\param wkt string containing \ref WKT
+\param out output iterator
+\note Because the output iterator doesn't always have the type value_type, it should be
+specified in the function call.
+\par Example:
+Small example showing how to use read_wkt with an output iterator
+\dontinclude doxygen_1.cpp
+\skip example_from_wkt_output_iterator
+\line {
+\until }
+*/
+template <typename Point, typename Out>
+inline void read_wkt(std::string const& wkt, Out out)
+{
+ ggl::concept::check<Point>();
+
+ // Todo: maybe take this from the string, or do not call initialize, such that
+ // any coordinate string is parsed and outputted
+ std::string const& tag = "linestring";
+
+ detail::wkt::tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
+ detail::wkt::tokenizer::iterator it;
+ if (detail::wkt::initialize<Point>(tokens, tag, wkt, it))
+ {
+ detail::wkt::container_inserter<Point>::apply(it, tokens.end(), wkt, out);
+ }
+}
+
+} // namespace ggl
+
+#endif // GGL_EXTENSIONS_GIS_IO_WKT_READ_WKT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/extensions/gis/io/wkt/read_wkt_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/extensions/gis/io/wkt/read_wkt_multi.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/extensions/gis/io/wkt/stream_wkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/extensions/gis/io/wkt/stream_wkt.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,40 @@
+// 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 Char, typename Traits, typename Geometry>
+inline std::basic_ostream<Char,Traits>& operator<<
+ (
+ std::basic_ostream<Char,Traits> &os,
+ Geometry const& geometry
+ )
+{
+ os << ggl::wkt(geometry);
+ return os;
+}
+
+//} // namespace ggl
+
+#endif // GGL_EXTENSIONS_GIS_IO_WKT_STREAM_WKT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/extensions/gis/io/wkt/wkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/extensions/gis/io/wkt/wkt.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/extensions/gis/io/wkt/write_wkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/extensions/gis/io/wkt/write_wkt.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+#include <ggl/core/ring_type.hpp>
+
+#include <ggl/geometries/concepts/check.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 << ")";
+ }
+};
+
+/*!
+\brief Stream ranges as WKT
+\note policy is used to stream prefix/postfix, enabling derived classes to override this
+*/
+template <typename Range, typename PrefixPolicy, typename SuffixPolicy>
+struct wkt_range
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Range const& range)
+ {
+ typedef typename boost::range_const_iterator<Range>::type iterator_type;
+
+ bool first = true;
+
+ os << PrefixPolicy::apply();
+
+ // TODO: check EMPTY here
+
+ for (iterator_type it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ os << (first ? "" : ",");
+ stream_coordinate
+ <
+ point_type, 0, dimension<point_type>::type::value
+ >::apply(os, *it);
+ first = false;
+ }
+
+ os << SuffixPolicy::apply();
+ }
+
+private:
+ typedef typename boost::range_value<Range>::type point_type;
+};
+
+/*!
+\brief Stream sequence of points as WKT-part, e.g. (1 2),(3 4)
+\note Used in polygon, all multi-geometries
+*/
+
+
+
+template <typename Range>
+struct wkt_sequence
+ : wkt_range
+ <
+ Range,
+ opening_parenthesis,
+ closing_parenthesis
+ >
+{};
+
+
+template <typename Polygon, typename PrefixPolicy>
+struct wkt_poly
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Polygon const& poly)
+ {
+ typedef typename ring_type<Polygon>::type ring;
+ typedef typename boost::range_const_iterator<
+ typename interior_type<Polygon>::type>::type iterator;
+
+ os << PrefixPolicy::apply();
+ // TODO: check EMPTY here
+ os << "(";
+ wkt_sequence<ring>::apply(os, exterior_ring(poly));
+ for (iterator it = boost::begin(interior_rings(poly));
+ it != boost::end(interior_rings(poly));
+ ++it)
+ {
+ os << ",";
+ wkt_sequence<ring>::apply(os, *it);
+ }
+ os << ")";
+ }
+};
+
+
+template <typename Box>
+struct wkt_box
+{
+ typedef typename point_type<Box>::type point_type;
+
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Box const& box)
+ {
+ // Convert to linear ring, then stream
+ typedef linear_ring<point_type> ring_type;
+ ring_type ring;
+ ggl::convert(box, ring);
+ os << "POLYGON(";
+ wkt_sequence<ring_type>::apply(os, ring);
+ os << ")";
+ }
+
+ private:
+
+ inline wkt_box()
+ {
+ // Only streaming of boxes with two dimensions is support, otherwise it is a polyhedron!
+ //assert_dimension<B, 2>();
+ }
+};
+
+}} // namespace detail::wkt
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+template <typename Tag, typename Geometry>
+struct wkt {};
+
+
+template <typename Point>
+struct wkt<point_tag, Point>
+ : detail::wkt::wkt_point
+ <
+ Point,
+ detail::wkt::prefix_point
+ >
+{};
+
+
+template <typename Linestring>
+struct wkt<linestring_tag, Linestring>
+ : detail::wkt::wkt_range
+ <
+ Linestring,
+ detail::wkt::prefix_linestring_par,
+ detail::wkt::closing_parenthesis
+ >
+{};
+
+
+/*!
+\brief Specialization to stream a box as WKT
+\details A "box" does not exist in WKT.
+It is therefore streamed as a polygon
+*/
+template <typename Box>
+struct wkt<box_tag, Box>
+ : detail::wkt::wkt_box<Box>
+{};
+
+
+/*!
+\brief Specialization to stream a ring as WKT
+\details A "linear_ring" does not exist in WKT.
+A linear ring is equivalent to a polygon without inner rings
+It is therefore streamed as a polygon
+*/
+template <typename Ring>
+struct wkt<ring_tag, Ring>
+ : detail::wkt::wkt_range
+ <
+ Ring,
+ detail::wkt::prefix_ring_par_par,
+ detail::wkt::double_closing_parenthesis
+ >
+{};
+
+
+/*!
+\brief Specialization to stream polygon as WKT
+*/
+template <typename Polygon>
+struct wkt<polygon_tag, Polygon>
+ : detail::wkt::wkt_poly
+ <
+ Polygon,
+ detail::wkt::prefix_polygon
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Generic geometry template manipulator class, takes corresponding output class from traits class
+\ingroup wkt
+\details Stream manipulator, streams geometry classes as \ref WKT streams
+\par Example:
+Small example showing how to use the wkt class
+\dontinclude doxygen_1.cpp
+\skip example_as_wkt_point
+\line {
+\until }
+*/
+template <typename Geometry>
+class wkt_manipulator
+{
+public:
+
+ inline wkt_manipulator(Geometry const& g)
+ : m_geometry(g)
+ {}
+
+ template <typename Char, typename Traits>
+ inline friend std::basic_ostream<Char, Traits>& operator<<(
+ std::basic_ostream<Char, Traits>& os,
+ wkt_manipulator const& m)
+ {
+ dispatch::wkt
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::apply(os, m.m_geometry);
+ os.flush();
+ return os;
+ }
+
+private:
+ Geometry const& m_geometry;
+};
+
+/*!
+\brief Main WKT-streaming function
+\ingroup wkt
+\par Example:
+Small example showing how to use the wkt helper function
+\dontinclude doxygen_1.cpp
+\skip example_as_wkt_vector
+\line {
+\until }
+*/
+template <typename Geometry>
+inline wkt_manipulator<Geometry> wkt(Geometry const& geometry)
+{
+ concept::check<const Geometry>();
+
+ return wkt_manipulator<Geometry>(geometry);
+}
+
+
+// Backward compatibility
+template <typename Geometry>
+inline wkt_manipulator<Geometry> make_wkt(Geometry const& geometry)
+{
+ concept::check<const Geometry>();
+
+ return wkt_manipulator<Geometry>(geometry);
+}
+
+} // namespace ggl
+
+#endif // GGL_EXTENSIONS_GIS_IO_WKT_WRITE_WKT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/extensions/gis/io/wkt/write_wkt_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/extensions/gis/io/wkt/write_wkt_multi.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/extensions/io/svg/write_svg.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/extensions/io/svg/write_svg.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,248 @@
+// 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/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/core/exterior_ring.hpp>
+#include <ggl/core/interior_rings.hpp>
+#include <ggl/core/ring_type.hpp>
+
+#include <ggl/geometries/concepts/check.hpp>
+
+/*!
+\defgroup svg x Extension 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 << "\"/>";
+ }
+};
+
+
+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 << "\"/>";
+ }
+};
+
+
+/*!
+\brief Stream ranges as SVG
+\note policy is used to select type (polyline/polygon)
+*/
+template <typename Range, typename Policy>
+struct svg_range
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Range const& range, std::string const& style, int size)
+ {
+ typedef typename boost::range_const_iterator<Range>::type iterator;
+
+ bool first = true;
+
+ os << "<" << Policy::prefix() << " points=\"";
+
+ for (iterator it = boost::begin(range);
+ it != boost::end(range);
+ ++it, first = false)
+ {
+ os << (first ? "" : " " ) << it->x() << "," << it->y();
+ }
+ os << "\" style=\"" << style << Policy::style() << "\"/>";
+ }
+};
+
+
+
+template <typename Polygon>
+struct svg_poly
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Polygon const& polygon, std::string const& style, int size)
+ {
+ typedef typename 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>";
+
+ }
+};
+
+
+
+struct prefix_linestring
+{
+ static inline const char* prefix() { return "polyline"; }
+ static inline const char* style() { return ";fill:none"; }
+};
+
+
+struct prefix_ring
+{
+ static inline const char* prefix() { return "polygon"; }
+ static inline const char* style() { return ""; }
+};
+
+
+
+}} // namespace detail::svg
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+/*!
+\brief Dispatching base struct for SVG streaming, specialized below per geometry type
+\details Specializations should implement a static method "stream" to stream a geometry
+The static method should have the signature:
+
+template <typename Char, typename Traits>
+static inline void apply(std::basic_ostream<Char, Traits>& os, const G& geometry)
+*/
+template <typename GeometryTag, typename Geometry>
+struct svg {};
+
+template <typename Point>
+struct svg<point_tag, Point> : detail::svg::svg_point<Point> {};
+
+template <typename Box>
+struct svg<box_tag, Box> : detail::svg::svg_box<Box> {};
+
+template <typename Linestring>
+struct svg<linestring_tag, Linestring>
+ : detail::svg::svg_range<Linestring, detail::svg::prefix_linestring> {};
+
+template <typename Ring>
+struct svg<ring_tag, Ring>
+ : detail::svg::svg_range<Ring, detail::svg::prefix_ring> {};
+
+template <typename Polygon>
+struct svg<polygon_tag, Polygon>
+ : detail::svg::svg_poly<Polygon> {};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Generic geometry template manipulator class, takes corresponding output class from traits class
+\ingroup svg
+\details Stream manipulator, streams geometry classes as Virtual Earth shape
+*/
+template <typename G>
+class svg_manipulator
+{
+public:
+
+ inline svg_manipulator(G const& g, std::string const& style, int size)
+ : m_geometry(g)
+ , m_style(style)
+ , m_size(size)
+ {}
+
+ template <typename Char, typename Traits>
+ inline friend std::basic_ostream<Char, Traits>& operator<<(
+ std::basic_ostream<Char, Traits>& os, svg_manipulator const& m)
+ {
+ dispatch::svg
+ <
+ typename tag<G>::type, G
+ >::apply(os, m.m_geometry, m.m_style, m.m_size);
+ os.flush();
+ return os;
+ }
+
+private:
+ G const& m_geometry;
+ std::string const& m_style;
+ int m_size;
+};
+
+/*!
+\brief Main svg function to stream geometries as SVG
+\ingroup svg
+*/
+template <typename Geometry>
+inline svg_manipulator<Geometry> svg(Geometry const& t, std::string const& style, int size = -1)
+{
+ concept::check<const Geometry>();
+
+ return svg_manipulator<Geometry>(t, style, size);
+}
+
+} // namespace ggl
+
+#endif // GGL_IO_SVG_WRITE_SVG_HPP

Added: sandbox/ggl/formal_review/boost/ggl/extensions/io/svg/write_svg_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/extensions/io/svg/write_svg_multi.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/geometries/adapted/boost_array_as_linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/adapted/boost_array_as_linestring.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_GEOMETRIES_ADAPTED_BOOST_ARRAY_AS_LINESTRING_HPP
+#define GGL_GEOMETRIES_ADAPTED_BOOST_ARRAY_AS_LINESTRING_HPP
+
+
+#ifdef GGL_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/boost/ggl/geometries/adapted/boost_array_as_ring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/adapted/boost_array_as_ring.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_GEOMETRIES_ADAPTED_BOOST_ARRAY_AS_RING_HPP
+#define GGL_GEOMETRIES_ADAPTED_BOOST_ARRAY_AS_RING_HPP
+
+
+#ifdef GGL_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/boost/ggl/geometries/adapted/c_array.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/adapted/c_array.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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 CoordinateType, std::size_t DimensionCount>
+struct tag<CoordinateType[DimensionCount]>
+ : detail::c_array_tag<boost::is_arithmetic<CoordinateType>::value> {};
+
+template <typename CoordinateType, std::size_t DimensionCount>
+struct coordinate_type<CoordinateType[DimensionCount]>
+{
+ typedef CoordinateType type;
+};
+
+template <typename CoordinateType, std::size_t DimensionCount>
+struct dimension<CoordinateType[DimensionCount]>: boost::mpl::int_<DimensionCount> {};
+
+template <typename CoordinateType, std::size_t DimensionCount, std::size_t Dimension>
+struct access<CoordinateType[DimensionCount], Dimension>
+{
+ static inline CoordinateType get(const CoordinateType p[DimensionCount])
+ {
+ return p[Dimension];
+ }
+
+ static inline void set(CoordinateType p[DimensionCount],
+ CoordinateType const& value)
+ {
+ p[Dimension] = value;
+ }
+};
+
+// The library user has
+// 1) either to specify the coordinate system
+// 2) or include <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/boost/ggl/geometries/adapted/c_array_cartesian.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/adapted/c_array_cartesian.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_GEOMETRIES_ADAPTED_C_ARRAY_CARTESIAN_HPP
+#define GGL_GEOMETRIES_ADAPTED_C_ARRAY_CARTESIAN_HPP
+
+#ifdef GGL_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/boost/ggl/geometries/adapted/std_as_linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/adapted/std_as_linestring.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,66 @@
+// 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_STD_AS_LINESTRING_HPP
+#define GGL_GEOMETRIES_ADAPTED_STD_AS_LINESTRING_HPP
+
+
+#ifdef GGL_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>
+
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+
+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/boost/ggl/geometries/adapted/std_as_ring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/adapted/std_as_ring.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_GEOMETRIES_ADAPTED_STD_AS_RING_HPP
+#define GGL_GEOMETRIES_ADAPTED_STD_AS_RING_HPP
+
+
+#ifdef GGL_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/boost/ggl/geometries/adapted/std_pair_as_segment.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/adapted/std_pair_as_segment.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,90 @@
+// Generic Geometry Library
+//
+// 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_STD_PAIR_AS_SEGMENT_HPP
+#define GGL_GEOMETRIES_ADAPTED_STD_PAIR_AS_SEGMENT_HPP
+
+// Only possible if the std::pair is not used for iterator/pair
+// (maybe it is possible to avoid that by detecting in the other file
+// if an iterator was used in the pair)
+
+#ifdef GGL_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 <ggl/core/access.hpp>
+#include <ggl/core/tag.hpp>
+#include <ggl/core/tags.hpp>
+
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+
+template <typename Point>
+struct tag<std::pair<Point, Point> >
+{
+ typedef segment_tag type;
+};
+
+template <typename Point>
+struct point_type<std::pair<Point, Point> >
+{
+ typedef Point type;
+};
+
+template <typename Point, std::size_t Dimension>
+struct indexed_access<std::pair<Point, Point>, 0, Dimension>
+{
+ typedef typename ggl::coordinate_type<Point>::type coordinate_type;
+
+ static inline coordinate_type get(std::pair<Point, Point> const& s)
+ {
+ return ggl::get<Dimension>(s.first);
+ }
+
+ static inline void set(std::pair<Point, Point>& s, coordinate_type const& value)
+ {
+ ggl::set<Dimension>(s.first, value);
+ }
+};
+
+
+template <typename Point, std::size_t Dimension>
+struct indexed_access<std::pair<Point, Point>, 1, Dimension>
+{
+ typedef typename ggl::coordinate_type<Point>::type coordinate_type;
+
+ static inline coordinate_type get(std::pair<Point, Point> const& s)
+ {
+ return ggl::get<Dimension>(s.second);
+ }
+
+ static inline void set(std::pair<Point, Point>& s, coordinate_type const& value)
+ {
+ ggl::set<Dimension>(s.second, value);
+ }
+};
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+
+#endif // GGL_GEOMETRIES_ADAPTED_STD_PAIR_AS_SEGMENT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/adapted/tuple.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/adapted/tuple.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,120 @@
+// 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 CoordinateType>
+struct coordinate_type<boost::tuple<CoordinateType, CoordinateType> >
+{
+ typedef CoordinateType type;
+};
+
+template <typename CoordinateType>
+struct dimension<boost::tuple<CoordinateType, CoordinateType> >
+ : boost::mpl::int_<2>
+{};
+
+template <typename CoordinateType, std::size_t Dimension>
+struct access
+ <
+ boost::tuple<CoordinateType, CoordinateType>,
+ Dimension
+ >
+{
+ static inline CoordinateType get(
+ boost::tuple<CoordinateType, CoordinateType> const& point)
+ {
+ return point.template get<Dimension>();
+ }
+
+ static inline void set(boost::tuple<CoordinateType, CoordinateType>& point,
+ CoordinateType const& value)
+ {
+ point.template get<Dimension>() = value;
+ }
+};
+
+template <typename CoordinateType>
+struct tag<boost::tuple<CoordinateType, CoordinateType> >
+{
+ typedef point_tag type;
+};
+
+// boost::tuple, 3D
+template <typename CoordinateType>
+struct coordinate_type
+ <
+ boost::tuple<CoordinateType, CoordinateType, CoordinateType>
+ >
+{
+ typedef CoordinateType type;
+};
+
+template <typename CoordinateType>
+struct dimension<boost::tuple<CoordinateType, CoordinateType, CoordinateType> >
+ : boost::mpl::int_<3>
+{};
+
+template <typename CoordinateType, std::size_t Dimension>
+struct access
+ <
+ boost::tuple<CoordinateType, CoordinateType, CoordinateType>,
+ Dimension
+ >
+{
+ static inline CoordinateType get(
+ boost::tuple
+ <
+ CoordinateType, CoordinateType, CoordinateType
+ > const& point)
+ {
+ return point.template get<Dimension>();
+ }
+
+ static inline void set(
+ boost::tuple<CoordinateType, CoordinateType, CoordinateType>& point,
+ CoordinateType const& value)
+ {
+ point.template get<Dimension>() = value;
+ }
+};
+
+template <typename CoordinateType>
+struct tag<boost::tuple<CoordinateType, CoordinateType, CoordinateType> >
+{
+ typedef point_tag type;
+};
+
+// The library user has
+// 1) either to specify the coordinate system using a traits class
+// 2) or include <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/boost/ggl/geometries/adapted/tuple_cartesian.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/adapted/tuple_cartesian.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_GEOMETRIES_ADAPTED_TUPLE_CARTESIAN_HPP
+#define GGL_GEOMETRIES_ADAPTED_TUPLE_CARTESIAN_HPP
+
+#ifdef GGL_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/boost/ggl/geometries/box.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/box.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_GEOMETRIES_BOX_HPP
+#define GGL_GEOMETRIES_BOX_HPP
+
+#include <cstddef>
+
+#include <boost/concept/assert.hpp>
+
+#include <ggl/geometries/concepts/point_concept.hpp>
+
+#include <ggl/util/copy.hpp>
+
+namespace ggl
+{
+
+/*!
+ \brief Class box: defines a box made of two describing points
+ \ingroup geometries
+ \details Box is always described by a min_corner() and a max_corner() point. If another
+ rectangle is used, use linear_ring or polygon.
+ \note Boxes are for selections and for calculating the envelope of geometries. Not all algorithms
+ are implemented for box. Boxes are also used in Spatial Indexes.
+ \tparam Point point type. The box takes a point type as template parameter.
+ The point type can be any point type.
+ It can be 2D but can also be 3D or more dimensional.
+ The box can also take a latlong point type as template parameter.
+ */
+
+template<typename Point>
+class box
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+public:
+
+ inline box() {}
+
+ /*!
+ \brief Constructor taking the minimum corner point and the maximum corner point
+ */
+ inline box(Point const& min_corner, Point const& max_corner)
+ {
+ copy_coordinates(min_corner, m_min_corner);
+ copy_coordinates(max_corner, m_max_corner);
+ }
+
+ inline Point const& min_corner() const { return m_min_corner; }
+ inline Point const& max_corner() const { return m_max_corner; }
+
+ inline Point& min_corner() { return m_min_corner; }
+ inline Point& max_corner() { return m_max_corner; }
+
+private:
+
+ Point m_min_corner;
+ Point m_max_corner;
+};
+
+
+// Traits specializations for box above
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename Point>
+struct tag<box<Point> >
+{
+ typedef box_tag type;
+};
+
+template <typename Point>
+struct point_type<box<Point> >
+{
+ typedef Point type;
+};
+
+template <typename Point, std::size_t Dimension>
+struct indexed_access<box<Point>, min_corner, Dimension>
+{
+ typedef typename ggl::coordinate_type<Point>::type coordinate_type;
+
+ static inline coordinate_type get(box<Point> const& b)
+ {
+ return ggl::get<Dimension>(b.min_corner());
+ }
+
+ static inline void set(box<Point>& b, coordinate_type const& value)
+ {
+ ggl::set<Dimension>(b.min_corner(), value);
+ }
+};
+
+template <typename Point, std::size_t Dimension>
+struct indexed_access<box<Point>, max_corner, Dimension>
+{
+ typedef typename ggl::coordinate_type<Point>::type coordinate_type;
+
+ static inline coordinate_type get(box<Point> const& b)
+ {
+ return ggl::get<Dimension>(b.max_corner());
+ }
+
+ static inline void set(box<Point>& b, coordinate_type const& value)
+ {
+ ggl::set<Dimension>(b.max_corner(), value);
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_BOX_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/cartesian2d.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/cartesian2d.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_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;
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_CARTESIAN2D_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/cartesian3d.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/cartesian3d.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,27 @@
+// 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;
+
+}
+
+
+#endif // GGL_CARTESIAN3D_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/concepts/box_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/concepts/box_concept.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,131 @@
+// 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_CONCEPTS_BOX_CONCEPT_HPP
+#define GGL_GEOMETRIES_CONCEPTS_BOX_CONCEPT_HPP
+
+
+#include <cstddef>
+
+#include <boost/concept_check.hpp>
+
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/coordinate_dimension.hpp>
+#include <ggl/core/point_type.hpp>
+
+
+
+namespace ggl { namespace concept {
+
+
+/*!
+\brief Box concept
+\ingroup concepts
+\par Formal definition:
+The box concept is defined as following:
+- there must be a specialization of traits::tag defining box_tag as type
+- there must be a specialization of traits::point_type to define the
+ underlying point type (even if it does not consist of points, it should define
+ this type, to indicate the points it can work with)
+- there must be a specialization of traits::indexed_access, per index
+ (min_corner, max_corner) and per dimension, with two functions:
+ - get to get a coordinate value
+ - set to set a coordinate value (this one is not checked for ConstBox)
+*/
+template <typename Geometry>
+class Box
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+
+
+ template
+ <
+ std::size_t Index,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+ >
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ Geometry* b;
+ ggl::set<Index, Dimension>(*b, ggl::get<Index, Dimension>(*b));
+ dimension_checker<Index, Dimension + 1, DimensionCount>::apply();
+ }
+ };
+
+ template <std::size_t Index, std::size_t DimensionCount>
+ struct dimension_checker<Index, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public :
+ BOOST_CONCEPT_USAGE(Box)
+ {
+ static const std::size_t n = dimension<Geometry>::type::value;
+ dimension_checker<min_corner, 0, n>::apply();
+ dimension_checker<max_corner, 0, n>::apply();
+ }
+#endif
+};
+
+
+/*!
+\brief Box concept (const version)
+\ingroup const_concepts
+\details The ConstBox concept apply the same as the Box concept,
+but does not apply write access.
+*/
+template <typename Geometry>
+class ConstBox
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename coordinate_type<Geometry>::type coordinate_type;
+
+ template
+ <
+ std::size_t Index,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+ >
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ const Geometry* b = 0;
+ coordinate_type coord(ggl::get<Index, Dimension>(*b));
+ boost::ignore_unused_variable_warning(coord);
+ dimension_checker<Index, Dimension + 1, DimensionCount>::apply();
+ }
+ };
+
+ template <std::size_t Index, std::size_t DimensionCount>
+ struct dimension_checker<Index, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public :
+ BOOST_CONCEPT_USAGE(ConstBox)
+ {
+ static const std::size_t n = dimension<Geometry>::type::value;
+ dimension_checker<min_corner, 0, n>::apply();
+ dimension_checker<max_corner, 0, n>::apply();
+ }
+#endif
+};
+
+}} // namespace ggl::concept
+
+
+#endif // GGL_GEOMETRIES_CONCEPTS_BOX_CONCEPT_HPP

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

Added: sandbox/ggl/formal_review/boost/ggl/geometries/concepts/detail/check_append.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/concepts/detail/check_append.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,58 @@
+// 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_CONCEPTS_DETAIL_CHECK_APPEND_HPP
+#define GGL_GEOMETRIES_CONCEPTS_DETAIL_CHECK_APPEND_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+
+#include <ggl/core/access.hpp>
+
+
+namespace ggl { namespace concept {
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+ template <typename Geometry, typename Point, bool UseStd>
+ struct check_append
+ {};
+
+ template <typename Geometry, typename Point>
+ struct check_append<Geometry, Point, true>
+ {
+ static void apply(Geometry& geometry, Point const& p)
+ {
+ geometry.push_back(p);
+ }
+ };
+
+
+ template <typename Geometry, typename Point>
+ struct check_append<Geometry, Point, false>
+ {
+ static void apply(Geometry& geometry, Point const& p)
+ {
+ ggl::traits::append_point
+ <
+ typename boost::remove_const<Geometry>::type,
+ Point
+ >::apply(geometry, p, -1, -1);
+ }
+ };
+}
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace ggl::concept
+
+
+#endif // GGL_GEOMETRIES_CONCEPTS_DETAIL_CHECK_APPEND_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/concepts/detail/check_clear.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/concepts/detail/check_clear.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_GEOMETRIES_CONCEPTS_DETAIL_CHECK_CLEAR_HPP
+#define GGL_GEOMETRIES_CONCEPTS_DETAIL_CHECK_CLEAR_HPP
+
+
+#include <boost/type_traits/remove_const.hpp>
+
+#include <ggl/core/access.hpp>
+
+
+namespace ggl { namespace concept {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+ template <typename Geometry, bool UseStd>
+ struct check_clear
+ {};
+
+ template <typename Geometry>
+ struct check_clear<Geometry, true>
+ {
+ static void apply(Geometry& geometry)
+ {
+ geometry.clear();
+ }
+ };
+
+
+ template <typename Geometry>
+ struct check_clear<Geometry, false>
+ {
+ static void apply(Geometry& geometry)
+ {
+ ggl::traits::clear
+ <
+ typename boost::remove_const<Geometry>::type
+ >::apply(geometry);
+ }
+ };
+
+}
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace ggl::concept
+
+
+#endif // GGL_GEOMETRIES_CONCEPTS_DETAIL_CHECK_CLEAR_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/concepts/linestring_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/concepts/linestring_concept.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_CONCEPTS_LINESTRING_CONCEPT_HPP
+#define GGL_GEOMETRIES_CONCEPTS_LINESTRING_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/point_type.hpp>
+
+#include <ggl/geometries/concepts/point_concept.hpp>
+
+#include <ggl/geometries/concepts/detail/check_clear.hpp>
+#include <ggl/geometries/concepts/detail/check_append.hpp>
+
+
+namespace ggl { namespace concept {
+
+
+/*!
+\brief Linestring concept
+\ingroup concepts
+\par Formal definition:
+The linestring concept is defined as following:
+- there must be a specialization of traits::tag defining linestring_tag as type
+- it must behave like a Boost.Range
+- either it can behave like the std library, having push_back and clear
+- or it can implement a mechanism for clearing and adding points:
+ - there can be a specialization of traits::use_std class indicating
+ that it does not use the standard library (for modifications)
+ - there should then be a specialization of traits::clear
+ to make a linestring empty
+ - there should then be a specialization of traits::append_point
+ to add a point to a linestring
+
+\note to fulfil the concepts, no traits class has to be specialized to
+define the point type. The point type is taken using boost::range_value<X>::type
+
+\par Example:
+
+A custom linestring, defining the necessary specializations to fulfil to the concept.
+
+Suppose that the following linestring is defined:
+\dontinclude doxygen_5.cpp
+\skip custom_linestring1
+\until };
+
+It can then be adapted to the concept as following:
+\dontinclude doxygen_5.cpp
+\skip adapt custom_linestring1
+\until }}
+
+\note
+- There is also the registration macro GEOMETRY_REGISTER_LINESTRING
+- For registration of std::vector<P> (and deque, and list) it is enough to
+include the header-file geometries/adapted/std_as_linestring.hpp. That registers
+a vector as a linestring (so it cannot be registered as a linear ring then,
+in the same source code).
+
+
+*/
+
+template <typename Geometry>
+class Linestring
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Point<point_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(Linestring)
+ {
+ // Check if it can be modified
+ static const bool use_std = traits::use_std
+ <
+ typename boost::remove_const<Geometry>::type
+ >::value;
+
+ Geometry* ls;
+ detail::check_clear<Geometry, use_std>::apply(*ls);
+
+ point_type* p;
+ detail::check_append<Geometry, point_type, use_std>::apply(*ls, *p);
+ }
+#endif
+};
+
+
+/*!
+\brief Linestring concept (const version)
+\ingroup const_concepts
+\details The ConstLinestring concept check the same as the Linestring concept,
+but does not check write access.
+*/
+template <typename Geometry>
+class ConstLinestring
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstLinestring)
+ {
+ }
+#endif
+};
+
+}} // namespace ggl::concept
+
+
+#endif // GGL_GEOMETRIES_CONCEPTS_LINESTRING_CONCEPT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/concepts/point_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/concepts/point_concept.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,167 @@
+// 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_GEOMETRIES_CONCEPTS_POINT_CONCEPT_HPP
+#define GGL_GEOMETRIES_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>
+
+
+
+
+namespace ggl { namespace concept {
+
+/*!
+\brief Point concept
+\ingroup concepts
+
+\par Formal definition:
+The point concept is defined as following:
+- there must be a specialization of traits::tag defining point_tag as type
+- there must be a specialization of traits::coordinate_type defining the type
+ of its coordinates
+- there must be a specialization of traits::coordinate_system defining its
+ coordinate system (cartesian, spherical, etc)
+- there must be a specialization of traits::dimension defining its number
+ of dimensions (2, 3, ...) (derive it conveniently
+ from boost::mpl::int_&lt;X&gt; for X-D)
+- there must be a specialization of traits::access, per dimension,
+ with two functions:
+ - \b get to get a coordinate value
+ - \b set to set a coordinate value (this one is not checked for ConstPoint)
+
+\par Example:
+
+A legacy point, defining the necessary specializations to fulfil to the concept.
+
+Suppose that the following point is defined:
+\dontinclude doxygen_5.cpp
+\skip legacy_point1
+\until };
+
+It can then be adapted to the concept as following:
+\dontinclude doxygen_5.cpp
+\skip adapt legacy_point1
+\until }}
+
+Note that it is done like above to show the system. Users will normally use the registration macro.
+
+\par Example:
+
+A read-only legacy point, using a macro to fulfil to the ConstPoint concept.
+It cannot be modified by the library but can be used in all algorithms where
+points are not modified.
+
+The point looks like the following:
+
+\dontinclude doxygen_5.cpp
+\skip legacy_point2
+\until };
+
+It uses the macro as following:
+\dontinclude doxygen_5.cpp
+\skip adapt legacy_point2
+\until end adaptation
+
+*/
+
+template <typename Geometry>
+class Point
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ typedef typename coordinate_type<Geometry>::type ctype;
+ typedef typename coordinate_system<Geometry>::type csystem;
+
+ enum { ccount = dimension<Geometry>::value };
+
+
+ template <typename P, std::size_t Dimension, std::size_t DimensionCount>
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ P* p;
+ ggl::set<Dimension>(*p, ggl::get<Dimension>(*p));
+ dimension_checker<P, Dimension+1, DimensionCount>::apply();
+ }
+ };
+
+
+ template <typename P, std::size_t DimensionCount>
+ struct dimension_checker<P, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public:
+
+ /// BCCL macro to apply the Point concept
+ BOOST_CONCEPT_USAGE(Point)
+ {
+ dimension_checker<Geometry, 0, ccount>::apply();
+ }
+#endif
+};
+
+
+/*!
+\brief point concept (const version)
+\ingroup const_concepts
+\details The ConstPoint concept apply the same as the Point concept,
+but does not apply write access.
+*/
+template <typename Geometry>
+class ConstPoint
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ typedef typename coordinate_type<Geometry>::type ctype;
+ typedef typename coordinate_system<Geometry>::type csystem;
+
+ enum { ccount = dimension<Geometry>::value };
+
+
+ template <typename P, std::size_t Dimension, std::size_t DimensionCount>
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ const P* p = 0;
+ ctype coord(ggl::get<Dimension>(*p));
+ boost::ignore_unused_variable_warning(coord);
+ dimension_checker<P, Dimension+1, DimensionCount>::apply();
+ }
+ };
+
+
+ template <typename P, std::size_t DimensionCount>
+ struct dimension_checker<P, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public:
+
+ /// BCCL macro to apply the ConstPoint concept
+ BOOST_CONCEPT_USAGE(ConstPoint)
+ {
+ dimension_checker<Geometry, 0, ccount>::apply();
+ }
+#endif
+};
+
+}} // namespace ggl::concept
+
+#endif // GGL_GEOMETRIES_CONCEPTS_POINT_CONCEPT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/concepts/polygon_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/concepts/polygon_concept.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_GEOMETRIES_CONCEPTS_POLYGON_CONCEPT_HPP
+#define GGL_GEOMETRIES_CONCEPTS_POLYGON_CONCEPT_HPP
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.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/geometries/concepts/point_concept.hpp>
+#include <ggl/geometries/concepts/ring_concept.hpp>
+
+namespace ggl { namespace concept {
+
+
+/*!
+\brief Polygon concept
+\ingroup concepts
+\par Formal definition:
+The polygon concept is defined as following:
+- there must be a specialization of traits::tag defining polygon_tag as type
+- there must be a specialization of traits::ring_type defining the type of its
+exterior ring and interior rings as type
+- there must be a specialization of traits::interior_type defining the type of
+the collection of its interior rings as type
+- there must be a specialization of traits::exterior_ring
+ with two functions named "get",
+ returning the exterior ring, a const version and a mutable version
+- there must be a specialization of traits::interior_rings
+ with two functions named "get", returning the interior rings,
+ a const version and a mutable version
+
+\note to fulfil the concepts, no traits class has to be specialized to
+define the point type. The point type is automatically defined as
+typename range_value<typename ring_type<P>::type>::type
+*/
+template <typename Geometry>
+class Polygon
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename ring_type<Geometry>::type ring_type;
+ typedef typename interior_type<Geometry>::type interior_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Point<point_type>) );
+ BOOST_CONCEPT_ASSERT( (concept::Ring<ring_type>) );
+
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<interior_type>) );
+
+ struct checker
+ {
+ static inline void apply()
+ {
+ Geometry* poly;
+ ring_type& e = exterior_ring(*poly);
+ ring_type const& ce = exterior_ring(*poly);
+
+ interior_type& i = interior_rings(*poly);
+ interior_type const& ci = interior_rings(*poly);
+
+ boost::ignore_unused_variable_warning(e);
+ boost::ignore_unused_variable_warning(ce);
+ boost::ignore_unused_variable_warning(i);
+ boost::ignore_unused_variable_warning(ci);
+ boost::ignore_unused_variable_warning(poly);
+ }
+
+ };
+
+public:
+
+
+ BOOST_CONCEPT_USAGE(Polygon)
+ {
+ // Check if it can be modified
+ // TODO
+
+ //Geometry* poly;
+ //clear(*poly);
+ //append(*poly, point_type());
+
+ checker::apply();
+ }
+#endif
+};
+
+
+/*!
+\brief Polygon concept (const version)
+\ingroup const_concepts
+\details The ConstPolygon concept check the same as the Polygon concept,
+but does not check write access.
+*/
+template <typename Geometry>
+class ConstPolygon
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename ring_type<Geometry>::type ring_type;
+ typedef typename interior_type<Geometry>::type interior_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point_type>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstRing<ring_type>) );
+
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<interior_type>) );
+
+ struct checker
+ {
+ static inline void apply()
+ {
+ Geometry* poly;
+ ring_type const& ce = exterior_ring(*poly);
+ interior_type const& ci = interior_rings(*poly);
+
+ boost::ignore_unused_variable_warning(ce);
+ boost::ignore_unused_variable_warning(ci);
+ boost::ignore_unused_variable_warning(poly);
+ }
+ };
+
+
+public:
+
+ BOOST_CONCEPT_USAGE(ConstPolygon)
+ {
+ checker::apply();
+ }
+#endif
+};
+
+}} // namespace ggl::concept
+
+#endif // GGL_GEOMETRIES_CONCEPTS_POLYGON_CONCEPT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/concepts/ring_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/concepts/ring_concept.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,103 @@
+// 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_CONCEPTS_RING_CONCEPT_HPP
+#define GGL_GEOMETRIES_CONCEPTS_RING_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/point_type.hpp>
+
+#include <ggl/geometries/concepts/point_concept.hpp>
+
+#include <ggl/geometries/concepts/detail/check_clear.hpp>
+#include <ggl/geometries/concepts/detail/check_append.hpp>
+
+
+namespace ggl { namespace concept {
+
+
+/*!
+\brief ring concept
+\ingroup concepts
+\par Formal definition:
+The ring concept is defined as following:
+- there must be a specialization of traits::tag defining ring_tag as type
+- it must behave like a Boost.Range
+- there can optionally be a specialization of traits::point_order defining the
+ order or orientation of its points, clockwise or counterclockwise.
+- either it can behave like the std library, having pushback
+- or it can implement a mechanism for clearing and adding points.
+ This is the same as the for the concept Linestring, and described there.
+
+\note to fulfil the concepts, no traits class has to be specialized to
+define the point type. The point type is taken using boost::range_value<X>::type
+*/
+template <typename Geometry>
+class Ring
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Point<point_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(Ring)
+ {
+ // Check if it can be modified
+ static const bool use_std = traits::use_std
+ <
+ typename boost::remove_const<Geometry>::type
+ >::value;
+
+ Geometry* ring;
+ detail::check_clear<Geometry, use_std>::apply(*ring);
+
+ point_type* p;
+ detail::check_append<Geometry, point_type, use_std>::apply(*ring, *p);
+ }
+#endif
+};
+
+
+/*!
+\brief (linear) ring concept (const version)
+\ingroup const_concepts
+\details The ConstLinearRing concept check the same as the Geometry concept,
+but does not check write access.
+*/
+template <typename Geometry>
+class ConstRing
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstRing)
+ {
+ }
+#endif
+};
+
+}} // namespace ggl::concept
+
+
+#endif // GGL_GEOMETRIES_CONCEPTS_RING_CONCEPT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/concepts/segment_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/concepts/segment_concept.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,133 @@
+// 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_CONCEPTS_SEGMENT_CONCEPT_HPP
+#define GGL_GEOMETRIES_CONCEPTS_SEGMENT_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+
+#include <ggl/geometries/concepts/point_concept.hpp>
+
+
+
+#include <ggl/core/access.hpp>
+#include <ggl/core/point_type.hpp>
+
+
+
+namespace ggl { namespace concept {
+
+
+/*!
+\brief segment concept
+\ingroup concepts
+\par Formal definition:
+The segment concept is defined as following:
+- there must be a specialization of traits::tag defining segment_tag as type
+- there must be a specialization of traits::point_type to define the
+ underlying point type (even if it does not consist of points, it should define
+ this type, to indicate the points it can work with)
+- there must be a specialization of traits::indexed_access, per index
+ and per dimension, with two functions:
+ - get to get a coordinate value
+ - set to set a coordinate value (this one is not checked for ConstSegment)
+
+\note The segment concept is similar to the box concept, defining another tag.
+However, the box concept assumes the index as min_corner, max_corner, while
+for the segment concept there is no assumption.
+*/
+template <typename Geometry>
+class Segment
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Point<point_type>) );
+
+
+ template <size_t Index, size_t Dimension, size_t DimensionCount>
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ Geometry* s;
+ ggl::set<Index, Dimension>(*s, ggl::get<Index, Dimension>(*s));
+ dimension_checker<Index, Dimension + 1, DimensionCount>::apply();
+ }
+ };
+
+ template <size_t Index, size_t DimensionCount>
+ struct dimension_checker<Index, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public :
+
+ BOOST_CONCEPT_USAGE(Segment)
+ {
+ static const size_t n = dimension<point_type>::type::value;
+ dimension_checker<0, 0, n>::apply();
+ dimension_checker<1, 0, n>::apply();
+ }
+#endif
+};
+
+
+/*!
+\brief Segment concept (const version)
+\ingroup const_concepts
+\details The ConstSegment concept verifies the same as the Segment concept,
+but does not verify write access.
+*/
+template <typename Geometry>
+class ConstSegment
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename coordinate_type<Geometry>::type coordinate_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point_type>) );
+
+
+ template <size_t Index, size_t Dimension, size_t DimensionCount>
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ const Geometry* s = 0;
+ coordinate_type coord(ggl::get<Index, Dimension>(*s));
+ boost::ignore_unused_variable_warning(coord);
+ dimension_checker<Index, Dimension + 1, DimensionCount>::apply();
+ }
+ };
+
+ template <size_t Index, size_t DimensionCount>
+ struct dimension_checker<Index, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstSegment)
+ {
+ static const size_t n = dimension<point_type>::type::value;
+ dimension_checker<0, 0, n>::apply();
+ dimension_checker<1, 0, n>::apply();
+ }
+#endif
+};
+
+
+}} // namespace ggl::concept
+
+
+#endif // GGL_GEOMETRIES_CONCEPTS_SEGMENT_CONCEPT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/geometries.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/geometries.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,35 @@
+// 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
+
+
+/*!
+\defgroup geometries geometries: geometries provided by default
+\details The GGL can be used with the geometry classes provided by the library,
+and with custom geometries registered by traits classes or registration
+macros.
+
+This documentation page refers to the geometry classes provided by the library.
+
+*/
+
+#include <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/segment.hpp>
+
+#endif // GGL_GEOMETRIES_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/linear_ring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/linear_ring.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,94 @@
+// 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/point_order.hpp>
+
+#include <ggl/geometries/concepts/point_concept.hpp>
+
+
+namespace ggl
+{
+
+/*!
+ \brief A linear_ring (linear linear_ring) is a closed line which should not be selfintersecting
+ \ingroup geometries
+ \tparam P point type
+ \tparam V optional container type, for example std::vector, std::list, std::deque
+ \tparam A optional container-allocator-type
+*/
+template
+<
+ typename P,
+ template<typename, typename> class V = std::vector,
+ bool ClockWise = true,
+ template<typename> class A = std::allocator
+>
+class linear_ring : public V<P, A<P> >
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<P>) );
+};
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename P,
+ template<typename, typename> class V,
+ bool ClockWise,
+ template<typename> class A
+>
+struct tag< linear_ring<P, V, ClockWise, A> >
+{
+ typedef ring_tag type;
+};
+
+
+template
+<
+ typename P,
+ template<typename, typename> class V,
+ template<typename> class A
+>
+struct point_order< linear_ring<P, V, false, A> >
+{
+ static const order_selector value = counterclockwise;
+};
+
+
+template
+<
+ typename P,
+ template<typename, typename> class V,
+ template<typename> class A
+>
+struct point_order< linear_ring<P, V, true, A> >
+{
+ static const order_selector value = clockwise;
+};
+
+
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_LINEAR_RING_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/linestring.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/geometries/concepts/point_concept.hpp>
+
+
+namespace ggl
+{
+
+/*!
+ \brief A linestring (named so by OGC) is a collection (default a vector) of points.
+ \ingroup geometries
+ \tparam P point type
+ \tparam V optional container type, for example std::vector, std::list, std::deque
+ \tparam A optional container-allocator-type
+ (see http://accu.org/index.php/journals/427#ftn.d0e249 )
+ \par Concepts:
+ All algorithms work on ranges, based on a container with point types fulfilling
+ the point concepts. They will take linestring, but also vector, std::pair, or other containers.
+*/
+template
+<
+ typename P,
+ template<typename,typename> class V = std::vector,
+ template<typename> class A = std::allocator
+>
+class linestring : public V<P, A<P> >
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<P>) );
+};
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename P,
+ template<typename,typename> class V,
+ template<typename> class A
+>
+struct tag<linestring<P, V, A> >
+{
+ typedef linestring_tag type;
+};
+} // namespace traits
+
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_LINESTRING_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/point.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/point.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_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 geometries
+ \tparam T numeric type, for example double, float, int
+ \tparam D coordinate dimension as number of coordinates, for example 2
+ \tparam C coordinate system, for example cs::cartesian
+*/
+template<typename T, std::size_t D, typename C>
+class point
+{
+public:
+
+ // Concept typedefs and members
+ typedef T coordinate_type;
+ typedef C coordinate_system;
+
+ static const std::size_t coordinate_count = D;
+
+ /// Default constructor, no initialization at all
+ inline point()
+ {}
+
+ /// Constructs with one, or optionally two or three values
+ inline point(T const& v0, T const& v1 = 0, T const& v2 = 0)
+ {
+ if (D >= 1) m_values[0] = v0;
+ if (D >= 2) m_values[1] = v1;
+ if (D >= 3) m_values[2] = v2;
+ }
+
+
+ /// Compile time access to coordinate values
+ template <std::size_t K>
+ inline T const& get() const
+ {
+ BOOST_STATIC_ASSERT(K < D);
+ return m_values[K];
+ }
+
+ template <std::size_t K>
+ inline void set(T value)
+ {
+ BOOST_STATIC_ASSERT(K < D);
+ m_values[K] = value;
+ }
+
+
+private:
+
+ T m_values[D];
+};
+
+
+// Adapt the point to the concept
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+template
+<
+ typename CoordinateType,
+ std::size_t DimensionCount,
+ typename CoordinateSystem
+>
+struct tag<point<CoordinateType, DimensionCount, CoordinateSystem> >
+{
+ typedef point_tag type;
+};
+
+template
+<
+ typename CoordinateType,
+ std::size_t DimensionCount,
+ typename CoordinateSystem
+>
+struct coordinate_type<point<CoordinateType, DimensionCount, CoordinateSystem> >
+{
+ typedef CoordinateType type;
+};
+
+template
+<
+ typename CoordinateType,
+ std::size_t DimensionCount,
+ typename CoordinateSystem
+>
+struct coordinate_system<point<CoordinateType, DimensionCount, CoordinateSystem> >
+{
+ typedef CoordinateSystem type;
+};
+
+template
+<
+ typename CoordinateType,
+ std::size_t DimensionCount,
+ typename CoordinateSystem
+>
+struct dimension<point<CoordinateType, DimensionCount, CoordinateSystem> >
+ : boost::mpl::int_<DimensionCount>
+{};
+
+template
+<
+ typename CoordinateType,
+ std::size_t DimensionCount,
+ typename CoordinateSystem,
+ std::size_t Dimension
+>
+struct access<point<CoordinateType, DimensionCount, CoordinateSystem>, Dimension>
+{
+ static inline CoordinateType get(
+ point<CoordinateType, DimensionCount, CoordinateSystem> const& p)
+ {
+ return p.template get<Dimension>();
+ }
+
+ static inline void set(
+ point<CoordinateType, DimensionCount, CoordinateSystem>& p,
+ CoordinateType const& value)
+ {
+ p.template set<Dimension>(value);
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_POINT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/point_xy.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/point_xy.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_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 geometries
+ \tparam T numeric type, arguments can be, for example, double, float, int
+*/
+template<typename T, typename C = cs::cartesian>
+class point_xy : public point<T, 2, C>
+{
+public:
+
+ /// Default constructor, does not initialize anything
+ inline point_xy() : point<T, 2, C>() {}
+
+ /// Constructor with x/y values
+ inline point_xy(T const& x, T const& y) : point<T, 2, C>(x, y) {}
+
+ /// Get x-value
+ inline T const& x() const
+ { return this->template get<0>(); }
+
+ /// Get y-value
+ inline T const& y() const
+ { return this->template get<1>(); }
+
+ /// Set x-value
+ inline void x(T const& v)
+ { this->template set<0>(v); }
+
+ /// Set y-value
+ inline void y(T const& v)
+ { this->template set<1>(v); }
+};
+
+// Adapt the point_xy to the concept
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename CoordinateType, typename CoordinateSystem>
+struct tag<point_xy<CoordinateType, CoordinateSystem> >
+{
+ typedef point_tag type;
+};
+
+template<typename CoordinateType, typename CoordinateSystem>
+struct coordinate_type<point_xy<CoordinateType, CoordinateSystem> >
+{
+ typedef CoordinateType type;
+};
+
+template<typename CoordinateType, typename CoordinateSystem>
+struct coordinate_system<point_xy<CoordinateType, CoordinateSystem> >
+{
+ typedef CoordinateSystem type;
+};
+
+template<typename CoordinateType, typename CoordinateSystem>
+struct dimension<point_xy<CoordinateType, CoordinateSystem> >
+ : boost::mpl::int_<2>
+{};
+
+template<typename CoordinateType, typename CoordinateSystem, std::size_t Dimension>
+struct access<point_xy<CoordinateType, CoordinateSystem>, Dimension >
+{
+ static inline CoordinateType get(
+ point_xy<CoordinateType, CoordinateSystem> const& p)
+ {
+ return p.template get<Dimension>();
+ }
+
+ static inline void set(point_xy<CoordinateType, CoordinateSystem>& p,
+ CoordinateType const& value)
+ {
+ p.template set<Dimension>(value);
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_POINT_XY_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/polygon.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/polygon.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_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/geometries/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 geometries
+ \tparam P point type
+ \tparam PointList optional container type for points,
+ for example std::vector, std::list, std::deque
+ \tparam RingList optional container type for inner rings,
+ for example std::vector, std::list, std::deque
+ \tparam ClockWise optional parameter, true for clockwise direction,
+ false for CounterClockWise direction
+ \tparam PointAlloc container-allocator-type
+ \tparam RingAlloc container-allocator-type
+ \note The container collecting the points in the rings can be different
+ from the container collecting the inner rings. They all default to vector.
+*/
+template
+<
+ typename Point,
+ template<typename, typename> class PointList = std::vector,
+ template<typename, typename> class RingList = std::vector,
+ bool ClockWise = true,
+ template<typename> class PointAlloc = std::allocator,
+ template<typename> class RingAlloc = std::allocator
+>
+class polygon
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+public:
+
+ // Member types
+ typedef Point point_type;
+ typedef linear_ring<Point, PointList, ClockWise, PointAlloc> ring_type;
+ typedef RingList<ring_type , RingAlloc<ring_type > > inner_container_type;
+
+ inline ring_type const& outer() const { return m_outer; }
+ inline inner_container_type const& inners() const { return m_inners; }
+
+ inline ring_type& outer() { return m_outer; }
+ inline inner_container_type & inners() { return m_inners; }
+
+ /// Utility method, clears outer and inner rings
+ inline void clear()
+ {
+ m_outer.clear();
+ m_inners.clear();
+ }
+
+private:
+
+ ring_type m_outer;
+ inner_container_type m_inners;
+};
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename Point,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ bool ClockWise,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct tag<polygon<Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc> >
+{
+ typedef polygon_tag type;
+};
+
+template
+<
+ typename Point,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ bool ClockWise,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct ring_type<polygon<Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc> >
+{
+ typedef typename polygon
+ <
+ Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc
+ >::ring_type type;
+};
+
+template
+<
+ typename Point,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ bool ClockWise,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct interior_type< polygon<Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc> >
+{
+ typedef typename polygon
+ <
+ Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc
+ >::inner_container_type type;
+};
+
+template
+<
+ typename Point,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ bool ClockWise,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct exterior_ring< polygon<Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc> >
+{
+ typedef polygon<Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc> polygon_type;
+
+ static inline typename polygon_type::ring_type& get(polygon_type& p)
+ {
+ return p.outer();
+ }
+
+ static inline typename polygon_type::ring_type const & get(polygon_type const& p)
+ {
+ return p.outer();
+ }
+};
+
+template
+<
+ typename Point,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ bool ClockWise,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct interior_rings< polygon<Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc> >
+{
+ typedef polygon<Point, PointList, RingList, ClockWise, PointAlloc, RingAlloc> polygon_type;
+
+ static inline typename polygon_type::inner_container_type& get(
+ polygon_type& p)
+ {
+ return p.inners();
+ }
+
+ static inline typename polygon_type::inner_container_type const& get(
+ polygon_type const& p)
+ {
+ return p.inners();
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_POLYGON_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/register/box.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/register/box.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,124 @@
+// 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
+
+
+#define GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS(Box, Point, MinCorner, MaxCorner) \
+template <size_t D> \
+struct indexed_access<Box, min_corner, D> \
+{ \
+ typedef typename coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) \
+ { return ggl::get<D>(b. MinCorner); } \
+ static inline void set(Box& b, ct const& value) \
+ { ggl::set<D>(b. MinCorner, value); } \
+}; \
+template <size_t D> \
+struct indexed_access<Box, max_corner, D> \
+{ \
+ typedef typename coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) \
+ { return ggl::get<D>(b. MaxCorner); } \
+ static inline void set(Box& b, ct const& value) \
+ { ggl::set<D>(b. MaxCorner, value); } \
+};
+
+
+#define GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_TEMPLATIZED(Box, MinCorner, MaxCorner) \
+template <typename P, size_t D> \
+struct indexed_access<Box<P>, min_corner, D> \
+{ \
+ typedef typename coordinate_type<P>::type ct; \
+ static inline ct get(Box<P> const& b) \
+ { return ggl::get<D>(b. MinCorner); } \
+ static inline void set(Box<P>& b, ct const& value) \
+ { ggl::set<D>(b. MinCorner, value); } \
+}; \
+template <typename P, size_t D> \
+struct indexed_access<Box<P>, max_corner, D> \
+{ \
+ typedef typename coordinate_type<P>::type ct; \
+ static inline ct get(Box<P> const& b) \
+ { return ggl::get<D>(b. MaxCorner); } \
+ static inline void set(Box<P>& b, ct const& value) \
+ { ggl::set<D>(b. MaxCorner, value); } \
+};
+
+
+#define GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_4VALUES(Box, Point, Left, Bottom, Right, Top) \
+template <> struct indexed_access<Box, min_corner, 0> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) { return b. Left; } \
+ static inline void set(Box& b, ct const& value) { b. Left = value; } \
+}; \
+template <> struct indexed_access<Box, min_corner, 1> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) { return b. Bottom; } \
+ static inline void set(Box& b, ct const& value) { b. Bottom = value; } \
+}; \
+template <> struct indexed_access<Box, max_corner, 0> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) { return b. Right; } \
+ static inline void set(Box& b, ct const& value) { b. Right = value; } \
+}; \
+template <> struct indexed_access<Box, max_corner, 1> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) { return b. Top; } \
+ static inline void set(Box& b, ct const& value) { b. Top = value; } \
+};
+
+
+
+
+#define 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. Postponed.
+
+
+#endif // GGL_GEOMETRIES_REGISTER_BOX_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/register/linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/register/linestring.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/geometries/register/point.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/register/point.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,158 @@
+// 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",
+// 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<std::size_t Dimension> struct Point##accessor {};
+
+
+// Non Const version
+#define GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, CoordinateType) \
+ template<std::size_t Dimension> struct access<Point, Dimension> { \
+ static inline CoordinateType get(Point const& p) \
+ { return Point##accessor<Dimension>::get(p); } \
+ static inline void set(Point& p, CoordinateType const& value) \
+ { Point##accessor<Dimension>::set(p, value); } \
+ };
+
+// Const version
+#define GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, CoordinateType) \
+ template<std::size_t Dimension> struct access<Point, Dimension> { \
+ static inline CoordinateType get(Point const& p) \
+ { return Point##accessor<Dimension>::get(p); } \
+ };
+
+
+
+
+// Specialize the point-specific-accessor class, declared below, per dimension
+#define GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR(Point, Dim, CoordinateType, Get, Set) \
+ template<> struct Point##accessor< Dim > \
+ { \
+ static inline CoordinateType get(Point const& p) { return p. Get; } \
+ static inline void set(Point& p, CoordinateType const& value) { p. Set = value; } \
+ };
+
+
+// Const version
+#define GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_CONST(Point, Dim, CoordinateType, Get) \
+ template<> struct Point##accessor< Dim > \
+ { \
+ static inline CoordinateType get(Point const& p) \
+ { return p. Get; } \
+ };
+
+
+// Get/set version
+#define GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESSOR_GET_SET(Point, Dim, CoordinateType, Get, Set) \
+ template<> struct Point##accessor< Dim > \
+ { \
+ static inline CoordinateType get(Point const& p) \
+ { return p. Get (); } \
+ static inline void set(Point& p, CoordinateType const& value) \
+ { p. Set ( value ); } \
+ };
+
+
+
+#define 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/boost/ggl/geometries/register/ring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/register/ring.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/geometries/register/segment.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/register/segment.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,124 @@
+// 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_SEGMENT_HPP
+#define GGL_GEOMETRIES_REGISTER_SEGMENT_HPP
+
+
+#ifndef DOXYGEN_NO_SPECIALIZATIONS
+
+
+#define GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS(Segment, Point, Index0, Index1) \
+template <size_t D> \
+struct indexed_access<Segment, min_corner, D> \
+{ \
+ typedef typename coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) \
+ { return ggl::get<D>(b. Index0); } \
+ static inline void set(Segment& b, ct const& value) \
+ { ggl::set<D>(b. Index0, value); } \
+}; \
+template <size_t D> \
+struct indexed_access<Segment, max_corner, D> \
+{ \
+ typedef typename coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) \
+ { return ggl::get<D>(b. Index1); } \
+ static inline void set(Segment& b, ct const& value) \
+ { ggl::set<D>(b. Index1, value); } \
+};
+
+
+#define GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS_TEMPLATIZED(Segment, Index0, Index1) \
+template <typename P, size_t D> \
+struct indexed_access<Segment<P>, min_corner, D> \
+{ \
+ typedef typename coordinate_type<P>::type ct; \
+ static inline ct get(Segment<P> const& b) \
+ { return ggl::get<D>(b. Index0); } \
+ static inline void set(Segment<P>& b, ct const& value) \
+ { ggl::set<D>(b. Index0, value); } \
+}; \
+template <typename P, size_t D> \
+struct indexed_access<Segment<P>, max_corner, D> \
+{ \
+ typedef typename coordinate_type<P>::type ct; \
+ static inline ct get(Segment<P> const& b) \
+ { return ggl::get<D>(b. Index1); } \
+ static inline void set(Segment<P>& b, ct const& value) \
+ { ggl::set<D>(b. Index1, value); } \
+};
+
+
+#define GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS_4VALUES(Segment, Point, Left, Bottom, Right, Top) \
+template <> struct indexed_access<Segment, min_corner, 0> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) { return b. Left; } \
+ static inline void set(Segment& b, ct const& value) { b. Left = value; } \
+}; \
+template <> struct indexed_access<Segment, min_corner, 1> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) { return b. Bottom; } \
+ static inline void set(Segment& b, ct const& value) { b. Bottom = value; } \
+}; \
+template <> struct indexed_access<Segment, max_corner, 0> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) { return b. Right; } \
+ static inline void set(Segment& b, ct const& value) { b. Right = value; } \
+}; \
+template <> struct indexed_access<Segment, max_corner, 1> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) { return b. Top; } \
+ static inline void set(Segment& b, ct const& value) { b. Top = value; } \
+};
+
+
+
+
+#define GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS(Segment, PointType) \
+ template<> struct tag<Segment > { typedef segment_tag type; }; \
+ template<> struct point_type<Segment > { typedef PointType type; };
+
+#define GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS_TEMPLATIZED(Segment) \
+ template<typename P> struct tag<Segment<P> > { typedef segment_tag type; }; \
+ template<typename P> struct point_type<Segment<P> > { typedef P type; };
+
+#endif // DOXYGEN_NO_SPECIALIZATIONS
+
+
+
+#define GEOMETRY_REGISTER_SEGMENT(Segment, PointType, Index0, Index1) \
+namespace ggl { namespace traits { \
+ GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS(Segment, PointType) \
+ GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS(Segment, PointType, Index0, Index1) \
+}}
+
+
+#define GEOMETRY_REGISTER_SEGMENT_TEMPLATIZED(Segment, Index0, Index1) \
+namespace ggl { namespace traits { \
+ GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS_TEMPLATIZED(Segment) \
+ GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS_TEMPLATIZED(Segment, Index0, Index1) \
+}}
+
+#define GEOMETRY_REGISTER_SEGMENT_2D_4VALUES(Segment, PointType, Left, Bottom, Right, Top) \
+namespace ggl { namespace traits { \
+ GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS(Segment, PointType) \
+ GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS_4VALUES(Segment, PointType, Left, Bottom, Right, Top) \
+}}
+
+
+
+// CONST versions are for segments probably not that common. Postponed.
+
+
+#endif // GGL_GEOMETRIES_REGISTER_SEGMENT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/geometries/segment.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/geometries/segment.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_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/geometries/concepts/point_concept.hpp>
+
+namespace ggl
+{
+
+/*!
+\brief Class segment: small class containing two (templatized) point references
+\ingroup geometries
+\details From Wikipedia: In geometry, a line segment is a part of a line that is bounded
+ by two distinct end points, and contains every point on the line between its end points.
+\note The structure is like std::pair, and can often be used interchangeable.
+Difference is that it refers to points, does not have points.
+\note Like std::pair, points are public available.
+\note type is const or non const, so ggl::segment<P> or ggl::segment<const P>
+\note We cannot derive from std::pair<P&, P&> because of
+reference assignments.
+\tparam ConstOrNonConstPoint point type of the segment, maybe a point or a const point
+*/
+template<typename ConstOrNonConstPoint>
+class segment
+{
+ BOOST_CONCEPT_ASSERT( (
+ typename boost::mpl::if_
+ <
+ boost::is_const<ConstOrNonConstPoint>,
+ concept::Point<ConstOrNonConstPoint>,
+ concept::ConstPoint<ConstOrNonConstPoint>
+ >
+ ) );
+
+ typedef ConstOrNonConstPoint point_type;
+
+public:
+
+ point_type& first;
+ point_type& second;
+
+ inline segment(point_type& p1, point_type& p2)
+ : first(p1)
+ , second(p2)
+ {}
+};
+
+// Traits specializations for segment above
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename ConstOrNonConstPoint>
+struct tag<segment<ConstOrNonConstPoint> >
+{
+ typedef segment_tag type;
+};
+
+template <typename ConstOrNonConstPoint>
+struct point_type<segment<ConstOrNonConstPoint> >
+{
+ typedef ConstOrNonConstPoint type;
+};
+
+template <typename ConstOrNonConstPoint, std::size_t Dimension>
+struct indexed_access<segment<ConstOrNonConstPoint>, 0, Dimension>
+{
+ typedef segment<ConstOrNonConstPoint> segment_type;
+ typedef typename ggl::coordinate_type<segment_type>::type coordinate_type;
+
+ static inline coordinate_type get(segment_type const& s)
+ {
+ return ggl::get<Dimension>(s.first);
+ }
+
+ static inline void set(segment_type& s, coordinate_type const& value)
+ {
+ ggl::set<Dimension>(s.first, value);
+ }
+};
+
+
+template <typename ConstOrNonConstPoint, std::size_t Dimension>
+struct indexed_access<segment<ConstOrNonConstPoint>, 1, Dimension>
+{
+ typedef segment<ConstOrNonConstPoint> segment_type;
+ typedef typename ggl::coordinate_type<segment_type>::type coordinate_type;
+
+ static inline coordinate_type get(segment_type const& s)
+ {
+ return ggl::get<Dimension>(s.second);
+ }
+
+ static inline void set(segment_type& s, coordinate_type const& value)
+ {
+ ggl::set<Dimension>(s.second, value);
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_GEOMETRIES_SEGMENT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/ggl.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/ggl.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,63 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 1995-2009, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008, 2009
+// Copyright (c) 2009 Mateusz Loskot <mateusz_at_[hidden]>
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef GGL_GGL_HPP
+#define GGL_GGL_HPP
+
+// Shortcut to include all header files
+
+
+#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/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/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/simplify.hpp>
+#include <ggl/algorithms/transform.hpp>
+#include <ggl/algorithms/within.hpp>
+
+// check includes all concepts
+#include <ggl/geometries/concepts/check.hpp>
+
+#include <ggl/util/copy.hpp>
+#include <ggl/util/for_each_coordinate.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/boost/ggl/iterators/base.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/iterators/base.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_ITERATORS_BASE_HPP
+#define GGL_ITERATORS_BASE_HPP
+
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+#include <boost/mpl/if.hpp>
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace 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
+
+
+#endif // GGL_ITERATORS_BASE_HPP

Added: sandbox/ggl/formal_review/boost/ggl/iterators/circular_iterator.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/iterators/circular_iterator.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_ITERATORS_CIRCULAR_ITERATOR_HPP
+#define GGL_ITERATORS_CIRCULAR_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 goes circular through a range, starting at a point, ending at that point
+ \tparam Iterator iterator on which this class is based on
+ \ingroup iterators
+*/
+template <typename Iterator>
+struct circular_iterator :
+ public detail::iterators::iterator_base
+ <
+ circular_iterator<Iterator>,
+ Iterator
+ >
+{
+ friend class boost::iterator_core_access;
+
+ explicit inline circular_iterator(Iterator begin, Iterator end, Iterator start)
+ : m_begin(begin)
+ , m_end(end)
+ , m_start(start)
+ {
+ this->base_reference() = start;
+ }
+
+ // Constructor to indicate the end of a range, to enable e.g. std::copy
+ explicit inline circular_iterator(Iterator end)
+ : m_begin(end)
+ , m_end(end)
+ , m_start(end)
+ {
+ this->base_reference() = end;
+ }
+
+ /// Navigate to a certain position, should be in [start .. end], it at end
+ /// it will circle again.
+ inline void moveto(Iterator it)
+ {
+ this->base_reference() = it;
+ check_end();
+ }
+
+private:
+
+ inline void increment()
+ {
+ if (this->base() != m_end)
+ {
+ (this->base_reference())++;
+ check_end();
+ }
+ }
+
+ inline void check_end()
+ {
+ if (this->base() == this->m_end)
+ {
+ this->base_reference() = this->m_begin;
+ }
+
+ if (this->base() == m_start)
+ {
+ this->base_reference() = this->m_end;
+ }
+ }
+
+ Iterator m_begin;
+ Iterator m_end;
+ Iterator m_start;
+};
+
+} // namespace ggl
+
+#endif // GGL_ITERATORS_CIRCULAR_ITERATOR_HPP

Added: sandbox/ggl/formal_review/boost/ggl/iterators/ever_circling_iterator.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/iterators/ever_circling_iterator.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/iterators/range_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/iterators/range_type.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,82 @@
+// Generic Geometry Library
+//
+// 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_ITERATORS_RANGE_TYPE_HPP
+#define GGL_ITERATORS_RANGE_TYPE_HPP
+
+#include <boost/type_traits.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 {
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename GeometryTag, typename Geometry>
+struct range_type
+{
+ // Even if it is not recognized, define itself as a type.
+ // This enables calling range_type over any range
+ // (not necessarily a geometry)
+
+ // Furthermore, applicable for ring/linestring
+ typedef Geometry type;
+};
+
+
+template <typename Geometry>
+struct range_type<point_tag, Geometry>
+{
+ typedef void type;
+};
+
+
+template <typename Geometry>
+struct range_type<polygon_tag, Geometry>
+{
+ typedef typename ring_type<Geometry>::type type;
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+/*!
+\brief Meta-function defining a type which is a boost-range.
+\details
+- For linestrings and rings, it defines the type itself.
+- For polygons it defines the ring type.
+- For multi-points, it defines the type itself
+- For multi-polygons and multi-linestrings, it defines the single-version
+ (so in the end the linestring and ring-type-of-multi-polygon)
+\ingroup iterators
+*/
+template <typename Geometry>
+struct range_type
+{
+ typedef typename dispatch::range_type
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::type type;
+};
+
+
+} // namespace ggl
+
+
+#endif // GGL_ITERATORS_RANGE_TYPE_HPP

Added: sandbox/ggl/formal_review/boost/ggl/iterators/segment_iterator.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/iterators/segment_iterator.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,137 @@
+// 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)
+ {
+ }
+
+ 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/boost/ggl/multi/algorithms/area.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/area.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,47 @@
+// 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, order_selector Order, typename Strategy>
+struct area<multi_polygon_tag, MultiGeometry, Order, Strategy>
+ : detail::multi_sum
+ <
+ typename Strategy::return_type,
+ MultiGeometry,
+ Strategy,
+ area
+ <
+ polygon_tag,
+ typename boost::range_value<MultiGeometry>::type,
+ Order,
+ Strategy
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_ALGORITHMS_AREA_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/algorithms/centroid.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/centroid.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_MULTI_ALGORITHMS_CENTROID_HPP
+#define GGL_MULTI_ALGORITHMS_CENTROID_HPP
+
+#include <ggl/algorithms/centroid.hpp>
+#include <ggl/algorithms/num_points.hpp>
+#include <ggl/multi/core/point_type.hpp>
+#include <ggl/multi/algorithms/detail/multi_sum.hpp>
+#include <ggl/multi/algorithms/num_points.hpp>
+
+
+namespace ggl {
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace centroid {
+
+
+/*!
+ \brief Building block of a multi-point, to be used as Policy in the
+ more generec centroid_multi
+*/
+template
+<
+ typename Point,
+ typename Strategy
+>
+struct centroid_multi_point_state
+{
+ static inline void apply(Point const& point,
+ Strategy const& strategy, typename Strategy::state_type& state)
+ {
+ strategy.apply(point, state);
+ }
+};
+
+
+
+/*!
+ \brief Generic implementation which calls a policy to calculate the
+ centroid of the total of its single-geometries
+ \details The Policy is, in general, the single-version, with state. So
+ detail::centroid::centroid_polygon_state is used as a policy for this
+ detail::centroid::centroid_multi
+
+*/
+template
+<
+ typename Multi,
+ typename Point,
+ typename Strategy,
+ typename Policy
+>
+struct centroid_multi
+{
+ static inline void apply(Multi const& multi, Point& centroid,
+ Strategy const& strategy)
+ {
+ // If there is nothing in any of the ranges, it is not possible
+ // to calculate the centroid
+ if (ggl::num_points(multi) == 0)
+ {
+ throw centroid_exception();
+ }
+
+ typename Strategy::state_type state;
+
+ for (typename boost::range_const_iterator<Multi>::type
+ it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ Policy::apply(*it, strategy, state);
+ }
+ Strategy::result(state, centroid);
+ }
+};
+
+
+
+}} // namespace detail::centroid
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename MultiPolygon,
+ typename Point,
+ typename Strategy
+>
+struct centroid<multi_polygon_tag, MultiPolygon, Point, Strategy>
+ : detail::centroid::centroid_multi
+ <
+ MultiPolygon,
+ Point,
+ Strategy,
+ detail::centroid::centroid_polygon_state
+ <
+ typename boost::range_value<MultiPolygon>::type,
+ Strategy
+ >
+ >
+{};
+
+
+template
+<
+ typename MultiPoint,
+ typename Point,
+ typename Strategy
+>
+struct centroid<multi_point_tag, MultiPoint, Point, Strategy>
+ : detail::centroid::centroid_multi
+ <
+ MultiPoint,
+ Point,
+ Strategy,
+ detail::centroid::centroid_multi_point_state
+ <
+ typename boost::range_value<MultiPoint>::type,
+ Strategy
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_ALGORITHMS_CENTROID_HPP
+

Added: sandbox/ggl/formal_review/boost/ggl/multi/algorithms/convex_hull.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/convex_hull.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,22 @@
+// Generic Geometry Library
+//
+// 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_ALGORITHMS_CONVEX_HULL_HPP
+#define GGL_MULTI_ALGORITHMS_CONVEX_HULL_HPP
+
+
+#include <ggl/multi/iterators/range_type.hpp>
+#include <ggl/multi/util/for_each_range.hpp>
+
+// Note that this file is, furthermore, empty,
+// there is no specialization necessary
+// as this is in fact done by for_each_range
+
+// Might therefore be obsoleted.
+
+
+#endif // GGL_MULTI_ALGORITHMS_CONVEX_HULL_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/algorithms/correct.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/correct.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_CORRECT_HPP
+#define GGL_MULTI_ALGORITHMS_CORRECT_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <ggl/algorithms/correct.hpp>
+
+#include <ggl/multi/core/tags.hpp>
+
+
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace correct {
+
+template <typename MultiPolygon>
+struct correct_multi_polygon
+{
+ static inline void apply(MultiPolygon& mp)
+ {
+ typedef typename boost::range_value<MultiPolygon>::type polygon_type;
+ for (typename boost::range_iterator<MultiPolygon>::type it
+ = boost::begin(mp);
+ it != boost::end(mp);
+ ++it)
+ {
+ correct_polygon<polygon_type>::apply(*it);
+ }
+ }
+};
+
+}} // namespace detail::correct
+#endif
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Geometry>
+struct correct<multi_polygon_tag, Geometry>
+ : detail::correct::correct_multi_polygon<Geometry>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_ALGORITHMS_CORRECT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/algorithms/detail/modify_with_predicate.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/detail/modify_with_predicate.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/multi/algorithms/detail/multi_sum.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/detail/multi_sum.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_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 ReturnType,
+ typename MultiGeometry,
+ typename Strategy,
+ typename Policy
+>
+struct multi_sum
+{
+ static inline ReturnType apply(MultiGeometry const& geometry, Strategy const& strategy)
+ {
+ ReturnType sum = ReturnType();
+ for (typename boost::range_const_iterator
+ <
+ MultiGeometry
+ >::type it = boost::begin(geometry);
+ it != boost::end(geometry);
+ ++it)
+ {
+ sum += Policy::apply(*it, strategy);
+ }
+ return sum;
+ }
+};
+
+
+} // namespace detail
+#endif
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_SUM_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/algorithms/distance.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/distance.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,136 @@
+// 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>
+#include <ggl/util/select_coordinate_type.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());
+
+ for(typename range_const_iterator<MultiGeometry>::type 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/boost/ggl/multi/algorithms/envelope.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/envelope.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_MULTI_ALGORITHMS_ENVELOPE_HPP
+#define GGL_MULTI_ALGORITHMS_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>
+struct envelope_multi_linestring
+{
+ static inline void apply(MultiLinestring const& mp, Box& mbr)
+ {
+ assign_inverse(mbr);
+ for (typename boost::range_const_iterator<MultiLinestring>::type
+ it = mp.begin();
+ it != mp.end();
+ ++it)
+ {
+ envelope_range_additional(*it, mbr);
+ }
+ }
+};
+
+
+// version for multi_polygon: outer linear_ring's of all polygons
+template<typename MultiPolygon, typename Box>
+struct envelope_multi_polygon
+{
+ static inline void apply(MultiPolygon const& mp, Box& mbr)
+ {
+ assign_inverse(mbr);
+ for (typename boost::range_const_iterator<MultiPolygon>::type
+ it = mp.begin();
+ it != mp.end();
+ ++it)
+ {
+ envelope_range_additional(exterior_ring(*it), mbr);
+ }
+ }
+};
+
+
+}} // namespace detail::envelope
+
+#endif
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Multi, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope<multi_point_tag, box_tag, Multi, Box, StrategyLess, StrategyGreater>
+ : detail::envelope::envelope_range<Multi, Box>
+{};
+
+template
+<
+ typename Multi, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope<multi_linestring_tag, box_tag, Multi, Box, StrategyLess, StrategyGreater>
+ : detail::envelope::envelope_multi_linestring<Multi, Box>
+{};
+
+
+template
+<
+ typename Multi, typename Box,
+ typename StrategyLess, typename StrategyGreater
+>
+struct envelope<multi_polygon_tag, box_tag, Multi, Box, StrategyLess, StrategyGreater>
+ : detail::envelope::envelope_multi_polygon<Multi, Box>
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_ALGORITHMS_ENVELOPE_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/algorithms/for_each.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/for_each.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,126 @@
+// Generic Geometry Library
+//
+// 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_ALGORITHMS_FOR_EACH_HPP
+#define GGL_MULTI_ALGORITHMS_FOR_EACH_HPP
+
+
+#include <ggl/multi/core/tags.hpp>
+#include <ggl/multi/core/is_multi.hpp>
+#include <ggl/multi/core/point_type.hpp>
+
+
+#include <ggl/algorithms/for_each.hpp>
+
+
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace for_each {
+
+// Implementation of multi, for both point and segment,
+// just calling the single version.
+template
+<
+ typename MultiGeometry,
+ typename Functor,
+ bool IsConst,
+ typename Policy
+>
+struct for_each_multi
+{
+ static inline Functor apply(
+ typename add_const_if_c<IsConst, MultiGeometry>::type& multi,
+ Functor f)
+ {
+ typedef typename range_iterator_const_if_c
+ <
+ IsConst,
+ MultiGeometry
+ >::type iterator_type;
+
+ for(iterator_type it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ f = Policy::apply(*it, f);
+ }
+ return f;
+ }
+};
+
+
+}} // namespace detail::for_each
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename MultiTag,
+ typename MultiGeometry,
+ typename Functor,
+ bool IsConst
+>
+struct for_each_point<MultiTag, true, MultiGeometry, Functor, IsConst>
+ : detail::for_each::for_each_multi
+ <
+ MultiGeometry,
+ Functor,
+ IsConst,
+ // Specify the dispatch of the single-version as policy
+ for_each_point
+ <
+ typename single_tag<MultiTag>::type,
+ false,
+ typename boost::range_value<MultiGeometry>::type,
+ Functor,
+ IsConst
+ >
+ >
+{};
+
+
+template
+<
+ typename MultiTag,
+ typename MultiGeometry,
+ typename Functor,
+ bool IsConst
+>
+struct for_each_segment<MultiTag, true, MultiGeometry, Functor, IsConst>
+ : detail::for_each::for_each_multi
+ <
+ MultiGeometry,
+ Functor,
+ IsConst,
+ // Specify the dispatch of the single-version as policy
+ for_each_segment
+ <
+ typename single_tag<MultiTag>::type,
+ false,
+ typename boost::range_value<MultiGeometry>::type,
+ Functor,
+ IsConst
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_ALGORITHMS_FOR_EACH_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/algorithms/get_section.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/get_section.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,60 @@
+// 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 boost::range_const_iterator
+ <
+ typename ggl::range_type<MultiPolygon>::type
+ >::type iterator_type;
+
+ static inline void apply(MultiPolygon const& multi_polygon, Section const& section,
+ iterator_type& begin, iterator_type& end)
+ {
+ BOOST_ASSERT(section.multi_index >= 0 && section.multi_index < boost::size(multi_polygon));
+
+ get_section<polygon_tag, typename boost::range_value<MultiPolygon>::type, Section>
+ ::apply(multi_polygon[section.multi_index], section, begin, end);
+
+ }
+};
+
+
+} // namespace dispatch
+#endif
+
+
+
+
+} // namespace ggl
+
+#endif // GGL_MULTI_ALGORITHMS_GET_SECTION_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/algorithms/intersection.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/intersection.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,47 @@
+// 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_inserter
+ <
+ multi_polygon_tag, multi_polygon_tag, polygon_tag,
+ MultiPolygon1, MultiPolygon2,
+ OutputIterator, GeometryOut
+ >
+{
+ // todo: implement this
+};
+
+
+} // namespace dispatch
+#endif
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_ALGORITHMS_INTERSECTION_HPP
+

Added: sandbox/ggl/formal_review/boost/ggl/multi/algorithms/length.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/length.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,45 @@
+// Generic Geometry Library
+//
+// 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_ALGORITHMS_LENGTH_HPP
+#define GGL_MULTI_ALGORITHMS_LENGTH_HPP
+
+#include <ggl/algorithms/length.hpp>
+#include <ggl/multi/core/tags.hpp>
+#include <ggl/multi/algorithms/detail/multi_sum.hpp>
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename MultiLinestring, typename Strategy>
+struct length<multi_linestring_tag, MultiLinestring, Strategy>
+ : detail::multi_sum
+ <
+ typename length_result<MultiLinestring>::type,
+ MultiLinestring,
+ Strategy,
+ detail::length::range_length
+ <
+ typename boost::range_value<MultiLinestring>::type,
+ Strategy
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_ALGORITHMS_LENGTH_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/algorithms/num_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/num_points.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/multi/algorithms/overlay/copy_segments.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/overlay/copy_segments.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/multi/algorithms/overlay/get_intersection_points.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/overlay/get_intersection_points.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/range_type.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/boost/ggl/multi/algorithms/perimeter.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/perimeter.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,47 @@
+// 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_PERIMETER_HPP
+#define GGL_MULTI_ALGORITHMS_PERIMETER_HPP
+
+#include <ggl/algorithms/perimeter.hpp>
+
+#include <ggl/multi/core/tags.hpp>
+
+#include <ggl/multi/algorithms/detail/multi_sum.hpp>
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+template <typename MultiPolygon, typename Strategy>
+struct perimeter<multi_polygon_tag, MultiPolygon, Strategy>
+ : detail::multi_sum
+ <
+ typename length_result<MultiPolygon>::type,
+ MultiPolygon,
+ Strategy,
+ perimeter
+ <
+ polygon_tag,
+ typename boost::range_value<MultiPolygon>::type,
+ Strategy
+ >
+ >
+{};
+
+} // namespace dispatch
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_ALGORITHMS_PERIMETER_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/algorithms/sectionalize.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/sectionalize.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/multi/algorithms/simplify.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/simplify.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,112 @@
+// 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_SIMPLIFY_HPP
+#define GGL_MULTI_ALGORITHMS_SIMPLIFY_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/iterators/range_type.hpp>
+
+#include <ggl/algorithms/simplify.hpp>
+
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace simplify {
+
+template<typename MultiGeometry, typename Strategy, typename Policy>
+struct simplify_multi
+{
+ static inline void apply(MultiGeometry const& multi, MultiGeometry& out,
+ double max_distance, Strategy const& strategy)
+ {
+ out.resize(boost::size(multi));
+
+ typename boost::range_iterator<MultiGeometry>::type it_out
+ = boost::begin(out);
+ for (typename boost::range_const_iterator<MultiGeometry>::type it_in
+ = boost::begin(multi);
+ it_in != boost::end(multi);
+ ++it_in, ++it_out)
+ {
+ Policy::apply(*it_in, *it_out, max_distance, strategy);
+ }
+ }
+};
+
+
+
+}} // namespace detail::simplify
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename MultiPoint, typename Strategy>
+struct simplify<multi_point_tag, MultiPoint, Strategy>
+ : detail::simplify::simplify_copy
+ <
+ MultiPoint,
+ Strategy
+ >
+
+{};
+
+
+template <typename MultiLinestring, typename Strategy>
+struct simplify<multi_linestring_tag, MultiLinestring, Strategy>
+ : detail::simplify::simplify_multi
+ <
+ MultiLinestring,
+ Strategy,
+ detail::simplify::simplify_range
+ <
+ typename boost::range_value<MultiLinestring>::type,
+ Strategy,
+ 2
+ >
+ >
+
+{};
+
+
+template <typename MultiPolygon, typename Strategy>
+struct simplify<multi_polygon_tag, MultiPolygon, Strategy>
+ : detail::simplify::simplify_multi
+ <
+ MultiPolygon,
+ Strategy,
+ detail::simplify::simplify_polygon
+ <
+ typename boost::range_value<MultiPolygon>::type,
+ Strategy
+ >
+ >
+
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_ALGORITHMS_SIMPLIFY_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/algorithms/transform.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/transform.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,93 @@
+// 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, typename Strategy>
+struct transform
+ <
+ multi_polygon_tag, multi_polygon_tag,
+ Multi1, Multi2,
+ Strategy
+ >
+ : detail::transform::transform_multi
+ <
+ Multi1,
+ Multi2,
+ detail::transform::transform_polygon
+ <
+ typename boost::range_value<Multi1>::type,
+ typename boost::range_value<Multi2>::type,
+ Strategy
+ >
+ >
+{};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+} // namespace ggl
+
+#endif // GGL_MULTI_ALGORITHMS_TRANSFORM_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/algorithms/within.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/algorithms/within.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,82 @@
+// 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 <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/algorithms/within.hpp>
+#include <ggl/multi/core/tags.hpp>
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace within {
+
+
+template
+<
+ typename Geometry,
+ typename MultiGeometry,
+ typename Strategy,
+ typename Policy
+>
+struct geometry_in_multi
+{
+ static inline bool apply(Geometry const& geometry,
+ MultiGeometry const& multi,
+ Strategy const& strategy)
+ {
+ for (typename boost::range_const_iterator<MultiGeometry>::type it
+ = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ // Geometry within a multi: true if within one of them
+ if (Policy::apply(geometry, *it, strategy))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+}} // namespace detail::within
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Point, typename MultiPolygon, typename Strategy>
+struct within<point_tag, multi_polygon_tag, Point, MultiPolygon, Strategy>
+ : detail::within::geometry_in_multi
+ <
+ Point,
+ MultiPolygon,
+ Strategy,
+ detail::within::point_in_polygon
+ <
+ Point,
+ typename boost::range_value<MultiPolygon>::type,
+ Strategy
+ >
+ >
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+} // namespace ggl
+
+#endif // GGL_MULTI_ALGORITHMS_WITHIN_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/core/geometry_id.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/core/geometry_id.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/multi/core/is_multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/core/is_multi.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/multi/core/point_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/core/point_type.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/multi/core/ring_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/core/ring_type.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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/boost/ggl/multi/core/tags.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/core/tags.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_MULTI_CORE_TAGS_HPP
+#define GGL_MULTI_CORE_TAGS_HPP
+
+#include <ggl/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 {};
+
+
+
+
+/*!
+ \brief Meta-function to get for a tag of a multi-geometry
+ the tag of the corresponding single-geometry
+*/
+template <typename Tag>
+struct single_tag
+{};
+
+#ifndef DOXYGEN_NO_DETAIL
+
+template <>
+struct single_tag<multi_point_tag>
+{
+ typedef point_tag type;
+};
+
+template <>
+struct single_tag<multi_linestring_tag>
+{
+ typedef linestring_tag type;
+};
+
+template <>
+struct single_tag<multi_polygon_tag>
+{
+ typedef polygon_tag type;
+};
+
+#endif
+
+
+} // namespace ggl
+
+#endif // GGL_MULTI_CORE_TAGS_HPP

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

Added: sandbox/ggl/formal_review/boost/ggl/multi/geometries/concepts/multi_linestring_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/geometries/concepts/multi_linestring_concept.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_MULTI_GEOMETRIES_CONCEPTS_MULTI_LINESTRING_CONCEPT_HPP
+#define GGL_MULTI_GEOMETRIES_CONCEPTS_MULTI_LINESTRING_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <ggl/geometries/concepts/linestring_concept.hpp>
+
+
+namespace ggl { namespace concept {
+
+
+/*!
+\brief multi-linestring concept
+\ingroup concepts
+\par Formal definition:
+The multi linestring concept is defined as following:
+- there must be a specialization of traits::tag defining multi_linestring_tag as
+ type
+- it must behave like a Boost.Range
+- its range value must fulfil the Linestring concept
+
+*/
+template <typename Geometry>
+class MultiLinestring
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type linestring_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Linestring<linestring_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(MultiLinestring)
+ {
+ }
+#endif
+};
+
+
+/*!
+\brief concept for multi-linestring (const version)
+\ingroup const_concepts
+*/
+template <typename Geometry>
+class ConstMultiLinestring
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type linestring_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstLinestring<linestring_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstMultiLinestring)
+ {
+ }
+#endif
+};
+
+}} // namespace ggl::concept
+
+
+#endif // GGL_MULTI_GEOMETRIES_CONCEPTS_MULTI_LINESTRING_CONCEPT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/geometries/concepts/multi_point_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/geometries/concepts/multi_point_concept.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,79 @@
+// 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_CONCEPTS_MULTI_POINT_CONCEPT_HPP
+#define GGL_MULTI_GEOMETRIES_CONCEPTS_MULTI_POINT_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <ggl/geometries/concepts/point_concept.hpp>
+
+
+namespace ggl { namespace concept {
+
+
+/*!
+\brief MultiPoint concept
+\ingroup concepts
+\par Formal definition:
+The multi point concept is defined as following:
+- there must be a specialization of traits::tag defining multi_point_tag as type
+- it must behave like a Boost.Range
+- its range value must fulfil the Point concept
+
+*/
+template <typename Geometry>
+class MultiPoint
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Point<point_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(MultiPoint)
+ {
+ }
+#endif
+};
+
+
+/*!
+\brief concept for multi-point (const version)
+\ingroup const_concepts
+*/
+template <typename Geometry>
+class ConstMultiPoint
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstMultiPoint)
+ {
+ }
+#endif
+};
+
+}} // namespace ggl::concept
+
+
+#endif // GGL_MULTI_GEOMETRIES_CONCEPTS_MULTI_POINT_CONCEPT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/geometries/concepts/multi_polygon_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/geometries/concepts/multi_polygon_concept.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_MULTI_GEOMETRIES_CONCEPTS_MULTI_POLYGON_CONCEPT_HPP
+#define GGL_MULTI_GEOMETRIES_CONCEPTS_MULTI_POLYGON_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <ggl/geometries/concepts/polygon_concept.hpp>
+
+
+namespace ggl { namespace concept {
+
+
+/*!
+\brief multi-polygon concept
+\ingroup concepts
+\par Formal definition:
+The multi polygon concept is defined as following:
+- there must be a specialization of traits::tag defining multi_polygon_tag
+ as type
+- it must behave like a Boost.Range
+- its range value must fulfil the Polygon concept
+
+*/
+template <typename Geometry>
+class MultiPolygon
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type polygon_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Polygon<polygon_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(MultiPolygon)
+ {
+ }
+#endif
+};
+
+
+/*!
+\brief concept for multi-polygon (const version)
+\ingroup const_concepts
+*/
+template <typename Geometry>
+class ConstMultiPolygon
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type polygon_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPolygon<polygon_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstMultiPolygon)
+ {
+ }
+#endif
+};
+
+}} // namespace ggl::concept
+
+
+#endif // GGL_MULTI_GEOMETRIES_CONCEPTS_MULTI_POLYGON_CONCEPT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/geometries/multi_linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/geometries/multi_linestring.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,63 @@
+// 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_LINESTRING_HPP
+#define GGL_MULTI_GEOMETRIES_LINESTRING_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/requires.hpp>
+
+#include <ggl/geometries/concepts/linestring_concept.hpp>
+
+#include <ggl/multi/core/tags.hpp>
+
+namespace ggl
+{
+
+/*!
+ \brief multi_line, a collection of linestring
+ \details Multi-linestring can be used to group lines belonging to each other,
+ e.g. a highway (with interruptions)
+ \ingroup geometries
+*/
+template
+<
+ typename L,
+ template<typename, typename> class V = std::vector,
+ template<typename> class A = std::allocator
+>
+struct multi_linestring : public V<L, A<L> >
+{
+ BOOST_CONCEPT_ASSERT( (concept::Linestring<L>) );
+};
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename L,
+ template<typename, typename> class V,
+ template<typename> class A
+>
+struct tag< multi_linestring<L, V, A> >
+{
+ typedef multi_linestring_tag type;
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+} // namespace ggl
+
+#endif // GGL_MULTI_GEOMETRIES_LINESTRING_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/geometries/multi_point.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/geometries/multi_point.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_MULTI_GEOMETRIES_MULTI_POINT_HPP
+#define GGL_MULTI_GEOMETRIES_MULTI_POINT_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/requires.hpp>
+
+#include <ggl/geometries/concepts/point_concept.hpp>
+
+#include <ggl/multi/core/tags.hpp>
+
+namespace ggl
+{
+
+/*!
+ \brief multi_point, a collection of points
+ \details Multipoint can be used to group points belonging to each other,
+ e.g. a constellation
+ \ingroup geometries
+*/
+template
+<
+ typename P,
+ template<typename, typename> class V = std::vector,
+ template<typename> class A = std::allocator
+>
+struct multi_point : public V<P, A<P> >
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<P>) );
+};
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename P,
+ template<typename, typename> class V,
+ template<typename> class A
+>
+struct tag< multi_point<P, V, A> >
+{
+ typedef multi_point_tag type;
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_MULTI_GEOMETRIES_MULTI_POINT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/geometries/multi_polygon.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/geometries/multi_polygon.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_MULTI_GEOMETRIES_MULTI_POLYGON_HPP
+#define GGL_MULTI_GEOMETRIES_MULTI_POLYGON_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/requires.hpp>
+
+#include <ggl/multi/core/tags.hpp>
+
+#include <ggl/geometries/concepts/polygon_concept.hpp>
+
+namespace ggl
+{
+
+/*!
+ \brief multi_polygon, a collection of linestring
+ \details Multi-polygon can be used to group polygons belonging to each other,
+ e.g. Hawaii
+ \ingroup geometries
+*/
+template
+<
+ typename P,
+ template<typename, typename> class V = std::vector,
+ template<typename> class A = std::allocator
+>
+struct multi_polygon : public V<P, A<P> >
+{
+ BOOST_CONCEPT_ASSERT( (concept::Polygon<P>) );
+};
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename P,
+ template<typename, typename> class V,
+ template<typename> class A
+>
+struct tag< multi_polygon<P, V, A> >
+{
+ typedef multi_polygon_tag type;
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+} // namespace ggl
+
+#endif // GGL_MULTI_GEOMETRIES_MULTI_POLYGON_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/iterators/range_type.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/iterators/range_type.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,57 @@
+// Generic Geometry Library
+//
+// 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_ITERATORS_RANGE_TYPE_HPP
+#define GGL_MULTI_ITERATORS_RANGE_TYPE_HPP
+
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/multi/core/is_multi.hpp>
+
+#include <ggl/iterators/range_type.hpp>
+
+namespace ggl {
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// multi-point acts itself as a range
+template <typename Geometry>
+struct range_type<multi_point_tag, Geometry>
+{
+ typedef Geometry type;
+};
+
+
+template <typename Geometry>
+struct range_type<multi_linestring_tag, Geometry>
+{
+ typedef typename boost::range_value<Geometry>::type type;
+};
+
+
+template <typename Geometry>
+struct range_type<multi_polygon_tag, Geometry>
+{
+ // Call its single-version
+ typedef typename ggl::ring_type
+ <
+ typename boost::range_value<Geometry>::type
+ >::type type;
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+} // namespace ggl
+
+#endif // GGL_MULTI_ITERATORS_RANGE_TYPE_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/multi.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/multi.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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
+// Copyright Mateusz Loskot 2009
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef GGL_MULTI_HPP
+#define GGL_MULTI_HPP
+
+
+#include <ggl/multi/core/geometry_id.hpp>
+#include <ggl/multi/core/is_multi.hpp>
+#include <ggl/multi/core/point_type.hpp>
+#include <ggl/multi/core/ring_type.hpp>
+#include <ggl/multi/core/tags.hpp>
+#include <ggl/multi/core/topological_dimension.hpp>
+
+
+#include <ggl/multi/algorithms/area.hpp>
+#include <ggl/multi/algorithms/centroid.hpp>
+#include <ggl/multi/algorithms/convex_hull.hpp>
+#include <ggl/multi/algorithms/correct.hpp>
+#include <ggl/multi/algorithms/distance.hpp>
+#include <ggl/multi/algorithms/envelope.hpp>
+#include <ggl/multi/algorithms/for_each.hpp>
+#include <ggl/multi/algorithms/get_section.hpp>
+#include <ggl/multi/algorithms/intersection.hpp>
+#include <ggl/multi/algorithms/length.hpp>
+#include <ggl/multi/algorithms/num_points.hpp>
+#include <ggl/multi/algorithms/perimeter.hpp>
+#include <ggl/multi/algorithms/sectionalize.hpp>
+#include <ggl/multi/algorithms/simplify.hpp>
+#include <ggl/multi/algorithms/transform.hpp>
+#include <ggl/multi/algorithms/within.hpp>
+#include <ggl/multi/algorithms/detail/modify_with_predicate.hpp>
+#include <ggl/multi/algorithms/detail/multi_sum.hpp>
+#include <ggl/multi/algorithms/overlay/copy_segments.hpp>
+#include <ggl/multi/algorithms/overlay/get_intersection_points.hpp>
+
+
+#include <ggl/multi/geometries/multi_point.hpp>
+#include <ggl/multi/geometries/multi_linestring.hpp>
+#include <ggl/multi/geometries/multi_polygon.hpp>
+#include <ggl/multi/geometries/concepts/check.hpp>
+#include <ggl/multi/geometries/concepts/multi_point_concept.hpp>
+#include <ggl/multi/geometries/concepts/multi_linestring_concept.hpp>
+#include <ggl/multi/geometries/concepts/multi_polygon_concept.hpp>
+
+#include <ggl/multi/iterators/range_type.hpp>
+
+#include <ggl/multi/strategies/centroid.hpp>
+#include <ggl/multi/strategies/cartesian/centroid_average.hpp>
+
+#include <ggl/multi/util/write_dsv.hpp>
+
+
+
+#endif // GGL_MULTI_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/strategies/cartesian/centroid_average.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/strategies/cartesian/centroid_average.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,96 @@
+// 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_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP
+#define GGL_MULTI_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP
+
+
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/type_traits.hpp>
+
+#include <ggl/core/coordinate_type.hpp>
+#include <ggl/core/point_type.hpp>
+#include <ggl/arithmetic/arithmetic.hpp>
+#include <ggl/strategies/centroid.hpp>
+#include <ggl/util/copy.hpp>
+
+
+namespace ggl
+{
+
+namespace strategy { namespace centroid_ {
+
+
+template
+<
+ typename PointCentroid,
+ typename Point = PointCentroid
+>
+class centroid_average
+{
+private :
+
+ /*! subclass to keep state */
+ class sum
+ {
+ friend class centroid_average;
+ int count;
+ PointCentroid centroid;
+
+ public :
+ inline sum()
+ : count(0)
+ {
+ assign_zero(centroid);
+ }
+ };
+
+public :
+ typedef sum state_type;
+ typedef PointCentroid centroid_point_type;
+ typedef Point point_type;
+
+ static inline void apply(Point const& p, sum& state)
+ {
+ add_point(state.centroid, p);
+ state.count++;
+ }
+
+ static inline void result(sum const& state, PointCentroid& centroid)
+ {
+ centroid = state.centroid;
+ divide_value(centroid, state.count);
+ }
+
+};
+
+
+}} // namespace strategy::centroid
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+
+template <typename Point, typename Geometry>
+struct strategy_centroid<cartesian_tag, multi_point_tag, 2, Point, Geometry>
+{
+ typedef strategy::centroid_::centroid_average
+ <
+ Point,
+ typename point_type<Geometry>::type
+ > type;
+};
+
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/strategies/centroid.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/strategies/centroid.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_MULTI_STRATEGY_CENTROID_HPP
+#define GGL_MULTI_STRATEGY_CENTROID_HPP
+
+#include <ggl/strategies/cartesian/centroid_bashein_detmer.hpp>
+
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+template <typename Point, typename Geometry>
+struct strategy_centroid<cartesian_tag, multi_polygon_tag, 2, Point, Geometry>
+{
+ typedef strategy::centroid_::bashein_detmer
+ <
+ Point,
+ typename point_type<Geometry>::type
+ > type;
+};
+
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_STRATEGY_CENTROID_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/util/for_each_range.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/util/for_each_range.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_UTIL_FOR_EACH_RANGE_HPP
+#define GGL_MULTI_UTIL_FOR_EACH_RANGE_HPP
+
+
+#include <ggl/util/for_each_range.hpp>
+#include <ggl/util/range_iterator_const_if_c.hpp>
+
+#include <ggl/multi/core/tags.hpp>
+
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace for_each {
+
+
+template <typename Multi, typename Actor, bool IsConst>
+struct fe_range_multi
+{
+ static inline void apply(
+ typename add_const_if_c<IsConst, Multi>::type& multi,
+ Actor& actor)
+ {
+ for (typename range_iterator_const_if_c<IsConst, Multi>::type
+ it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ ggl::for_each_range(*it, actor);
+ }
+ }
+};
+
+
+
+}} // namespace detail::for_each
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Geometry, typename Actor, bool IsConst>
+struct for_each_range<multi_linestring_tag, true, Geometry, Actor, IsConst>
+ : detail::for_each::fe_range_multi<Geometry, Actor, IsConst>
+{};
+
+
+template <typename Geometry, typename Actor, bool IsConst>
+struct for_each_range<multi_polygon_tag, true, Geometry, Actor, IsConst>
+ : detail::for_each::fe_range_multi<Geometry, Actor, IsConst>
+{};
+
+
+template <typename MultiPoint, typename Actor, bool IsConst>
+struct for_each_range<multi_point_tag, true, MultiPoint, Actor, IsConst>
+ : detail::for_each::fe_range_range<MultiPoint, Actor, IsConst>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+} // namespace ggl
+
+
+#endif // GGL_MULTI_UTIL_FOR_EACH_RANGE_HPP

Added: sandbox/ggl/formal_review/boost/ggl/multi/util/write_dsv.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/multi/util/write_dsv.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_MULTI_UTIL_WRITE_DSV_HPP
+#define GGL_MULTI_UTIL_WRITE_DSV_HPP
+
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <ggl/util/write_dsv.hpp>
+
+namespace ggl
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace dsv {
+
+
+template <typename MultiGeometry>
+struct dsv_multi
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ MultiGeometry const& multi,
+ dsv_settings const& settings)
+ {
+ os << settings.list_open;
+
+ typedef typename boost::range_const_iterator
+ <
+ MultiGeometry
+ >::type iterator;
+ for(iterator it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ os << ggl::dsv(*it);
+ }
+ os << settings.list_close;
+ }
+};
+
+
+
+
+}} // namespace detail::dsv
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+
+template <typename Tag, typename Geometry>
+struct dsv<Tag, true, Geometry>
+ : detail::dsv::dsv_multi<Geometry>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+} // namespace ggl
+
+#endif // GGL_MULTI_UTIL_WRITE_DSV_HPP

Added: sandbox/ggl/formal_review/boost/ggl/policies/compare.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/policies/compare.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,246 @@
+// Generic Geometry Library
+//
+// Copyright Barend Gehrels 2009, Geodan, Amsterdam, the Netherlands.
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef GGL_POLICIES_COMPARE_HPP
+#define GGL_POLICIES_COMPARE_HPP
+
+
+/*!
+\defgroup compare compare: define compare functors for points
+\details Useful for:
+- std::map (use ggl::less<P>)
+- std::sort (use ggl::less<P> or ggl::greater<P> or ggl::less<P, 1>)
+- std::unique_copy (use ggl::equals<P>)
+
+\par Geometries:
+- \b point
+*/
+
+#include <ggl/strategies/compare.hpp>
+#include <ggl/util/math.hpp>
+
+namespace ggl
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace compare {
+
+
+template
+<
+ int Direction,
+ typename Point,
+ typename Strategy,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct compare_loop
+{
+ typedef typename strategy::compare::detail::select_strategy
+ <
+ Strategy, Direction, Point, Dimension
+ >::type compare_type;
+
+ typedef typename ggl::coordinate_type<Point>::type coordinate_type;
+
+ static inline bool apply(Point const& left, Point const& right)
+ {
+ coordinate_type const& cleft = ggl::get<Dimension>(left);
+ coordinate_type const& cright = ggl::get<Dimension>(right);
+
+ if (ggl::math::equals(cleft, cright))
+ {
+ return compare_loop
+ <
+ Direction, Point, Strategy,
+ Dimension + 1, DimensionCount
+ >::apply(left, right);
+ }
+ else
+ {
+ compare_type compare;
+ return compare(cleft, cright);
+ }
+ }
+};
+
+template
+<
+ int Direction,
+ typename Point,
+ typename Strategy,
+ std::size_t DimensionCount
+>
+struct compare_loop<Direction, Point, Strategy, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Point const&, Point const&)
+ {
+ return false;
+ }
+};
+
+
+template <int Direction, typename Point, typename Strategy>
+struct compare_in_all_dimensions
+{
+ inline bool operator()(Point const& left, Point const& right) const
+ {
+ return detail::compare::compare_loop
+ <
+ Direction, Point, Strategy,
+ 0, ggl::dimension<Point>::type::value
+ >::apply(left, right);
+ }
+};
+
+
+template
+<
+ typename Point,
+ typename Strategy,
+ std::size_t Dimension
+>
+class compare_in_one_dimension
+{
+ Strategy compare;
+
+public :
+ inline bool operator()(Point const& left, Point const& right) const
+ {
+ typedef typename ggl::coordinate_type<Point>::type coordinate_type;
+
+ coordinate_type const& cleft = get<Dimension>(left);
+ coordinate_type const& cright = get<Dimension>(right);
+ return compare(cleft, cright);
+ }
+};
+
+}} // namespace detail::compare
+
+#endif
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ int Direction,
+ typename Point,
+ typename Strategy,
+ int Dimension
+>
+struct compare_geometries
+ : detail::compare::compare_in_one_dimension
+ <
+ Point,
+ typename strategy::compare::detail::select_strategy
+ <
+ Strategy, Direction, Point, Dimension
+ >::type,
+ Dimension
+ >
+{};
+
+
+// Specialization with -1: compare in all dimensions
+template <int Direction, typename Point, typename Strategy>
+struct compare_geometries<Direction, Point, Strategy, -1>
+ : detail::compare::compare_in_all_dimensions<Direction, Point, Strategy>
+{};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Less functor, to sort points in ascending order.
+\ingroup compare
+\details This functor compares points and orders them on x,
+ then on y, then on z coordinate.
+\tparam Geometry the geometry
+\tparam Dimension the dimension to sort on, defaults to -1,
+ indicating ALL dimensions. That's to say, first on x,
+ on equal x-es then on y, etc.
+ If a dimension is specified, only that dimension is considered
+\tparam Strategy underlying coordinate comparing functor,
+ defaults to the default comparison strategies
+ related to the point coordinate system. If specified, the specified
+ strategy is used. This can e.g. be std::less<double>.
+*/
+template
+<
+ typename Point,
+ int Dimension = -1,
+ typename Strategy = strategy::compare::default_strategy
+>
+struct less
+ : dispatch::compare_geometries
+ <
+ 1, // indicates ascending
+ Point,
+ Strategy,
+ Dimension
+ >
+{};
+
+
+/*!
+\brief Greater functor
+\ingroup compare
+\details Can be used to sort points in reverse order
+\see Less functor
+*/
+template
+<
+ typename Point,
+ int Dimension = -1,
+ typename Strategy = strategy::compare::default_strategy
+>
+struct greater
+ : dispatch::compare_geometries
+ <
+ -1, // indicates descending
+ Point,
+ Strategy,
+ Dimension
+ >
+{};
+
+
+/*!
+\brief Equal To functor, to compare if points are equal
+\ingroup compare
+\tparam Geometry the geometry
+\tparam Dimension the dimension to compare on, defaults to -1,
+ indicating ALL dimensions.
+ If a dimension is specified, only that dimension is considered
+\tparam Strategy underlying coordinate comparing functor
+*/
+template
+<
+ typename Point,
+ int Dimension = 0,
+ typename Strategy = strategy::compare::default_strategy
+>
+struct equal_to
+ : dispatch::compare_geometries
+ <
+ 0,
+ Point,
+ Strategy,
+ Dimension
+ >
+{};
+
+
+} // namespace ggl
+
+#endif // GGL_POLICIES_COMPARE_HPP

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

Added: sandbox/ggl/formal_review/boost/ggl/strategies/agnostic/point_in_poly_winding.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/strategies/agnostic/point_in_poly_winding.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
+#define GGL_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
+
+
+
+#include <ggl/util/select_calculation_type.hpp>
+
+#include <ggl/strategies/point_in_poly.hpp>
+
+
+
+namespace ggl
+{
+
+namespace strategy { namespace within {
+
+/*!
+ \brief Within detection using winding rule
+ \tparam Point point type of point to examine
+ \tparam PointOfSegment point type of segments, defaults to Point
+ \author Barend Gehrels
+ \note The implementation is inspired by terralib http://www.terralib.org (LGPL)
+ \note but totally revised afterwards, especially for cases on segments
+ \note Only dependant on "side", -> agnostic, suitable for spherical/latlong
+ */
+template
+<
+ typename Point,
+ typename PointOfSegment = Point,
+ typename CalculationType = void
+>
+class winding
+{
+ typedef typename select_calculation_type
+ <
+ Point,
+ PointOfSegment,
+ CalculationType
+ >::type calculation_type;
+
+
+ typedef typename strategy_side
+ <
+ typename cs_tag<Point>::type
+ >::type strategy_side_type;
+
+
+ /*! subclass to keep state */
+ class counter
+ {
+ int count;
+ bool touches;
+
+ inline bool within_no_touch() const
+ {
+ return ! touches && count != 0;
+ }
+ public :
+ friend class winding;
+
+ inline counter()
+ : count(0)
+ , touches(false)
+ {}
+
+ };
+
+
+ template <size_t D>
+ static inline int check_touch(Point const& point,
+ PointOfSegment const& seg1, PointOfSegment const& seg2,
+ counter& state)
+ {
+ calculation_type const p = get<D>(point);
+ calculation_type const s1 = get<D>(seg1);
+ calculation_type const s2 = get<D>(seg2);
+ if ((s1 <= p && s2 >= p) || (s2 <= p && s1 >= p))
+ {
+ state.touches = true;
+ }
+ return 0;
+ }
+
+
+ template <size_t D>
+ static inline int check_segment(Point const& point,
+ PointOfSegment const& seg1, PointOfSegment const& seg2,
+ counter& state)
+ {
+ calculation_type const p = get<D>(point);
+ calculation_type const s1 = get<D>(seg1);
+ calculation_type const s2 = get<D>(seg2);
+
+ // Check if one of segment endpoints is at same level of point
+ bool eq1 = math::equals(s1, p);
+ bool eq2 = math::equals(s2, p);
+
+ if (eq1 && eq2)
+ {
+ // Both equal p -> segment is horizontal (or vertical for D=0)
+ // The only thing which has to be done is check if point is ON segment
+ return check_touch<1 - D>(point, seg1, seg2,state);
+ }
+
+ return
+ eq1 ? (s2 > p ? 1 : -1) // Point on level s1, UP/DOWN depending on s2
+ : eq2 ? (s1 > p ? -1 : 1) // idem
+ : s1 < p && s2 > p ? 2 // Point between s1 -> s2 --> UP
+ : s2 < p && s1 > p ? -2 // Point between s2 -> s1 --> DOWN
+ : 0;
+ }
+
+
+
+
+public :
+
+ // Typedefs and static methods to fulfill the concept
+ typedef Point point_type;
+ typedef PointOfSegment segment_point_type;
+ typedef counter state_type;
+
+ static inline bool apply(Point const& point,
+ PointOfSegment const& s1, PointOfSegment const& s2,
+ counter& state)
+ {
+ int count = check_segment<1>(point, s1, s2, state);
+ if (count != 0)
+ {
+ int side = strategy_side_type::apply(s1, s2, point);
+ if (side == 0)
+ {
+ // Point is lying on segment
+ state.touches = true;
+ state.count = 0;
+ return false;
+ }
+
+ // Side is NEG for right, POS for left.
+ // The count is -2 for down, 2 for up (or -1/1)
+ // Side positive thus means UP and LEFTSIDE or DOWN and RIGHTSIDE
+ // See accompagnying figure (TODO)
+ if (side * count > 0)
+ {
+ state.count += count;
+ }
+
+ }
+ return ! state.touches;
+ }
+
+ static inline bool result(counter const& state)
+ {
+ return state.within_no_touch();
+ }
+};
+
+}} // namespace strategy::within
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+template <typename Point, typename PointOfSegment>
+struct strategy_within<cartesian_tag, cartesian_tag, Point, PointOfSegment>
+{
+ typedef strategy::within::winding<Point, PointOfSegment> type;
+};
+
+template <typename Point, typename PointOfSegment>
+struct strategy_within<geographic_tag, geographic_tag, Point, PointOfSegment>
+{
+ typedef strategy::within::winding<Point, PointOfSegment> type;
+};
+
+#endif
+
+
+} // namespace ggl
+
+
+#endif // GGL_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP

Added: sandbox/ggl/formal_review/boost/ggl/strategies/agnostic/simplify_douglas_peucker.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/strategies/agnostic/simplify_douglas_peucker.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,216 @@
+// 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_DOUGLAS_PEUCKER_HPP
+#define GGL_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP
+
+#include <vector>
+#include <boost/range/functions.hpp>
+
+#include <ggl/core/cs.hpp>
+#include <ggl/strategies/distance_result.hpp>
+#include <ggl/util/copy.hpp>
+
+
+//#define GL_DEBUG_DOUGLAS_PEUCKER
+
+#ifdef GL_DEBUG_DOUGLAS_PEUCKER
+#include <ggl/util/write_dsv.hpp>
+#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
+ It has a const-reference to the original point (so no copy here)
+ \tparam the enclosed point type
+ */
+ template<typename Point>
+ struct douglas_peucker_point
+ {
+ Point const& p;
+ bool included;
+
+ inline douglas_peucker_point(Point const& ap)
+ : p(ap)
+ , included(false)
+ {}
+
+ // Necessary for proper compilation
+ inline douglas_peucker_point<Point> operator=(
+ douglas_peucker_point<Point> const& other)
+ {
+ return douglas_peucker_point<Point>(*this);
+ }
+ };
+}
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief Implements the simplify algorithm.
+ \ingroup simplify
+ \details The douglas_peucker strategy simplifies a linestring, ring or
+ vector of points using the well-known Douglas-Peucker algorithm.
+ For the algorithm, see for example:
+ \see http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
+ \see http://www2.dcs.hull.ac.uk/CISRG/projects/Royal-Inst/demos/dp.html
+ \tparam Point the point type
+ \tparam PointDistanceStrategy point-segment distance strategy to be used
+ \note This strategy uses itself a point-segment-distance strategy which
+ can be specified
+ \author Barend and Maarten, 1995/1996
+ \author Barend, revised for Generic Geometry Library, 2008
+*/
+template
+<
+ typename Point,
+ typename PointDistanceStrategy
+>
+class douglas_peucker
+{
+ typedef detail::douglas_peucker_point<Point> dp_point_type;
+ typedef typename std::vector<dp_point_type>::iterator iterator_type;
+
+ typedef typename PointDistanceStrategy::return_type return_type;
+
+ static inline void consider(iterator_type begin,
+ iterator_type end,
+ return_type const& max_dist, int& n,
+ PointDistanceStrategy const& ps_distance_strategy)
+ {
+ std::size_t size = end - begin;
+
+ // size must be at least 3
+ // because we want to consider a candidate point in between
+ if (size <= 2)
+ {
+#ifdef GL_DEBUG_DOUGLAS_PEUCKER
+ if (begin != end)
+ {
+ std::cout << "ignore between " << dsv(begin->p)
+ << " and " << dsv((end - 1)->p)
+ << " size=" << size << std::endl;
+ }
+ std::cout << "return because size=" << size << std::endl;
+#endif
+ return;
+ }
+
+ iterator_type last = end - 1;
+
+#ifdef GL_DEBUG_DOUGLAS_PEUCKER
+ std::cout << "find between " << dsv(begin->p)
+ << " and " << dsv(last->p)
+ << " size=" << size << std::endl;
+#endif
+
+
+ // Find most distance point, compare to the current segment
+ //ggl::segment<const Point> s(begin->p, last->p);
+ return_type md(-1.0); // any value < 0
+ iterator_type candidate;
+ for(iterator_type it = begin + 1; it != last; ++it)
+ {
+ return_type dist = ps_distance_strategy.apply(it->p, begin->p, last->p);
+
+#ifdef GL_DEBUG_DOUGLAS_PEUCKER
+ std::cout << "consider " << dsv(it->p)
+ << " at " << double(dist)
+ << ((dist > max_dist) ? " maybe" : " no")
+ << std::endl;
+
+#endif
+ if (dist > md)
+ {
+ md = dist;
+ candidate = it;
+ }
+ }
+
+ // If a point is found, set the include flag
+ // and handle segments in between recursively
+ if (md > max_dist)
+ {
+#ifdef GL_DEBUG_DOUGLAS_PEUCKER
+ std::cout << "use " << dsv(candidate->p) << std::endl;
+#endif
+
+ candidate->included = true;
+ n++;
+
+ consider(begin, candidate + 1, max_dist, n, ps_distance_strategy);
+ consider(candidate, end, max_dist, n, ps_distance_strategy);
+ }
+ }
+
+
+public :
+
+ typedef PointDistanceStrategy distance_strategy_type;
+
+
+ template <typename Range, typename OutputIterator>
+ static inline OutputIterator apply(Range const& range,
+ OutputIterator out, double max_distance)
+ {
+ PointDistanceStrategy strategy;
+
+ // Copy coordinates, a vector of references to all points
+ std::vector<dp_point_type> ref_candidates(boost::begin(range),
+ boost::end(range));
+
+ // Include first and last point of line,
+ // they are always part of the line
+ int n = 2;
+ ref_candidates.front().included = true;
+ ref_candidates.back().included = true;
+
+ // Get points, recursively, including them if they are further away
+ // than the specified distance
+ typedef typename PointDistanceStrategy::return_type return_type;
+
+ consider(boost::begin(ref_candidates), boost::end(ref_candidates),
+ make_distance_result<return_type>(max_distance), n, strategy);
+
+ // Copy included elements to the output
+ for(typename std::vector<dp_point_type>::const_iterator it
+ = boost::begin(ref_candidates);
+ it != boost::end(ref_candidates);
+ ++it)
+ {
+ if (it->included)
+ {
+ // copy-coordinates does not work because OutputIterator
+ // does not model Point (??)
+ //ggl::copy_coordinates(it->p, *out);
+ *out = it->p;
+ out++;
+ }
+ }
+ return out;
+ }
+
+};
+
+}} // namespace strategy::simplify
+
+
+} // namespace ggl
+
+#endif // GGL_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP

Added: sandbox/ggl/formal_review/boost/ggl/strategies/area.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/strategies/area.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,34 @@
+// 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_AREA_HPP
+#define GGL_STRATEGIES_AREA_HPP
+
+#include <ggl/strategies/tags.hpp>
+
+
+namespace ggl
+{
+
+
+/*!
+ \brief Traits class binding an area strategy to a coordinate system
+ \ingroup area
+ \tparam Tag tag of coordinate system
+ \tparam PointOfSegment point-type
+*/
+template <typename Tag, typename PointOfSegment>
+struct strategy_area
+{
+ typedef strategy::not_implemented type;
+};
+
+
+} // namespace ggl
+
+#endif // GGL_STRATEGIES_AREA_HPP

Added: sandbox/ggl/formal_review/boost/ggl/strategies/area_result.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/strategies/area_result.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,45 @@
+// Generic Geometry Library
+//
+// 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_STRATEGIES_AREA_RESULT_HPP
+#define GGL_STRATEGIES_AREA_RESULT_HPP
+
+
+#include <ggl/core/cs.hpp>
+#include <ggl/core/coordinate_type.hpp>
+#include <ggl/strategies/area.hpp>
+#include <ggl/util/select_most_precise.hpp>
+
+
+namespace ggl
+{
+
+/*!
+ \brief Meta-function defining return type of area function
+ \ingroup area
+ \note The strategy defines the return-type (so this situation is different
+ from length, where distance is sqr/sqrt, but length always squared)
+
+ */
+template <typename Geometry>
+struct area_result
+{
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename strategy_area
+ <
+ typename cs_tag<point_type>::type,
+ point_type
+ >::type strategy_type;
+
+ typedef typename strategy_type::return_type type;
+};
+
+
+} // namespace ggl
+
+
+#endif // GGL_STRATEGIES_AREA_RESULT_HPP

Added: sandbox/ggl/formal_review/boost/ggl/strategies/cartesian/area_by_triangles.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/strategies/cartesian/area_by_triangles.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 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_STRATEGIES_CARTESIAN_AREA_BY_TRIANGLES_HPP
+#define GGL_STRATEGIES_CARTESIAN_AREA_BY_TRIANGLES_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+#include <ggl/geometries/point_xy.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 PointOfSegment point type of segments
+*/
+template
+<
+ typename PointOfSegment,
+ typename CalculationType = void
+>
+class by_triangles
+{
+public :
+ // If user specified a calculation type, use that type,
+ // whatever it is and whatever the point-type is.
+ // Else, use the pointtype, but at least double
+ typedef typename
+ boost::mpl::if_c
+ <
+ boost::is_void<CalculationType>::type::value,
+ typename select_most_precise
+ <
+ typename coordinate_type<PointOfSegment>::type,
+ double
+ >::type,
+ CalculationType
+ >::type return_type;
+
+
+private :
+
+ class summation
+ {
+ friend class by_triangles;
+
+ return_type sum;
+ public :
+
+ inline summation() : sum(return_type())
+ {
+ // Strategy supports only 2D areas
+ assert_dimension<PointOfSegment, 2>();
+ }
+ inline return_type area() const
+ {
+ return_type result = sum;
+ result *= 0.5;
+ return result;
+ }
+ };
+
+public :
+ typedef summation state_type;
+ typedef PointOfSegment segment_point_type;
+
+ static inline void apply(PointOfSegment const& p1,
+ PointOfSegment const& p2,
+ summation& state)
+ {
+ // SUM += x2 * y1 - x1 * y2;
+ state.sum += get<0>(p2) * get<1>(p1) - get<0>(p1) * get<1>(p2);
+ }
+
+ static inline return_type result(summation const& state)
+ {
+ return state.area();
+ }
+
+};
+
+}} // namespace strategy::area
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+template <typename Point>
+struct strategy_area<cartesian_tag, Point>
+{
+ typedef strategy::area::by_triangles<Point> type;
+};
+
+#endif
+
+} // namespace ggl
+
+
+#endif // GGL_STRATEGIES_CARTESIAN_AREA_BY_TRIANGLES_HPP

Added: sandbox/ggl/formal_review/boost/ggl/strategies/cartesian/cart_intersect.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/strategies/cartesian/cart_intersect.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,354 @@
+// 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_CARTESIAN_INTERSECTION_HPP
+#define GGL_STRATEGIES_CARTESIAN_INTERSECTION_HPP
+
+#include <algorithm>
+
+#include <ggl/core/exception.hpp>
+
+#include <ggl/geometries/concepts/point_concept.hpp>
+#include <ggl/geometries/concepts/segment_concept.hpp>
+
+#include <ggl/util/math.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_STRATEGIES_CARTESIAN_INTERSECTION_HPP

Added: sandbox/ggl/formal_review/boost/ggl/strategies/cartesian/centroid_bashein_detmer.hpp
==============================================================================
--- (empty file)
+++ sandbox/ggl/formal_review/boost/ggl/strategies/cartesian/centroid_bashein_detmer.hpp 2009-11-04 12:09:58 EST (Wed, 04 Nov 2009)
@@ -0,0 +1,238 @@
+// 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_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP
+#define GGL_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/type_traits.hpp>
+
+#include <ggl/core/coordinate_type.hpp>
+#include <ggl/core/point_type.hpp>
+#include <ggl/strategies/centroid.hpp>
+#include <ggl/util/select_coordinate_type.hpp>
+#include <ggl/util/copy.hpp>
+
+
+namespace ggl
+{
+
+// Note: when calling the namespace "centroid", it sometimes,
+// somehow, in gcc, gives compilation problems (confusion with function centroid).
+
+namespace strategy { namespace centroid_ {
+
+
+
+/*!
+ \brief Centroid calculation using algorith Bashein / Detmer
+ \details Calculates centroid using triangulation method published by
+ Bashein / Detmer
+ \tparam Point point type of centroid to calculate
+ \tparam PointOfSegment point type of segments, defaults to Point
+ \par Concepts for Point and PointOfSegment:
+ - specialized point_traits class
+ \author Adapted from "Centroid of a Polygon" by
+ Gerard Bashein and Paul R. Detmer<em>,
+ in "Graphics Gems IV", Academic Press, 1994</em>
+ \par Research notes
+ The algorithm gives the same results as Oracle and PostGIS but
+ differs from MySQL
+ (tried 5.0.21 / 5.0.45 / 5.0.51a / 5.1.23).
+
+ Without holes:
+ - this: POINT(4.06923363095238 1.65055803571429)
+ - geolib: POINT(4.07254 1.66819)
+ - MySQL: POINT(3.6636363636364 1.6272727272727)'
+ - PostGIS: POINT(4.06923363095238 1.65055803571429)
+ - Oracle: 4.06923363095238 1.65055803571429
+ - SQL Server: POINT(4.06923362245959 1.65055804168294)
+
+ Statements:
+ - \b MySQL/PostGIS: select AsText(Centroid(GeomFromText(
+ 'POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.1 3,5.3 2.6
+ ,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3))')))
+ - \b Oracle: select sdo_geom.sdo_centroid(sdo_geometry(2003, null, null,
+ sdo_elem_info_array(1, 1003, 1), sdo_ordinate_array(
+ 2,1.3,2.4,1.7,2.8,1.8,3.4,1.2,3.7,1.6,3.4,2,4.1,3,5.3,2.6
+ ,5.4,1.2,4.9,0.8,2.9,0.7,2,1.3))
+ , mdsys.sdo_dim_array(mdsys.sdo_dim_element('x',0,10,.00000005)
+ ,mdsys.sdo_dim_element('y',0,10,.00000005)))
+ from dual
+ - \b SQL Server 2008: select geometry::STGeomFromText(
+ 'POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2,3.7 1.6,3.4 2,4.1 3,5.3 2.6
+ ,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3))',0)
+ .STCentroid()
+ .STAsText()
+
+ With holes:
+ - this: POINT(4.04663 1.6349)
+ - geolib: POINT(4.04675 1.65735)
+ - MySQL: POINT(3.6090580503834 1.607573932092)
+ - PostGIS: POINT(4.0466265060241 1.63489959839357)
+ - Oracle: 4.0466265060241 1.63489959839357
+ - SQL Server: POINT(4.0466264962959677 1.6348996057331333)
+
+ Statements:
+ - \b MySQL/PostGIS: select AsText(Centroid(GeomFromText(
+ 'POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2
+ ,3.7 1.6,3.4 2,4.1 3,5.3 2.6,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3)
+ ,(4 2,4.2 1.4,4.8 1.9,4.4 2.2,4 2))')));
+ - \b Oracle: select sdo_geom.sdo_centroid(sdo_geometry(2003, null, null
+ , sdo_elem_info_array(1, 1003, 1, 25, 2003, 1)
+ , sdo_ordinate_array(2,1.3,2.4,1.7,2.8,1.8,3.4,1.2,3.7,1.6,3.4,
+ 2,4.1,3,5.3,2.6,5.4,1.2,4.9,0.8,2.9,0.7,2,1.3,4,2, 4.2,1.4,
+ 4.8,1.9, 4.4,2.2, 4,2))
+ , mdsys.sdo_dim_array(mdsys.sdo_dim_element('x',0,10,.00000005)
+ ,mdsys.sdo_dim_element('y',0,10,.00000005)))
+ from dual
+ */
+template
+<
+ typename Point,
+ typename PointOfSegment = Point,
+ typename CalculationType = void
+>
+class bashein_detmer
+{
+private :
+ // If user specified a calculation type, use that type,
+ // whatever it is and whatever the point-type(s) are.
+ // Else, use the most appropriate coordinate type
+ // of the two points, but at least double
+ typedef typename
+ boost::mpl::if_c
+ <
+ boost::is_void<CalculationType>::type::value,
+ typename select_most_precise
+ <
+ typename select_coordinate_type
+ <
+ Point,
+ PointOfSegment
+ >::type,
+ double
+ >::type,
+ CalculationType
+ >::type calculation_type;
+
+ /*! subclass to keep state */
+ class sums
+ {
+ friend class bashein_detmer;
+ int count;
+ calculation_type sum_a2;
+ calculation_type sum_x;
+ calculation_type sum_y;
+
+ public :
+ inline sums()
+ : count(0)
+ , sum_a2(calculation_type())
+ , sum_x(calculation_type())
+ , sum_y(calculation_type())
+ {
+ typedef calculation_type ct;
+ //std::cout << "-> calctype: " << typeid(ct).name()
+ // << " size: " << sizeof(ct)
+ // << " init: " << sum_a2
+ // << std::endl;
+ }
+ };
+
+public :
+ typedef sums state_type;
+ typedef Point point_type;
+ typedef PointOfSegment segment_point_type;
+
+ static inline void apply(PointOfSegment const& p1,
+ PointOfSegment const& p2, sums& state)
+ {
+ /* Algorithm:
+ For each segment:
+ begin
+ ai = x1 * y2 - x2 * y1;
+ sum_a2 += ai;
+ sum_x += ai * (x1 + x2);
+ sum_y += ai * (y1 + y2);
+ end
+ return POINT(sum_x / (3 * sum_a2), sum_y / (3 * sum_a2) )
+ */
+
+ // Get coordinates and promote them to calculation_type
+ calculation_type const x1 = boost::numeric_cast<calculation_type>(get<0>(p1));
+ calculation_type const y1 = boost::numeric_cast<calculation_type>(get<1>(p1));
+ calculation_type const x2 = boost::numeric_cast<calculation_type>(get<0>(p2));
+ calculation_type const y2 = boost::numeric_cast<calculation_type>(get<1>(p2));
+ calculation_type const ai = x1 * y2 - x2 * y1;
+ state.count++;
+ state.sum_a2 += ai;
+ state.sum_x += ai * (x1 + x2);
+ state.sum_y += ai * (y1 + y2);
+ }
+
+ static inline bool result(sums const& state, Point& centroid)
+ {
+ if (state.count &g