summaryrefslogtreecommitdiff
path: root/boost/geometry
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2013-06-25 22:59:01 +0000
committer <>2013-09-27 11:49:28 +0000
commit8c4528713d907ee2cfd3bfcbbad272c749867f84 (patch)
treec09e2ce80f47b90c85cc720f5139089ad9c8cfff /boost/geometry
downloadboost-tarball-8c4528713d907ee2cfd3bfcbbad272c749867f84.tar.gz
Imported from /home/lorry/working-area/delta_boost-tarball/boost_1_54_0.tar.bz2.boost_1_54_0baserock/morph
Diffstat (limited to 'boost/geometry')
-rw-r--r--boost/geometry/algorithms/append.hpp292
-rw-r--r--boost/geometry/algorithms/area.hpp299
-rw-r--r--boost/geometry/algorithms/assign.hpp171
-rw-r--r--boost/geometry/algorithms/buffer.hpp171
-rw-r--r--boost/geometry/algorithms/centroid.hpp429
-rw-r--r--boost/geometry/algorithms/clear.hpp184
-rw-r--r--boost/geometry/algorithms/comparable_distance.hpp74
-rw-r--r--boost/geometry/algorithms/convert.hpp461
-rw-r--r--boost/geometry/algorithms/convex_hull.hpp249
-rw-r--r--boost/geometry/algorithms/correct.hpp272
-rw-r--r--boost/geometry/algorithms/covered_by.hpp197
-rw-r--r--boost/geometry/algorithms/detail/as_range.hpp107
-rw-r--r--boost/geometry/algorithms/detail/assign_box_corners.hpp103
-rw-r--r--boost/geometry/algorithms/detail/assign_indexed_point.hpp94
-rw-r--r--boost/geometry/algorithms/detail/assign_values.hpp443
-rw-r--r--boost/geometry/algorithms/detail/calculate_null.hpp38
-rw-r--r--boost/geometry/algorithms/detail/calculate_sum.hpp58
-rw-r--r--boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp80
-rw-r--r--boost/geometry/algorithms/detail/convert_point_to_point.hpp68
-rw-r--r--boost/geometry/algorithms/detail/disjoint.hpp239
-rw-r--r--boost/geometry/algorithms/detail/equals/collect_vectors.hpp315
-rw-r--r--boost/geometry/algorithms/detail/for_each_range.hpp149
-rw-r--r--boost/geometry/algorithms/detail/get_left_turns.hpp371
-rw-r--r--boost/geometry/algorithms/detail/has_self_intersections.hpp120
-rw-r--r--boost/geometry/algorithms/detail/not.hpp50
-rw-r--r--boost/geometry/algorithms/detail/occupation_info.hpp329
-rw-r--r--boost/geometry/algorithms/detail/overlay/add_rings.hpp159
-rw-r--r--boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp53
-rw-r--r--boost/geometry/algorithms/detail/overlay/assign_parents.hpp338
-rw-r--r--boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp170
-rw-r--r--boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp64
-rw-r--r--boost/geometry/algorithms/detail/overlay/check_enrich.hpp172
-rw-r--r--boost/geometry/algorithms/detail/overlay/clip_linestring.hpp242
-rw-r--r--boost/geometry/algorithms/detail/overlay/convert_ring.hpp110
-rw-r--r--boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp295
-rw-r--r--boost/geometry/algorithms/detail/overlay/copy_segments.hpp328
-rw-r--r--boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp66
-rw-r--r--boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp525
-rw-r--r--boost/geometry/algorithms/detail/overlay/enrichment_info.hpp76
-rw-r--r--boost/geometry/algorithms/detail/overlay/follow.hpp416
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp146
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_relative_order.hpp108
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_ring.hpp102
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info.hpp1122
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turns.hpp890
-rw-r--r--boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp703
-rw-r--r--boost/geometry/algorithms/detail/overlay/intersection_insert.hpp646
-rw-r--r--boost/geometry/algorithms/detail/overlay/overlay.hpp312
-rw-r--r--boost/geometry/algorithms/detail/overlay/overlay_type.hpp29
-rw-r--r--boost/geometry/algorithms/detail/overlay/ring_properties.hpp78
-rw-r--r--boost/geometry/algorithms/detail/overlay/segment_identifier.hpp91
-rw-r--r--boost/geometry/algorithms/detail/overlay/select_rings.hpp295
-rw-r--r--boost/geometry/algorithms/detail/overlay/self_turn_points.hpp308
-rw-r--r--boost/geometry/algorithms/detail/overlay/stream_info.hpp75
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal_info.hpp47
-rw-r--r--boost/geometry/algorithms/detail/overlay/traverse.hpp410
-rw-r--r--boost/geometry/algorithms/detail/overlay/turn_info.hpp152
-rw-r--r--boost/geometry/algorithms/detail/overlay/visit_info.hpp136
-rw-r--r--boost/geometry/algorithms/detail/partition.hpp425
-rw-r--r--boost/geometry/algorithms/detail/point_on_border.hpp246
-rw-r--r--boost/geometry/algorithms/detail/ring_identifier.hpp70
-rw-r--r--boost/geometry/algorithms/detail/sections/range_by_section.hpp131
-rw-r--r--boost/geometry/algorithms/detail/sections/sectionalize.hpp672
-rw-r--r--boost/geometry/algorithms/detail/throw_on_empty_input.hpp53
-rw-r--r--boost/geometry/algorithms/difference.hpp152
-rw-r--r--boost/geometry/algorithms/disjoint.hpp296
-rw-r--r--boost/geometry/algorithms/distance.hpp596
-rw-r--r--boost/geometry/algorithms/envelope.hpp195
-rw-r--r--boost/geometry/algorithms/equals.hpp382
-rw-r--r--boost/geometry/algorithms/expand.hpp300
-rw-r--r--boost/geometry/algorithms/for_each.hpp271
-rw-r--r--boost/geometry/algorithms/intersection.hpp208
-rw-r--r--boost/geometry/algorithms/intersects.hpp106
-rw-r--r--boost/geometry/algorithms/length.hpp275
-rw-r--r--boost/geometry/algorithms/make.hpp200
-rw-r--r--boost/geometry/algorithms/not_implemented.hpp117
-rw-r--r--boost/geometry/algorithms/num_geometries.hpp89
-rw-r--r--boost/geometry/algorithms/num_interior_rings.hpp84
-rw-r--r--boost/geometry/algorithms/num_points.hpp212
-rw-r--r--boost/geometry/algorithms/overlaps.hpp184
-rw-r--r--boost/geometry/algorithms/perimeter.hpp137
-rw-r--r--boost/geometry/algorithms/reverse.hpp125
-rw-r--r--boost/geometry/algorithms/simplify.hpp371
-rw-r--r--boost/geometry/algorithms/sym_difference.hpp162
-rw-r--r--boost/geometry/algorithms/touches.hpp181
-rw-r--r--boost/geometry/algorithms/transform.hpp339
-rw-r--r--boost/geometry/algorithms/union.hpp245
-rw-r--r--boost/geometry/algorithms/unique.hpp147
-rw-r--r--boost/geometry/algorithms/within.hpp348
-rw-r--r--boost/geometry/arithmetic/arithmetic.hpp281
-rw-r--r--boost/geometry/arithmetic/determinant.hpp76
-rw-r--r--boost/geometry/arithmetic/dot_product.hpp82
-rw-r--r--boost/geometry/core/access.hpp398
-rw-r--r--boost/geometry/core/closure.hpp180
-rw-r--r--boost/geometry/core/coordinate_dimension.hpp126
-rw-r--r--boost/geometry/core/coordinate_system.hpp100
-rw-r--r--boost/geometry/core/coordinate_type.hpp108
-rw-r--r--boost/geometry/core/cs.hpp220
-rw-r--r--boost/geometry/core/exception.hpp60
-rw-r--r--boost/geometry/core/exterior_ring.hpp144
-rw-r--r--boost/geometry/core/geometry_id.hpp94
-rw-r--r--boost/geometry/core/interior_rings.hpp139
-rw-r--r--boost/geometry/core/interior_type.hpp161
-rw-r--r--boost/geometry/core/is_areal.hpp60
-rw-r--r--boost/geometry/core/mutable_range.hpp98
-rw-r--r--boost/geometry/core/point_order.hpp162
-rw-r--r--boost/geometry/core/point_type.hpp130
-rw-r--r--boost/geometry/core/radian_access.hpp152
-rw-r--r--boost/geometry/core/reverse_dispatch.hpp67
-rw-r--r--boost/geometry/core/ring_type.hpp170
-rw-r--r--boost/geometry/core/tag.hpp71
-rw-r--r--boost/geometry/core/tag_cast.hpp84
-rw-r--r--boost/geometry/core/tags.hpp94
-rw-r--r--boost/geometry/core/topological_dimension.hpp88
-rw-r--r--boost/geometry/geometries/adapted/boost_array.hpp120
-rw-r--r--boost/geometry/geometries/adapted/boost_fusion.hpp172
-rw-r--r--boost/geometry/geometries/adapted/boost_polygon.hpp18
-rw-r--r--boost/geometry/geometries/adapted/boost_polygon/box.hpp141
-rw-r--r--boost/geometry/geometries/adapted/boost_polygon/hole_iterator.hpp84
-rw-r--r--boost/geometry/geometries/adapted/boost_polygon/holes_proxy.hpp204
-rw-r--r--boost/geometry/geometries/adapted/boost_polygon/point.hpp102
-rw-r--r--boost/geometry/geometries/adapted/boost_polygon/polygon.hpp111
-rw-r--r--boost/geometry/geometries/adapted/boost_polygon/ring.hpp163
-rw-r--r--boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp301
-rw-r--r--boost/geometry/geometries/adapted/boost_range/adjacent_filtered.hpp40
-rw-r--r--boost/geometry/geometries/adapted/boost_range/filtered.hpp40
-rw-r--r--boost/geometry/geometries/adapted/boost_range/reversed.hpp40
-rw-r--r--boost/geometry/geometries/adapted/boost_range/sliced.hpp36
-rw-r--r--boost/geometry/geometries/adapted/boost_range/strided.hpp36
-rw-r--r--boost/geometry/geometries/adapted/boost_range/uniqued.hpp40
-rw-r--r--boost/geometry/geometries/adapted/boost_tuple.hpp109
-rw-r--r--boost/geometry/geometries/adapted/c_array.hpp111
-rw-r--r--boost/geometry/geometries/adapted/std_pair_as_segment.hpp98
-rw-r--r--boost/geometry/geometries/box.hpp134
-rw-r--r--boost/geometry/geometries/concepts/box_concept.hpp136
-rw-r--r--boost/geometry/geometries/concepts/check.hpp205
-rw-r--r--boost/geometry/geometries/concepts/linestring_concept.hpp125
-rw-r--r--boost/geometry/geometries/concepts/point_concept.hpp176
-rw-r--r--boost/geometry/geometries/concepts/polygon_concept.hpp135
-rw-r--r--boost/geometry/geometries/concepts/ring_concept.hpp99
-rw-r--r--boost/geometry/geometries/concepts/segment_concept.hpp135
-rw-r--r--boost/geometry/geometries/geometries.hpp25
-rw-r--r--boost/geometry/geometries/linestring.hpp95
-rw-r--r--boost/geometry/geometries/point.hpp188
-rw-r--r--boost/geometry/geometries/point_xy.hpp128
-rw-r--r--boost/geometry/geometries/polygon.hpp319
-rw-r--r--boost/geometry/geometries/register/box.hpp179
-rw-r--r--boost/geometry/geometries/register/linestring.hpp60
-rw-r--r--boost/geometry/geometries/register/point.hpp173
-rw-r--r--boost/geometry/geometries/register/ring.hpp60
-rw-r--r--boost/geometry/geometries/register/segment.hpp129
-rw-r--r--boost/geometry/geometries/ring.hpp153
-rw-r--r--boost/geometry/geometries/segment.hpp203
-rw-r--r--boost/geometry/geometries/variant.hpp34
-rw-r--r--boost/geometry/geometry.hpp92
-rw-r--r--boost/geometry/index/adaptors/query.hpp88
-rw-r--r--boost/geometry/index/detail/algorithms/bounds.hpp41
-rw-r--r--boost/geometry/index/detail/algorithms/comparable_distance_centroid.hpp77
-rw-r--r--boost/geometry/index/detail/algorithms/comparable_distance_far.hpp66
-rw-r--r--boost/geometry/index/detail/algorithms/comparable_distance_near.hpp77
-rw-r--r--boost/geometry/index/detail/algorithms/content.hpp85
-rw-r--r--boost/geometry/index/detail/algorithms/diff_abs.hpp39
-rw-r--r--boost/geometry/index/detail/algorithms/intersection_content.hpp36
-rw-r--r--boost/geometry/index/detail/algorithms/is_valid.hpp79
-rw-r--r--boost/geometry/index/detail/algorithms/margin.hpp167
-rw-r--r--boost/geometry/index/detail/algorithms/minmaxdist.hpp119
-rw-r--r--boost/geometry/index/detail/algorithms/path_intersection.hpp114
-rw-r--r--boost/geometry/index/detail/algorithms/segment_intersection.hpp141
-rw-r--r--boost/geometry/index/detail/algorithms/smallest_for_indexable.hpp80
-rw-r--r--boost/geometry/index/detail/algorithms/sum_for_indexable.hpp76
-rw-r--r--boost/geometry/index/detail/algorithms/union_content.hpp33
-rw-r--r--boost/geometry/index/detail/assert.hpp30
-rw-r--r--boost/geometry/index/detail/config_begin.hpp21
-rw-r--r--boost/geometry/index/detail/config_end.hpp12
-rw-r--r--boost/geometry/index/detail/distance_predicates.hpp161
-rw-r--r--boost/geometry/index/detail/exception.hpp72
-rw-r--r--boost/geometry/index/detail/meta.hpp42
-rw-r--r--boost/geometry/index/detail/predicates.hpp814
-rw-r--r--boost/geometry/index/detail/pushable_array.hpp171
-rw-r--r--boost/geometry/index/detail/rtree/adaptors.hpp54
-rw-r--r--boost/geometry/index/detail/rtree/kmeans/kmeans.hpp16
-rw-r--r--boost/geometry/index/detail/rtree/kmeans/split.hpp87
-rw-r--r--boost/geometry/index/detail/rtree/linear/linear.hpp16
-rw-r--r--boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp447
-rw-r--r--boost/geometry/index/detail/rtree/node/auto_deallocator.hpp38
-rw-r--r--boost/geometry/index/detail/rtree/node/concept.hpp85
-rw-r--r--boost/geometry/index/detail/rtree/node/dynamic_visitor.hpp88
-rw-r--r--boost/geometry/index/detail/rtree/node/node.hpp175
-rw-r--r--boost/geometry/index/detail/rtree/node/node_auto_ptr.hpp79
-rw-r--r--boost/geometry/index/detail/rtree/node/node_d_mem_dynamic.hpp358
-rw-r--r--boost/geometry/index/detail/rtree/node/node_d_mem_static.hpp199
-rw-r--r--boost/geometry/index/detail/rtree/node/node_s_mem_dynamic.hpp276
-rw-r--r--boost/geometry/index/detail/rtree/node/node_s_mem_static.hpp202
-rw-r--r--boost/geometry/index/detail/rtree/node/pairs.hpp71
-rw-r--r--boost/geometry/index/detail/rtree/node/static_visitor.hpp66
-rw-r--r--boost/geometry/index/detail/rtree/options.hpp155
-rw-r--r--boost/geometry/index/detail/rtree/pack_create.hpp376
-rw-r--r--boost/geometry/index/detail/rtree/quadratic/quadratic.hpp16
-rw-r--r--boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp298
-rw-r--r--boost/geometry/index/detail/rtree/query_iterators.hpp230
-rw-r--r--boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp426
-rw-r--r--boost/geometry/index/detail/rtree/rstar/insert.hpp567
-rw-r--r--boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp441
-rw-r--r--boost/geometry/index/detail/rtree/rstar/rstar.hpp18
-rw-r--r--boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp140
-rw-r--r--boost/geometry/index/detail/rtree/utilities/are_levels_ok.hpp109
-rw-r--r--boost/geometry/index/detail/rtree/utilities/gl_draw.hpp223
-rw-r--r--boost/geometry/index/detail/rtree/utilities/print.hpp203
-rw-r--r--boost/geometry/index/detail/rtree/utilities/statistics.hpp105
-rw-r--r--boost/geometry/index/detail/rtree/utilities/view.hpp61
-rw-r--r--boost/geometry/index/detail/rtree/visitors/children_box.hpp55
-rw-r--r--boost/geometry/index/detail/rtree/visitors/copy.hpp92
-rw-r--r--boost/geometry/index/detail/rtree/visitors/count.hpp118
-rw-r--r--boost/geometry/index/detail/rtree/visitors/destroy.hpp70
-rw-r--r--boost/geometry/index/detail/rtree/visitors/distance_query.hpp540
-rw-r--r--boost/geometry/index/detail/rtree/visitors/insert.hpp516
-rw-r--r--boost/geometry/index/detail/rtree/visitors/is_leaf.hpp41
-rw-r--r--boost/geometry/index/detail/rtree/visitors/remove.hpp316
-rw-r--r--boost/geometry/index/detail/rtree/visitors/spatial_query.hpp198
-rw-r--r--boost/geometry/index/detail/tags.hpp25
-rw-r--r--boost/geometry/index/detail/translator.hpp60
-rw-r--r--boost/geometry/index/detail/tuples.hpp201
-rw-r--r--boost/geometry/index/detail/type_erased_iterators.hpp60
-rw-r--r--boost/geometry/index/detail/utilities.hpp46
-rw-r--r--boost/geometry/index/detail/varray.hpp2209
-rw-r--r--boost/geometry/index/detail/varray_detail.hpp714
-rw-r--r--boost/geometry/index/distance_predicates.hpp204
-rw-r--r--boost/geometry/index/equal_to.hpp221
-rw-r--r--boost/geometry/index/indexable.hpp179
-rw-r--r--boost/geometry/index/inserter.hpp78
-rw-r--r--boost/geometry/index/parameters.hpp257
-rw-r--r--boost/geometry/index/predicates.hpp394
-rw-r--r--boost/geometry/index/rtree.hpp1550
-rw-r--r--boost/geometry/io/dsv/write.hpp375
-rw-r--r--boost/geometry/io/io.hpp58
-rw-r--r--boost/geometry/io/svg/svg_mapper.hpp392
-rw-r--r--boost/geometry/io/svg/write_svg.hpp277
-rw-r--r--boost/geometry/io/svg/write_svg_multi.hpp78
-rw-r--r--boost/geometry/io/wkt/detail/prefix.hpp45
-rw-r--r--boost/geometry/io/wkt/detail/wkt_multi.hpp57
-rw-r--r--boost/geometry/io/wkt/read.hpp697
-rw-r--r--boost/geometry/io/wkt/stream.hpp40
-rw-r--r--boost/geometry/io/wkt/wkt.hpp25
-rw-r--r--boost/geometry/io/wkt/write.hpp421
-rw-r--r--boost/geometry/iterators/base.hpp70
-rw-r--r--boost/geometry/iterators/closing_iterator.hpp157
-rw-r--r--boost/geometry/iterators/ever_circling_iterator.hpp212
-rw-r--r--boost/geometry/multi/algorithms/append.hpp53
-rw-r--r--boost/geometry/multi/algorithms/area.hpp58
-rw-r--r--boost/geometry/multi/algorithms/centroid.hpp134
-rw-r--r--boost/geometry/multi/algorithms/clear.hpp44
-rw-r--r--boost/geometry/multi/algorithms/convert.hpp129
-rw-r--r--boost/geometry/multi/algorithms/correct.hpp67
-rw-r--r--boost/geometry/multi/algorithms/covered_by.hpp71
-rw-r--r--boost/geometry/multi/algorithms/detail/for_each_range.hpp87
-rw-r--r--boost/geometry/multi/algorithms/detail/modify.hpp53
-rw-r--r--boost/geometry/multi/algorithms/detail/modify_with_predicate.hpp52
-rw-r--r--boost/geometry/multi/algorithms/detail/multi_sum.hpp52
-rw-r--r--boost/geometry/multi/algorithms/detail/overlay/copy_segment_point.hpp102
-rw-r--r--boost/geometry/multi/algorithms/detail/overlay/copy_segments.hpp105
-rw-r--r--boost/geometry/multi/algorithms/detail/overlay/get_ring.hpp56
-rw-r--r--boost/geometry/multi/algorithms/detail/overlay/get_turns.hpp113
-rw-r--r--boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp65
-rw-r--r--boost/geometry/multi/algorithms/detail/overlay/self_turn_points.hpp57
-rw-r--r--boost/geometry/multi/algorithms/detail/point_on_border.hpp96
-rw-r--r--boost/geometry/multi/algorithms/detail/sections/range_by_section.hpp91
-rw-r--r--boost/geometry/multi/algorithms/detail/sections/sectionalize.hpp97
-rw-r--r--boost/geometry/multi/algorithms/disjoint.hpp44
-rw-r--r--boost/geometry/multi/algorithms/distance.hpp158
-rw-r--r--boost/geometry/multi/algorithms/envelope.hpp107
-rw-r--r--boost/geometry/multi/algorithms/equals.hpp65
-rw-r--r--boost/geometry/multi/algorithms/for_each.hpp101
-rw-r--r--boost/geometry/multi/algorithms/intersection.hpp402
-rw-r--r--boost/geometry/multi/algorithms/length.hpp62
-rw-r--r--boost/geometry/multi/algorithms/num_geometries.hpp53
-rw-r--r--boost/geometry/multi/algorithms/num_interior_rings.hpp62
-rw-r--r--boost/geometry/multi/algorithms/num_points.hpp78
-rw-r--r--boost/geometry/multi/algorithms/perimeter.hpp56
-rw-r--r--boost/geometry/multi/algorithms/reverse.hpp63
-rw-r--r--boost/geometry/multi/algorithms/simplify.hpp92
-rw-r--r--boost/geometry/multi/algorithms/transform.hpp91
-rw-r--r--boost/geometry/multi/algorithms/unique.hpp86
-rw-r--r--boost/geometry/multi/algorithms/within.hpp105
-rw-r--r--boost/geometry/multi/core/closure.hpp58
-rw-r--r--boost/geometry/multi/core/geometry_id.hpp56
-rw-r--r--boost/geometry/multi/core/interior_rings.hpp55
-rw-r--r--boost/geometry/multi/core/is_areal.hpp43
-rw-r--r--boost/geometry/multi/core/point_order.hpp57
-rw-r--r--boost/geometry/multi/core/point_type.hpp64
-rw-r--r--boost/geometry/multi/core/ring_type.hpp66
-rw-r--r--boost/geometry/multi/core/tags.hpp71
-rw-r--r--boost/geometry/multi/core/topological_dimension.hpp52
-rw-r--r--boost/geometry/multi/geometries/concepts/check.hpp83
-rw-r--r--boost/geometry/multi/geometries/concepts/multi_linestring_concept.hpp86
-rw-r--r--boost/geometry/multi/geometries/concepts/multi_point_concept.hpp85
-rw-r--r--boost/geometry/multi/geometries/concepts/multi_polygon_concept.hpp86
-rw-r--r--boost/geometry/multi/geometries/multi_geometries.hpp21
-rw-r--r--boost/geometry/multi/geometries/multi_linestring.hpp80
-rw-r--r--boost/geometry/multi/geometries/multi_point.hpp94
-rw-r--r--boost/geometry/multi/geometries/multi_polygon.hpp78
-rw-r--r--boost/geometry/multi/geometries/register/multi_linestring.hpp59
-rw-r--r--boost/geometry/multi/geometries/register/multi_point.hpp59
-rw-r--r--boost/geometry/multi/geometries/register/multi_polygon.hpp59
-rw-r--r--boost/geometry/multi/io/dsv/write.hpp86
-rw-r--r--boost/geometry/multi/io/wkt/detail/prefix.hpp51
-rw-r--r--boost/geometry/multi/io/wkt/read.hpp168
-rw-r--r--boost/geometry/multi/io/wkt/wkt.hpp20
-rw-r--r--boost/geometry/multi/io/wkt/write.hpp109
-rw-r--r--boost/geometry/multi/multi.hpp78
-rw-r--r--boost/geometry/multi/strategies/cartesian/centroid_average.hpp116
-rw-r--r--boost/geometry/multi/views/detail/range_type.hpp62
-rw-r--r--boost/geometry/policies/compare.hpp242
-rw-r--r--boost/geometry/policies/relate/de9im.hpp177
-rw-r--r--boost/geometry/policies/relate/direction.hpp362
-rw-r--r--boost/geometry/policies/relate/intersection_points.hpp165
-rw-r--r--boost/geometry/policies/relate/tupled.hpp175
-rw-r--r--boost/geometry/strategies/agnostic/hull_graham_andrew.hpp384
-rw-r--r--boost/geometry/strategies/agnostic/point_in_box_by_side.hpp151
-rw-r--r--boost/geometry/strategies/agnostic/point_in_poly_oriented_winding.hpp208
-rw-r--r--boost/geometry/strategies/agnostic/point_in_poly_winding.hpp232
-rw-r--r--boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp229
-rw-r--r--boost/geometry/strategies/area.hpp50
-rw-r--r--boost/geometry/strategies/cartesian/area_surveyor.hpp134
-rw-r--r--boost/geometry/strategies/cartesian/box_in_box.hpp176
-rw-r--r--boost/geometry/strategies/cartesian/cart_intersect.hpp754
-rw-r--r--boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp242
-rw-r--r--boost/geometry/strategies/cartesian/centroid_weighted_length.hpp144
-rw-r--r--boost/geometry/strategies/cartesian/distance_projected_point.hpp320
-rw-r--r--boost/geometry/strategies/cartesian/distance_pythagoras.hpp349
-rw-r--r--boost/geometry/strategies/cartesian/point_in_box.hpp172
-rw-r--r--boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp124
-rw-r--r--boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp118
-rw-r--r--boost/geometry/strategies/cartesian/side_by_triangle.hpp121
-rw-r--r--boost/geometry/strategies/centroid.hpp72
-rw-r--r--boost/geometry/strategies/compare.hpp172
-rw-r--r--boost/geometry/strategies/concepts/area_concept.hpp75
-rw-r--r--boost/geometry/strategies/concepts/centroid_concept.hpp78
-rw-r--r--boost/geometry/strategies/concepts/convex_hull_concept.hpp75
-rw-r--r--boost/geometry/strategies/concepts/distance_concept.hpp206
-rw-r--r--boost/geometry/strategies/concepts/segment_intersect_concept.hpp78
-rw-r--r--boost/geometry/strategies/concepts/simplify_concept.hpp109
-rw-r--r--boost/geometry/strategies/concepts/within_concept.hpp291
-rw-r--r--boost/geometry/strategies/convex_hull.hpp47
-rw-r--r--boost/geometry/strategies/covered_by.hpp72
-rw-r--r--boost/geometry/strategies/default_area_result.hpp51
-rw-r--r--boost/geometry/strategies/default_distance_result.hpp50
-rw-r--r--boost/geometry/strategies/default_length_result.hpp46
-rw-r--r--boost/geometry/strategies/distance.hpp135
-rw-r--r--boost/geometry/strategies/intersection.hpp93
-rw-r--r--boost/geometry/strategies/intersection_result.hpp174
-rw-r--r--boost/geometry/strategies/side.hpp55
-rw-r--r--boost/geometry/strategies/side_info.hpp176
-rw-r--r--boost/geometry/strategies/spherical/area_huiller.hpp202
-rw-r--r--boost/geometry/strategies/spherical/compare_circular.hpp152
-rw-r--r--boost/geometry/strategies/spherical/distance_cross_track.hpp382
-rw-r--r--boost/geometry/strategies/spherical/distance_haversine.hpp330
-rw-r--r--boost/geometry/strategies/spherical/side_by_cross_track.hpp100
-rw-r--r--boost/geometry/strategies/spherical/ssf.hpp136
-rw-r--r--boost/geometry/strategies/strategies.hpp59
-rw-r--r--boost/geometry/strategies/strategy_transform.hpp504
-rw-r--r--boost/geometry/strategies/tags.hpp41
-rw-r--r--boost/geometry/strategies/transform.hpp63
-rw-r--r--boost/geometry/strategies/transform/inverse_transformer.hpp78
-rw-r--r--boost/geometry/strategies/transform/map_transformer.hpp173
-rw-r--r--boost/geometry/strategies/transform/matrix_transformers.hpp422
-rw-r--r--boost/geometry/strategies/within.hpp71
-rw-r--r--boost/geometry/util/add_const_if_c.hpp56
-rw-r--r--boost/geometry/util/bare_type.hpp38
-rw-r--r--boost/geometry/util/calculation_type.hpp176
-rw-r--r--boost/geometry/util/closure_as_bool.hpp46
-rw-r--r--boost/geometry/util/coordinate_cast.hpp55
-rw-r--r--boost/geometry/util/for_each_coordinate.hpp94
-rw-r--r--boost/geometry/util/math.hpp237
-rw-r--r--boost/geometry/util/order_as_direction.hpp46
-rw-r--r--boost/geometry/util/parameter_type_of.hpp75
-rw-r--r--boost/geometry/util/promote_floating_point.hpp50
-rw-r--r--boost/geometry/util/rational.hpp179
-rw-r--r--boost/geometry/util/readme.txt17
-rw-r--r--boost/geometry/util/select_calculation_type.hpp57
-rw-r--r--boost/geometry/util/select_coordinate_type.hpp45
-rw-r--r--boost/geometry/util/select_most_precise.hpp162
-rw-r--r--boost/geometry/views/box_view.hpp114
-rw-r--r--boost/geometry/views/closeable_view.hpp109
-rw-r--r--boost/geometry/views/detail/points_view.hpp141
-rw-r--r--boost/geometry/views/detail/range_type.hpp106
-rw-r--r--boost/geometry/views/identity_view.hpp61
-rw-r--r--boost/geometry/views/reversible_view.hpp74
-rw-r--r--boost/geometry/views/segment_view.hpp100
388 files changed, 65998 insertions, 0 deletions
diff --git a/boost/geometry/algorithms/append.hpp b/boost/geometry/algorithms/append.hpp
new file mode 100644
index 000000000..f2d0d366d
--- /dev/null
+++ b/boost/geometry/algorithms/append.hpp
@@ -0,0 +1,292 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP
+
+
+#include <boost/geometry/algorithms/num_interior_rings.hpp>
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/mutable_range.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/geometries/variant.hpp>
+#include <boost/range.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/apply_visitor.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace append
+{
+
+template <typename Geometry, typename Point>
+struct append_no_action
+{
+ static inline void apply(Geometry& , Point const& ,
+ int = 0, int = 0)
+ {
+ }
+};
+
+template <typename Geometry, typename Point>
+struct append_point
+{
+ static inline void apply(Geometry& geometry, Point const& point,
+ int = 0, int = 0)
+ {
+ typename geometry::point_type<Geometry>::type copy;
+ geometry::detail::conversion::convert_point_to_point(point, copy);
+ traits::push_back<Geometry>::apply(geometry, copy);
+ }
+};
+
+
+template <typename Geometry, typename Range>
+struct append_range
+{
+ typedef typename boost::range_value<Range>::type point_type;
+
+ static inline void apply(Geometry& geometry, Range const& range,
+ int = 0, int = 0)
+ {
+ for (typename boost::range_iterator<Range const>::type
+ it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ append_point<Geometry, point_type>::apply(geometry, *it);
+ }
+ }
+};
+
+
+template <typename Polygon, typename Point>
+struct point_to_polygon
+{
+ typedef typename ring_type<Polygon>::type ring_type;
+
+ static inline void apply(Polygon& polygon, Point const& point,
+ int ring_index, int = 0)
+ {
+ if (ring_index == -1)
+ {
+ append_point<ring_type, Point>::apply(
+ exterior_ring(polygon), point);
+ }
+ else if (ring_index < int(num_interior_rings(polygon)))
+ {
+ append_point<ring_type, Point>::apply(
+ interior_rings(polygon)[ring_index], point);
+ }
+ }
+};
+
+
+template <typename Polygon, typename Range>
+struct range_to_polygon
+{
+ 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>::apply(
+ exterior_ring(polygon), range);
+ }
+ else if (ring_index < int(num_interior_rings(polygon)))
+ {
+ append_range<ring_type, Range>::apply(
+ interior_rings(polygon)[ring_index], range);
+ }
+ }
+};
+
+
+}} // namespace detail::append
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+namespace splitted_dispatch
+{
+
+template <typename Tag, typename Geometry, typename Point>
+struct append_point
+ : detail::append::append_no_action<Geometry, Point>
+{};
+
+template <typename Geometry, typename Point>
+struct append_point<linestring_tag, Geometry, Point>
+ : detail::append::append_point<Geometry, Point>
+{};
+
+template <typename Geometry, typename Point>
+struct append_point<ring_tag, Geometry, Point>
+ : detail::append::append_point<Geometry, Point>
+{};
+
+
+template <typename Polygon, typename Point>
+struct append_point<polygon_tag, Polygon, Point>
+ : detail::append::point_to_polygon<Polygon, Point>
+{};
+
+
+template <typename Tag, typename Geometry, typename Range>
+struct append_range
+ : detail::append::append_no_action<Geometry, Range>
+{};
+
+template <typename Geometry, typename Range>
+struct append_range<linestring_tag, Geometry, Range>
+ : detail::append::append_range<Geometry, Range>
+{};
+
+template <typename Geometry, typename Range>
+struct append_range<ring_tag, Geometry, Range>
+ : detail::append::append_range<Geometry, Range>
+{};
+
+
+template <typename Polygon, typename Range>
+struct append_range<polygon_tag, Polygon, Range>
+ : detail::append::range_to_polygon<Polygon, Range>
+{};
+
+} // namespace splitted_dispatch
+
+
+// Default: append a range (or linestring or ring or whatever) to any geometry
+template
+<
+ typename Geometry, typename RangeOrPoint,
+ typename TagRangeOrPoint = typename tag<RangeOrPoint>::type
+>
+struct append
+ : splitted_dispatch::append_range<typename tag<Geometry>::type, Geometry, RangeOrPoint>
+{};
+
+// Specialization for point to append a point to any geometry
+template <typename Geometry, typename RangeOrPoint>
+struct append<Geometry, RangeOrPoint, point_tag>
+ : splitted_dispatch::append_point<typename tag<Geometry>::type, Geometry, RangeOrPoint>
+{};
+
+template <typename Geometry>
+struct devarianted_append
+{
+ template <typename RangeOrPoint>
+ static inline void apply(Geometry& geometry,
+ RangeOrPoint const& range_or_point,
+ int ring_index,
+ int multi_index)
+ {
+ concept::check<Geometry>();
+ append<Geometry, RangeOrPoint>::apply(geometry,
+ range_or_point,
+ ring_index,
+ multi_index);
+ }
+};
+
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct devarianted_append<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename RangeOrPoint>
+ struct visitor: boost::static_visitor<void>
+ {
+ RangeOrPoint const& m_range_or_point;
+ int m_ring_index;
+ int m_multi_index;
+
+ visitor(RangeOrPoint const& range_or_point,
+ int ring_index,
+ int multi_index):
+ m_range_or_point(range_or_point),
+ m_ring_index(ring_index),
+ m_multi_index(multi_index)
+ {}
+
+ template <typename Geometry>
+ void operator()(Geometry& geometry) const
+ {
+ concept::check<Geometry>();
+ append<Geometry, RangeOrPoint>::apply(geometry,
+ m_range_or_point,
+ m_ring_index,
+ m_multi_index);
+ }
+ };
+
+ template <typename RangeOrPoint>
+ static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& variant_geometry,
+ RangeOrPoint const& range_or_point,
+ int ring_index,
+ int multi_index)
+ {
+ apply_visitor(
+ visitor<RangeOrPoint>(
+ range_or_point,
+ ring_index,
+ multi_index
+ ),
+ variant_geometry
+ );
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Appends one or more points to a linestring, ring, polygon, multi-geometry
+\ingroup append
+\tparam Geometry \tparam_geometry
+\tparam RangeOrPoint Either a range or a point, fullfilling Boost.Range concept or Boost.Geometry Point Concept
+\param geometry \param_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 or multi linestrings
+
+\qbk{[include reference/algorithms/append.qbk]}
+}
+ */
+template <typename Geometry, typename RangeOrPoint>
+inline void append(Geometry& geometry, RangeOrPoint const& range_or_point,
+ int ring_index = -1, int multi_index = 0)
+{
+ dispatch::devarianted_append<Geometry>
+ ::apply(geometry, range_or_point, ring_index, multi_index);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP
diff --git a/boost/geometry/algorithms/area.hpp b/boost/geometry/algorithms/area.hpp
new file mode 100644
index 000000000..537a36763
--- /dev/null
+++ b/boost/geometry/algorithms/area.hpp
@@ -0,0 +1,299 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
+
+#include <boost/concept_check.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/range/functions.hpp>
+#include <boost/range/metafunctions.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/point_order.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/detail/calculate_null.hpp>
+#include <boost/geometry/algorithms/detail/calculate_sum.hpp>
+// #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
+
+#include <boost/geometry/strategies/area.hpp>
+#include <boost/geometry/strategies/default_area_result.hpp>
+
+#include <boost/geometry/strategies/concepts/area_concept.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/order_as_direction.hpp>
+#include <boost/geometry/views/closeable_view.hpp>
+#include <boost/geometry/views/reversible_view.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace area
+{
+
+struct box_area
+{
+ template <typename Box, typename Strategy>
+ static inline typename coordinate_type<Box>::type
+ apply(Box const& box, Strategy const&)
+ {
+ // Currently only works for 2D Cartesian boxes
+ assert_dimension<Box, 2>();
+
+ return (get<max_corner, 0>(box) - get<min_corner, 0>(box))
+ * (get<max_corner, 1>(box) - get<min_corner, 1>(box));
+ }
+};
+
+
+template
+<
+ iterate_direction Direction,
+ closure_selector Closure
+>
+struct ring_area
+{
+ template <typename Ring, typename Strategy>
+ static inline typename Strategy::return_type
+ apply(Ring const& ring, Strategy const& strategy)
+ {
+ BOOST_CONCEPT_ASSERT( (geometry::concept::AreaStrategy<Strategy>) );
+ assert_dimension<Ring, 2>();
+
+ // Ignore warning (because using static method sometimes) on strategy
+ boost::ignore_unused_variable_warning(strategy);
+
+ // An open ring has at least three points,
+ // A closed ring has at least four points,
+ // if not, there is no (zero) area
+ if (int(boost::size(ring))
+ < core_detail::closure::minimum_ring_size<Closure>::value)
+ {
+ return typename Strategy::return_type();
+ }
+
+ typedef typename reversible_view<Ring const, Direction>::type rview_type;
+ typedef typename closeable_view
+ <
+ rview_type const, Closure
+ >::type view_type;
+ typedef typename boost::range_iterator<view_type const>::type iterator_type;
+
+ rview_type rview(ring);
+ view_type view(rview);
+ typename Strategy::state_type state;
+ iterator_type it = boost::begin(view);
+ iterator_type end = boost::end(view);
+
+ for (iterator_type previous = it++;
+ it != end;
+ ++previous, ++it)
+ {
+ strategy.apply(*previous, *it, state);
+ }
+
+ return strategy.result(state);
+ }
+};
+
+
+}} // namespace detail::area
+
+
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry,
+ typename Tag = typename tag<Geometry>::type
+>
+struct area : detail::calculate_null
+{
+ template <typename Strategy>
+ static inline typename Strategy::return_type apply(Geometry const& geometry, Strategy const& strategy)
+ {
+ return calculate_null::apply<typename Strategy::return_type>(geometry, strategy);
+ }
+};
+
+
+template <typename Geometry>
+struct area<Geometry, box_tag> : detail::area::box_area
+{};
+
+
+template <typename Ring>
+struct area<Ring, ring_tag>
+ : detail::area::ring_area
+ <
+ order_as_direction<geometry::point_order<Ring>::value>::value,
+ geometry::closure<Ring>::value
+ >
+{};
+
+
+template <typename Polygon>
+struct area<Polygon, polygon_tag> : detail::calculate_polygon_sum
+{
+ template <typename Strategy>
+ static inline typename Strategy::return_type apply(Polygon const& polygon, Strategy const& strategy)
+ {
+ return calculate_polygon_sum::apply<
+ typename Strategy::return_type,
+ detail::area::ring_area
+ <
+ order_as_direction<geometry::point_order<Polygon>::value>::value,
+ geometry::closure<Polygon>::value
+ >
+ >(polygon, strategy);
+ }
+};
+
+
+template <typename Geometry>
+struct devarianted_area
+{
+ template <typename Strategy>
+ static inline typename Strategy::return_type apply(Geometry const& geometry,
+ Strategy const& strategy)
+ {
+ return area<Geometry>::apply(geometry, strategy);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct devarianted_area<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename Strategy>
+ struct visitor: boost::static_visitor<typename Strategy::return_type>
+ {
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy): m_strategy(strategy) {}
+
+ template <typename Geometry>
+ typename Strategy::return_type operator()(Geometry const& geometry) const
+ {
+ return devarianted_area<Geometry>::apply(geometry, m_strategy);
+ }
+ };
+
+ template <typename Strategy>
+ static inline typename Strategy::return_type
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
+ Strategy const& strategy)
+ {
+ return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+/*!
+\brief \brief_calc{area}
+\ingroup area
+\details \details_calc{area}. \details_default_strategy
+
+The area algorithm calculates the surface area of all geometries having a surface, namely
+box, polygon, ring, multipolygon. The units are the square of the units used for the points
+defining the surface. If subject geometry is defined in meters, then area is calculated
+in square meters.
+
+The area calculation can be done in all three common coordinate systems, Cartesian, Spherical
+and Geographic as well.
+
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\return \return_calc{area}
+
+\qbk{[include reference/algorithms/area.qbk]}
+\qbk{[heading Examples]}
+\qbk{[area] [area_output]}
+*/
+template <typename Geometry>
+inline typename default_area_result<Geometry>::type area(Geometry const& geometry)
+{
+ concept::check<Geometry const>();
+
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename strategy::area::services::default_strategy
+ <
+ typename cs_tag<point_type>::type,
+ point_type
+ >::type strategy_type;
+
+ // detail::throw_on_empty_input(geometry);
+
+ return dispatch::devarianted_area<Geometry>::apply(geometry, strategy_type());
+}
+
+/*!
+\brief \brief_calc{area} \brief_strategy
+\ingroup area
+\details \details_calc{area} \brief_strategy. \details_strategy_reasons
+\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{Area}
+\param geometry \param_geometry
+\param strategy \param_strategy{area}
+\return \return_calc{area}
+
+\qbk{distinguish,with strategy}
+
+\qbk{
+[include reference/algorithms/area.qbk]
+
+[heading Example]
+[area_with_strategy]
+[area_with_strategy_output]
+
+[heading Available Strategies]
+\* [link geometry.reference.strategies.strategy_area_surveyor Surveyor (cartesian)]
+\* [link geometry.reference.strategies.strategy_area_huiller Huiller (spherical)]
+}
+ */
+template <typename Geometry, typename Strategy>
+inline typename Strategy::return_type area(
+ Geometry const& geometry, Strategy const& strategy)
+{
+ concept::check<Geometry const>();
+
+ // detail::throw_on_empty_input(geometry);
+
+ return dispatch::devarianted_area<Geometry>::apply(geometry, strategy);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_AREA_HPP
diff --git a/boost/geometry/algorithms/assign.hpp b/boost/geometry/algorithms/assign.hpp
new file mode 100644
index 000000000..97a033d1d
--- /dev/null
+++ b/boost/geometry/algorithms/assign.hpp
@@ -0,0 +1,171 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP
+
+
+#include <cstddef>
+
+#include <boost/concept/requires.hpp>
+#include <boost/concept_check.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/numeric/conversion/bounds.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
+#include <boost/geometry/algorithms/detail/assign_values.hpp>
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/algorithms/append.hpp>
+#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/util/for_each_coordinate.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+\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 assign
+\tparam Geometry \tparam_geometry
+\tparam Range \tparam_range_point
+\param geometry \param_geometry
+\param range \param_range_point
+
+\qbk{
+[heading Notes]
+[note Assign automatically clears the geometry before assigning (use append if you don't want that)]
+[heading Example]
+[assign_points] [assign_points_output]
+
+[heading See also]
+\* [link geometry.reference.algorithms.append append]
+}
+ */
+template <typename Geometry, typename Range>
+inline void assign_points(Geometry& geometry, Range const& range)
+{
+ concept::check<Geometry>();
+
+ clear(geometry);
+ geometry::append(geometry, range, -1, 0);
+}
+
+
+/*!
+\brief assign to a box inverse infinite
+\details The assign_inverse function initialize a 2D or 3D box with large coordinates, the
+min corner is very large, the max corner is very small. This is a convenient starting point to
+collect the minimum bounding box of a geometry.
+\ingroup assign
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+
+\qbk{
+[heading Example]
+[assign_inverse] [assign_inverse_output]
+
+[heading See also]
+\* [link geometry.reference.algorithms.make.make_inverse make_inverse]
+}
+ */
+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 assign
+\details The assign_zero function initializes a 2D or 3D point or box with coordinates of zero
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+
+ */
+template <typename Geometry>
+inline void assign_zero(Geometry& geometry)
+{
+ concept::check<Geometry>();
+
+ dispatch::assign_zero
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::apply(geometry);
+}
+
+/*!
+\brief Assigns one geometry to another geometry
+\details The assign algorithm assigns one geometry, e.g. a BOX, to another
+geometry, e.g. a RING. This only works if it is possible and applicable.
+\ingroup assign
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry (target)
+\param geometry2 \param_geometry (source)
+
+\qbk{
+[heading Example]
+[assign] [assign_output]
+
+[heading See also]
+\* [link geometry.reference.algorithms.convert convert]
+}
+ */
+template <typename Geometry1, typename Geometry2>
+inline void assign(Geometry1& geometry1, Geometry2 const& geometry2)
+{
+ concept::check_concepts_and_equal_dimensions<Geometry1, Geometry2 const>();
+
+ bool const same_point_order =
+ point_order<Geometry1>::value == point_order<Geometry2>::value;
+ bool const same_closure =
+ closure<Geometry1>::value == closure<Geometry2>::value;
+
+ BOOST_MPL_ASSERT_MSG
+ (
+ same_point_order, ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_POINT_ORDER
+ , (types<Geometry1, Geometry2>)
+ );
+ BOOST_MPL_ASSERT_MSG
+ (
+ same_closure, ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_CLOSURE
+ , (types<Geometry1, Geometry2>)
+ );
+
+ dispatch::convert<Geometry2, Geometry1>::apply(geometry2, geometry1);
+}
+
+
+}} // namespace boost::geometry
+
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP
diff --git a/boost/geometry/algorithms/buffer.hpp b/boost/geometry/algorithms/buffer.hpp
new file mode 100644
index 000000000..29966d8cc
--- /dev/null
+++ b/boost/geometry/algorithms/buffer.hpp
@@ -0,0 +1,171 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
+
+#include <cstddef>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+
+#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/algorithms/detail/disjoint.hpp>
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/geometries/segment.hpp>
+#include <boost/geometry/util/math.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace buffer
+{
+
+template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t D, std::size_t N>
+struct box_loop
+{
+ typedef typename coordinate_type<BoxOut>::type coordinate_type;
+
+ static inline void apply(BoxIn const& box_in, T const& distance, BoxOut& box_out)
+ {
+ coordinate_type d = distance;
+ set<C, D>(box_out, get<C, D>(box_in) + d);
+ box_loop<BoxIn, BoxOut, T, C, D + 1, N>::apply(box_in, distance, box_out);
+ }
+};
+
+template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t N>
+struct box_loop<BoxIn, BoxOut, T, C, N, N>
+{
+ static inline void apply(BoxIn const&, T const&, BoxOut&) {}
+};
+
+// Extends a box with the same amount in all directions
+template<typename BoxIn, typename BoxOut, typename T>
+inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out)
+{
+ assert_dimension_equal<BoxIn, BoxOut>();
+
+ static const std::size_t N = dimension<BoxIn>::value;
+
+ box_loop<BoxIn, BoxOut, T, min_corner, 0, N>::apply(box_in, -distance, box_out);
+ box_loop<BoxIn, BoxOut, T, max_corner, 0, N>::apply(box_in, distance, box_out);
+}
+
+
+
+}} // namespace detail::buffer
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Input,
+ typename Output,
+ typename TagIn = typename tag<Input>::type,
+ typename TagOut = typename tag<Output>::type
+>
+struct buffer: not_implemented<TagIn, TagOut>
+{};
+
+
+template <typename BoxIn, typename BoxOut>
+struct buffer<BoxIn, BoxOut, box_tag, box_tag>
+{
+ template <typename Distance>
+ static inline void apply(BoxIn const& box_in, Distance const& distance,
+ Distance const& , BoxIn& box_out)
+ {
+ detail::buffer::buffer_box(box_in, distance, box_out);
+ }
+};
+
+// Many things to do. Point is easy, other geometries require self intersections
+// For point, note that it should output as a polygon (like the rest). Buffers
+// of a set of geometries are often lateron combined using a "dissolve" operation.
+// Two points close to each other get a combined kidney shaped buffer then.
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief \brief_calc{buffer}
+\ingroup buffer
+\details \details_calc{buffer, \det_buffer}.
+\tparam Input \tparam_geometry
+\tparam Output \tparam_geometry
+\tparam Distance \tparam_numeric
+\param geometry_in \param_geometry
+\param geometry_out \param_geometry
+\param distance The distance to be used for the buffer
+\param chord_length (optional) The length of the chord's in the generated arcs around points or bends
+\note Currently only implemented for box, the trivial case, but still useful
+
+\qbk{[include reference/algorithms/buffer.qbk]}
+ */
+template <typename Input, typename Output, typename Distance>
+inline void buffer(Input const& geometry_in, Output& geometry_out,
+ Distance const& distance, Distance const& chord_length = -1)
+{
+ concept::check<Input const>();
+ concept::check<Output>();
+
+ dispatch::buffer
+ <
+ Input,
+ Output
+ >::apply(geometry_in, distance, chord_length, geometry_out);
+}
+
+/*!
+\brief \brief_calc{buffer}
+\ingroup buffer
+\details \details_calc{return_buffer, \det_buffer}. \details_return{buffer}.
+\tparam Input \tparam_geometry
+\tparam Output \tparam_geometry
+\tparam Distance \tparam_numeric
+\param geometry \param_geometry
+\param distance The distance to be used for the buffer
+\param chord_length (optional) The length of the chord's in the generated arcs
+ around points or bends
+\return \return_calc{buffer}
+ */
+template <typename Output, typename Input, typename Distance>
+Output return_buffer(Input const& geometry, Distance const& distance, Distance const& chord_length = -1)
+{
+ concept::check<Input const>();
+ concept::check<Output>();
+
+ Output geometry_out;
+
+ dispatch::buffer
+ <
+ Input,
+ Output
+ >::apply(geometry, distance, chord_length, geometry_out);
+
+ return geometry_out;
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
diff --git a/boost/geometry/algorithms/centroid.hpp b/boost/geometry/algorithms/centroid.hpp
new file mode 100644
index 000000000..9be51f409
--- /dev/null
+++ b/boost/geometry/algorithms/centroid.hpp
@@ -0,0 +1,429 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP
+
+
+#include <cstddef>
+
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/exception.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/algorithms/distance.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/strategies/centroid.hpp>
+#include <boost/geometry/strategies/concepts/centroid_concept.hpp>
+#include <boost/geometry/views/closeable_view.hpp>
+
+#include <boost/geometry/util/for_each_coordinate.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+
+#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)
+
+/*!
+\brief Centroid Exception
+\ingroup centroid
+\details The centroid_exception is thrown if the free centroid function is called with
+ geometries for which the centroid cannot be calculated. For example: a linestring
+ without points, a polygon without points, an empty multi-geometry.
+\qbk{
+[heading See also]
+\* [link geometry.reference.algorithms.centroid the centroid function]
+}
+
+ */
+class centroid_exception : public geometry::exception
+{
+public:
+
+ inline centroid_exception() {}
+
+ virtual char const* what() const throw()
+ {
+ return "Boost.Geometry Centroid calculation exception";
+ }
+};
+
+#endif
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace centroid
+{
+
+struct centroid_point
+{
+ template<typename Point, typename PointCentroid, typename Strategy>
+ static inline void apply(Point const& point, PointCentroid& centroid,
+ Strategy const&)
+ {
+ geometry::convert(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& )
+ {
+ }
+};
+
+
+struct centroid_box
+{
+ template<typename Box, typename Point, typename Strategy>
+ 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(BOOST_GEOMETRY_CENTROID_NO_THROW)
+ throw centroid_exception();
+#endif
+ return false;
+ }
+ else // if (n == 1)
+ {
+ // Take over the first point in a "coordinate neutral way"
+ geometry::convert(*boost::begin(range), centroid);
+ return false;
+ }
+ return true;
+}
+
+
+/*!
+ \brief Calculate the centroid of a ring.
+*/
+template <closure_selector Closure>
+struct centroid_range_state
+{
+ template<typename Ring, typename Strategy>
+ static inline void apply(Ring const& ring,
+ Strategy const& strategy, typename Strategy::state_type& state)
+ {
+ typedef typename closeable_view<Ring const, Closure>::type view_type;
+
+ typedef typename boost::range_iterator<view_type const>::type iterator_type;
+
+ view_type view(ring);
+ iterator_type it = boost::begin(view);
+ iterator_type end = boost::end(view);
+
+ for (iterator_type previous = it++;
+ it != end;
+ ++previous, ++it)
+ {
+ strategy.apply(*previous, *it, state);
+ }
+ }
+};
+
+template <closure_selector Closure>
+struct centroid_range
+{
+ template<typename Range, typename Point, typename Strategy>
+ static inline void apply(Range const& range, Point& centroid,
+ Strategy const& strategy)
+ {
+ if (range_ok(range, centroid))
+ {
+ typename Strategy::state_type state;
+ centroid_range_state<Closure>::apply(range, strategy, state);
+ strategy.result(state, centroid);
+ }
+ }
+};
+
+
+/*!
+ \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.
+*/
+struct centroid_polygon_state
+{
+ template<typename Polygon, typename Strategy>
+ static inline void apply(Polygon const& poly,
+ Strategy const& strategy, typename Strategy::state_type& state)
+ {
+ typedef typename ring_type<Polygon>::type ring_type;
+ typedef centroid_range_state<geometry::closure<ring_type>::value> per_ring;
+
+ per_ring::apply(exterior_ring(poly), strategy, state);
+
+ typename interior_return_type<Polygon const>::type rings
+ = interior_rings(poly);
+ for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
+ {
+ per_ring::apply(*it, strategy, state);
+ }
+ }
+};
+
+struct centroid_polygon
+{
+ template<typename Polygon, typename Point, typename Strategy>
+ 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::apply(poly, strategy, state);
+ strategy.result(state, centroid);
+ }
+ }
+};
+
+
+}} // namespace detail::centroid
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry,
+ typename Tag = typename tag<Geometry>::type
+>
+struct centroid: not_implemented<Tag>
+{};
+
+template <typename Geometry>
+struct centroid<Geometry, point_tag>
+ : detail::centroid::centroid_point
+{};
+
+template <typename Box>
+struct centroid<Box, box_tag>
+ : detail::centroid::centroid_box
+{};
+
+template <typename Ring>
+struct centroid<Ring, ring_tag>
+ : detail::centroid::centroid_range<geometry::closure<Ring>::value>
+{};
+
+template <typename Linestring>
+struct centroid<Linestring, linestring_tag>
+ : detail::centroid::centroid_range<closed>
+ {};
+
+template <typename Polygon>
+struct centroid<Polygon, polygon_tag>
+ : detail::centroid::centroid_polygon
+ {};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief \brief_calc{centroid} \brief_strategy
+\ingroup centroid
+\details \details_calc{centroid,geometric center (or: center of mass)}. \details_strategy_reasons
+\tparam Geometry \tparam_geometry
+\tparam Point \tparam_point
+\tparam Strategy \tparam_strategy{Centroid}
+\param geometry \param_geometry
+\param c \param_point \param_set{centroid}
+\param strategy \param_strategy{centroid}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/centroid.qbk]}
+\qbk{[include reference/algorithms/centroid_strategies.qbk]}
+}
+
+*/
+template<typename Geometry, typename Point, typename Strategy>
+inline void centroid(Geometry const& geometry, Point& c,
+ Strategy const& strategy)
+{
+ //BOOST_CONCEPT_ASSERT( (geometry::concept::CentroidStrategy<Strategy>) );
+
+ concept::check_concepts_and_equal_dimensions<Point, Geometry const>();
+
+ 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<Geometry>::apply(geometry, c, strategy);
+}
+
+
+/*!
+\brief \brief_calc{centroid}
+\ingroup centroid
+\details \details_calc{centroid,geometric center (or: center of mass)}. \details_default_strategy
+\tparam Geometry \tparam_geometry
+\tparam Point \tparam_point
+\param geometry \param_geometry
+\param c The calculated centroid will be assigned to this point reference
+
+\qbk{[include reference/algorithms/centroid.qbk]}
+\qbk{
+[heading Example]
+[centroid]
+[centroid_output]
+}
+ */
+template<typename Geometry, typename Point>
+inline void centroid(Geometry const& geometry, Point& c)
+{
+ concept::check_concepts_and_equal_dimensions<Point, Geometry const>();
+
+ typedef typename strategy::centroid::services::default_strategy
+ <
+ typename cs_tag<Geometry>::type,
+ typename tag_cast
+ <
+ typename tag<Geometry>::type,
+ pointlike_tag,
+ linear_tag,
+ areal_tag
+ >::type,
+ dimension<Geometry>::type::value,
+ Point,
+ Geometry
+ >::type strategy_type;
+
+ centroid(geometry, c, strategy_type());
+}
+
+
+/*!
+\brief \brief_calc{centroid}
+\ingroup centroid
+\details \details_calc{centroid,geometric center (or: center of mass)}. \details_return{centroid}.
+\tparam Point \tparam_point
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\return \return_calc{centroid}
+
+\qbk{[include reference/algorithms/centroid.qbk]}
+ */
+template<typename Point, typename Geometry>
+inline Point return_centroid(Geometry const& geometry)
+{
+ concept::check_concepts_and_equal_dimensions<Point, Geometry const>();
+
+ Point c;
+ centroid(geometry, c);
+ return c;
+}
+
+/*!
+\brief \brief_calc{centroid} \brief_strategy
+\ingroup centroid
+\details \details_calc{centroid,geometric center (or: center of mass)}. \details_return{centroid}. \details_strategy_reasons
+\tparam Point \tparam_point
+\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{centroid}
+\param geometry \param_geometry
+\param strategy \param_strategy{centroid}
+\return \return_calc{centroid}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/centroid.qbk]}
+\qbk{[include reference/algorithms/centroid_strategies.qbk]}
+ */
+template<typename Point, typename Geometry, typename Strategy>
+inline Point return_centroid(Geometry const& geometry, Strategy const& strategy)
+{
+ //BOOST_CONCEPT_ASSERT( (geometry::concept::CentroidStrategy<Strategy>) );
+
+ concept::check_concepts_and_equal_dimensions<Point, Geometry const>();
+
+ Point c;
+ centroid(geometry, c, strategy);
+ return c;
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP
diff --git a/boost/geometry/algorithms/clear.hpp b/boost/geometry/algorithms/clear.hpp
new file mode 100644
index 000000000..b8cd0dca7
--- /dev/null
+++ b/boost/geometry/algorithms/clear.hpp
@@ -0,0 +1,184 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP
+
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/mutable_range.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace clear
+{
+
+template <typename Geometry>
+struct collection_clear
+{
+ static inline void apply(Geometry& geometry)
+ {
+ traits::clear<Geometry>::apply(geometry);
+ }
+};
+
+template <typename Polygon>
+struct polygon_clear
+{
+ static inline void apply(Polygon& polygon)
+ {
+ traits::clear
+ <
+ typename boost::remove_reference
+ <
+ typename traits::interior_mutable_type<Polygon>::type
+ >::type
+ >::apply(interior_rings(polygon));
+ traits::clear
+ <
+ typename boost::remove_reference
+ <
+ typename traits::ring_mutable_type<Polygon>::type
+ >::type
+ >::apply(exterior_ring(polygon));
+ }
+};
+
+template <typename Geometry>
+struct no_action
+{
+ static inline void apply(Geometry& )
+ {
+ }
+};
+
+
+}} // namespace detail::clear
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry,
+ typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type
+>
+struct clear: not_implemented<Tag>
+{};
+
+// Point/box/segment do not have clear. So specialize to do nothing.
+template <typename Geometry>
+struct clear<Geometry, point_tag>
+ : detail::clear::no_action<Geometry>
+{};
+
+template <typename Geometry>
+struct clear<Geometry, box_tag>
+ : detail::clear::no_action<Geometry>
+{};
+
+template <typename Geometry>
+struct clear<Geometry, segment_tag>
+ : detail::clear::no_action<Geometry>
+{};
+
+template <typename Geometry>
+struct clear<Geometry, linestring_tag>
+ : detail::clear::collection_clear<Geometry>
+{};
+
+template <typename Geometry>
+struct clear<Geometry, ring_tag>
+ : detail::clear::collection_clear<Geometry>
+{};
+
+
+// Polygon can (indirectly) use std for clear
+template <typename Polygon>
+struct clear<Polygon, polygon_tag>
+ : detail::clear::polygon_clear<Polygon>
+{};
+
+
+template <typename Geometry>
+struct devarianted_clear
+{
+ static inline void apply(Geometry& geometry)
+ {
+ clear<Geometry>::apply(geometry);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct devarianted_clear<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ struct visitor: static_visitor<void>
+ {
+ template <typename Geometry>
+ inline void operator()(Geometry& geometry) const
+ {
+ clear<Geometry>::apply(geometry);
+ }
+ };
+
+ static inline void apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)
+ {
+ apply_visitor(visitor(), geometry);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Clears a linestring, ring or polygon (exterior+interiors) or multi*
+\details Generic function to clear a geometry. All points will be removed from the collection or collections
+ making up the geometry. In most cases this is equivalent to the .clear() method of a std::vector<...>. In
+ the case of a polygon, this clear functionality is automatically called for the exterior ring, and for the
+ interior ring collection. In the case of a point, boxes and segments, nothing will happen.
+\ingroup clear
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry which will be cleared
+\note points and boxes cannot be cleared, instead they can be set to zero by "assign_zero"
+
+\qbk{[include reference/algorithms/clear.qbk]}
+*/
+template <typename Geometry>
+inline void clear(Geometry& geometry)
+{
+ concept::check<Geometry>();
+
+ dispatch::devarianted_clear<Geometry>::apply(geometry);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_CLEAR_HPP
diff --git a/boost/geometry/algorithms/comparable_distance.hpp b/boost/geometry/algorithms/comparable_distance.hpp
new file mode 100644
index 000000000..3467045ca
--- /dev/null
+++ b/boost/geometry/algorithms/comparable_distance.hpp
@@ -0,0 +1,74 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_COMPARABLE_DISTANCE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_COMPARABLE_DISTANCE_HPP
+
+
+#include <boost/geometry/algorithms/distance.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+\brief \brief_calc2{comparable distance measurement}
+\ingroup distance
+\details The free function comparable_distance does not necessarily calculate the distance,
+ but it calculates a distance measure such that two distances are comparable to each other.
+ For example: for the Cartesian coordinate system, Pythagoras is used but the square root
+ is not taken, which makes it faster and the results of two point pairs can still be
+ compared to each other.
+\tparam Geometry1 first geometry type
+\tparam Geometry2 second geometry type
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\return \return_calc{comparable distance}
+
+\qbk{[include reference/algorithms/comparable_distance.qbk]}
+ */
+template <typename Geometry1, typename Geometry2>
+inline typename default_distance_result<Geometry1, Geometry2>::type comparable_distance(
+ Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+
+ 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 strategy::distance::services::comparable_type
+ <
+ typename boost::mpl::if_c
+ <
+ geometry::reverse_dispatch
+ <Geometry1, Geometry2>::type::value,
+ typename strategy::distance::services::default_strategy
+ <point_tag, point2_type, point1_type>::type,
+ typename strategy::distance::services::default_strategy
+ <point_tag, point1_type, point2_type>::type
+ >::type
+ >::type strategy_type;
+
+ return distance(geometry1, geometry2, strategy_type());
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_COMPARABLE_DISTANCE_HPP
diff --git a/boost/geometry/algorithms/convert.hpp b/boost/geometry/algorithms/convert.hpp
new file mode 100644
index 000000000..6b48ca604
--- /dev/null
+++ b/boost/geometry/algorithms/convert.hpp
@@ -0,0 +1,461 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
+
+
+#include <cstddef>
+
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/range.hpp>
+#include <boost/type_traits/is_array.hpp>
+
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/algorithms/append.hpp>
+#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/for_each.hpp>
+#include <boost/geometry/algorithms/detail/assign_values.hpp>
+#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
+#include <boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp>
+
+#include <boost/geometry/views/closeable_view.hpp>
+#include <boost/geometry/views/reversible_view.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/point_order.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+// Silence warning C4127: conditional expression is constant
+// Silence warning C4512: assignment operator could not be generated
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4127 4512)
+#endif
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace conversion
+{
+
+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& , Box& )
+ {}
+};
+
+template <typename Box, typename Range, bool Close, bool Reverse>
+struct box_to_range
+{
+ static inline void apply(Box const& box, Range& range)
+ {
+ traits::resize<Range>::apply(range, Close ? 5 : 4);
+ assign_box_corners_oriented<Reverse>(box, range);
+ if (Close)
+ {
+ range[4] = range[0];
+ }
+ }
+};
+
+template <typename Segment, typename Range>
+struct segment_to_range
+{
+ static inline void apply(Segment const& segment, Range& range)
+ {
+ traits::resize<Range>::apply(range, 2);
+
+ typename boost::range_iterator<Range>::type it = boost::begin(range);
+
+ assign_point_from_index<0>(segment, *it);
+ ++it;
+ assign_point_from_index<1>(segment, *it);
+ }
+};
+
+template
+<
+ typename Range1,
+ typename Range2,
+ bool Reverse = false
+>
+struct range_to_range
+{
+ typedef typename reversible_view
+ <
+ Range1 const,
+ Reverse ? iterate_reverse : iterate_forward
+ >::type rview_type;
+ typedef typename closeable_view
+ <
+ rview_type const,
+ geometry::closure<Range1>::value
+ >::type view_type;
+
+ static inline void apply(Range1 const& source, Range2& destination)
+ {
+ geometry::clear(destination);
+
+ rview_type rview(source);
+
+ // We consider input always as closed, and skip last
+ // point for open output.
+ view_type view(rview);
+
+ int n = boost::size(view);
+ if (geometry::closure<Range2>::value == geometry::open)
+ {
+ n--;
+ }
+
+ int i = 0;
+ for (typename boost::range_iterator<view_type const>::type it
+ = boost::begin(view);
+ it != boost::end(view) && i < n;
+ ++it, ++i)
+ {
+ geometry::append(destination, *it);
+ }
+ }
+};
+
+template <typename Polygon1, typename Polygon2>
+struct polygon_to_polygon
+{
+ typedef range_to_range
+ <
+ typename geometry::ring_type<Polygon1>::type,
+ typename geometry::ring_type<Polygon2>::type,
+ geometry::point_order<Polygon1>::value
+ != geometry::point_order<Polygon2>::value
+ > per_ring;
+
+ static inline void apply(Polygon1 const& source, Polygon2& destination)
+ {
+ // Clearing managed per ring, and in the resizing of interior rings
+
+ per_ring::apply(geometry::exterior_ring(source),
+ geometry::exterior_ring(destination));
+
+ // Container should be resizeable
+ traits::resize
+ <
+ typename boost::remove_reference
+ <
+ typename traits::interior_mutable_type<Polygon2>::type
+ >::type
+ >::apply(interior_rings(destination), num_interior_rings(source));
+
+ typename interior_return_type<Polygon1 const>::type rings_source
+ = interior_rings(source);
+ typename interior_return_type<Polygon2>::type rings_dest
+ = interior_rings(destination);
+
+ BOOST_AUTO_TPL(it_source, boost::begin(rings_source));
+ BOOST_AUTO_TPL(it_dest, boost::begin(rings_dest));
+
+ for ( ; it_source != boost::end(rings_source); ++it_source, ++it_dest)
+ {
+ per_ring::apply(*it_source, *it_dest);
+ }
+ }
+};
+
+
+}} // namespace detail::conversion
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,
+ typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type,
+ std::size_t DimensionCount = dimension<Geometry1>::type::value,
+ bool UseAssignment = boost::is_same<Geometry1, Geometry2>::value
+ && !boost::is_array<Geometry1>::value
+>
+struct convert: not_implemented<Tag1, Tag2, mpl::int_<DimensionCount> >
+{};
+
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag,
+ std::size_t DimensionCount
+>
+struct convert<Geometry1, Geometry2, Tag, Tag, DimensionCount, true>
+{
+ // Same geometry type -> copy whole geometry
+ static inline void apply(Geometry1 const& source, Geometry2& destination)
+ {
+ destination = source;
+ }
+};
+
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ std::size_t DimensionCount
+>
+struct convert<Geometry1, Geometry2, point_tag, point_tag, DimensionCount, false>
+ : detail::conversion::point_to_point<Geometry1, Geometry2, 0, DimensionCount>
+{};
+
+
+template
+<
+ typename Box1, typename Box2,
+ std::size_t DimensionCount
+>
+struct convert<Box1, Box2, box_tag, box_tag, DimensionCount, false>
+ : detail::conversion::indexed_to_indexed<Box1, Box2, 0, DimensionCount>
+{};
+
+
+template
+<
+ typename Segment1, typename Segment2,
+ std::size_t DimensionCount
+>
+struct convert<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, false>
+ : detail::conversion::indexed_to_indexed<Segment1, Segment2, 0, DimensionCount>
+{};
+
+
+template <typename Segment, typename LineString, std::size_t DimensionCount>
+struct convert<Segment, LineString, segment_tag, linestring_tag, DimensionCount, false>
+ : detail::conversion::segment_to_range<Segment, LineString>
+{};
+
+
+template <typename Ring1, typename Ring2, std::size_t DimensionCount>
+struct convert<Ring1, Ring2, ring_tag, ring_tag, DimensionCount, false>
+ : detail::conversion::range_to_range
+ <
+ Ring1,
+ Ring2,
+ geometry::point_order<Ring1>::value
+ != geometry::point_order<Ring2>::value
+ >
+{};
+
+template <typename LineString1, typename LineString2, std::size_t DimensionCount>
+struct convert<LineString1, LineString2, linestring_tag, linestring_tag, DimensionCount, false>
+ : detail::conversion::range_to_range<LineString1, LineString2>
+{};
+
+template <typename Polygon1, typename Polygon2, std::size_t DimensionCount>
+struct convert<Polygon1, Polygon2, polygon_tag, polygon_tag, DimensionCount, false>
+ : detail::conversion::polygon_to_polygon<Polygon1, Polygon2>
+{};
+
+template <typename Box, typename Ring>
+struct convert<Box, Ring, box_tag, ring_tag, 2, false>
+ : detail::conversion::box_to_range
+ <
+ Box,
+ Ring,
+ geometry::closure<Ring>::value == closed,
+ geometry::point_order<Ring>::value == counterclockwise
+ >
+{};
+
+
+template <typename Box, typename Polygon>
+struct convert<Box, Polygon, box_tag, polygon_tag, 2, false>
+{
+ static inline void apply(Box const& box, Polygon& polygon)
+ {
+ typedef typename ring_type<Polygon>::type ring_type;
+
+ convert
+ <
+ Box, ring_type,
+ box_tag, ring_tag,
+ 2, false
+ >::apply(box, exterior_ring(polygon));
+ }
+};
+
+
+template <typename Point, typename Box, std::size_t DimensionCount>
+struct convert<Point, Box, point_tag, box_tag, DimensionCount, false>
+{
+ static inline void apply(Point const& point, Box& box)
+ {
+ detail::conversion::point_to_box
+ <
+ Point, Box, min_corner, 0, DimensionCount
+ >::apply(point, box);
+ detail::conversion::point_to_box
+ <
+ Point, Box, max_corner, 0, DimensionCount
+ >::apply(point, box);
+ }
+};
+
+
+template <typename Ring, typename Polygon, std::size_t DimensionCount>
+struct convert<Ring, Polygon, ring_tag, polygon_tag, DimensionCount, false>
+{
+ static inline void apply(Ring const& ring, Polygon& polygon)
+ {
+ typedef typename ring_type<Polygon>::type ring_type;
+ convert
+ <
+ Ring, ring_type,
+ ring_tag, ring_tag,
+ DimensionCount, false
+ >::apply(ring, exterior_ring(polygon));
+ }
+};
+
+
+template <typename Polygon, typename Ring, std::size_t DimensionCount>
+struct convert<Polygon, Ring, polygon_tag, ring_tag, DimensionCount, false>
+{
+ static inline void apply(Polygon const& polygon, Ring& ring)
+ {
+ typedef typename ring_type<Polygon>::type ring_type;
+
+ convert
+ <
+ ring_type, Ring,
+ ring_tag, ring_tag,
+ DimensionCount, false
+ >::apply(exterior_ring(polygon), ring);
+ }
+};
+
+
+template <typename Geometry1, typename Geometry2>
+struct devarianted_convert
+{
+ static inline void apply(Geometry1 const& geometry1, Geometry2& geometry2)
+ {
+ concept::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2>();
+ convert<Geometry1, Geometry2>::apply(geometry1, geometry2);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
+struct devarianted_convert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+{
+ struct visitor: static_visitor<void>
+ {
+ Geometry2& m_geometry2;
+
+ visitor(Geometry2& geometry2)
+ : m_geometry2(geometry2)
+ {}
+
+ template <typename Geometry1>
+ inline void operator()(Geometry1 const& geometry1) const
+ {
+ devarianted_convert<Geometry1, Geometry2>::apply(geometry1, m_geometry2);
+ }
+ };
+
+ static inline void apply(
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2& geometry2
+ )
+ {
+ apply_visitor(visitor(geometry2), geometry1);
+ }
+};
+
+
+} // 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 works if it is possible and applicable.
+If the point-order is different, or the closure is different between two
+geometry types, it will be converted correctly by explicitly reversing the
+points or closing or opening the polygon rings.
+\ingroup convert
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry (source)
+\param geometry2 \param_geometry (target)
+
+\qbk{[include reference/algorithms/convert.qbk]}
+ */
+template <typename Geometry1, typename Geometry2>
+inline void convert(Geometry1 const& geometry1, Geometry2& geometry2)
+{
+ dispatch::devarianted_convert<Geometry1, Geometry2>::apply(geometry1, geometry2);
+}
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
diff --git a/boost/geometry/algorithms/convex_hull.hpp b/boost/geometry/algorithms/convex_hull.hpp
new file mode 100644
index 000000000..a623064bf
--- /dev/null
+++ b/boost/geometry/algorithms/convex_hull.hpp
@@ -0,0 +1,249 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP
+
+#include <boost/array.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/point_order.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/strategies/convex_hull.hpp>
+#include <boost/geometry/strategies/concepts/convex_hull_concept.hpp>
+
+#include <boost/geometry/views/detail/range_type.hpp>
+
+#include <boost/geometry/algorithms/num_points.hpp>
+#include <boost/geometry/algorithms/detail/as_range.hpp>
+#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace convex_hull
+{
+
+template <order_selector Order>
+struct hull_insert
+{
+
+ // Member template function (to avoid inconvenient declaration
+ // of output-iterator-type, from hull_to_geometry)
+ template <typename Geometry, typename OutputIterator, typename Strategy>
+ 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;
+ }
+};
+
+struct hull_to_geometry
+{
+ template <typename Geometry, typename OutputGeometry, typename Strategy>
+ static inline void apply(Geometry const& geometry, OutputGeometry& out,
+ Strategy const& strategy)
+ {
+ hull_insert
+ <
+ geometry::point_order<OutputGeometry>::value
+ >::apply(geometry,
+ std::back_inserter(
+ // Handle linestring, ring and polygon the same:
+ detail::as_range
+ <
+ typename range_type<OutputGeometry>::type
+ >(out)), strategy);
+ }
+};
+
+
+// Helper metafunction for default strategy retrieval
+template <typename Geometry>
+struct default_strategy
+ : strategy_convex_hull
+ <
+ Geometry,
+ typename point_type<Geometry>::type
+ >
+{};
+
+
+}} // namespace detail::convex_hull
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Geometry,
+ typename Tag = typename tag<Geometry>::type
+>
+struct convex_hull
+ : detail::convex_hull::hull_to_geometry
+{};
+
+template <typename Box>
+struct convex_hull<Box, box_tag>
+{
+ template <typename OutputGeometry, typename Strategy>
+ static inline void apply(Box const& box, OutputGeometry& out,
+ Strategy const& )
+ {
+ static bool const Close
+ = geometry::closure<OutputGeometry>::value == closed;
+ static bool const Reverse
+ = geometry::point_order<OutputGeometry>::value == counterclockwise;
+
+ // A hull for boxes is trivial. Any strategy is (currently) skipped.
+ boost::array<typename point_type<Box>::type, 4> range;
+ geometry::detail::assign_box_corners_oriented<Reverse>(box, range);
+ geometry::append(out, range);
+ if (Close)
+ {
+ geometry::append(out, *boost::begin(range));
+ }
+ }
+};
+
+
+
+template <order_selector Order>
+struct convex_hull_insert
+ : detail::convex_hull::hull_insert<Order>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+template<typename Geometry, typename OutputGeometry, typename Strategy>
+inline void convex_hull(Geometry const& geometry,
+ OutputGeometry& out, Strategy const& strategy)
+{
+ concept::check_concepts_and_equal_dimensions
+ <
+ const Geometry,
+ OutputGeometry
+ >();
+
+ BOOST_CONCEPT_ASSERT( (geometry::concept::ConvexHullStrategy<Strategy>) );
+
+ if (geometry::num_points(geometry) == 0)
+ {
+ // Leave output empty
+ return;
+ }
+
+ dispatch::convex_hull<Geometry>::apply(geometry, out, strategy);
+}
+
+
+/*!
+\brief \brief_calc{convex hull}
+\ingroup convex_hull
+\details \details_calc{convex_hull,convex hull}.
+\tparam Geometry the input geometry type
+\tparam OutputGeometry the output geometry type
+\param geometry \param_geometry, input geometry
+\param hull \param_geometry \param_set{convex hull}
+
+\qbk{[include reference/algorithms/convex_hull.qbk]}
+ */
+template<typename Geometry, typename OutputGeometry>
+inline void convex_hull(Geometry const& geometry,
+ OutputGeometry& hull)
+{
+ concept::check_concepts_and_equal_dimensions
+ <
+ const Geometry,
+ OutputGeometry
+ >();
+
+ typedef typename detail::convex_hull::default_strategy<Geometry>::type strategy_type;
+
+ convex_hull(geometry, hull, strategy_type());
+}
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace convex_hull
+{
+
+
+template<typename Geometry, typename OutputIterator, typename Strategy>
+inline OutputIterator convex_hull_insert(Geometry const& geometry,
+ OutputIterator out, Strategy const& strategy)
+{
+ // Concept: output point type = point type of input geometry
+ concept::check<Geometry const>();
+ concept::check<typename point_type<Geometry>::type>();
+
+ BOOST_CONCEPT_ASSERT( (geometry::concept::ConvexHullStrategy<Strategy>) );
+
+ return dispatch::convex_hull_insert
+ <
+ geometry::point_order<Geometry>::value
+ >::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_insert(Geometry const& geometry,
+ OutputIterator out)
+{
+ // Concept: output point type = point type of input geometry
+ concept::check<Geometry const>();
+ concept::check<typename point_type<Geometry>::type>();
+
+ typedef typename detail::convex_hull::default_strategy<Geometry>::type strategy_type;
+
+ return convex_hull_insert(geometry, out, strategy_type());
+}
+
+
+}} // namespace detail::convex_hull
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_HPP
diff --git a/boost/geometry/algorithms/correct.hpp b/boost/geometry/algorithms/correct.hpp
new file mode 100644
index 000000000..79c76a567
--- /dev/null
+++ b/boost/geometry/algorithms/correct.hpp
@@ -0,0 +1,272 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP
+
+
+#include <algorithm>
+#include <cstddef>
+#include <functional>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/mutable_range.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/algorithms/disjoint.hpp>
+#include <boost/geometry/util/order_as_direction.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+// Silence warning C4127: conditional expression is constant
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4127)
+#endif
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace correct
+{
+
+template <typename Geometry>
+struct correct_nop
+{
+ static inline void apply(Geometry& )
+ {}
+};
+
+
+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& )
+ {}
+
+};
+
+
+// Correct a box: make min/max correct
+template <typename Box>
+struct correct_box
+{
+
+ static inline void apply(Box& box)
+ {
+ // Currently only for Cartesian coordinates
+ // (or spherical without crossing dateline)
+ // Future version: adapt using strategies
+ correct_box_loop
+ <
+ Box, 0, dimension<Box>::type::value
+ >::apply(box);
+ }
+};
+
+
+// Close a ring, if not closed
+template <typename Ring, typename Predicate>
+struct correct_ring
+{
+ typedef typename point_type<Ring>::type point_type;
+ typedef typename coordinate_type<Ring>::type coordinate_type;
+
+ typedef typename strategy::area::services::default_strategy
+ <
+ typename cs_tag<point_type>::type,
+ point_type
+ >::type strategy_type;
+
+ typedef detail::area::ring_area
+ <
+ order_as_direction<geometry::point_order<Ring>::value>::value,
+ geometry::closure<Ring>::value
+ > ring_area_type;
+
+
+ static inline void apply(Ring& r)
+ {
+ // Check close-ness
+ if (boost::size(r) > 2)
+ {
+ // check if closed, if not, close it
+ bool const disjoint = geometry::disjoint(*boost::begin(r), *(boost::end(r) - 1));
+ closure_selector const s = geometry::closure<Ring>::value;
+
+ if (disjoint && (s == closed))
+ {
+ geometry::append(r, *boost::begin(r));
+ }
+ if (! disjoint && s != closed)
+ {
+ // Open it by removing last point
+ geometry::traits::resize<Ring>::apply(r, boost::size(r) - 1);
+ }
+ }
+ // Check area
+ Predicate predicate;
+ typedef typename default_area_result<Ring>::type area_result_type;
+ area_result_type const zero = area_result_type();
+ if (predicate(ring_area_type::apply(r, strategy_type()), zero))
+ {
+ std::reverse(boost::begin(r), boost::end(r));
+ }
+ }
+};
+
+// Correct a polygon: normalizes all rings, sets outer ring clockwise, sets all
+// inner rings counter clockwise (or vice versa depending on orientation)
+template <typename Polygon>
+struct correct_polygon
+{
+ typedef typename ring_type<Polygon>::type ring_type;
+ typedef typename default_area_result<Polygon>::type area_result_type;
+
+ static inline void apply(Polygon& poly)
+ {
+ correct_ring
+ <
+ ring_type,
+ std::less<area_result_type>
+ >::apply(exterior_ring(poly));
+
+ typename interior_return_type<Polygon>::type rings
+ = interior_rings(poly);
+ for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
+ {
+ correct_ring
+ <
+ ring_type,
+ std::greater<area_result_type>
+ >::apply(*it);
+ }
+ }
+};
+
+
+}} // namespace detail::correct
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct correct: not_implemented<Tag>
+{};
+
+template <typename Point>
+struct correct<Point, point_tag>
+ : detail::correct::correct_nop<Point>
+{};
+
+template <typename LineString>
+struct correct<LineString, linestring_tag>
+ : detail::correct::correct_nop<LineString>
+{};
+
+template <typename Segment>
+struct correct<Segment, segment_tag>
+ : detail::correct::correct_nop<Segment>
+{};
+
+
+template <typename Box>
+struct correct<Box, box_tag>
+ : detail::correct::correct_box<Box>
+{};
+
+template <typename Ring>
+struct correct<Ring, ring_tag>
+ : detail::correct::correct_ring
+ <
+ Ring,
+ std::less<typename default_area_result<Ring>::type>
+ >
+{};
+
+template <typename Polygon>
+struct correct<Polygon, polygon_tag>
+ : detail::correct::correct_polygon<Polygon>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Corrects a geometry
+\details Corrects a geometry: all rings which are wrongly oriented with respect
+ to their expected orientation are reversed. To all rings which do not have a
+ closing point and are typed as they should have one, the first point is
+ appended. Also boxes can be corrected.
+\ingroup correct
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry which will be corrected if necessary
+
+\qbk{[include reference/algorithms/correct.qbk]}
+*/
+template <typename Geometry>
+inline void correct(Geometry& geometry)
+{
+ concept::check<Geometry const>();
+
+ dispatch::correct<Geometry>::apply(geometry);
+}
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_CORRECT_HPP
diff --git a/boost/geometry/algorithms/covered_by.hpp b/boost/geometry/algorithms/covered_by.hpp
new file mode 100644
index 000000000..f0f572421
--- /dev/null
+++ b/boost/geometry/algorithms/covered_by.hpp
@@ -0,0 +1,197 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
+
+
+#include <cstddef>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/algorithms/within.hpp>
+
+#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
+#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Tag1 = typename tag<Geometry1>::type,
+ typename Tag2 = typename tag<Geometry2>::type
+>
+struct covered_by: not_implemented<Tag1, Tag2>
+{};
+
+
+template <typename Point, typename Box>
+struct covered_by<Point, Box, point_tag, box_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
+ {
+ ::boost::ignore_unused_variable_warning(strategy);
+ return strategy.apply(point, box);
+ }
+};
+
+template <typename Box1, typename Box2>
+struct covered_by<Box1, Box2, box_tag, box_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
+ {
+ assert_dimension_equal<Box1, Box2>();
+ ::boost::ignore_unused_variable_warning(strategy);
+ return strategy.apply(box1, box2);
+ }
+};
+
+
+
+template <typename Point, typename Ring>
+struct covered_by<Point, Ring, point_tag, ring_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Point const& point, Ring const& ring, Strategy const& strategy)
+ {
+ return detail::within::point_in_ring
+ <
+ Point,
+ Ring,
+ order_as_direction<geometry::point_order<Ring>::value>::value,
+ geometry::closure<Ring>::value,
+ Strategy
+ >::apply(point, ring, strategy) >= 0;
+ }
+};
+
+template <typename Point, typename Polygon>
+struct covered_by<Point, Polygon, point_tag, polygon_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Point const& point, Polygon const& polygon, Strategy const& strategy)
+ {
+ return detail::within::point_in_polygon
+ <
+ Point,
+ Polygon,
+ order_as_direction<geometry::point_order<Polygon>::value>::value,
+ geometry::closure<Polygon>::value,
+ Strategy
+ >::apply(point, polygon, strategy) >= 0;
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief \brief_check12{is inside or on border}
+\ingroup covered_by
+\details \details_check12{covered_by, is inside or on border}.
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry which might be inside or on the border of the second geometry
+\param geometry2 \param_geometry which might cover the first geometry
+\return true if geometry1 is inside of or on the border of geometry2,
+ else false
+\note The default strategy is used for covered_by detection
+
+\qbk{[include reference/algorithms/covered_by.qbk]}
+
+ */
+template<typename Geometry1, typename Geometry2>
+inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+ assert_dimension_equal<Geometry1, Geometry2>();
+
+ typedef typename point_type<Geometry1>::type point_type1;
+ typedef typename point_type<Geometry2>::type point_type2;
+
+ typedef typename strategy::covered_by::services::default_strategy
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ typename tag<Geometry1>::type,
+ typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
+ typename tag_cast
+ <
+ typename cs_tag<point_type1>::type, spherical_tag
+ >::type,
+ typename tag_cast
+ <
+ typename cs_tag<point_type2>::type, spherical_tag
+ >::type,
+ Geometry1,
+ Geometry2
+ >::type strategy_type;
+
+ return dispatch::covered_by
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy_type());
+}
+
+/*!
+\brief \brief_check12{is inside or on border} \brief_strategy
+\ingroup covered_by
+\details \details_check12{covered_by, is inside or on border}, \brief_strategy. \details_strategy_reasons
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry which might be inside or on the border of the second geometry
+\param geometry2 \param_geometry which might cover the first geometry
+\param strategy strategy to be used
+\return true if geometry1 is inside of or on the border of geometry2,
+ else false
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/covered_by.qbk]}
+
+*/
+template<typename Geometry1, typename Geometry2, typename Strategy>
+inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ concept::within::check
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
+ Strategy
+ >();
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+ assert_dimension_equal<Geometry1, Geometry2>();
+
+ return dispatch::covered_by
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
diff --git a/boost/geometry/algorithms/detail/as_range.hpp b/boost/geometry/algorithms/detail/as_range.hpp
new file mode 100644
index 000000000..d0dfb07e4
--- /dev/null
+++ b/boost/geometry/algorithms/detail/as_range.hpp
@@ -0,0 +1,107 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP
+
+
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/util/add_const_if_c.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename GeometryTag, typename Geometry, typename Range, bool IsConst>
+struct as_range
+{
+ static inline typename add_const_if_c<IsConst, Range>::type& get(
+ typename add_const_if_c<IsConst, Geometry>::type& input)
+ {
+ return input;
+ }
+};
+
+
+template <typename Geometry, typename Range, bool IsConst>
+struct as_range<polygon_tag, Geometry, Range, IsConst>
+{
+ static inline typename add_const_if_c<IsConst, Range>::type& get(
+ typename add_const_if_c<IsConst, Geometry>::type& input)
+ {
+ return exterior_ring(input);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+// Will probably be replaced by the more generic "view_as", therefore in detail
+namespace detail
+{
+
+/*!
+\brief Function getting either the range (ring, linestring) itself
+or the outer ring (polygon)
+\details Utility to handle polygon's outer ring as a range
+\ingroup utility
+*/
+template <typename Range, typename Geometry>
+inline Range& as_range(Geometry& input)
+{
+ return dispatch::as_range
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Range,
+ false
+ >::get(input);
+}
+
+
+/*!
+\brief Function getting either the range (ring, linestring) itself
+or the outer ring (polygon), const version
+\details Utility to handle polygon's outer ring as a range
+\ingroup utility
+*/
+template <typename Range, typename Geometry>
+inline Range const& as_range(Geometry const& input)
+{
+ return dispatch::as_range
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Range,
+ true
+ >::get(input);
+}
+
+}
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP
diff --git a/boost/geometry/algorithms/detail/assign_box_corners.hpp b/boost/geometry/algorithms/detail/assign_box_corners.hpp
new file mode 100644
index 000000000..1637c30cc
--- /dev/null
+++ b/boost/geometry/algorithms/detail/assign_box_corners.hpp
@@ -0,0 +1,103 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_BOX_CORNERS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_BOX_CORNERS_HPP
+
+
+#include <cstddef>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/detail/assign_values.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+// Note: this is moved to namespace detail because the names and parameter orders
+// are not yet 100% clear.
+
+/*!
+\brief Assign the four points of a 2D box
+\ingroup assign
+\note The order is crucial. Most logical is LOWER, UPPER and sub-order LEFT, RIGHT
+ so this is how it is implemented.
+\tparam Box \tparam_box
+\tparam Point \tparam_point
+\param box \param_box
+\param lower_left point being assigned to lower left coordinates of the box
+\param lower_right point being assigned to lower right coordinates of the box
+\param upper_left point being assigned to upper left coordinates of the box
+\param upper_right point being assigned to upper right coordinates of the box
+
+\qbk{
+[heading Example]
+[assign_box_corners] [assign_box_corners_output]
+}
+*/
+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<Box const>();
+ 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);
+}
+
+// Silence warning C4127: conditional expression is constant
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4127)
+#endif
+
+
+template <bool Reverse, typename Box, typename Range>
+inline void assign_box_corners_oriented(Box const& box, Range& corners)
+{
+ if (Reverse)
+ {
+ // make counterclockwise ll,lr,ur,ul
+ assign_box_corners(box, corners[0], corners[1], corners[3], corners[2]);
+ }
+ else
+ {
+ // make clockwise ll,ul,ur,lr
+ assign_box_corners(box, corners[0], corners[3], corners[1], corners[2]);
+ }
+}
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_BOX_CORNERS_HPP
diff --git a/boost/geometry/algorithms/detail/assign_indexed_point.hpp b/boost/geometry/algorithms/detail/assign_indexed_point.hpp
new file mode 100644
index 000000000..a1cffb80a
--- /dev/null
+++ b/boost/geometry/algorithms/detail/assign_indexed_point.hpp
@@ -0,0 +1,94 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_INDEXED_POINT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_INDEXED_POINT_HPP
+
+
+#include <cstddef>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/detail/assign_values.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+/*!
+\brief Assign a box or segment with the value of a point
+\ingroup assign
+\tparam Index indicates which box-corner, min_corner (0) or max_corner (1)
+ or which point of segment (0/1)
+\tparam Point \tparam_point
+\tparam Geometry \tparam_box_or_segment
+\param point \param_point
+\param geometry \param_box_or_segment
+
+\qbk{
+[heading Example]
+[assign_point_to_index] [assign_point_to_index_output]
+}
+*/
+template <std::size_t Index, typename Geometry, typename Point>
+inline void assign_point_to_index(Point const& point, Geometry& geometry)
+{
+ concept::check<Point const>();
+ 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 assign
+\tparam Index indicates which box-corner, min_corner (0) or max_corner (1)
+ or which point of segment (0/1)
+\tparam Geometry \tparam_box_or_segment
+\tparam Point \tparam_point
+\param geometry \param_box_or_segment
+\param point \param_point
+
+\qbk{
+[heading Example]
+[assign_point_from_index] [assign_point_from_index_output]
+}
+*/
+template <std::size_t Index, typename Point, typename Geometry>
+inline void assign_point_from_index(Geometry const& geometry, Point& point)
+{
+ concept::check<Geometry const>();
+ concept::check<Point>();
+
+ detail::assign::assign_point_from_index
+ <
+ Geometry, Point, Index, 0, dimension<Geometry>::type::value
+ >::apply(geometry, point);
+}
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ASSIGN_INDEXED_POINT_HPP
diff --git a/boost/geometry/algorithms/detail/assign_values.hpp b/boost/geometry/algorithms/detail/assign_values.hpp
new file mode 100644
index 000000000..ed4713493
--- /dev/null
+++ b/boost/geometry/algorithms/detail/assign_values.hpp
@@ -0,0 +1,443 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
+
+
+#include <cstddef>
+
+#include <boost/concept/requires.hpp>
+#include <boost/concept_check.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/numeric/conversion/bounds.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/algorithms/append.hpp>
+#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+
+#include <boost/geometry/util/for_each_coordinate.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace assign
+{
+
+
+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)
+ {
+ geometry::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)
+ {
+ geometry::assign_value(point, 0);
+ }
+};
+
+
+template <typename BoxOrSegment>
+struct assign_inverse_box_or_segment
+{
+ typedef typename point_type<BoxOrSegment>::type point_type;
+
+ static inline void apply(BoxOrSegment& geometry)
+ {
+ typedef typename coordinate_type<point_type>::type bound_type;
+
+ initialize
+ <
+ BoxOrSegment, 0, 0, dimension<BoxOrSegment>::type::value
+ >::apply(
+ geometry, boost::numeric::bounds<bound_type>::highest());
+ initialize
+ <
+ BoxOrSegment, 1, 0, dimension<BoxOrSegment>::type::value
+ >::apply(
+ geometry, boost::numeric::bounds<bound_type>::lowest());
+ }
+};
+
+
+template <typename BoxOrSegment>
+struct assign_zero_box_or_segment
+{
+ static inline void apply(BoxOrSegment& geometry)
+ {
+ typedef typename coordinate_type<BoxOrSegment>::type coordinate_type;
+
+ initialize
+ <
+ BoxOrSegment, 0, 0, dimension<BoxOrSegment>::type::value
+ >::apply(geometry, coordinate_type());
+ initialize
+ <
+ BoxOrSegment, 1, 0, dimension<BoxOrSegment>::type::value
+ >::apply(geometry, 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;
+
+ geometry::set<0>(point, boost::numeric_cast<coordinate_type>(get<Corner1, 0>(box)));
+ geometry::set<1>(point, boost::numeric_cast<coordinate_type>(get<Corner2, 1>(box)));
+}
+
+
+
+template
+<
+ typename Geometry, typename Point,
+ std::size_t Index,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct assign_point_to_index
+{
+
+ static inline void apply(Point const& point, Geometry& geometry)
+ {
+ geometry::set<Index, Dimension>(geometry, boost::numeric_cast
+ <
+ typename coordinate_type<Geometry>::type
+ >(geometry::get<Dimension>(point)));
+
+ assign_point_to_index
+ <
+ Geometry, Point, Index, Dimension + 1, DimensionCount
+ >::apply(point, geometry);
+ }
+};
+
+template
+<
+ typename Geometry, typename Point,
+ std::size_t Index,
+ std::size_t DimensionCount
+>
+struct assign_point_to_index
+ <
+ Geometry, Point,
+ Index,
+ DimensionCount, DimensionCount
+ >
+{
+ static inline void apply(Point const& , Geometry& )
+ {
+ }
+};
+
+
+template
+<
+ typename Geometry, typename Point,
+ std::size_t Index,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct assign_point_from_index
+{
+
+ static inline void apply(Geometry const& geometry, Point& point)
+ {
+ geometry::set<Dimension>( point, boost::numeric_cast
+ <
+ typename coordinate_type<Point>::type
+ >(geometry::get<Index, Dimension>(geometry)));
+
+ assign_point_from_index
+ <
+ Geometry, Point, Index, Dimension + 1, DimensionCount
+ >::apply(geometry, point);
+ }
+};
+
+template
+<
+ typename Geometry, typename Point,
+ std::size_t Index,
+ std::size_t DimensionCount
+>
+struct assign_point_from_index
+ <
+ Geometry, Point,
+ Index,
+ DimensionCount, DimensionCount
+ >
+{
+ static inline void apply(Geometry const&, Point&)
+ {
+ }
+};
+
+
+template <typename Geometry>
+struct assign_2d_box_or_segment
+{
+ typedef typename coordinate_type<Geometry>::type coordinate_type;
+
+ // Here we assign 4 coordinates to a box of segment
+ // -> Most logical is: x1,y1,x2,y2
+ // In case the user reverses x1/x2 or y1/y2, for a box, we could reverse them (THAT IS NOT IMPLEMENTED)
+
+ template <typename Type>
+ static inline void apply(Geometry& geometry,
+ Type const& x1, Type const& y1, Type const& x2, Type const& y2)
+ {
+ geometry::set<0, 0>(geometry, boost::numeric_cast<coordinate_type>(x1));
+ geometry::set<0, 1>(geometry, boost::numeric_cast<coordinate_type>(y1));
+ geometry::set<1, 0>(geometry, boost::numeric_cast<coordinate_type>(x2));
+ geometry::set<1, 1>(geometry, boost::numeric_cast<coordinate_type>(y2));
+ }
+};
+
+
+}} // namespace detail::assign
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename GeometryTag, typename Geometry, std::size_t DimensionCount>
+struct assign
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<Geometry>)
+ );
+};
+
+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>
+ : detail::assign::assign_2d_box_or_segment<Box>
+{};
+
+template <typename Segment>
+struct assign<segment_tag, Segment, 2>
+ : detail::assign::assign_2d_box_or_segment<Segment>
+{};
+
+
+
+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_or_segment<Box>
+{};
+
+template <typename Segment>
+struct assign_zero<segment_tag, Segment>
+ : detail::assign::assign_zero_box_or_segment<Segment>
+{};
+
+
+template <typename GeometryTag, typename Geometry>
+struct assign_inverse {};
+
+template <typename Box>
+struct assign_inverse<box_tag, Box>
+ : detail::assign::assign_inverse_box_or_segment<Box>
+{};
+
+template <typename Segment>
+struct assign_inverse<segment_tag, Segment>
+ : detail::assign::assign_inverse_box_or_segment<Segment>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Assign two coordinates to a geometry (usually a 2D point)
+\ingroup assign
+\tparam Geometry \tparam_geometry
+\tparam Type \tparam_numeric to specify the coordinates
+\param geometry \param_geometry
+\param c1 \param_x
+\param c2 \param_y
+
+\qbk{distinguish, 2 coordinate values}
+\qbk{
+[heading Example]
+[assign_2d_point] [assign_2d_point_output]
+
+[heading See also]
+\* [link geometry.reference.algorithms.make.make_2_2_coordinate_values make]
+}
+ */
+template <typename Geometry, typename Type>
+inline void assign_values(Geometry& geometry, Type const& c1, Type const& c2)
+{
+ concept::check<Geometry>();
+
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ geometry::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2);
+}
+
+/*!
+\brief Assign three values to a geometry (usually a 3D point)
+\ingroup assign
+\tparam Geometry \tparam_geometry
+\tparam Type \tparam_numeric to specify the coordinates
+\param geometry \param_geometry
+\param c1 \param_x
+\param c2 \param_y
+\param c3 \param_z
+
+\qbk{distinguish, 3 coordinate values}
+\qbk{
+[heading Example]
+[assign_3d_point] [assign_3d_point_output]
+
+[heading See also]
+\* [link geometry.reference.algorithms.make.make_3_3_coordinate_values make]
+}
+ */
+template <typename Geometry, typename Type>
+inline void assign_values(Geometry& geometry,
+ Type const& c1, Type const& c2, Type const& c3)
+{
+ concept::check<Geometry>();
+
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ geometry::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2, c3);
+}
+
+/*!
+\brief Assign four values to a geometry (usually a box or segment)
+\ingroup assign
+\tparam Geometry \tparam_geometry
+\tparam Type \tparam_numeric to specify the coordinates
+\param geometry \param_geometry
+\param c1 First coordinate (usually x1)
+\param c2 Second coordinate (usually y1)
+\param c3 Third coordinate (usually x2)
+\param c4 Fourth coordinate (usually y2)
+
+\qbk{distinguish, 4 coordinate values}
+ */
+template <typename Geometry, typename Type>
+inline void assign_values(Geometry& geometry,
+ Type const& c1, Type const& c2, Type const& c3, Type const& c4)
+{
+ concept::check<Geometry>();
+
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ geometry::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2, c3, c4);
+}
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
diff --git a/boost/geometry/algorithms/detail/calculate_null.hpp b/boost/geometry/algorithms/detail/calculate_null.hpp
new file mode 100644
index 000000000..3ebca8350
--- /dev/null
+++ b/boost/geometry/algorithms/detail/calculate_null.hpp
@@ -0,0 +1,38 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+struct calculate_null
+{
+ template<typename ReturnType, typename Geometry, typename Strategy>
+ static inline ReturnType apply(Geometry const& , Strategy const&)
+ {
+ return ReturnType();
+ }
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_NULL_HPP
diff --git a/boost/geometry/algorithms/detail/calculate_sum.hpp b/boost/geometry/algorithms/detail/calculate_sum.hpp
new file mode 100644
index 000000000..dd0399bb1
--- /dev/null
+++ b/boost/geometry/algorithms/detail/calculate_sum.hpp
@@ -0,0 +1,58 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP
+
+
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+class calculate_polygon_sum
+{
+ template <typename ReturnType, typename Policy, typename Rings, typename Strategy>
+ static inline ReturnType sum_interior_rings(Rings const& rings, Strategy const& strategy)
+ {
+ ReturnType sum = ReturnType();
+ for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
+ {
+ sum += Policy::apply(*it, strategy);
+ }
+ return sum;
+ }
+
+public :
+ template <typename ReturnType, typename Policy, typename Polygon, typename Strategy>
+ static inline ReturnType apply(Polygon const& poly, Strategy const& strategy)
+ {
+ return Policy::apply(exterior_ring(poly), strategy)
+ + sum_interior_rings<ReturnType, Policy>(interior_rings(poly), strategy)
+ ;
+ }
+};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CALCULATE_SUM_HPP
diff --git a/boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp b/boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp
new file mode 100644
index 000000000..d39824a61
--- /dev/null
+++ b/boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp
@@ -0,0 +1,80 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_INDEXED_TO_INDEXED_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_INDEXED_TO_INDEXED_HPP
+
+
+#include <cstddef>
+
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace conversion
+{
+
+
+template
+<
+ typename Source,
+ typename Destination,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct indexed_to_indexed
+{
+ static inline void apply(Source const& source, Destination& destination)
+ {
+ typedef typename coordinate_type<Destination>::type coordinate_type;
+
+ geometry::set<min_corner, Dimension>(destination,
+ boost::numeric_cast<coordinate_type>(
+ geometry::get<min_corner, Dimension>(source)));
+ geometry::set<max_corner, Dimension>(destination,
+ boost::numeric_cast<coordinate_type>(
+ geometry::get<max_corner, Dimension>(source)));
+
+ indexed_to_indexed
+ <
+ Source, Destination,
+ Dimension + 1, DimensionCount
+ >::apply(source, destination);
+ }
+};
+
+template
+<
+ typename Source,
+ typename Destination,
+ std::size_t DimensionCount
+>
+struct indexed_to_indexed<Source, Destination, DimensionCount, DimensionCount>
+{
+ static inline void apply(Source const& , Destination& )
+ {}
+};
+
+
+}} // namespace detail::conversion
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_INDEXED_TO_INDEXED_HPP
diff --git a/boost/geometry/algorithms/detail/convert_point_to_point.hpp b/boost/geometry/algorithms/detail/convert_point_to_point.hpp
new file mode 100644
index 000000000..c7d37b6ca
--- /dev/null
+++ b/boost/geometry/algorithms/detail/convert_point_to_point.hpp
@@ -0,0 +1,68 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_POINT_TO_POINT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_POINT_TO_POINT_HPP
+
+// Note: extracted from "convert.hpp" to avoid circular references convert/append
+
+#include <cstddef>
+
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace conversion
+{
+
+
+template <typename Source, typename Destination, std::size_t Dimension, std::size_t DimensionCount>
+struct point_to_point
+{
+ static inline void apply(Source const& source, Destination& destination)
+ {
+ typedef typename coordinate_type<Destination>::type coordinate_type;
+
+ set<Dimension>(destination, boost::numeric_cast<coordinate_type>(get<Dimension>(source)));
+ point_to_point<Source, Destination, Dimension + 1, DimensionCount>::apply(source, destination);
+ }
+};
+
+template <typename Source, typename Destination, std::size_t DimensionCount>
+struct point_to_point<Source, Destination, DimensionCount, DimensionCount>
+{
+ static inline void apply(Source const& , Destination& )
+ {}
+};
+
+
+template <typename Source, typename Destination>
+inline void convert_point_to_point(Source const& source, Destination& destination)
+{
+ point_to_point<Source, Destination, 0, dimension<Destination>::value>::apply(source, destination);
+}
+
+
+
+}} // namespace detail::conversion
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CONVERT_POINT_TO_POINT_HPP
diff --git a/boost/geometry/algorithms/detail/disjoint.hpp b/boost/geometry/algorithms/detail/disjoint.hpp
new file mode 100644
index 000000000..e944e5169
--- /dev/null
+++ b/boost/geometry/algorithms/detail/disjoint.hpp
@@ -0,0 +1,239 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_HPP
+
+// Note: contrary to most files, the geometry::detail::disjoint namespace
+// is partly implemented in a separate file, to avoid circular references
+// disjoint -> get_turns -> disjoint
+
+#include <cstddef>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/reverse_dispatch.hpp>
+
+#include <boost/geometry/algorithms/covered_by.hpp>
+
+#include <boost/geometry/util/math.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace disjoint
+{
+
+
+struct disjoint_interrupt_policy
+{
+ static bool const enabled = true;
+ bool has_intersections;
+
+ inline disjoint_interrupt_policy()
+ : has_intersections(false)
+ {}
+
+ template <typename Range>
+ inline bool apply(Range const& range)
+ {
+ // If there is any IP in the range, it is NOT disjoint
+ if (boost::size(range) > 0)
+ {
+ has_intersections = true;
+ return true;
+ }
+ return false;
+ }
+};
+
+
+
+template
+<
+ typename Point1, typename Point2,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct point_point
+{
+ static inline bool apply(Point1 const& p1, Point2 const& p2)
+ {
+ if (! geometry::math::equals(get<Dimension>(p1), get<Dimension>(p2)))
+ {
+ return true;
+ }
+ return point_point
+ <
+ Point1, Point2,
+ Dimension + 1, DimensionCount
+ >::apply(p1, p2);
+ }
+};
+
+
+template <typename Point1, typename Point2, std::size_t DimensionCount>
+struct point_point<Point1, Point2, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Point1 const& , Point2 const& )
+ {
+ return false;
+ }
+};
+
+
+template
+<
+ typename Point, typename Box,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct point_box
+{
+ static inline bool apply(Point const& point, Box const& box)
+ {
+ if (get<Dimension>(point) < get<min_corner, Dimension>(box)
+ || get<Dimension>(point) > get<max_corner, Dimension>(box))
+ {
+ return true;
+ }
+ return point_box
+ <
+ Point, Box,
+ Dimension + 1, DimensionCount
+ >::apply(point, box);
+ }
+};
+
+
+template <typename Point, typename Box, std::size_t DimensionCount>
+struct point_box<Point, Box, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Point const& , Box const& )
+ {
+ return false;
+ }
+};
+
+
+template
+<
+ typename Box1, typename Box2,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct box_box
+{
+ static inline bool apply(Box1 const& box1, Box2 const& box2)
+ {
+ if (get<max_corner, Dimension>(box1) < get<min_corner, Dimension>(box2))
+ {
+ return true;
+ }
+ if (get<min_corner, Dimension>(box1) > get<max_corner, Dimension>(box2))
+ {
+ return true;
+ }
+ return box_box
+ <
+ Box1, Box2,
+ Dimension + 1, DimensionCount
+ >::apply(box1, box2);
+ }
+};
+
+
+template <typename Box1, typename Box2, std::size_t DimensionCount>
+struct box_box<Box1, Box2, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Box1 const& , Box2 const& )
+ {
+ return false;
+ }
+};
+
+
+template
+<
+ typename Geometry1, typename Geometry2
+>
+struct reverse_covered_by
+{
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ {
+ return ! geometry::covered_by(geometry1, geometry2);
+ }
+};
+
+
+
+/*!
+ \brief Internal utility function to detect of boxes are disjoint
+ \note Is used from other algorithms, declared separately
+ to avoid circular references
+ */
+template <typename Box1, typename Box2>
+inline bool disjoint_box_box(Box1 const& box1, Box2 const& box2)
+{
+ return box_box
+ <
+ Box1, Box2,
+ 0, dimension<Box1>::type::value
+ >::apply(box1, box2);
+}
+
+
+
+/*!
+ \brief Internal utility function to detect of points are disjoint
+ \note To avoid circular references
+ */
+template <typename Point1, typename Point2>
+inline bool disjoint_point_point(Point1 const& point1, Point2 const& point2)
+{
+ return point_point
+ <
+ Point1, Point2,
+ 0, dimension<Point1>::type::value
+ >::apply(point1, point2);
+}
+
+
+}} // namespace detail::disjoint
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace equals
+{
+
+/*!
+ \brief Internal utility function to detect of points are disjoint
+ \note To avoid circular references
+ */
+template <typename Point1, typename Point2>
+inline bool equals_point_point(Point1 const& point1, Point2 const& point2)
+{
+ return ! detail::disjoint::disjoint_point_point(point1, point2);
+}
+
+
+}} // namespace detail::equals
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_HPP
diff --git a/boost/geometry/algorithms/detail/equals/collect_vectors.hpp b/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
new file mode 100644
index 000000000..9c2fe2805
--- /dev/null
+++ b/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
@@ -0,0 +1,315 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_COLLECT_VECTORS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_COLLECT_VECTORS_HPP
+
+
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/util/math.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+// TODO: if Boost.LA of Emil Dotchevski is accepted, adapt this
+template <typename T>
+struct collected_vector
+{
+ typedef T type;
+
+ inline collected_vector()
+ {}
+
+ inline collected_vector(T const& px, T const& py,
+ T const& pdx, T const& pdy)
+ : x(px)
+ , y(py)
+ , dx(pdx)
+ , dy(pdy)
+ , dx_0(T())
+ , dy_0(T())
+ {}
+
+ T x, y;
+ T dx, dy;
+ T dx_0, dy_0;
+
+ // For sorting
+ inline bool operator<(collected_vector<T> const& other) const
+ {
+ if (math::equals(x, other.x))
+ {
+ if (math::equals(y, other.y))
+ {
+ if (math::equals(dx, other.dx))
+ {
+ return dy < other.dy;
+ }
+ return dx < other.dx;
+ }
+ return y < other.y;
+ }
+ return x < other.x;
+ }
+
+ inline bool same_direction(collected_vector<T> const& other) const
+ {
+ // For high precision arithmetic, we have to be
+ // more relaxed then using ==
+ // Because 2/sqrt( (0,0)<->(2,2) ) == 1/sqrt( (0,0)<->(1,1) )
+ // is not always true (at least, it is not for ttmath)
+ return math::equals_with_epsilon(dx, other.dx)
+ && math::equals_with_epsilon(dy, other.dy);
+ }
+
+ // For std::equals
+ inline bool operator==(collected_vector<T> const& other) const
+ {
+ return math::equals(x, other.x)
+ && math::equals(y, other.y)
+ && same_direction(other);
+ }
+};
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace collect_vectors
+{
+
+
+template <typename Range, typename Collection>
+struct range_collect_vectors
+{
+ typedef typename boost::range_value<Collection>::type item_type;
+ typedef typename item_type::type calculation_type;
+
+ static inline void apply(Collection& collection, Range const& range)
+ {
+ if (boost::size(range) < 2)
+ {
+ return;
+ }
+
+ typedef typename boost::range_iterator<Range const>::type iterator;
+
+ bool first = true;
+ iterator it = boost::begin(range);
+
+ for (iterator prev = it++;
+ it != boost::end(range);
+ prev = it++)
+ {
+ typename boost::range_value<Collection>::type v;
+
+ v.x = get<0>(*prev);
+ v.y = get<1>(*prev);
+ v.dx = get<0>(*it) - v.x;
+ v.dy = get<1>(*it) - v.y;
+ v.dx_0 = v.dx;
+ v.dy_0 = v.dy;
+
+ // Normalize the vector -> this results in points+direction
+ // and is comparible between geometries
+ calculation_type magnitude = sqrt(
+ boost::numeric_cast<calculation_type>(v.dx * v.dx + v.dy * v.dy));
+
+ // Avoid non-duplicate points (AND division by zero)
+ if (magnitude > 0)
+ {
+ v.dx /= magnitude;
+ v.dy /= magnitude;
+
+ // Avoid non-direction changing points
+ if (first || ! v.same_direction(collection.back()))
+ {
+ collection.push_back(v);
+ }
+ first = false;
+ }
+ }
+
+ // If first one has same direction as last one, remove first one
+ if (boost::size(collection) > 1
+ && collection.front().same_direction(collection.back()))
+ {
+ collection.erase(collection.begin());
+ }
+ }
+};
+
+
+template <typename Box, typename Collection>
+struct box_collect_vectors
+{
+ // Calculate on coordinate type, but if it is integer,
+ // then use double
+ typedef typename boost::range_value<Collection>::type item_type;
+ typedef typename item_type::type calculation_type;
+
+ static inline void apply(Collection& collection, Box const& box)
+ {
+ typename point_type<Box>::type lower_left, lower_right,
+ upper_left, upper_right;
+ geometry::detail::assign_box_corners(box, lower_left, lower_right,
+ upper_left, upper_right);
+
+ typedef typename boost::range_value<Collection>::type item;
+
+ collection.push_back(item(get<0>(lower_left), get<1>(lower_left), 0, 1));
+ collection.push_back(item(get<0>(upper_left), get<1>(upper_left), 1, 0));
+ collection.push_back(item(get<0>(upper_right), get<1>(upper_right), 0, -1));
+ collection.push_back(item(get<0>(lower_right), get<1>(lower_right), -1, 0));
+ }
+};
+
+
+template <typename Polygon, typename Collection>
+struct polygon_collect_vectors
+{
+ static inline void apply(Collection& collection, Polygon const& polygon)
+ {
+ typedef typename geometry::ring_type<Polygon>::type ring_type;
+
+ typedef range_collect_vectors<ring_type, Collection> per_range;
+ per_range::apply(collection, exterior_ring(polygon));
+
+ typename interior_return_type<Polygon const>::type rings
+ = interior_rings(polygon);
+ for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
+ {
+ per_range::apply(collection, *it);
+ }
+ }
+};
+
+
+template <typename MultiGeometry, typename Collection, typename SinglePolicy>
+struct multi_collect_vectors
+{
+ static inline void apply(Collection& collection, MultiGeometry const& multi)
+ {
+ for (typename boost::range_iterator<MultiGeometry const>::type
+ it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ SinglePolicy::apply(collection, *it);
+ }
+ }
+};
+
+
+}} // namespace detail::collect_vectors
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Tag,
+ typename Collection,
+ typename Geometry
+>
+struct collect_vectors
+{
+ static inline void apply(Collection&, Geometry const&)
+ {}
+};
+
+
+template <typename Collection, typename Box>
+struct collect_vectors<box_tag, Collection, Box>
+ : detail::collect_vectors::box_collect_vectors<Box, Collection>
+{};
+
+
+
+template <typename Collection, typename Ring>
+struct collect_vectors<ring_tag, Collection, Ring>
+ : detail::collect_vectors::range_collect_vectors<Ring, Collection>
+{};
+
+
+template <typename Collection, typename LineString>
+struct collect_vectors<linestring_tag, Collection, LineString>
+ : detail::collect_vectors::range_collect_vectors<LineString, Collection>
+{};
+
+
+template <typename Collection, typename Polygon>
+struct collect_vectors<polygon_tag, Collection, Polygon>
+ : detail::collect_vectors::polygon_collect_vectors<Polygon, Collection>
+{};
+
+
+template <typename Collection, typename MultiPolygon>
+struct collect_vectors<multi_polygon_tag, Collection, MultiPolygon>
+ : detail::collect_vectors::multi_collect_vectors
+ <
+ MultiPolygon,
+ Collection,
+ detail::collect_vectors::polygon_collect_vectors
+ <
+ typename boost::range_value<MultiPolygon>::type,
+ Collection
+ >
+ >
+{};
+
+
+
+} // namespace dispatch
+#endif
+
+
+/*!
+ \ingroup collect_vectors
+ \tparam Collection Collection type, should be e.g. std::vector<>
+ \tparam Geometry geometry type
+ \param collection the collection of vectors
+ \param geometry the geometry to make collect_vectors
+*/
+template <typename Collection, typename Geometry>
+inline void collect_vectors(Collection& collection, Geometry const& geometry)
+{
+ concept::check<Geometry const>();
+
+ dispatch::collect_vectors
+ <
+ typename tag<Geometry>::type,
+ Collection,
+ Geometry
+ >::apply(collection, geometry);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_COLLECT_VECTORS_HPP
diff --git a/boost/geometry/algorithms/detail/for_each_range.hpp b/boost/geometry/algorithms/detail/for_each_range.hpp
new file mode 100644
index 000000000..7cb01fa9b
--- /dev/null
+++ b/boost/geometry/algorithms/detail/for_each_range.hpp
@@ -0,0 +1,149 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_FOR_EACH_RANGE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_FOR_EACH_RANGE_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/concept/requires.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+
+#include <boost/geometry/util/add_const_if_c.hpp>
+#include <boost/geometry/views/box_view.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace for_each
+{
+
+
+template <typename Range, typename Actor, bool IsConst>
+struct fe_range_range
+{
+ static inline void apply(
+ typename add_const_if_c<IsConst, Range>::type& range,
+ Actor& actor)
+ {
+ actor.apply(range);
+ }
+};
+
+
+template <typename Polygon, typename Actor, bool IsConst>
+struct fe_range_polygon
+{
+ static inline void apply(
+ typename add_const_if_c<IsConst, Polygon>::type& polygon,
+ Actor& actor)
+ {
+ actor.apply(exterior_ring(polygon));
+
+ // TODO: If some flag says true, also do the inner rings.
+ // for convex hull, it's not necessary
+ }
+};
+
+template <typename Box, typename Actor, bool IsConst>
+struct fe_range_box
+{
+ static inline void apply(
+ typename add_const_if_c<IsConst, Box>::type& box,
+ Actor& actor)
+ {
+ actor.apply(box_view<Box>(box));
+ }
+};
+
+
+}} // namespace detail::for_each
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Tag,
+ typename Geometry,
+ typename Actor,
+ bool IsConst
+>
+struct for_each_range
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<Geometry>)
+ );
+};
+
+
+template <typename Linestring, typename Actor, bool IsConst>
+struct for_each_range<linestring_tag, Linestring, Actor, IsConst>
+ : detail::for_each::fe_range_range<Linestring, Actor, IsConst>
+{};
+
+
+template <typename Ring, typename Actor, bool IsConst>
+struct for_each_range<ring_tag, Ring, Actor, IsConst>
+ : detail::for_each::fe_range_range<Ring, Actor, IsConst>
+{};
+
+
+template <typename Polygon, typename Actor, bool IsConst>
+struct for_each_range<polygon_tag, Polygon, Actor, IsConst>
+ : detail::for_each::fe_range_polygon<Polygon, Actor, IsConst>
+{};
+
+template <typename Box, typename Actor, bool IsConst>
+struct for_each_range<box_tag, Box, Actor, IsConst>
+ : detail::for_each::fe_range_box<Box, Actor, IsConst>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+namespace detail
+{
+
+template <typename Geometry, typename Actor>
+inline void for_each_range(Geometry const& geometry, Actor& actor)
+{
+ dispatch::for_each_range
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Actor,
+ true
+ >::apply(geometry, actor);
+}
+
+
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_FOR_EACH_RANGE_HPP
diff --git a/boost/geometry/algorithms/detail/get_left_turns.hpp b/boost/geometry/algorithms/detail/get_left_turns.hpp
new file mode 100644
index 000000000..d23f1e4c2
--- /dev/null
+++ b/boost/geometry/algorithms/detail/get_left_turns.hpp
@@ -0,0 +1,371 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP
+
+#include <boost/geometry/iterators/ever_circling_iterator.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+// TODO: move this to /util/
+template <typename T>
+static inline std::pair<T, T> ordered_pair(T const& first, T const& second)
+{
+ return first < second ? std::make_pair(first, second) : std::make_pair(second, first);
+}
+
+template <typename AngleInfo>
+inline void debug_left_turn(AngleInfo const& ai, AngleInfo const& previous)
+{
+#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_OCCUPATION
+ std::cout << "Angle: " << (ai.incoming ? "i" : "o")
+ << " " << si(ai.seg_id)
+ << " " << (math::r2d * (ai.angle) )
+ << " turn: " << ai.turn_index << "[" << ai.operation_index << "]"
+ ;
+
+ if (ai.turn_index != previous.turn_index
+ || ai.operation_index != previous.operation_index)
+ {
+ std::cout << " diff: " << math::r2d * math::abs(previous.angle - ai.angle);
+ }
+ std::cout << std::endl;
+#endif
+}
+
+template <typename AngleInfo>
+inline void debug_left_turn(std::string const& caption, AngleInfo const& ai, AngleInfo const& previous,
+ int code = -99, int code2 = -99, int code3 = -99, int code4 = -99)
+{
+#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_OCCUPATION
+ std::cout << " " << caption
+ << " turn: " << ai.turn_index << "[" << ai.operation_index << "]"
+ << " " << si(ai.seg_id)
+ << " " << (ai.incoming ? "i" : "o")
+ << " " << (math::r2d * (ai.angle) )
+ << " turn: " << previous.turn_index << "[" << previous.operation_index << "]"
+ << " " << si(previous.seg_id)
+ << " " << (previous.incoming ? "i" : "o")
+ << " " << (math::r2d * (previous.angle) )
+ ;
+
+ if (code != -99)
+ {
+ std::cout << " code: " << code << " , " << code2 << " , " << code3 << " , " << code4;
+ }
+ std::cout << std::endl;
+#endif
+}
+
+
+template <typename Operation>
+inline bool include_operation(Operation const& op,
+ segment_identifier const& outgoing_seg_id,
+ segment_identifier const& incoming_seg_id)
+{
+ return op.seg_id == outgoing_seg_id
+ && op.other_id == incoming_seg_id
+ && (op.operation == detail::overlay::operation_union
+ ||op.operation == detail::overlay::operation_continue)
+ ;
+}
+
+template <typename Turn>
+inline bool process_include(segment_identifier const& outgoing_seg_id, segment_identifier const& incoming_seg_id,
+ int turn_index, Turn& turn,
+ std::set<int>& keep_indices, int priority)
+{
+ bool result = false;
+ for (int i = 0; i < 2; i++)
+ {
+ if (include_operation(turn.operations[i], outgoing_seg_id, incoming_seg_id))
+ {
+ turn.operations[i].include_in_occupation_map = true;
+ if (priority > turn.priority)
+ {
+ turn.priority = priority;
+ }
+ keep_indices.insert(turn_index);
+ result = true;
+ }
+ }
+ return result;
+}
+
+template <typename AngleInfo, typename Turns, typename TurnSegmentIndices>
+inline bool include_left_turn_of_all(
+ AngleInfo const& outgoing, AngleInfo const& incoming,
+ Turns& turns, TurnSegmentIndices const& turn_segment_indices,
+ std::set<int>& keep_indices, int priority)
+{
+ segment_identifier const& outgoing_seg_id = turns[outgoing.turn_index].operations[outgoing.operation_index].seg_id;
+ segment_identifier const& incoming_seg_id = turns[incoming.turn_index].operations[incoming.operation_index].seg_id;
+
+ if (outgoing.turn_index == incoming.turn_index)
+ {
+ return process_include(outgoing_seg_id, incoming_seg_id, outgoing.turn_index, turns[outgoing.turn_index], keep_indices, priority);
+ }
+
+ bool result = false;
+ std::pair<segment_identifier, segment_identifier> pair = ordered_pair(outgoing_seg_id, incoming_seg_id);
+ typename boost::range_iterator<TurnSegmentIndices const>::type it = turn_segment_indices.find(pair);
+ if (it != turn_segment_indices.end())
+ {
+ for (std::set<int>::const_iterator sit = it->second.begin(); sit != it->second.end(); ++sit)
+ {
+ if (process_include(outgoing_seg_id, incoming_seg_id, *sit, turns[*sit], keep_indices, priority))
+ {
+ result = true;
+ }
+ }
+ }
+ return result;
+}
+
+template <std::size_t Index, typename Turn>
+inline bool corresponds(Turn const& turn, segment_identifier const& seg_id)
+{
+ return turn.operations[Index].operation == detail::overlay::operation_union
+ && turn.operations[Index].seg_id == seg_id;
+}
+
+
+template <typename Turns, typename TurnSegmentIndices>
+inline bool prefer_by_other(Turns const& turns,
+ TurnSegmentIndices const& turn_segment_indices,
+ std::set<int>& indices)
+{
+ std::map<segment_identifier, int> map;
+ for (std::set<int>::const_iterator sit = indices.begin();
+ sit != indices.end();
+ ++sit)
+ {
+ map[turns[*sit].operations[0].seg_id]++;
+ map[turns[*sit].operations[1].seg_id]++;
+ }
+
+ std::set<segment_identifier> segment_occuring_once;
+ for (std::map<segment_identifier, int>::const_iterator mit = map.begin();
+ mit != map.end();++mit)
+ {
+ if (mit->second == 1)
+ {
+ segment_occuring_once.insert(mit->first);
+ }
+#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_PREFER
+ std::cout << si(mit->first) << " " << mit->second << std::endl;
+#endif
+ }
+
+ if (segment_occuring_once.size() == 2)
+ {
+ // Try to find within all turns a turn with these two segments
+
+ std::set<segment_identifier>::const_iterator soo_it = segment_occuring_once.begin();
+ segment_identifier front = *soo_it;
+ soo_it++;
+ segment_identifier back = *soo_it;
+
+ std::pair<segment_identifier, segment_identifier> pair = ordered_pair(front, back);
+
+ typename boost::range_iterator<TurnSegmentIndices const>::type it = turn_segment_indices.find(pair);
+ if (it != turn_segment_indices.end())
+ {
+ // debug_turns_by_indices("Found", it->second);
+ // Check which is the union/continue
+ segment_identifier good;
+ for (std::set<int>::const_iterator sit = it->second.begin(); sit != it->second.end(); ++sit)
+ {
+ if (turns[*sit].operations[0].operation == detail::overlay::operation_union)
+ {
+ good = turns[*sit].operations[0].seg_id;
+ }
+ else if (turns[*sit].operations[1].operation == detail::overlay::operation_union)
+ {
+ good = turns[*sit].operations[1].seg_id;
+ }
+ }
+
+#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_PREFER
+ std::cout << "Good: " << si(good) << std::endl;
+#endif
+
+ // Find in indexes-to-keep this segment with the union. Discard the other one
+ std::set<int> ok_indices;
+ for (std::set<int>::const_iterator sit = indices.begin(); sit != indices.end(); ++sit)
+ {
+ if (corresponds<0>(turns[*sit], good) || corresponds<1>(turns[*sit], good))
+ {
+ ok_indices.insert(*sit);
+ }
+ }
+ if (ok_indices.size() > 0 && ok_indices.size() < indices.size())
+ {
+ indices = ok_indices;
+ std::cout << "^";
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+template <typename Turns>
+inline void prefer_by_priority(Turns const& turns, std::set<int>& indices)
+{
+ // Find max prio
+ int min_prio = 1024, max_prio = 0;
+ for (std::set<int>::const_iterator sit = indices.begin(); sit != indices.end(); ++sit)
+ {
+ if (turns[*sit].priority > max_prio)
+ {
+ max_prio = turns[*sit].priority;
+ }
+ if (turns[*sit].priority < min_prio)
+ {
+ min_prio = turns[*sit].priority;
+ }
+ }
+
+ if (min_prio == max_prio)
+ {
+ return;
+ }
+
+ // Only keep indices with high prio
+ std::set<int> ok_indices;
+ for (std::set<int>::const_iterator sit = indices.begin(); sit != indices.end(); ++sit)
+ {
+ if (turns[*sit].priority >= max_prio)
+ {
+ ok_indices.insert(*sit);
+ }
+ }
+ if (ok_indices.size() > 0 && ok_indices.size() < indices.size())
+ {
+ indices = ok_indices;
+ std::cout << "%";
+ }
+}
+
+template <typename AngleInfo, typename Angles, typename Turns, typename TurnSegmentIndices>
+inline void calculate_left_turns(Angles const& angles,
+ Turns& turns, TurnSegmentIndices const& turn_segment_indices,
+ std::set<int>& keep_indices)
+{
+ bool debug_indicate_size = false;
+
+ typedef typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<typename AngleInfo::point_type>::type
+ >::type side_strategy;
+
+ std::size_t i = 0;
+ std::size_t n = boost::size(angles);
+
+ typedef geometry::ever_circling_range_iterator<Angles const> circling_iterator;
+ circling_iterator cit(angles);
+
+ debug_left_turn(*cit, *cit);
+ for(circling_iterator prev = cit++; i < n; prev = cit++, i++)
+ {
+ debug_left_turn(*cit, *prev);
+
+ bool const include = ! geometry::math::equals(prev->angle, cit->angle)
+ && ! prev->incoming
+ && cit->incoming;
+
+ if (include)
+ {
+ // Go back to possibly include more same left outgoing angles:
+ // Because we check on side too we can take a large "epsilon"
+ circling_iterator back = prev - 1;
+
+ typename AngleInfo::angle_type eps = 0.00001;
+ int b = 1;
+ for(std::size_t d = 0;
+ math::abs(prev->angle - back->angle) < eps
+ && ! back->incoming
+ && d < n;
+ d++)
+ {
+ --back;
+ ++b;
+ }
+
+ // Same but forward to possibly include more incoming angles
+ int f = 1;
+ circling_iterator forward = cit + 1;
+ for(std::size_t d = 0;
+ math::abs(cit->angle - forward->angle) < eps
+ && forward->incoming
+ && d < n;
+ d++)
+ {
+ ++forward;
+ ++f;
+ }
+
+#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_OCCUPATION
+ std::cout << "HANDLE " << b << "/" << f << " ANGLES" << std::endl;
+#endif
+ for(circling_iterator bit = prev; bit != back; --bit)
+ {
+ int code = side_strategy::apply(bit->direction_point, prev->intersection_point, prev->direction_point);
+ int code2 = side_strategy::apply(prev->direction_point, bit->intersection_point, bit->direction_point);
+ for(circling_iterator fit = cit; fit != forward; ++fit)
+ {
+ int code3 = side_strategy::apply(fit->direction_point, cit->intersection_point, cit->direction_point);
+ int code4 = side_strategy::apply(cit->direction_point, fit->intersection_point, fit->direction_point);
+
+ int priority = 2;
+ if (code == -1 && code2 == 1)
+ {
+ // This segment is lying right of the other one.
+ // Cannot ignore it (because of robustness, see a.o. #rt_p21 from unit test).
+ // But if we find more we can prefer later by priority
+ // (a.o. necessary for #rt_o2 from unit test)
+ priority = 1;
+ }
+
+ bool included = include_left_turn_of_all(*bit, *fit, turns, turn_segment_indices, keep_indices, priority);
+ debug_left_turn(included ? "KEEP" : "SKIP", *fit, *bit, code, code2, code3, code4);
+ }
+ }
+ }
+ }
+
+ if (debug_indicate_size)
+ {
+ std::cout << " size=" << keep_indices.size();
+ }
+
+ if (keep_indices.size() >= 2)
+ {
+ prefer_by_other(turns, turn_segment_indices, keep_indices);
+ }
+ if (keep_indices.size() >= 2)
+ {
+ prefer_by_priority(turns, keep_indices);
+ }
+}
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GET_LEFT_TURNS_HPP
diff --git a/boost/geometry/algorithms/detail/has_self_intersections.hpp b/boost/geometry/algorithms/detail/has_self_intersections.hpp
new file mode 100644
index 000000000..1e6215ed9
--- /dev/null
+++ b/boost/geometry/algorithms/detail/has_self_intersections.hpp
@@ -0,0 +1,120 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_HAS_SELF_INTERSECTIONS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_HAS_SELF_INTERSECTIONS_HPP
+
+#include <deque>
+
+#include <boost/range.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
+#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
+
+#include <boost/geometry/multi/algorithms/detail/overlay/self_turn_points.hpp>
+
+#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS
+# include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
+# include <boost/geometry/io/dsv/write.hpp>
+#endif
+
+
+namespace boost { namespace geometry
+{
+
+
+#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
+
+/*!
+\brief Overlay Invalid Input Exception
+\ingroup overlay
+\details The overlay_invalid_input_exception is thrown at invalid input
+ */
+class overlay_invalid_input_exception : public geometry::exception
+{
+public:
+
+ inline overlay_invalid_input_exception() {}
+
+ virtual char const* what() const throw()
+ {
+ return "Boost.Geometry Overlay invalid input exception";
+ }
+};
+
+#endif
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+template <typename Geometry>
+inline bool has_self_intersections(Geometry const& geometry)
+{
+ typedef typename point_type<Geometry>::type point_type;
+ typedef detail::overlay::turn_info<point_type> turn_info;
+ std::deque<turn_info> turns;
+ detail::disjoint::disjoint_interrupt_policy policy;
+ geometry::self_turns<detail::overlay::assign_null_policy>(geometry, turns, policy);
+
+#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS
+ bool first = true;
+#endif
+ for(typename std::deque<turn_info>::const_iterator it = boost::begin(turns);
+ it != boost::end(turns); ++it)
+ {
+ turn_info const& info = *it;
+ bool const both_union_turn =
+ info.operations[0].operation == detail::overlay::operation_union
+ && info.operations[1].operation == detail::overlay::operation_union;
+ bool const both_intersection_turn =
+ info.operations[0].operation == detail::overlay::operation_intersection
+ && info.operations[1].operation == detail::overlay::operation_intersection;
+
+ bool const valid = (both_union_turn || both_intersection_turn)
+ && (info.method == detail::overlay::method_touch
+ || info.method == detail::overlay::method_touch_interior);
+
+ if (! valid)
+ {
+#ifdef BOOST_GEOMETRY_DEBUG_HAS_SELF_INTERSECTIONS
+ if (first)
+ {
+ std::cout << "turn points: " << std::endl;
+ first = false;
+ }
+ std::cout << method_char(info.method);
+ for (int i = 0; i < 2; i++)
+ {
+ std::cout << " " << operation_char(info.operations[i].operation);
+ }
+ std::cout << " " << geometry::dsv(info.point) << std::endl;
+#endif
+
+#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
+ throw overlay_invalid_input_exception();
+#endif
+ }
+
+ }
+ return false;
+}
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_HAS_SELF_INTERSECTIONS_HPP
+
diff --git a/boost/geometry/algorithms/detail/not.hpp b/boost/geometry/algorithms/detail/not.hpp
new file mode 100644
index 000000000..abc3a4e16
--- /dev/null
+++ b/boost/geometry/algorithms/detail/not.hpp
@@ -0,0 +1,50 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_NOT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_NOT_HPP
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+
+/*!
+\brief Structure negating the result of specified policy
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Policy
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\return Negation of the result of the policy
+ */
+template <typename Geometry1, typename Geometry2, typename Policy>
+struct not_
+{
+ static inline bool apply(Geometry1 const &geometry1, Geometry2 const& geometry2)
+ {
+ return ! Policy::apply(geometry1, geometry2);
+ }
+};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_NOT_HPP
diff --git a/boost/geometry/algorithms/detail/occupation_info.hpp b/boost/geometry/algorithms/detail/occupation_info.hpp
new file mode 100644
index 000000000..f4d5adac8
--- /dev/null
+++ b/boost/geometry/algorithms/detail/occupation_info.hpp
@@ -0,0 +1,329 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP
+
+#if ! defined(NDEBUG)
+// #define BOOST_GEOMETRY_DEBUG_BUFFER_OCCUPATION
+#endif
+
+#include <algorithm>
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/algorithms/equals.hpp>
+#include <boost/geometry/iterators/closing_iterator.hpp>
+
+#include <boost/geometry/algorithms/detail/get_left_turns.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename P>
+class relaxed_less
+{
+ typedef typename geometry::coordinate_type<P>::type coordinate_type;
+
+ coordinate_type epsilon;
+
+public :
+
+ inline relaxed_less()
+ {
+ // TODO: adapt for ttmath, and maybe build the map in another way
+ // (e.g. exact constellations of segment-id's), maybe adaptive.
+ epsilon = std::numeric_limits<double>::epsilon() * 100.0;
+ }
+
+ inline bool operator()(P const& a, P const& b) const
+ {
+ coordinate_type const dx = math::abs(geometry::get<0>(a) - geometry::get<0>(b));
+ coordinate_type const dy = math::abs(geometry::get<1>(a) - geometry::get<1>(b));
+
+
+ if (dx < epsilon && dy < epsilon)
+ {
+ return false;
+ }
+ if (dx < epsilon)
+ {
+ return geometry::get<1>(a) < geometry::get<1>(b);
+ }
+
+ return geometry::get<0>(a) < geometry::get<0>(b);
+ }
+
+ inline bool equals(P const& a, P const& b) const
+ {
+ typedef typename geometry::coordinate_type<P>::type coordinate_type;
+
+ coordinate_type const dx = math::abs(geometry::get<0>(a) - geometry::get<0>(b));
+ coordinate_type const dy = math::abs(geometry::get<1>(a) - geometry::get<1>(b));
+
+ return dx < epsilon && dy < epsilon;
+ };
+};
+
+
+template <typename T, typename P1, typename P2>
+inline T calculate_angle(P1 const& from_point, P2 const& to_point)
+{
+ typedef P1 vector_type;
+ vector_type v = from_point;
+ geometry::subtract_point(v, to_point);
+ return atan2(geometry::get<1>(v), geometry::get<0>(v));
+}
+
+template <typename Iterator, typename Vector>
+inline Iterator advance_circular(Iterator it, Vector const& vector, segment_identifier& seg_id, bool forward = true)
+{
+ int const increment = forward ? 1 : -1;
+ if (it == boost::begin(vector) && increment < 0)
+ {
+ it = boost::end(vector);
+ seg_id.segment_index = boost::size(vector);
+ }
+ it += increment;
+ seg_id.segment_index += increment;
+ if (it == boost::end(vector))
+ {
+ seg_id.segment_index = 0;
+ it = boost::begin(vector);
+ }
+ return it;
+}
+
+template <typename Point, typename T>
+struct angle_info
+{
+ typedef T angle_type;
+ typedef Point point_type;
+
+ segment_identifier seg_id;
+ int turn_index;
+ int operation_index;
+ Point intersection_point;
+ Point direction_point;
+ T angle;
+ bool incoming;
+};
+
+template <typename AngleInfo>
+class occupation_info
+{
+ typedef std::vector<AngleInfo> collection_type;
+
+ struct angle_sort
+ {
+ inline bool operator()(AngleInfo const& left, AngleInfo const& right) const
+ {
+ // In this case we can compare even double using equals
+ // return geometry::math::equals(left.angle, right.angle)
+ return left.angle == right.angle
+ ? int(left.incoming) < int(right.incoming)
+ : left.angle < right.angle
+ ;
+ }
+ };
+
+public :
+ collection_type angles;
+private :
+ bool m_occupied;
+ bool m_calculated;
+
+ inline bool is_occupied()
+ {
+ if (boost::size(angles) <= 1)
+ {
+ return false;
+ }
+
+ std::sort(angles.begin(), angles.end(), angle_sort());
+
+ typedef geometry::closing_iterator<collection_type const> closing_iterator;
+ closing_iterator vit(angles);
+ closing_iterator end(angles, true);
+
+ closing_iterator prev = vit++;
+ for( ; vit != end; prev = vit++)
+ {
+ if (! geometry::math::equals(prev->angle, vit->angle)
+ && ! prev->incoming
+ && vit->incoming)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+public :
+ inline occupation_info()
+ : m_occupied(false)
+ , m_calculated(false)
+ {}
+
+ template <typename PointC, typename Point1, typename Point2>
+ inline void add(PointC const& map_point, Point1 const& direction_point, Point2 const& intersection_point,
+ int turn_index, int operation_index,
+ segment_identifier const& seg_id, bool incoming)
+ {
+ //std::cout << "-> adding angle " << geometry::wkt(direction_point) << " .. " << geometry::wkt(intersection_point) << " " << int(incoming) << std::endl;
+ if (geometry::equals(direction_point, intersection_point))
+ {
+ //std::cout << "EQUAL! Skipping" << std::endl;
+ return;
+ }
+
+ AngleInfo info;
+ info.incoming = incoming;
+ info.angle = calculate_angle<typename AngleInfo::angle_type>(direction_point, map_point);
+ info.seg_id = seg_id;
+ info.turn_index = turn_index;
+ info.operation_index = operation_index;
+ info.intersection_point = intersection_point;
+ info.direction_point = direction_point;
+ angles.push_back(info);
+
+ m_calculated = false;
+ }
+
+ inline bool occupied()
+ {
+ if (! m_calculated)
+ {
+ m_occupied = is_occupied();
+ m_calculated = true;
+ }
+ return m_occupied;
+ }
+
+ template <typename Turns, typename TurnSegmentIndices>
+ inline void get_left_turns(
+ Turns& turns, TurnSegmentIndices const& turn_segment_indices,
+ std::set<int>& keep_indices)
+ {
+ std::sort(angles.begin(), angles.end(), angle_sort());
+ calculate_left_turns<AngleInfo>(angles, turns, turn_segment_indices, keep_indices);
+ }
+};
+
+
+template <typename Point, typename Ring, typename Info>
+inline void add_incoming_and_outgoing_angles(Point const& map_point, Point const& intersection_point,
+ Ring const& ring,
+ int turn_index,
+ int operation_index,
+ segment_identifier seg_id,
+ Info& info)
+{
+ typedef typename boost::range_iterator
+ <
+ Ring const
+ >::type iterator_type;
+
+ int const n = boost::size(ring);
+ if (seg_id.segment_index >= n || seg_id.segment_index < 0)
+ {
+ return;
+ }
+
+ segment_identifier real_seg_id = seg_id;
+ iterator_type it = boost::begin(ring) + seg_id.segment_index;
+
+ // TODO: if we use turn-info ("to", "middle"), we know if to advance without resorting to equals
+ relaxed_less<Point> comparator;
+
+ if (comparator.equals(intersection_point, *it))
+ {
+ // It should be equal only once. But otherwise we skip it (in "add")
+ it = advance_circular(it, ring, seg_id, false);
+ }
+
+ info.add(map_point, *it, intersection_point, turn_index, operation_index, real_seg_id, true);
+
+ if (comparator.equals(intersection_point, *it))
+ {
+ it = advance_circular(it, ring, real_seg_id);
+ }
+ else
+ {
+ // Don't upgrade the ID
+ it = advance_circular(it, ring, seg_id);
+ }
+ for (int defensive_check = 0;
+ comparator.equals(intersection_point, *it) && defensive_check < n;
+ defensive_check++)
+ {
+ it = advance_circular(it, ring, real_seg_id);
+ }
+
+ info.add(map_point, *it, intersection_point, turn_index, operation_index, real_seg_id, false);
+}
+
+
+// Map in two senses of the word: it is a std::map where the key is a point.
+// Per point an "occupation_info" record is kept
+// Used for the buffer (but will also be used for intersections/unions having complex self-tangencies)
+template <typename Point, typename OccupationInfo>
+class occupation_map
+{
+public :
+ typedef std::map<Point, OccupationInfo, relaxed_less<Point> > map_type;
+
+ map_type map;
+ std::set<int> turn_indices;
+
+ inline OccupationInfo& find_or_insert(Point const& point, Point& mapped_point)
+ {
+ typename map_type::iterator it = map.find(point);
+ if (it == boost::end(map))
+ {
+ std::pair<typename map_type::iterator, bool> pair
+ = map.insert(std::make_pair(point, OccupationInfo()));
+ it = pair.first;
+ }
+ mapped_point = it->first;
+ return it->second;
+ }
+
+ inline bool contains(Point const& point) const
+ {
+ typename map_type::const_iterator it = map.find(point);
+ return it != boost::end(map);
+ }
+
+ inline bool contains_turn_index(int index) const
+ {
+ return turn_indices.count(index) > 0;
+ }
+
+ inline void insert_turn_index(int index)
+ {
+ turn_indices.insert(index);
+ }
+};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/add_rings.hpp b/boost/geometry/algorithms/detail/overlay/add_rings.hpp
new file mode 100644
index 000000000..5ff0b57d6
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/add_rings.hpp
@@ -0,0 +1,159 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP
+
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/algorithms/detail/overlay/convert_ring.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename RingCollection
+>
+inline void convert_and_add(GeometryOut& result,
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ RingCollection const& collection,
+ ring_identifier id,
+ bool reversed, bool append)
+{
+ typedef typename geometry::tag<Geometry1>::type tag1;
+ typedef typename geometry::tag<Geometry2>::type tag2;
+ typedef typename geometry::tag<GeometryOut>::type tag_out;
+
+ if (id.source_index == 0)
+ {
+ convert_ring<tag_out>::apply(result,
+ get_ring<tag1>::apply(id, geometry1),
+ append, reversed);
+ }
+ else if (id.source_index == 1)
+ {
+ convert_ring<tag_out>::apply(result,
+ get_ring<tag2>::apply(id, geometry2),
+ append, reversed);
+ }
+ else if (id.source_index == 2)
+ {
+ convert_ring<tag_out>::apply(result,
+ get_ring<void>::apply(id, collection),
+ append, reversed);
+ }
+}
+
+template
+<
+ typename GeometryOut,
+ typename SelectionMap,
+ typename Geometry1,
+ typename Geometry2,
+ typename RingCollection,
+ typename OutputIterator
+>
+inline OutputIterator add_rings(SelectionMap const& map,
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ RingCollection const& collection,
+ OutputIterator out)
+{
+ typedef typename SelectionMap::const_iterator iterator;
+ typedef typename SelectionMap::mapped_type property_type;
+ typedef typename property_type::area_type area_type;
+
+ area_type const zero = 0;
+ std::size_t const min_num_points = core_detail::closure::minimum_ring_size
+ <
+ geometry::closure
+ <
+ typename boost::range_value
+ <
+ RingCollection const
+ >::type
+ >::value
+ >::value;
+
+
+ for (iterator it = boost::begin(map);
+ it != boost::end(map);
+ ++it)
+ {
+ if (! it->second.discarded
+ && it->second.parent.source_index == -1)
+ {
+ GeometryOut result;
+ convert_and_add(result, geometry1, geometry2, collection,
+ it->first, it->second.reversed, false);
+
+ // Add children
+ for (typename std::vector<ring_identifier>::const_iterator child_it
+ = it->second.children.begin();
+ child_it != it->second.children.end();
+ ++child_it)
+ {
+ iterator mit = map.find(*child_it);
+ if (mit != map.end()
+ && ! mit->second.discarded)
+ {
+ convert_and_add(result, geometry1, geometry2, collection,
+ *child_it, mit->second.reversed, true);
+ }
+ }
+
+ // Only add rings if they satisfy minimal requirements.
+ // This cannot be done earlier (during traversal), not
+ // everything is figured out yet (sum of positive/negative rings)
+ if (geometry::num_points(result) >= min_num_points
+ && math::larger(geometry::area(result), zero))
+ {
+ *out++ = result;
+ }
+ }
+ }
+ return out;
+}
+
+
+template
+<
+ typename GeometryOut,
+ typename SelectionMap,
+ typename Geometry,
+ typename RingCollection,
+ typename OutputIterator
+>
+inline OutputIterator add_rings(SelectionMap const& map,
+ Geometry const& geometry,
+ RingCollection const& collection,
+ OutputIterator out)
+{
+ Geometry empty;
+ return add_rings<GeometryOut>(map, geometry, empty, collection, out);
+}
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp b/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp
new file mode 100644
index 000000000..2c0f88e2a
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp
@@ -0,0 +1,53 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPLICATES_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPLICATES_HPP
+
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/append.hpp>
+#include <boost/geometry/algorithms/detail/disjoint.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+template <typename Range, typename Point>
+inline void append_no_duplicates(Range& range, Point const& point, bool force = false)
+{
+ if (boost::size(range) == 0
+ || force
+ || ! geometry::detail::equals::equals_point_point(*(boost::end(range)-1), point))
+ {
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ std::cout << " add: ("
+ << geometry::get<0>(point) << ", " << geometry::get<1>(point) << ")"
+ << std::endl;
+#endif
+ geometry::append(range, point);
+ }
+}
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_APPEND_NO_DUPLICATES_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
new file mode 100644
index 000000000..5063f49eb
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
@@ -0,0 +1,338 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_PARENTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_PARENTS_HPP
+
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/algorithms/expand.hpp>
+#include <boost/geometry/algorithms/detail/partition.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
+#include <boost/geometry/algorithms/within.hpp>
+
+#include <boost/geometry/geometries/box.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+
+template
+<
+ typename Item,
+ typename Geometry1, typename Geometry2,
+ typename RingCollection
+>
+static inline bool within_selected_input(Item const& item2, ring_identifier const& ring_id,
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ RingCollection const& collection)
+{
+ typedef typename geometry::tag<Geometry1>::type tag1;
+ typedef typename geometry::tag<Geometry2>::type tag2;
+
+ switch (ring_id.source_index)
+ {
+ case 0 :
+ return geometry::within(item2.point,
+ get_ring<tag1>::apply(ring_id, geometry1));
+ break;
+ case 1 :
+ return geometry::within(item2.point,
+ get_ring<tag2>::apply(ring_id, geometry2));
+ break;
+ case 2 :
+ return geometry::within(item2.point,
+ get_ring<void>::apply(ring_id, collection));
+ break;
+ }
+ return false;
+}
+
+
+template <typename Point>
+struct ring_info_helper
+{
+ typedef typename geometry::default_area_result<Point>::type area_type;
+
+ ring_identifier id;
+ area_type real_area;
+ area_type abs_area;
+ model::box<Point> envelope;
+
+ inline ring_info_helper()
+ : real_area(0), abs_area(0)
+ {}
+
+ inline ring_info_helper(ring_identifier i, area_type a)
+ : id(i), real_area(a), abs_area(geometry::math::abs(a))
+ {}
+};
+
+
+struct ring_info_helper_get_box
+{
+ template <typename Box, typename InputItem>
+ static inline void apply(Box& total, InputItem const& item)
+ {
+ geometry::expand(total, item.envelope);
+ }
+};
+
+struct ring_info_helper_ovelaps_box
+{
+ template <typename Box, typename InputItem>
+ static inline bool apply(Box const& box, InputItem const& item)
+ {
+ return ! geometry::detail::disjoint::disjoint_box_box(box, item.envelope);
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Collection, typename RingMap>
+struct assign_visitor
+{
+ typedef typename RingMap::mapped_type ring_info_type;
+
+ Geometry1 const& m_geometry1;
+ Geometry2 const& m_geometry2;
+ Collection const& m_collection;
+ RingMap& m_ring_map;
+ bool m_check_for_orientation;
+
+
+ inline assign_visitor(Geometry1 const& g1, Geometry2 const& g2, Collection const& c,
+ RingMap& map, bool check)
+ : m_geometry1(g1)
+ , m_geometry2(g2)
+ , m_collection(c)
+ , m_ring_map(map)
+ , m_check_for_orientation(check)
+ {}
+
+ template <typename Item>
+ inline void apply(Item const& outer, Item const& inner, bool first = true)
+ {
+ if (first && outer.real_area < 0)
+ {
+ // Reverse arguments
+ apply(inner, outer, false);
+ return;
+ }
+
+ if (math::larger(outer.real_area, 0))
+ {
+ if (inner.real_area < 0 || m_check_for_orientation)
+ {
+ ring_info_type& inner_in_map = m_ring_map[inner.id];
+
+ if (geometry::within(inner_in_map.point, outer.envelope)
+ && within_selected_input(inner_in_map, outer.id, m_geometry1, m_geometry2, m_collection)
+ )
+ {
+ // Only assign parent if that parent is smaller (or if it is the first)
+ if (inner_in_map.parent.source_index == -1
+ || outer.abs_area < inner_in_map.parent_area)
+ {
+ inner_in_map.parent = outer.id;
+ inner_in_map.parent_area = outer.abs_area;
+ }
+ }
+ }
+ }
+ }
+};
+
+
+
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename RingCollection,
+ typename RingMap
+>
+inline void assign_parents(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ RingCollection const& collection,
+ RingMap& ring_map,
+ bool check_for_orientation = false)
+{
+ typedef typename geometry::tag<Geometry1>::type tag1;
+ typedef typename geometry::tag<Geometry2>::type tag2;
+
+ typedef typename RingMap::mapped_type ring_info_type;
+ typedef typename ring_info_type::point_type point_type;
+ typedef model::box<point_type> box_type;
+
+ typedef typename RingMap::iterator map_iterator_type;
+
+ {
+ typedef ring_info_helper<point_type> helper;
+ typedef std::vector<helper> vector_type;
+ typedef typename boost::range_iterator<vector_type const>::type vector_iterator_type;
+
+#ifdef BOOST_GEOMETRY_TIME_OVERLAY
+ boost::timer timer;
+#endif
+
+
+ std::size_t count_total = ring_map.size();
+ std::size_t count_positive = 0;
+ std::size_t index_positive = 0; // only used if count_positive>0
+ std::size_t index = 0;
+
+ // Copy to vector (with new approach this might be obsolete as well, using the map directly)
+ vector_type vector(count_total);
+
+ for (map_iterator_type it = boost::begin(ring_map);
+ it != boost::end(ring_map); ++it, ++index)
+ {
+ vector[index] = helper(it->first, it->second.get_area());
+ helper& item = vector[index];
+ switch(it->first.source_index)
+ {
+ case 0 :
+ geometry::envelope(get_ring<tag1>::apply(it->first, geometry1),
+ item.envelope);
+ break;
+ case 1 :
+ geometry::envelope(get_ring<tag2>::apply(it->first, geometry2),
+ item.envelope);
+ break;
+ case 2 :
+ geometry::envelope(get_ring<void>::apply(it->first, collection),
+ item.envelope);
+ break;
+ }
+ if (item.real_area > 0)
+ {
+ count_positive++;
+ index_positive = index;
+ }
+ }
+
+#ifdef BOOST_GEOMETRY_TIME_OVERLAY
+ std::cout << " ap: created helper vector: " << timer.elapsed() << std::endl;
+#endif
+
+ if (! check_for_orientation)
+ {
+ if (count_positive == count_total)
+ {
+ // Optimization for only positive rings
+ // -> no assignment of parents or reversal necessary, ready here.
+ return;
+ }
+
+ if (count_positive == 1)
+ {
+ // Optimization for one outer ring
+ // -> assign this as parent to all others (all interior rings)
+ // In unions, this is probably the most occuring case and gives
+ // a dramatic improvement (factor 5 for star_comb testcase)
+ ring_identifier id_of_positive = vector[index_positive].id;
+ ring_info_type& outer = ring_map[id_of_positive];
+ std::size_t index = 0;
+ for (vector_iterator_type it = boost::begin(vector);
+ it != boost::end(vector); ++it, ++index)
+ {
+ if (index != index_positive)
+ {
+ ring_info_type& inner = ring_map[it->id];
+ inner.parent = id_of_positive;
+ outer.children.push_back(it->id);
+ }
+ }
+ return;
+ }
+ }
+
+ assign_visitor
+ <
+ Geometry1, Geometry2,
+ RingCollection, RingMap
+ > visitor(geometry1, geometry2, collection, ring_map, check_for_orientation);
+
+ geometry::partition
+ <
+ box_type, ring_info_helper_get_box, ring_info_helper_ovelaps_box
+ >::apply(vector, visitor);
+
+#ifdef BOOST_GEOMETRY_TIME_OVERLAY
+ std::cout << " ap: quadradic loop: " << timer.elapsed() << std::endl;
+ std::cout << " ap: check_for_orientation " << check_for_orientation << std::endl;
+#endif
+ }
+
+ if (check_for_orientation)
+ {
+ for (map_iterator_type it = boost::begin(ring_map);
+ it != boost::end(ring_map); ++it)
+ {
+ if (geometry::math::equals(it->second.get_area(), 0))
+ {
+ it->second.discarded = true;
+ }
+ else if (it->second.parent.source_index >= 0 && it->second.get_area() > 0)
+ {
+ // Discard positive inner ring with parent
+ it->second.discarded = true;
+ it->second.parent.source_index = -1;
+ }
+ else if (it->second.parent.source_index < 0 && it->second.get_area() < 0)
+ {
+ // Reverse negative ring without parent
+ it->second.reversed = true;
+ }
+ }
+ }
+
+ // Assign childlist
+ for (map_iterator_type it = boost::begin(ring_map);
+ it != boost::end(ring_map); ++it)
+ {
+ if (it->second.parent.source_index >= 0)
+ {
+ ring_map[it->second.parent].children.push_back(it->first);
+ }
+ }
+}
+
+template
+<
+ typename Geometry,
+ typename RingCollection,
+ typename RingMap
+>
+inline void assign_parents(Geometry const& geometry,
+ RingCollection const& collection,
+ RingMap& ring_map,
+ bool check_for_orientation)
+{
+ // Call it with an empty geometry
+ // (ring_map should be empty for source_id==1)
+
+ Geometry empty;
+ assign_parents(geometry, empty, collection, ring_map, check_for_orientation);
+}
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ASSIGN_PARENTS_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp b/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp
new file mode 100644
index 000000000..012b3aca3
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp
@@ -0,0 +1,170 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP
+
+#include <cstddef>
+#include <string>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+#include <boost/geometry/algorithms/detail/has_self_intersections.hpp>
+#if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) || defined(BOOST_GEOMETRY_OVERLAY_REPORT_WKT)
+# include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
+# include <boost/geometry/io/wkt/wkt.hpp>
+#endif
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+template <typename Turns>
+inline void clear_visit_info(Turns& turns)
+{
+ typedef typename boost::range_value<Turns>::type tp_type;
+
+ for (typename boost::range_iterator<Turns>::type
+ it = boost::begin(turns);
+ it != boost::end(turns);
+ ++it)
+ {
+ for (typename boost::range_iterator
+ <
+ typename tp_type::container_type
+ >::type op_it = boost::begin(it->operations);
+ op_it != boost::end(it->operations);
+ ++op_it)
+ {
+ op_it->visited.clear();
+ }
+ it->discarded = false;
+ }
+}
+
+struct backtrack_state
+{
+ bool m_good;
+
+ inline backtrack_state() : m_good(true) {}
+ inline void reset() { m_good = true; }
+ inline bool good() const { return m_good; }
+};
+
+
+template
+<
+ typename Geometry1,
+ typename Geometry2
+>
+class backtrack_check_self_intersections
+{
+ struct state : public backtrack_state
+ {
+ bool m_checked;
+ inline state()
+ : m_checked()
+ {}
+ };
+public :
+ typedef state state_type;
+
+ template <typename Operation, typename Rings, typename Turns>
+ static inline void apply(std::size_t size_at_start,
+ Rings& rings, typename boost::range_value<Rings>::type& ring,
+ Turns& turns, Operation& operation,
+ std::string const& ,
+ Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ state_type& state
+ )
+ {
+ state.m_good = false;
+
+ // Check self-intersections and throw exception if appropriate
+ if (! state.m_checked)
+ {
+ state.m_checked = true;
+ has_self_intersections(geometry1);
+ has_self_intersections(geometry2);
+ }
+
+ // Make bad output clean
+ rings.resize(size_at_start);
+ ring.clear();
+
+ // Reject this as a starting point
+ operation.visited.set_rejected();
+
+ // And clear all visit info
+ clear_visit_info(turns);
+ }
+};
+
+#ifdef BOOST_GEOMETRY_OVERLAY_REPORT_WKT
+template
+<
+ typename Geometry1,
+ typename Geometry2
+>
+class backtrack_debug
+{
+public :
+ typedef backtrack_state state_type;
+
+ template <typename Operation, typename Rings, typename Turns>
+ static inline void apply(std::size_t size_at_start,
+ Rings& rings, typename boost::range_value<Rings>::type& ring,
+ Turns& turns, Operation& operation,
+ std::string const& reason,
+ Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ state_type& state
+ )
+ {
+ std::cout << " REJECT " << reason << std::endl;
+
+ state.m_good = false;
+
+ rings.resize(size_at_start);
+ ring.clear();
+ operation.visited.set_rejected();
+ clear_visit_info(turns);
+
+ int c = 0;
+ for (int i = 0; i < turns.size(); i++)
+ {
+ for (int j = 0; j < 2; j++)
+ {
+ if (turns[i].operations[j].visited.rejected())
+ {
+ c++;
+ }
+ }
+ }
+ std::cout << "BACKTRACK (" << reason << " )"
+ << " " << c << " of " << turns.size() << " rejected"
+ << std::endl;
+ std::cout
+ << geometry::wkt(geometry1) << std::endl
+ << geometry::wkt(geometry2) << std::endl;
+ }
+};
+#endif // BOOST_GEOMETRY_OVERLAY_REPORT_WKT
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp b/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp
new file mode 100644
index 000000000..a365ccf90
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp
@@ -0,0 +1,64 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CALCULATE_DISTANCE_POLICY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CALCULATE_DISTANCE_POLICY_HPP
+
+
+#include <boost/geometry/algorithms/comparable_distance.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+/*!
+ \brief Policy calculating distance
+ \details get_turn_info has an optional policy to get some
+ extra information.
+ This policy calculates the distance (using default distance strategy)
+ */
+struct calculate_distance_policy
+{
+ static bool const include_no_turn = false;
+ static bool const include_degenerate = false;
+ static bool const include_opposite = false;
+
+ template
+ <
+ typename Info,
+ typename Point1,
+ typename Point2,
+ typename IntersectionInfo,
+ typename DirInfo
+ >
+ static inline void apply(Info& info, Point1 const& p1, Point2 const& p2,
+ IntersectionInfo const&, DirInfo const&)
+ {
+ info.operations[0].enriched.distance
+ = geometry::comparable_distance(info.point, p1);
+ info.operations[1].enriched.distance
+ = geometry::comparable_distance(info.point, p2);
+ }
+
+};
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CALCULATE_DISTANCE_POLICY_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/check_enrich.hpp b/boost/geometry/algorithms/detail/overlay/check_enrich.hpp
new file mode 100644
index 000000000..b210fd04b
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/check_enrich.hpp
@@ -0,0 +1,172 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CHECK_ENRICH_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CHECK_ENRICH_HPP
+
+
+#include <cstddef>
+
+
+#include <boost/assert.hpp>
+#include <boost/range.hpp>
+
+
+
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+template<typename Turn>
+struct meta_turn
+{
+ int index;
+ Turn const* turn;
+ bool handled[2];
+
+ inline meta_turn(int i, Turn const& t)
+ : index(i), turn(&t)
+ {
+ handled[0] = false;
+ handled[1] = false;
+ }
+};
+
+
+template <typename MetaTurn>
+inline void display(MetaTurn const& meta_turn, std::string const& reason = "")
+{
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ std::cout << meta_turn.index
+ << "\tMethods: " << method_char(meta_turn.turn->method)
+ << " operations: " << operation_char(meta_turn.turn->operations[0].operation)
+ << operation_char(meta_turn.turn->operations[1].operation)
+ << " travels to " << meta_turn.turn->operations[0].enriched.travels_to_ip_index
+ << " and " << meta_turn.turn->operations[1].enriched.travels_to_ip_index
+ //<< " -> " << op_index
+ << " " << reason
+ << std::endl;
+#endif
+}
+
+
+template <typename MetaTurns, typename MetaTurn>
+inline void check_detailed(MetaTurns& meta_turns, MetaTurn const& meta_turn,
+ int op_index, int cycle, int start, operation_type for_operation,
+ bool& error)
+{
+ display(meta_turn);
+ int const ip_index = meta_turn.turn->operations[op_index].enriched.travels_to_ip_index;
+ if (ip_index >= 0)
+ {
+ bool found = false;
+
+ if (ip_index == start)
+ {
+ display(meta_turns[ip_index], " FINISH");
+ return;
+ }
+
+ // check on continuing, or on same-operation-on-same-geometry
+ if (! meta_turns[ip_index].handled[op_index]
+ && (meta_turns[ip_index].turn->operations[op_index].operation == operation_continue
+ || meta_turns[ip_index].turn->operations[op_index].operation == for_operation)
+ )
+ {
+ meta_turns[ip_index].handled[op_index] = true;
+ check_detailed(meta_turns, meta_turns[ip_index], op_index, cycle, start, for_operation, error);
+ found = true;
+ }
+ // check on other geometry
+ if (! found)
+ {
+ int const other_index = 1 - op_index;
+ if (! meta_turns[ip_index].handled[other_index]
+ && meta_turns[ip_index].turn->operations[other_index].operation == for_operation)
+ {
+ meta_turns[ip_index].handled[other_index] = true;
+ check_detailed(meta_turns, meta_turns[ip_index], other_index, cycle, start, for_operation, error);
+ found = true;
+ }
+ }
+
+ if (! found)
+ {
+ display(meta_turns[ip_index], " STOP");
+ error = true;
+#ifndef BOOST_GEOMETRY_DEBUG_ENRICH
+ //std::cout << " STOP";
+#endif
+ }
+ }
+}
+
+
+template <typename TurnPoints>
+inline bool check_graph(TurnPoints& turn_points, operation_type for_operation)
+{
+ typedef typename boost::range_value<TurnPoints>::type turn_point_type;
+
+ bool error = false;
+ int index = 0;
+
+ std::vector<meta_turn<turn_point_type> > meta_turns;
+ for (typename boost::range_iterator<TurnPoints const>::type
+ it = boost::begin(turn_points);
+ it != boost::end(turn_points);
+ ++it, ++index)
+ {
+ meta_turns.push_back(meta_turn<turn_point_type>(index, *it));
+ }
+
+ int cycle = 0;
+ for (typename boost::range_iterator<std::vector<meta_turn<turn_point_type> > > ::type
+ it = boost::begin(meta_turns);
+ it != boost::end(meta_turns);
+ ++it)
+ {
+ if (! (it->turn->blocked() || it->turn->is_discarded()))
+ {
+ for (int i = 0 ; i < 2; i++)
+ {
+ if (! it->handled[i]
+ && it->turn->operations[i].operation == for_operation)
+ {
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ std::cout << "CYCLE " << cycle << std::endl;
+#endif
+ it->handled[i] = true;
+ check_detailed(meta_turns, *it, i, cycle++, it->index, for_operation, error);
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ std::cout <<" END CYCLE " << it->index << std::endl;
+#endif
+ }
+ }
+ }
+ }
+ return error;
+}
+
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CHECK_ENRICH_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp b/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp
new file mode 100644
index 000000000..fc4f65732
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp
@@ -0,0 +1,242 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLIP_LINESTRING_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLIP_LINESTRING_HPP
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/convert.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>
+
+#include <boost/geometry/util/select_coordinate_type.hpp>
+#include <boost/geometry/geometries/segment.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace intersection
+{
+
+/*!
+ \brief Strategy: line clipping algorithm after Liang Barsky
+ \ingroup overlay
+ \details The Liang-Barsky line clipping algorithm clips a line with a clipping box.
+ It is slightly adapted in the sense that it returns which points are clipped
+ \tparam B input box type of clipping box
+ \tparam P input/output point-type of segments to be clipped
+ \note The algorithm is currently only implemented for 2D Cartesian points
+ \note Though it is implemented in namespace strategy, and theoretically another
+ strategy could be used, it is not (yet) updated to the general strategy concepts,
+ and not (yet) splitted into a file in folder strategies
+ \author Barend Gehrels, and the following recourses
+ - A tutorial: http://www.skytopia.com/project/articles/compsci/clipping.html
+ - a German applet (link broken): http://ls7-www.cs.uni-dortmund.de/students/projectgroups/acit/lineclip.shtml
+*/
+template<typename Box, typename Point>
+class liang_barsky
+{
+private:
+ typedef model::referring_segment<Point> segment_type;
+
+ template <typename T>
+ inline bool check_edge(T const& p, T const& q, T& t1, T& t2) const
+ {
+ bool visible = true;
+
+ if(p < 0)
+ {
+ T const r = q / p;
+ if (r > t2)
+ visible = false;
+ else if (r > t1)
+ t1 = r;
+ }
+ else if(p > 0)
+ {
+ T const r = q / p;
+ if (r < t1)
+ visible = false;
+ else if (r < t2)
+ t2 = r;
+ }
+ else
+ {
+ if (q < 0)
+ visible = false;
+ }
+
+ return visible;
+ }
+
+public:
+
+ inline bool clip_segment(Box const& b, segment_type& s, bool& sp1_clipped, bool& sp2_clipped) const
+ {
+ typedef typename select_coordinate_type<Box, Point>::type coordinate_type;
+
+ coordinate_type t1 = 0;
+ coordinate_type t2 = 1;
+
+ coordinate_type const dx = get<1, 0>(s) - get<0, 0>(s);
+ coordinate_type const dy = get<1, 1>(s) - get<0, 1>(s);
+
+ coordinate_type const p1 = -dx;
+ coordinate_type const p2 = dx;
+ coordinate_type const p3 = -dy;
+ coordinate_type const p4 = dy;
+
+ coordinate_type const q1 = get<0, 0>(s) - get<min_corner, 0>(b);
+ coordinate_type const q2 = get<max_corner, 0>(b) - get<0, 0>(s);
+ coordinate_type const q3 = get<0, 1>(s) - get<min_corner, 1>(b);
+ coordinate_type const q4 = get<max_corner, 1>(b) - get<0, 1>(s);
+
+ if (check_edge(p1, q1, t1, t2) // left
+ && check_edge(p2, q2, t1, t2) // right
+ && check_edge(p3, q3, t1, t2) // bottom
+ && check_edge(p4, q4, t1, t2)) // top
+ {
+ sp1_clipped = t1 > 0;
+ sp2_clipped = t2 < 1;
+
+ if (sp2_clipped)
+ {
+ set<1, 0>(s, get<0, 0>(s) + t2 * dx);
+ set<1, 1>(s, get<0, 1>(s) + t2 * dy);
+ }
+
+ if(sp1_clipped)
+ {
+ set<0, 0>(s, get<0, 0>(s) + t1 * dx);
+ set<0, 1>(s, get<0, 1>(s) + t1 * dy);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ template<typename Linestring, typename OutputIterator>
+ inline void apply(Linestring& line_out, OutputIterator out) const
+ {
+ if (!boost::empty(line_out))
+ {
+ *out = line_out;
+ ++out;
+ geometry::clear(line_out);
+ }
+ }
+};
+
+
+}} // namespace strategy::intersection
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersection
+{
+
+/*!
+ \brief Clips a linestring with a box
+ \details A linestring is intersected (clipped) by the specified box
+ and the resulting linestring, or pieces of linestrings, are sent to the specified output operator.
+ \tparam OutputLinestring type of the output linestrings
+ \tparam OutputIterator an output iterator which outputs linestrings
+ \tparam Linestring linestring-type, for example a vector of points, matching the output-iterator type,
+ the points should also match the input-iterator type
+ \tparam Box box type
+ \tparam Strategy strategy, a clipping strategy which should implement the methods "clip_segment" and "apply"
+*/
+template
+<
+ typename OutputLinestring,
+ typename OutputIterator,
+ typename Range,
+ typename Box,
+ typename Strategy
+>
+OutputIterator clip_range_with_box(Box const& b, Range const& range,
+ OutputIterator out, Strategy const& strategy)
+{
+ if (boost::begin(range) == boost::end(range))
+ {
+ return out;
+ }
+
+ typedef typename point_type<OutputLinestring>::type point_type;
+
+ OutputLinestring line_out;
+
+ typedef typename boost::range_iterator<Range const>::type iterator_type;
+ iterator_type vertex = boost::begin(range);
+ for(iterator_type previous = vertex++;
+ vertex != boost::end(range);
+ ++previous, ++vertex)
+ {
+ point_type p1, p2;
+ geometry::convert(*previous, p1);
+ geometry::convert(*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;
+ model::referring_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))
+ {
+ detail::overlay::append_no_duplicates(line_out, p1, true);
+ }
+ detail::overlay::append_no_duplicates(line_out, p2);
+
+ // c. If c2 is clipped, finish the line
+ if (c2)
+ {
+ strategy.apply(line_out, out);
+ }
+ }
+
+ }
+
+ // Add last part
+ strategy.apply(line_out, out);
+ return out;
+}
+
+}} // namespace detail::intersection
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLIP_LINESTRING_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/convert_ring.hpp b/boost/geometry/algorithms/detail/overlay/convert_ring.hpp
new file mode 100644
index 000000000..51955b515
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/convert_ring.hpp
@@ -0,0 +1,110 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CONVERT_RING_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CONVERT_RING_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/range.hpp>
+#include <boost/range/algorithm/reverse.hpp>
+
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
+
+#include <boost/geometry/algorithms/convert.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+template<typename Tag>
+struct convert_ring
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TAG
+ , (types<Tag>)
+ );
+};
+
+template<>
+struct convert_ring<ring_tag>
+{
+ template<typename Destination, typename Source>
+ static inline void apply(Destination& destination, Source const& source,
+ bool append, bool reverse)
+ {
+ if (! append)
+ {
+ geometry::convert(source, destination);
+ if (reverse)
+ {
+ boost::reverse(destination);
+ }
+ }
+ }
+};
+
+
+template<>
+struct convert_ring<polygon_tag>
+{
+ template<typename Destination, typename Source>
+ static inline void apply(Destination& destination, Source const& source,
+ bool append, bool reverse)
+ {
+ if (! append)
+ {
+ geometry::convert(source, exterior_ring(destination));
+ if (reverse)
+ {
+ boost::reverse(exterior_ring(destination));
+ }
+ }
+ else
+ {
+ // Avoid adding interior rings which are invalid
+ // because of its number of points:
+ std::size_t const min_num_points
+ = core_detail::closure::minimum_ring_size
+ <
+ geometry::closure<Destination>::value
+ >::value;
+
+ if (geometry::num_points(source) >= min_num_points)
+ {
+ interior_rings(destination).resize(
+ interior_rings(destination).size() + 1);
+ geometry::convert(source, interior_rings(destination).back());
+ if (reverse)
+ {
+ boost::reverse(interior_rings(destination).back());
+ }
+ }
+ }
+ }
+};
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CONVERT_RING_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
new file mode 100644
index 000000000..5e18d0453
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
@@ -0,0 +1,295 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP
+
+
+#include <boost/array.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/views/closeable_view.hpp>
+#include <boost/geometry/views/reversible_view.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace copy_segments
+{
+
+
+template <typename Range, bool Reverse, typename SegmentIdentifier, typename PointOut>
+struct copy_segment_point_range
+{
+ typedef typename closeable_view
+ <
+ Range const,
+ closure<Range>::value
+ >::type cview_type;
+
+ typedef typename reversible_view
+ <
+ cview_type const,
+ Reverse ? iterate_reverse : iterate_forward
+ >::type rview_type;
+
+ static inline bool apply(Range const& range,
+ SegmentIdentifier const& seg_id, bool second,
+ PointOut& point)
+ {
+ int index = seg_id.segment_index;
+ if (second)
+ {
+ index++;
+ if (index >= int(boost::size(range)))
+ {
+ index = 0;
+ }
+ }
+
+ // Exception?
+ if (index >= int(boost::size(range)))
+ {
+ return false;
+ }
+
+ cview_type cview(range);
+ rview_type view(cview);
+
+
+ geometry::convert(*(boost::begin(view) + index), point);
+ return true;
+ }
+};
+
+
+template <typename Polygon, bool Reverse, typename SegmentIdentifier, typename PointOut>
+struct copy_segment_point_polygon
+{
+ static inline bool apply(Polygon const& polygon,
+ SegmentIdentifier const& seg_id, bool second,
+ PointOut& point)
+ {
+ // Call ring-version with the right ring
+ return copy_segment_point_range
+ <
+ typename geometry::ring_type<Polygon>::type,
+ Reverse,
+ SegmentIdentifier,
+ PointOut
+ >::apply
+ (
+ seg_id.ring_index < 0
+ ? geometry::exterior_ring(polygon)
+ : geometry::interior_rings(polygon)[seg_id.ring_index],
+ seg_id, second,
+ point
+ );
+ }
+};
+
+
+template <typename Box, bool Reverse, typename SegmentIdentifier, typename PointOut>
+struct copy_segment_point_box
+{
+ static inline bool apply(Box const& box,
+ SegmentIdentifier const& seg_id, bool second,
+ PointOut& point)
+ {
+ int index = seg_id.segment_index;
+ if (second)
+ {
+ index++;
+ }
+
+ boost::array<typename point_type<Box>::type, 4> bp;
+ assign_box_corners_oriented<Reverse>(box, bp);
+ point = bp[index % 4];
+ return true;
+ }
+};
+
+
+
+
+}} // namespace detail::copy_segments
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Tag,
+ typename GeometryIn,
+ bool Reverse,
+ typename SegmentIdentifier,
+ typename PointOut
+>
+struct copy_segment_point
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<GeometryIn>)
+ );
+};
+
+
+template <typename LineString, bool Reverse, typename SegmentIdentifier, typename PointOut>
+struct copy_segment_point<linestring_tag, LineString, Reverse, SegmentIdentifier, PointOut>
+ : detail::copy_segments::copy_segment_point_range
+ <
+ LineString, Reverse, SegmentIdentifier, PointOut
+ >
+{};
+
+
+template <typename Ring, bool Reverse, typename SegmentIdentifier, typename PointOut>
+struct copy_segment_point<ring_tag, Ring, Reverse, SegmentIdentifier, PointOut>
+ : detail::copy_segments::copy_segment_point_range
+ <
+ Ring, Reverse, SegmentIdentifier, PointOut
+ >
+{};
+
+template <typename Polygon, bool Reverse, typename SegmentIdentifier, typename PointOut>
+struct copy_segment_point<polygon_tag, Polygon, Reverse, SegmentIdentifier, PointOut>
+ : detail::copy_segments::copy_segment_point_polygon
+ <
+ Polygon, Reverse, SegmentIdentifier, PointOut
+ >
+{};
+
+
+template <typename Box, bool Reverse, typename SegmentIdentifier, typename PointOut>
+struct copy_segment_point<box_tag, Box, Reverse, SegmentIdentifier, PointOut>
+ : detail::copy_segments::copy_segment_point_box
+ <
+ Box, Reverse, SegmentIdentifier, PointOut
+ >
+{};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+
+
+/*!
+ \brief Helper function, copies a point from a segment
+ \ingroup overlay
+ */
+template<bool Reverse, typename Geometry, typename SegmentIdentifier, typename PointOut>
+inline bool copy_segment_point(Geometry const& geometry,
+ SegmentIdentifier const& seg_id, bool second,
+ PointOut& point_out)
+{
+ concept::check<Geometry const>();
+
+ return dispatch::copy_segment_point
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Reverse,
+ SegmentIdentifier,
+ PointOut
+ >::apply(geometry, seg_id, second, point_out);
+}
+
+
+/*!
+ \brief Helper function, to avoid the same construct several times,
+ copies a point, based on a source-index and two geometries
+ \ingroup overlay
+ */
+template
+<
+ bool Reverse1, bool Reverse2,
+ typename Geometry1, typename Geometry2,
+ typename SegmentIdentifier,
+ typename PointOut
+>
+inline bool copy_segment_point(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ SegmentIdentifier const& seg_id, bool second,
+ PointOut& point_out)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+
+ if (seg_id.source_index == 0)
+ {
+ return dispatch::copy_segment_point
+ <
+ typename tag<Geometry1>::type,
+ Geometry1,
+ Reverse1,
+ SegmentIdentifier,
+ PointOut
+ >::apply(geometry1, seg_id, second, point_out);
+ }
+ else if (seg_id.source_index == 1)
+ {
+ return dispatch::copy_segment_point
+ <
+ typename tag<Geometry2>::type,
+ Geometry2,
+ Reverse2,
+ SegmentIdentifier,
+ PointOut
+ >::apply(geometry2, seg_id, second, point_out);
+ }
+ // Exception?
+ return false;
+}
+
+
+/*!
+ \brief Helper function, to avoid the same construct several times,
+ copies a point, based on a source-index and two geometries
+ \ingroup overlay
+ */
+template
+<
+ bool Reverse1, bool Reverse2,
+ typename Geometry1, typename Geometry2,
+ typename SegmentIdentifier,
+ typename PointOut
+>
+inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ SegmentIdentifier const& seg_id,
+ PointOut& point1, PointOut& point2)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+
+ return copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, false, point1)
+ && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, true, point2);
+}
+
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/copy_segments.hpp b/boost/geometry/algorithms/detail/overlay/copy_segments.hpp
new file mode 100644
index 000000000..805f3923e
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/copy_segments.hpp
@@ -0,0 +1,328 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP
+
+
+#include <boost/array.hpp>
+#include <boost/mpl/assert.hpp>
+#include <vector>
+
+#include <boost/assert.hpp>
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/iterators/ever_circling_iterator.hpp>
+#include <boost/geometry/views/closeable_view.hpp>
+#include <boost/geometry/views/reversible_view.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace copy_segments
+{
+
+
+template
+<
+ typename Ring,
+ bool Reverse,
+ typename SegmentIdentifier,
+ typename RangeOut
+>
+struct copy_segments_ring
+{
+ typedef typename closeable_view
+ <
+ Ring const,
+ closure<Ring>::value
+ >::type cview_type;
+
+ typedef typename reversible_view
+ <
+ cview_type const,
+ Reverse ? iterate_reverse : iterate_forward
+ >::type rview_type;
+
+ typedef typename boost::range_iterator<rview_type const>::type iterator;
+ typedef geometry::ever_circling_iterator<iterator> ec_iterator;
+
+ static inline void apply(Ring const& ring,
+ SegmentIdentifier const& seg_id, int to_index,
+ RangeOut& current_output)
+ {
+ cview_type cview(ring);
+ rview_type view(cview);
+
+ // 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 const from_index = seg_id.segment_index + 1;
+
+ // Sanity check
+ BOOST_ASSERT(from_index < int(boost::size(view)));
+
+ ec_iterator it(boost::begin(view), boost::end(view),
+ boost::begin(view) + 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
+ typedef typename boost::range_difference<Ring>::type size_type;
+ size_type const count = from_index <= to_index
+ ? to_index - from_index + 1
+ : int(boost::size(view)) - from_index + to_index + 1;
+
+ for (size_type i = 0; i < count; ++i, ++it)
+ {
+ detail::overlay::append_no_duplicates(current_output, *it);
+ }
+ }
+};
+
+template
+<
+ typename LineString,
+ bool Reverse,
+ typename SegmentIdentifier,
+ typename RangeOut
+>
+struct copy_segments_linestring
+{
+
+ typedef typename boost::range_iterator<LineString const>::type iterator;
+
+ static inline void apply(LineString const& ls,
+ SegmentIdentifier const& seg_id, int to_index,
+ RangeOut& current_output)
+ {
+ int const from_index = seg_id.segment_index + 1;
+
+ // Sanity check
+ if (from_index > to_index || from_index < 0 || to_index >= int(boost::size(ls)))
+ {
+ return;
+ }
+
+ typedef typename boost::range_difference<LineString>::type size_type;
+ size_type const count = to_index - from_index + 1;
+
+ typename boost::range_iterator<LineString const>::type it = boost::begin(ls) + from_index;
+
+ for (size_type i = 0; i < count; ++i, ++it)
+ {
+ detail::overlay::append_no_duplicates(current_output, *it);
+ }
+ }
+};
+
+template
+<
+ typename Polygon,
+ bool Reverse,
+ typename SegmentIdentifier,
+ typename RangeOut
+>
+struct copy_segments_polygon
+{
+ static inline void apply(Polygon const& polygon,
+ SegmentIdentifier const& seg_id, int to_index,
+ RangeOut& current_output)
+ {
+ // Call ring-version with the right ring
+ copy_segments_ring
+ <
+ typename geometry::ring_type<Polygon>::type,
+ Reverse,
+ SegmentIdentifier,
+ RangeOut
+ >::apply
+ (
+ seg_id.ring_index < 0
+ ? geometry::exterior_ring(polygon)
+ : geometry::interior_rings(polygon)[seg_id.ring_index],
+ seg_id, to_index,
+ current_output
+ );
+ }
+};
+
+
+template
+<
+ typename Box,
+ bool Reverse,
+ 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)
+ {
+ int index = seg_id.segment_index + 1;
+ BOOST_ASSERT(index < 5);
+
+ int const count = index <= to_index
+ ? to_index - index + 1
+ : 5 - index + to_index + 1;
+
+ // Create array of points, the fifth one closes it
+ boost::array<typename point_type<Box>::type, 5> bp;
+ assign_box_corners_oriented<Reverse>(box, bp);
+ bp[4] = bp[0];
+
+ // (possibly cyclic) copy to output
+ // (see comments in ring-version)
+ for (int i = 0; i < count; i++, index++)
+ {
+ detail::overlay::append_no_duplicates(current_output, bp[index % 5]);
+
+ }
+ }
+};
+
+
+}} // namespace detail::copy_segments
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag,
+ typename GeometryIn,
+ bool Reverse,
+ typename SegmentIdentifier,
+ typename RangeOut
+>
+struct copy_segments
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<GeometryIn>)
+ );
+};
+
+
+template
+<
+ typename Ring,
+ bool Reverse,
+ typename SegmentIdentifier,
+ typename RangeOut
+>
+struct copy_segments<ring_tag, Ring, Reverse, SegmentIdentifier, RangeOut>
+ : detail::copy_segments::copy_segments_ring
+ <
+ Ring, Reverse, SegmentIdentifier, RangeOut
+ >
+{};
+
+
+
+template
+<
+ typename LineString,
+ bool Reverse,
+ typename SegmentIdentifier,
+ typename RangeOut
+>
+struct copy_segments<linestring_tag, LineString, Reverse, SegmentIdentifier, RangeOut>
+ : detail::copy_segments::copy_segments_linestring
+ <
+ LineString, Reverse, SegmentIdentifier, RangeOut
+ >
+{};
+
+template
+<
+ typename Polygon,
+ bool Reverse,
+ typename SegmentIdentifier,
+ typename RangeOut
+>
+struct copy_segments<polygon_tag, Polygon, Reverse, SegmentIdentifier, RangeOut>
+ : detail::copy_segments::copy_segments_polygon
+ <
+ Polygon, Reverse, SegmentIdentifier, RangeOut
+ >
+{};
+
+
+template
+<
+ typename Box,
+ bool Reverse,
+ typename SegmentIdentifier,
+ typename RangeOut
+>
+struct copy_segments<box_tag, Box, Reverse, SegmentIdentifier, RangeOut>
+ : detail::copy_segments::copy_segments_box
+ <
+ Box, Reverse, SegmentIdentifier, RangeOut
+ >
+{};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Copy segments from a geometry, starting with the specified segment (seg_id)
+ until the specified index (to_index)
+ \ingroup overlay
+ */
+template
+<
+ bool Reverse,
+ 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<Geometry const>();
+
+ dispatch::copy_segments
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Reverse,
+ SegmentIdentifier,
+ RangeOut
+ >::apply(geometry, seg_id, to_index, range_out);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp b/boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp
new file mode 100644
index 000000000..0cc34255c
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp
@@ -0,0 +1,66 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DEBUG_TURN_INFO_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DEBUG_TURN_INFO_HPP
+
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+#include <boost/geometry/algorithms/detail/overlay/visit_info.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+inline char method_char(detail::overlay::method_type const& method)
+{
+ using namespace detail::overlay;
+ switch(method)
+ {
+ case method_none : return '-';
+ case method_disjoint : return 'd';
+ case method_crosses : return 'i';
+ case method_touch : return 't';
+ case method_touch_interior : return 'm';
+ case method_collinear : return 'c';
+ case method_equal : return 'e';
+ case method_error : return '!';
+ default : return '?';
+ }
+}
+
+inline char operation_char(detail::overlay::operation_type const& operation)
+{
+ using namespace detail::overlay;
+ switch(operation)
+ {
+ case operation_none : return '-';
+ case operation_union : return 'u';
+ case operation_intersection : return 'i';
+ case operation_blocked : return 'x';
+ case operation_continue : return 'c';
+ case operation_opposite : return 'o';
+ default : return '?';
+ }
+}
+
+inline char visited_char(detail::overlay::visit_info const& v)
+{
+ if (v.rejected()) return 'R';
+ if (v.started()) return 's';
+ if (v.visited()) return 'v';
+ if (v.none()) return '-';
+ if (v.finished()) return 'f';
+ return '?';
+}
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DEBUG_TURN_INFO_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
new file mode 100644
index 000000000..00b7a5c3a
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
@@ -0,0 +1,525 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICH_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICH_HPP
+
+#include <cstddef>
+#include <algorithm>
+#include <map>
+#include <set>
+#include <vector>
+
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+# include <iostream>
+# include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
+# include <boost/geometry/io/wkt/wkt.hpp>
+# define BOOST_GEOMETRY_DEBUG_IDENTIFIER
+#endif
+
+#include <boost/assert.hpp>
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
+#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_relative_order.hpp>
+#include <boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp>
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+# include <boost/geometry/algorithms/detail/overlay/check_enrich.hpp>
+#endif
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+// Wraps "turn_operation" from turn_info.hpp,
+// giving it extra information
+template <typename TurnOperation>
+struct indexed_turn_operation
+{
+ typedef TurnOperation type;
+
+ int index;
+ int operation_index;
+ bool discarded;
+ TurnOperation subject;
+
+ inline indexed_turn_operation(int i, int oi, TurnOperation const& s)
+ : index(i)
+ , operation_index(oi)
+ , discarded(false)
+ , subject(s)
+ {}
+};
+
+template <typename IndexedTurnOperation>
+struct remove_discarded
+{
+ inline bool operator()(IndexedTurnOperation const& operation) const
+ {
+ return operation.discarded;
+ }
+};
+
+
+template
+<
+ typename TurnPoints,
+ typename Indexed,
+ typename Geometry1, typename Geometry2,
+ bool Reverse1, bool Reverse2,
+ typename Strategy
+>
+struct sort_on_segment_and_distance
+{
+ inline sort_on_segment_and_distance(TurnPoints const& turn_points
+ , Geometry1 const& geometry1
+ , Geometry2 const& geometry2
+ , Strategy const& strategy
+ , bool* clustered)
+ : m_turn_points(turn_points)
+ , m_geometry1(geometry1)
+ , m_geometry2(geometry2)
+ , m_strategy(strategy)
+ , m_clustered(clustered)
+ {
+ }
+
+private :
+
+ TurnPoints const& m_turn_points;
+ Geometry1 const& m_geometry1;
+ Geometry2 const& m_geometry2;
+ Strategy const& m_strategy;
+ mutable bool* m_clustered;
+
+ inline bool consider_relative_order(Indexed const& left,
+ Indexed const& right) const
+ {
+ typedef typename geometry::point_type<Geometry1>::type point_type;
+ point_type pi, pj, ri, rj, si, sj;
+
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
+ left.subject.seg_id,
+ pi, pj);
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
+ left.subject.other_id,
+ ri, rj);
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
+ right.subject.other_id,
+ si, sj);
+
+ int const order = get_relative_order
+ <
+ point_type
+ >::apply(pi, pj,ri, rj, si, sj);
+ //debug("r/o", order == -1);
+ return order == -1;
+ }
+
+public :
+
+ // Note that left/right do NOT correspond to m_geometry1/m_geometry2
+ // but to the "indexed_turn_operation"
+ inline bool operator()(Indexed const& left, Indexed const& right) const
+ {
+ segment_identifier const& sl = left.subject.seg_id;
+ segment_identifier const& sr = right.subject.seg_id;
+
+ if (sl == sr)
+ {
+ // Both left and right are located on the SAME segment.
+ typedef typename geometry::coordinate_type<Geometry1>::type coordinate_type;
+ coordinate_type diff = geometry::math::abs(left.subject.enriched.distance - right.subject.enriched.distance);
+ if (diff < geometry::math::relaxed_epsilon<coordinate_type>(10))
+ {
+ // First check "real" intersection (crosses)
+ // -> distance zero due to precision, solve it by sorting
+ if (m_turn_points[left.index].method == method_crosses
+ && m_turn_points[right.index].method == method_crosses)
+ {
+ return consider_relative_order(left, right);
+ }
+
+ // If that is not the case, cluster it later on.
+ // Indicate that this is necessary.
+ *m_clustered = true;
+
+ return left.subject.enriched.distance < right.subject.enriched.distance;
+ }
+ }
+ return sl == sr
+ ? left.subject.enriched.distance < right.subject.enriched.distance
+ : sl < sr;
+
+ }
+};
+
+
+template<typename Turns, typename Operations>
+inline void update_discarded(Turns& turn_points, Operations& operations)
+{
+ // Vice-versa, set discarded to true for discarded operations;
+ // AND set discarded points to true
+ for (typename boost::range_iterator<Operations>::type it = boost::begin(operations);
+ it != boost::end(operations);
+ ++it)
+ {
+ if (turn_points[it->index].discarded)
+ {
+ it->discarded = true;
+ }
+ else if (it->discarded)
+ {
+ turn_points[it->index].discarded = true;
+ }
+ }
+}
+
+
+// Sorts IP-s of this ring on segment-identifier, and if on same segment,
+// on distance.
+// Then assigns for each IP which is the next IP on this segment,
+// plus the vertex-index to travel to, plus the next IP
+// (might be on another segment)
+template
+<
+ typename IndexType,
+ bool Reverse1, bool Reverse2,
+ typename Container,
+ typename TurnPoints,
+ typename Geometry1, typename Geometry2,
+ typename Strategy
+>
+inline void enrich_sort(Container& operations,
+ TurnPoints& turn_points,
+ operation_type for_operation,
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ typedef typename IndexType::type operations_type;
+
+ bool clustered = false;
+ std::sort(boost::begin(operations),
+ boost::end(operations),
+ sort_on_segment_and_distance
+ <
+ TurnPoints,
+ IndexType,
+ Geometry1, Geometry2,
+ Reverse1, Reverse2,
+ Strategy
+ >(turn_points, geometry1, geometry2, strategy, &clustered));
+
+ // DONT'T discard xx / (for union) ix / ii / (for intersection) ux / uu here
+ // It would give way to "lonely" ui turn points, traveling all
+ // the way round. See #105
+
+ if (clustered)
+ {
+ typedef typename boost::range_iterator<Container>::type nc_iterator;
+ nc_iterator it = boost::begin(operations);
+ nc_iterator begin_cluster = boost::end(operations);
+ for (nc_iterator prev = it++;
+ it != boost::end(operations);
+ prev = it++)
+ {
+ operations_type& prev_op = turn_points[prev->index]
+ .operations[prev->operation_index];
+ operations_type& op = turn_points[it->index]
+ .operations[it->operation_index];
+
+ if (prev_op.seg_id == op.seg_id
+ && (turn_points[prev->index].method != method_crosses
+ || turn_points[it->index].method != method_crosses)
+ && geometry::math::equals(prev_op.enriched.distance,
+ op.enriched.distance))
+ {
+ if (begin_cluster == boost::end(operations))
+ {
+ begin_cluster = prev;
+ }
+ }
+ else if (begin_cluster != boost::end(operations))
+ {
+ handle_cluster<IndexType, Reverse1, Reverse2>(begin_cluster, it, turn_points,
+ for_operation, geometry1, geometry2, strategy);
+ begin_cluster = boost::end(operations);
+ }
+ }
+ if (begin_cluster != boost::end(operations))
+ {
+ handle_cluster<IndexType, Reverse1, Reverse2>(begin_cluster, it, turn_points,
+ for_operation, geometry1, geometry2, strategy);
+ }
+ }
+
+ update_discarded(turn_points, operations);
+}
+
+
+template
+<
+ typename IndexType,
+ typename Container,
+ typename TurnPoints
+>
+inline void enrich_discard(Container& operations, TurnPoints& turn_points)
+{
+ update_discarded(turn_points, operations);
+
+ // Then delete discarded operations from vector
+ remove_discarded<IndexType> predicate;
+ operations.erase(
+ std::remove_if(boost::begin(operations),
+ boost::end(operations),
+ predicate),
+ boost::end(operations));
+}
+
+template
+<
+ typename IndexType,
+ typename Container,
+ typename TurnPoints,
+ typename Geometry1,
+ typename Geometry2,
+ typename Strategy
+>
+inline void enrich_assign(Container& operations,
+ TurnPoints& turn_points,
+ operation_type ,
+ Geometry1 const& , Geometry2 const& ,
+ Strategy const& )
+{
+ typedef typename IndexType::type operations_type;
+ typedef typename boost::range_iterator<Container const>::type iterator_type;
+
+
+ if (operations.size() > 0)
+ {
+ // Assign travel-to-vertex/ip index for each turning point.
+ // Because IP's are circular, PREV starts at the very last one,
+ // being assigned from the first one.
+ // "next ip on same segment" should not be considered circular.
+ bool first = true;
+ iterator_type it = boost::begin(operations);
+ for (iterator_type prev = it + (boost::size(operations) - 1);
+ it != boost::end(operations);
+ prev = it++)
+ {
+ operations_type& prev_op
+ = turn_points[prev->index].operations[prev->operation_index];
+ operations_type& op
+ = turn_points[it->index].operations[it->operation_index];
+
+ prev_op.enriched.travels_to_ip_index
+ = it->index;
+ prev_op.enriched.travels_to_vertex_index
+ = it->subject.seg_id.segment_index;
+
+ if (! first
+ && prev_op.seg_id.segment_index == op.seg_id.segment_index)
+ {
+ prev_op.enriched.next_ip_index = it->index;
+ }
+ first = false;
+ }
+ }
+
+ // DEBUG
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ {
+ for (iterator_type it = boost::begin(operations);
+ it != boost::end(operations);
+ ++it)
+ {
+ operations_type& op = turn_points[it->index]
+ .operations[it->operation_index];
+
+ std::cout << it->index
+ << " meth: " << method_char(turn_points[it->index].method)
+ << " seg: " << op.seg_id
+ << " dst: " << boost::numeric_cast<double>(op.enriched.distance)
+ << " op: " << operation_char(turn_points[it->index].operations[0].operation)
+ << operation_char(turn_points[it->index].operations[1].operation)
+ << " dsc: " << (turn_points[it->index].discarded ? "T" : "F")
+ << " ->vtx " << op.enriched.travels_to_vertex_index
+ << " ->ip " << op.enriched.travels_to_ip_index
+ << " ->nxt ip " << op.enriched.next_ip_index
+ //<< " vis: " << visited_char(op.visited)
+ << std::endl;
+ ;
+ }
+ }
+#endif
+ // END DEBUG
+
+}
+
+
+template <typename IndexedType, typename TurnPoints, typename MappedVector>
+inline void create_map(TurnPoints const& turn_points, MappedVector& mapped_vector)
+{
+ typedef typename boost::range_value<TurnPoints>::type turn_point_type;
+ typedef typename turn_point_type::container_type container_type;
+
+ int index = 0;
+ for (typename boost::range_iterator<TurnPoints const>::type
+ it = boost::begin(turn_points);
+ it != boost::end(turn_points);
+ ++it, ++index)
+ {
+ // Add operations on this ring, but skip discarded ones
+ if (! it->discarded)
+ {
+ int op_index = 0;
+ for (typename boost::range_iterator<container_type const>::type
+ op_it = boost::begin(it->operations);
+ op_it != boost::end(it->operations);
+ ++op_it, ++op_index)
+ {
+ // We should NOT skip blocked operations here
+ // because they can be relevant for "the other side"
+ // NOT if (op_it->operation != operation_blocked)
+
+ ring_identifier ring_id
+ (
+ op_it->seg_id.source_index,
+ op_it->seg_id.multi_index,
+ op_it->seg_id.ring_index
+ );
+ mapped_vector[ring_id].push_back
+ (
+ IndexedType(index, op_index, *op_it)
+ );
+ }
+ }
+ }
+}
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+
+/*!
+\brief All intersection points are enriched with successor information
+\ingroup overlay
+\tparam TurnPoints type of intersection container
+ (e.g. vector of "intersection/turn point"'s)
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Strategy side strategy type
+\param turn_points container containing intersectionpoints
+\param for_operation operation_type (union or intersection)
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param strategy strategy
+ */
+template
+<
+ bool Reverse1, bool Reverse2,
+ typename TurnPoints,
+ typename Geometry1, typename Geometry2,
+ typename Strategy
+>
+inline void enrich_intersection_points(TurnPoints& turn_points,
+ detail::overlay::operation_type for_operation,
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ typedef typename boost::range_value<TurnPoints>::type turn_point_type;
+ typedef typename turn_point_type::turn_operation_type turn_operation_type;
+ typedef detail::overlay::indexed_turn_operation
+ <
+ turn_operation_type
+ > indexed_turn_operation;
+
+ typedef std::map
+ <
+ ring_identifier,
+ std::vector<indexed_turn_operation>
+ > mapped_vector_type;
+
+ // DISCARD ALL UU
+ // #76 is the reason that this is necessary...
+ // With uu, at all points there is the risk that rings are being traversed twice or more.
+ // Without uu, all rings having only uu will be untouched and gathered by assemble
+ for (typename boost::range_iterator<TurnPoints>::type
+ it = boost::begin(turn_points);
+ it != boost::end(turn_points);
+ ++it)
+ {
+ if (it->both(detail::overlay::operation_union))
+ {
+ it->discarded = true;
+ }
+ }
+
+
+ // Create a map of vectors of indexed operation-types to be able
+ // to sort intersection points PER RING
+ mapped_vector_type mapped_vector;
+
+ detail::overlay::create_map<indexed_turn_operation>(turn_points, mapped_vector);
+
+
+ // No const-iterator; contents of mapped copy is temporary,
+ // and changed by enrich
+ for (typename mapped_vector_type::iterator mit
+ = mapped_vector.begin();
+ mit != mapped_vector.end();
+ ++mit)
+ {
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ std::cout << "ENRICH-sort Ring "
+ << mit->first << std::endl;
+#endif
+ detail::overlay::enrich_sort<indexed_turn_operation, Reverse1, Reverse2>(mit->second, turn_points, for_operation,
+ geometry1, geometry2, strategy);
+ }
+
+ for (typename mapped_vector_type::iterator mit
+ = mapped_vector.begin();
+ mit != mapped_vector.end();
+ ++mit)
+ {
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ std::cout << "ENRICH-discard Ring "
+ << mit->first << std::endl;
+#endif
+ detail::overlay::enrich_discard<indexed_turn_operation>(mit->second, turn_points);
+ }
+
+ for (typename mapped_vector_type::iterator mit
+ = mapped_vector.begin();
+ mit != mapped_vector.end();
+ ++mit)
+ {
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ std::cout << "ENRICH-assign Ring "
+ << mit->first << std::endl;
+#endif
+ detail::overlay::enrich_assign<indexed_turn_operation>(mit->second, turn_points, for_operation,
+ geometry1, geometry2, strategy);
+ }
+
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ //detail::overlay::check_graph(turn_points, for_operation);
+#endif
+
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICH_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp b/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp
new file mode 100644
index 000000000..8c8ed9618
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp
@@ -0,0 +1,76 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICHMENT_INFO_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICHMENT_INFO_HPP
+
+
+#include <boost/geometry/strategies/distance.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+/*!
+\brief Keeps info to enrich intersection info (per source)
+\details Class to keep information necessary for traversal phase (a phase
+ of the overlay process). The information is gathered during the
+ enrichment phase
+ */
+template<typename P>
+struct enrichment_info
+{
+ typedef typename strategy::distance::services::return_type
+ <
+ typename strategy::distance::services::comparable_type
+ <
+ typename strategy::distance::services::default_strategy
+ <
+ point_tag,
+ P
+ >::type
+ >::type
+ >::type distance_type;
+
+ inline enrichment_info()
+ : travels_to_vertex_index(-1)
+ , travels_to_ip_index(-1)
+ , next_ip_index(-1)
+ , distance(distance_type())
+ {}
+
+ // vertex to which is free travel after this IP,
+ // so from "segment_index+1" to "travels_to_vertex_index", without IP-s,
+ // can be -1
+ int travels_to_vertex_index;
+
+ // same but now IP index, so "next IP index" but not on THIS segment
+ int travels_to_ip_index;
+
+ // index of next IP on this segment, -1 if there is no one
+ int next_ip_index;
+
+ distance_type distance; // distance-measurement from segment.first to IP
+};
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICHMENT_INFO_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/follow.hpp b/boost/geometry/algorithms/detail/overlay/follow.hpp
new file mode 100644
index 000000000..b110cc960
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/follow.hpp
@@ -0,0 +1,416 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_HPP
+
+#include <cstddef>
+
+#include <boost/range.hpp>
+#include <boost/mpl/assert.hpp>
+
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>
+#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>
+#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+
+#include <boost/geometry/algorithms/covered_by.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+namespace following
+{
+
+template <typename Turn, typename Operation>
+static inline bool is_entering(Turn const& /* TODO remove this parameter */, Operation const& op)
+{
+ // (Blocked means: blocked for polygon/polygon intersection, because
+ // they are reversed. But for polygon/line it is similar to continue)
+ return op.operation == operation_intersection
+ || op.operation == operation_continue
+ || op.operation == operation_blocked
+ ;
+}
+
+template
+<
+ typename Turn,
+ typename Operation,
+ typename LineString,
+ typename Polygon
+>
+static inline bool last_covered_by(Turn const& turn, Operation const& op,
+ LineString const& linestring, Polygon const& polygon)
+{
+ // Check any point between the this one and the first IP
+ typedef typename geometry::point_type<LineString>::type point_type;
+ point_type point_in_between;
+ detail::point_on_border::midpoint_helper
+ <
+ point_type,
+ 0, dimension<point_type>::value
+ >::apply(point_in_between, linestring[op.seg_id.segment_index], turn.point);
+
+ return geometry::covered_by(point_in_between, polygon);
+}
+
+
+template
+<
+ typename Turn,
+ typename Operation,
+ typename LineString,
+ typename Polygon
+>
+static inline bool is_leaving(Turn const& turn, Operation const& op,
+ bool entered, bool first,
+ LineString const& linestring, Polygon const& polygon)
+{
+ if (op.operation == operation_union)
+ {
+ return entered
+ || turn.method == method_crosses
+ || (first && last_covered_by(turn, op, linestring, polygon))
+ ;
+ }
+ return false;
+}
+
+
+template
+<
+ typename Turn,
+ typename Operation,
+ typename LineString,
+ typename Polygon
+>
+static inline bool is_staying_inside(Turn const& turn, Operation const& op,
+ bool entered, bool first,
+ LineString const& linestring, Polygon const& polygon)
+{
+ if (turn.method == method_crosses)
+ {
+ // The normal case, this is completely covered with entering/leaving
+ // so stay out of this time consuming "covered_by"
+ return false;
+ }
+
+ if (is_entering(turn, op))
+ {
+ return entered || (first && last_covered_by(turn, op, linestring, polygon));
+ }
+
+ return false;
+}
+
+template
+<
+ typename Turn,
+ typename Operation,
+ typename Linestring,
+ typename Polygon
+>
+static inline bool was_entered(Turn const& turn, Operation const& op, bool first,
+ Linestring const& linestring, Polygon const& polygon)
+{
+ if (first && (turn.method == method_collinear || turn.method == method_equal))
+ {
+ return last_covered_by(turn, op, linestring, polygon);
+ }
+ return false;
+}
+
+
+// Template specialization structure to call the right actions for the right type
+template<overlay_type OverlayType>
+struct action_selector
+{
+ // If you get here the overlay type is not intersection or difference
+ // BOOST_MPL_ASSERT(false);
+};
+
+// Specialization for intersection, containing the implementation
+template<>
+struct action_selector<overlay_intersection>
+{
+ template
+ <
+ typename OutputIterator,
+ typename LineStringOut,
+ typename LineString,
+ typename Point,
+ typename Operation
+ >
+ static inline void enter(LineStringOut& current_piece,
+ LineString const& ,
+ segment_identifier& segment_id,
+ int , Point const& point,
+ Operation const& operation, OutputIterator& )
+ {
+ // On enter, append the intersection point and remember starting point
+ detail::overlay::append_no_duplicates(current_piece, point);
+ segment_id = operation.seg_id;
+ }
+
+ template
+ <
+ typename OutputIterator,
+ typename LineStringOut,
+ typename LineString,
+ typename Point,
+ typename Operation
+ >
+ static inline void leave(LineStringOut& current_piece,
+ LineString const& linestring,
+ segment_identifier& segment_id,
+ int index, Point const& point,
+ Operation const& , OutputIterator& out)
+ {
+ // On leave, copy all segments from starting point, append the intersection point
+ // and add the output piece
+ geometry::copy_segments<false>(linestring, segment_id, index, current_piece);
+ detail::overlay::append_no_duplicates(current_piece, point);
+ if (current_piece.size() > 1)
+ {
+ *out++ = current_piece;
+ }
+ current_piece.clear();
+ }
+
+ static inline bool is_entered(bool entered)
+ {
+ return entered;
+ }
+
+ template <typename Point, typename Geometry>
+ static inline bool included(Point const& point, Geometry const& geometry)
+ {
+ return geometry::covered_by(point, geometry);
+ }
+
+};
+
+// Specialization for difference, which reverses these actions
+template<>
+struct action_selector<overlay_difference>
+{
+ typedef action_selector<overlay_intersection> normal_action;
+
+ template
+ <
+ typename OutputIterator,
+ typename LineStringOut,
+ typename LineString,
+ typename Point,
+ typename Operation
+ >
+ static inline void enter(LineStringOut& current_piece,
+ LineString const& linestring,
+ segment_identifier& segment_id,
+ int index, Point const& point,
+ Operation const& operation, OutputIterator& out)
+ {
+ normal_action::leave(current_piece, linestring, segment_id, index,
+ point, operation, out);
+ }
+
+ template
+ <
+ typename OutputIterator,
+ typename LineStringOut,
+ typename LineString,
+ typename Point,
+ typename Operation
+ >
+ static inline void leave(LineStringOut& current_piece,
+ LineString const& linestring,
+ segment_identifier& segment_id,
+ int index, Point const& point,
+ Operation const& operation, OutputIterator& out)
+ {
+ normal_action::enter(current_piece, linestring, segment_id, index,
+ point, operation, out);
+ }
+
+ static inline bool is_entered(bool entered)
+ {
+ return ! normal_action::is_entered(entered);
+ }
+
+ template <typename Point, typename Geometry>
+ static inline bool included(Point const& point, Geometry const& geometry)
+ {
+ return ! normal_action::included(point, geometry);
+ }
+
+};
+
+}
+
+/*!
+\brief Follows a linestring from intersection point to intersection point, outputting which
+ is inside, or outside, a ring or polygon
+\ingroup overlay
+ */
+template
+<
+ typename LineStringOut,
+ typename LineString,
+ typename Polygon,
+ overlay_type OverlayType
+>
+class follow
+{
+
+ template<typename Turn>
+ struct sort_on_segment
+ {
+ // In case of turn point at the same location, we want to have continue/blocked LAST
+ // because that should be followed (intersection) or skipped (difference).
+ inline int operation_order(Turn const& turn) const
+ {
+ operation_type const& operation = turn.operations[0].operation;
+ switch(operation)
+ {
+ case operation_opposite : return 0;
+ case operation_none : return 0;
+ case operation_union : return 1;
+ case operation_intersection : return 2;
+ case operation_blocked : return 3;
+ case operation_continue : return 4;
+ }
+ return -1;
+ };
+
+ inline bool use_operation(Turn const& left, Turn const& right) const
+ {
+ // If they are the same, OK.
+ return operation_order(left) < operation_order(right);
+ }
+
+ inline bool use_distance(Turn const& left, Turn const& right) const
+ {
+ return geometry::math::equals(left.operations[0].enriched.distance, right.operations[0].enriched.distance)
+ ? use_operation(left, right)
+ : left.operations[0].enriched.distance < right.operations[0].enriched.distance
+ ;
+ }
+
+ inline bool operator()(Turn const& left, Turn const& right) const
+ {
+ segment_identifier const& sl = left.operations[0].seg_id;
+ segment_identifier const& sr = right.operations[0].seg_id;
+
+ return sl == sr
+ ? use_distance(left, right)
+ : sl < sr
+ ;
+
+ }
+ };
+
+
+
+public :
+
+ template <typename Point, typename Geometry>
+ static inline bool included(Point const& point, Geometry const& geometry)
+ {
+ return following::action_selector<OverlayType>::included(point, geometry);
+ }
+
+ template<typename Turns, typename OutputIterator>
+ static inline OutputIterator apply(LineString const& linestring, Polygon const& polygon,
+ detail::overlay::operation_type , // TODO: this parameter might be redundant
+ Turns& turns, OutputIterator out)
+ {
+ typedef typename boost::range_iterator<Turns>::type turn_iterator;
+ typedef typename boost::range_value<Turns>::type turn_type;
+ typedef typename boost::range_iterator
+ <
+ typename turn_type::container_type
+ >::type turn_operation_iterator_type;
+
+ typedef following::action_selector<OverlayType> action;
+
+ // Sort intersection points on segments-along-linestring, and distance
+ // (like in enrich is done for poly/poly)
+ std::sort(boost::begin(turns), boost::end(turns), sort_on_segment<turn_type>());
+
+ LineStringOut current_piece;
+ geometry::segment_identifier current_segment_id(0, -1, -1, -1);
+
+ // Iterate through all intersection points (they are ordered along the line)
+ bool entered = false;
+ bool first = true;
+ for (turn_iterator it = boost::begin(turns); it != boost::end(turns); ++it)
+ {
+ turn_operation_iterator_type iit = boost::begin(it->operations);
+
+ if (following::was_entered(*it, *iit, first, linestring, polygon))
+ {
+ debug_traverse(*it, *iit, "-> Was entered");
+ entered = true;
+ }
+
+ if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon))
+ {
+ debug_traverse(*it, *iit, "-> Staying inside");
+
+ entered = true;
+ }
+ else if (following::is_entering(*it, *iit))
+ {
+ debug_traverse(*it, *iit, "-> Entering");
+
+ entered = true;
+ action::enter(current_piece, linestring, current_segment_id, iit->seg_id.segment_index, it->point, *iit, out);
+ }
+ else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon))
+ {
+ debug_traverse(*it, *iit, "-> Leaving");
+
+ entered = false;
+ action::leave(current_piece, linestring, current_segment_id, iit->seg_id.segment_index, it->point, *iit, out);
+ }
+ first = false;
+ }
+
+ if (action::is_entered(entered))
+ {
+ geometry::copy_segments<false>(linestring, current_segment_id,
+ boost::size(linestring) - 1,
+ current_piece);
+ }
+
+ // Output the last one, if applicable
+ if (current_piece.size() > 1)
+ {
+ *out++ = current_piece;
+ }
+ return out;
+ }
+
+};
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_FOLLOW_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp
new file mode 100644
index 000000000..019c3ba3f
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp
@@ -0,0 +1,146 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_INTERSECTION_POINTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_INTERSECTION_POINTS_HPP
+
+
+#include <cstddef>
+
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
+
+#include <boost/geometry/geometries/segment.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace get_intersection_points
+{
+
+
+template
+<
+ typename Point1,
+ typename Point2,
+ typename TurnInfo
+>
+struct get_turn_without_info
+{
+ typedef strategy_intersection
+ <
+ typename cs_tag<typename TurnInfo::point_type>::type,
+ Point1,
+ Point2,
+ typename TurnInfo::point_type
+ > si;
+
+ typedef typename si::segment_intersection_strategy_type strategy;
+
+
+
+ template <typename OutputIterator>
+ static inline OutputIterator apply(
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ TurnInfo const& ,
+ OutputIterator out)
+ {
+ typedef model::referring_segment<Point1 const> segment_type1;
+ typedef model::referring_segment<Point1 const> segment_type2;
+ segment_type1 p1(pi, pj), p2(pj, pk);
+ segment_type2 q1(qi, qj), q2(qj, qk);
+
+ //
+ typename strategy::return_type result = strategy::apply(p1, q1);
+
+ for (std::size_t i = 0; i < result.template get<0>().count; i++)
+ {
+
+ TurnInfo tp;
+ geometry::convert(result.template get<0>().intersections[i], tp.point);
+ *out++ = tp;
+ }
+
+ return out;
+ }
+};
+
+}} // namespace detail::get_intersection_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Turns
+>
+inline void get_intersection_points(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Turns& turns)
+{
+ concept::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2 const>();
+
+ typedef detail::get_intersection_points::get_turn_without_info
+ <
+ typename point_type<Geometry1>::type,
+ typename point_type<Geometry2>::type,
+ typename boost::range_value<Turns>::type
+ > TurnPolicy;
+
+ typedef typename strategy_intersection
+ <
+ typename cs_tag<Geometry1>::type,
+ Geometry1,
+ Geometry2,
+ typename boost::range_value<Turns>::type
+ >::segment_intersection_strategy_type segment_intersection_strategy_type;
+
+ detail::get_turns::no_interrupt_policy interrupt_policy;
+
+ boost::mpl::if_c
+ <
+ reverse_dispatch<Geometry1, Geometry2>::type::value,
+ dispatch::get_turns_reversed
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ Geometry1, Geometry2,
+ false, false,
+ Turns, TurnPolicy,
+ //segment_intersection_strategy_type,
+ detail::get_turns::no_interrupt_policy
+ >,
+ dispatch::get_turns
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ Geometry1, Geometry2,
+ false, false,
+ Turns, TurnPolicy,
+ //segment_intersection_strategy_type,
+ detail::get_turns::no_interrupt_policy
+ >
+ >::type::apply(
+ 0, geometry1,
+ 1, geometry2,
+ turns, interrupt_policy);
+}
+
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_INTERSECTION_POINTS_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/get_relative_order.hpp b/boost/geometry/algorithms/detail/overlay/get_relative_order.hpp
new file mode 100644
index 000000000..522ef6838
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/get_relative_order.hpp
@@ -0,0 +1,108 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RELATIVE_ORDER_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RELATIVE_ORDER_HPP
+
+
+#include <boost/geometry/algorithms/distance.hpp>
+
+#include <boost/geometry/strategies/intersection.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+/*!
+ \brief Get relative order
+ \details Can indicate which of two segments R and S,
+ both crossing a common segment P, comes first.
+ If the two segments cross P very close (e.g. in a spike),
+ the distance between the intersection points can be zero,
+ but we still need to know which comes first.
+ Therefore, it is useful that using sides we are able to discover this.
+ */
+template <typename Point1>
+struct get_relative_order
+{
+ typedef strategy_intersection
+ <
+ typename cs_tag<Point1>::type,
+ Point1,
+ Point1,
+ Point1
+ > si;
+
+ typedef typename si::side_strategy_type strategy;
+
+ template <typename Point>
+ static inline int value_via_product(Point const& ti, Point const& tj,
+ Point const& ui, Point const& uj, int factor)
+ {
+ int const side_ti_u = strategy::apply(ti, tj, ui);
+ int const side_tj_u = strategy::apply(ti, tj, uj);
+
+#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
+ std::cout << (factor == 1 ? " r//s " : " s//r ")
+ << side_ti_u << " / " << side_tj_u;
+#endif
+
+ return side_ti_u * side_tj_u >= 0
+ ? factor * (side_ti_u != 0 ? side_ti_u : side_tj_u)
+ : 0;
+ }
+
+
+ static inline int apply(
+ Point1 const& pi, Point1 const& pj,
+ Point1 const& ri, Point1 const& rj,
+ Point1 const& si, Point1 const& sj)
+ {
+ int const side_ri_p = strategy::apply(pi, pj, ri);
+ int const side_si_p = strategy::apply(pi, pj, si);
+
+#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
+ int const side_rj_p = strategy::apply(pi, pj, rj);
+ int const side_sj_p = strategy::apply(pi, pj, sj);
+ std::cout << "r//p: " << side_ri_p << " / " << side_rj_p;
+ std::cout << " s//p: " << side_si_p << " / " << side_sj_p;
+#endif
+
+ int value = value_via_product(si, sj, ri, rj, 1);
+ if (value == 0)
+ {
+ value = value_via_product(ri, rj, si, sj, -1);
+ }
+
+ int const order = side_ri_p * side_ri_p * side_si_p * value;
+
+#ifdef BOOST_GEOMETRY_DEBUG_RELATIVE_ORDER
+ std::cout
+ << " o: " << order
+ << std::endl << std::endl;
+#endif
+
+ return order;
+ }
+};
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RELATIVE_ORDER_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/get_ring.hpp b/boost/geometry/algorithms/detail/overlay/get_ring.hpp
new file mode 100644
index 000000000..c2c698057
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/get_ring.hpp
@@ -0,0 +1,102 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP
+
+
+#include <boost/assert.hpp>
+#include <boost/range.hpp>
+
+
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+template<typename Tag>
+struct get_ring
+{};
+
+// A container of rings (multi-ring but that does not exist)
+// gets the "void" tag and is dispatched here.
+template<>
+struct get_ring<void>
+{
+ template<typename Container>
+ static inline typename boost::range_value<Container>::type const&
+ apply(ring_identifier const& id, Container const& container)
+ {
+ return container[id.multi_index];
+ }
+};
+
+
+
+
+template<>
+struct get_ring<ring_tag>
+{
+ template<typename Ring>
+ static inline Ring const& apply(ring_identifier const& , Ring const& ring)
+ {
+ return ring;
+ }
+};
+
+
+template<>
+struct get_ring<box_tag>
+{
+ template<typename Box>
+ static inline Box const& apply(ring_identifier const& ,
+ Box const& box)
+ {
+ return box;
+ }
+};
+
+
+template<>
+struct get_ring<polygon_tag>
+{
+ template<typename Polygon>
+ static inline typename ring_return_type<Polygon const>::type const apply(
+ ring_identifier const& id,
+ Polygon const& polygon)
+ {
+ BOOST_ASSERT
+ (
+ id.ring_index >= -1
+ && id.ring_index < int(boost::size(interior_rings(polygon)))
+ );
+ return id.ring_index < 0
+ ? exterior_ring(polygon)
+ : interior_rings(polygon)[id.ring_index];
+ }
+};
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
new file mode 100644
index 000000000..68aa62bb4
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
@@ -0,0 +1,1122 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP
+
+
+#include <boost/assert.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+
+#include <boost/geometry/geometries/segment.hpp>
+
+
+// Silence warning C4127: conditional expression is constant
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4127)
+#endif
+
+
+namespace boost { namespace geometry
+{
+
+#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
+class turn_info_exception : public geometry::exception
+{
+ std::string message;
+public:
+
+ // NOTE: "char" will be replaced by enum in future version
+ inline turn_info_exception(char const method)
+ {
+ message = "Boost.Geometry Turn exception: ";
+ message += method;
+ }
+
+ virtual ~turn_info_exception() throw()
+ {}
+
+ virtual char const* what() const throw()
+ {
+ return message.c_str();
+ }
+};
+#endif
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+struct base_turn_handler
+{
+ // Returns true if both sides are opposite
+ static inline bool opposite(int side1, int side2)
+ {
+ // We cannot state side1 == -side2, because 0 == -0
+ // So either side1*side2==-1 or side1==-side2 && side1 != 0
+ return side1 * side2 == -1;
+ }
+
+ // Same side of a segment (not being 0)
+ static inline bool same(int side1, int side2)
+ {
+ return side1 * side2 == 1;
+ }
+
+ // Both continue
+ template <typename TurnInfo>
+ static inline void both(TurnInfo& ti, operation_type const op)
+ {
+ ti.operations[0].operation = op;
+ ti.operations[1].operation = op;
+ }
+
+ // If condition, first union/second intersection, else vice versa
+ template <typename TurnInfo>
+ static inline void ui_else_iu(bool condition, TurnInfo& ti)
+ {
+ ti.operations[0].operation = condition
+ ? operation_union : operation_intersection;
+ ti.operations[1].operation = condition
+ ? operation_intersection : operation_union;
+ }
+
+ // If condition, both union, else both intersection
+ template <typename TurnInfo>
+ static inline void uu_else_ii(bool condition, TurnInfo& ti)
+ {
+ both(ti, condition ? operation_union : operation_intersection);
+ }
+};
+
+
+template
+<
+ typename TurnInfo,
+ typename SideStrategy
+>
+struct touch_interior : public base_turn_handler
+{
+ // Index: 0, P is the interior, Q is touching and vice versa
+ template
+ <
+ int Index,
+ typename Point1,
+ typename Point2,
+ typename IntersectionInfo,
+ typename DirInfo
+ >
+ static inline void apply(
+ Point1 const& pi, Point1 const& pj, Point1 const& ,
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ TurnInfo& ti,
+ IntersectionInfo const& intersection_info,
+ DirInfo const& dir_info)
+ {
+ ti.method = method_touch_interior;
+ geometry::convert(intersection_info.intersections[0], ti.point);
+
+ // Both segments of q touch segment p somewhere in its interior
+ // 1) We know: if q comes from LEFT or RIGHT
+ // (i.e. dir_info.sides.get<Index,0>() == 1 or -1)
+ // 2) Important is: if q_k goes to LEFT, RIGHT, COLLINEAR
+ // and, if LEFT/COLL, if it is lying LEFT or RIGHT w.r.t. q_i
+
+ static int const index_p = Index;
+ static int const index_q = 1 - Index;
+
+ int const side_qi_p = dir_info.sides.template get<index_q, 0>();
+ int const side_qk_p = SideStrategy::apply(pi, pj, qk);
+
+ if (side_qi_p == -side_qk_p)
+ {
+ // Q crosses P from left->right or from right->left (test "ML1")
+ // Union: folow P (left->right) or Q (right->left)
+ // Intersection: other turn
+ int index = side_qk_p == -1 ? index_p : index_q;
+ ti.operations[index].operation = operation_union;
+ ti.operations[1 - index].operation = operation_intersection;
+ return;
+ }
+
+ int const side_qk_q = SideStrategy::apply(qi, qj, qk);
+
+ if (side_qi_p == -1 && side_qk_p == -1 && side_qk_q == 1)
+ {
+ // Q turns left on the right side of P (test "MR3")
+ // Both directions for "intersection"
+ both(ti, operation_intersection);
+ }
+ else if (side_qi_p == 1 && side_qk_p == 1 && side_qk_q == -1)
+ {
+ // Q turns right on the left side of P (test "ML3")
+ // Union: take both operation
+ // Intersection: skip
+ both(ti, operation_union);
+ }
+ else if (side_qi_p == side_qk_p && side_qi_p == side_qk_q)
+ {
+ // Q turns left on the left side of P (test "ML2")
+ // or Q turns right on the right side of P (test "MR2")
+ // Union: take left turn (Q if Q turns left, P if Q turns right)
+ // Intersection: other turn
+ int index = side_qk_q == 1 ? index_q : index_p;
+ ti.operations[index].operation = operation_union;
+ ti.operations[1 - index].operation = operation_intersection;
+ }
+ else if (side_qk_p == 0)
+ {
+ // Q intersects on interior of P and continues collinearly
+ if (side_qk_q == side_qi_p)
+ {
+ // Collinearly in the same direction
+ // (Q comes from left of P and turns left,
+ // OR Q comes from right of P and turns right)
+ // Omit intersection point.
+ // Union: just continue
+ // Intersection: just continue
+ both(ti, operation_continue);
+ }
+ else
+ {
+ // Opposite direction, which is never travelled.
+ // If Q turns left, P continues for intersection
+ // If Q turns right, P continues for union
+ ti.operations[Index].operation = side_qk_q == 1
+ ? operation_intersection
+ : operation_union;
+ ti.operations[1 - Index].operation = operation_blocked;
+ }
+ }
+ else
+ {
+ // Should not occur!
+ ti.method = method_error;
+ }
+ }
+};
+
+
+template
+<
+ typename TurnInfo,
+ typename SideStrategy
+>
+struct touch : public base_turn_handler
+{
+ static inline bool between(int side1, int side2, int turn)
+ {
+ return side1 == side2 && ! opposite(side1, turn);
+ }
+
+ /*static inline void block_second(bool block, TurnInfo& ti)
+ {
+ if (block)
+ {
+ ti.operations[1].operation = operation_blocked;
+ }
+ }*/
+
+
+ template
+ <
+ typename Point1,
+ typename Point2,
+ typename IntersectionInfo,
+ typename DirInfo
+ >
+ static inline void apply(
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ TurnInfo& ti,
+ IntersectionInfo const& intersection_info,
+ DirInfo const& dir_info)
+ {
+ ti.method = method_touch;
+ geometry::convert(intersection_info.intersections[0], ti.point);
+
+ int const side_qi_p1 = dir_info.sides.template get<1, 0>();
+ int const side_qk_p1 = SideStrategy::apply(pi, pj, qk);
+
+
+ // If Qi and Qk are both at same side of Pi-Pj,
+ // or collinear (so: not opposite sides)
+ if (! opposite(side_qi_p1, side_qk_p1))
+ {
+ int const side_pk_q2 = SideStrategy::apply(qj, qk, pk);
+ int const side_pk_p = SideStrategy::apply(pi, pj, pk);
+ int const side_qk_q = SideStrategy::apply(qi, qj, qk);
+
+ bool const both_continue = side_pk_p == 0 && side_qk_q == 0;
+ bool const robustness_issue_in_continue = both_continue && side_pk_q2 != 0;
+
+ bool const q_turns_left = side_qk_q == 1;
+ bool const block_q = side_qk_p1 == 0
+ && ! same(side_qi_p1, side_qk_q)
+ && ! robustness_issue_in_continue
+ ;
+
+ // If Pk at same side as Qi/Qk
+ // (the "or" is for collinear case)
+ // or Q is fully collinear && P turns not to left
+ if (side_pk_p == side_qi_p1
+ || side_pk_p == side_qk_p1
+ || (side_qi_p1 == 0 && side_qk_p1 == 0 && side_pk_p != -1)
+ )
+ {
+ // Collinear -> lines join, continue
+ // (#BRL2)
+ if (side_pk_q2 == 0 && ! block_q)
+ {
+ both(ti, operation_continue);
+ return;
+ }
+
+ int const side_pk_q1 = SideStrategy::apply(qi, qj, pk);
+
+
+ // Collinear opposite case -> block P
+ // (#BRL4, #BLR8)
+ if (side_pk_q1 == 0)
+ {
+ ti.operations[0].operation = operation_blocked;
+ // Q turns right -> union (both independent),
+ // Q turns left -> intersection
+ ti.operations[1].operation = block_q ? operation_blocked
+ : q_turns_left ? operation_intersection
+ : operation_union;
+ return;
+ }
+
+ // Pk between Qi and Qk
+ // (#BRL3, #BRL7)
+ if (between(side_pk_q1, side_pk_q2, side_qk_q))
+ {
+ ui_else_iu(q_turns_left, ti);
+ if (block_q)
+ {
+ ti.operations[1].operation = operation_blocked;
+ }
+ //block_second(block_q, ti);
+ return;
+ }
+
+ // Pk between Qk and P, so left of Qk (if Q turns right) and vv
+ // (#BRL1)
+ if (side_pk_q2 == -side_qk_q)
+ {
+ ui_else_iu(! q_turns_left, ti);
+ return;
+ }
+
+ //
+ // (#BRL5, #BRL9)
+ if (side_pk_q1 == -side_qk_q)
+ {
+ uu_else_ii(! q_turns_left, ti);
+ if (block_q)
+ {
+ ti.operations[1].operation = operation_blocked;
+ }
+ //block_second(block_q, ti);
+ return;
+ }
+ }
+ else
+ {
+ // Pk at other side than Qi/Pk
+ int const side_qk_q = SideStrategy::apply(qi, qj, qk);
+ bool const q_turns_left = side_qk_q == 1;
+
+ ti.operations[0].operation = q_turns_left
+ ? operation_intersection
+ : operation_union;
+ ti.operations[1].operation = block_q
+ ? operation_blocked
+ : side_qi_p1 == 1 || side_qk_p1 == 1
+ ? operation_union
+ : operation_intersection;
+
+ return;
+ }
+ }
+ else
+ {
+ // From left to right or from right to left
+ int const side_pk_p = SideStrategy::apply(pi, pj, pk);
+ bool const right_to_left = side_qk_p1 == 1;
+
+ // If p turns into direction of qi (1,2)
+ if (side_pk_p == side_qi_p1)
+ {
+ int const side_pk_q1 = SideStrategy::apply(qi, qj, pk);
+
+ // Collinear opposite case -> block P
+ if (side_pk_q1 == 0)
+ {
+ ti.operations[0].operation = operation_blocked;
+ ti.operations[1].operation = right_to_left
+ ? operation_union : operation_intersection;
+ return;
+ }
+
+ if (side_pk_q1 == side_qk_p1)
+ {
+ uu_else_ii(right_to_left, ti);
+ return;
+ }
+ }
+
+ // If p turns into direction of qk (4,5)
+ if (side_pk_p == side_qk_p1)
+ {
+ int const side_pk_q2 = SideStrategy::apply(qj, qk, pk);
+
+ // Collinear case -> lines join, continue
+ if (side_pk_q2 == 0)
+ {
+ both(ti, operation_continue);
+ return;
+ }
+ if (side_pk_q2 == side_qk_p1)
+ {
+ ui_else_iu(right_to_left, ti);
+ return;
+ }
+ }
+ // otherwise (3)
+ ui_else_iu(! right_to_left, ti);
+ return;
+ }
+
+#ifdef BOOST_GEOMETRY_DEBUG_GET_TURNS
+ // Normally a robustness issue.
+ // TODO: more research if still occuring
+ std::cout << "Not yet handled" << std::endl
+ << "pi " << get<0>(pi) << " , " << get<1>(pi)
+ << " pj " << get<0>(pj) << " , " << get<1>(pj)
+ << " pk " << get<0>(pk) << " , " << get<1>(pk)
+ << std::endl
+ << "qi " << get<0>(qi) << " , " << get<1>(qi)
+ << " qj " << get<0>(qj) << " , " << get<1>(qj)
+ << " qk " << get<0>(qk) << " , " << get<1>(qk)
+ << std::endl;
+#endif
+
+ }
+};
+
+
+template
+<
+ typename TurnInfo,
+ typename SideStrategy
+>
+struct equal : public base_turn_handler
+{
+ template
+ <
+ typename Point1,
+ typename Point2,
+ typename IntersectionInfo,
+ typename DirInfo
+ >
+ static inline void apply(
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,
+ Point2 const& , Point2 const& qj, Point2 const& qk,
+ TurnInfo& ti,
+ IntersectionInfo const& intersection_info,
+ DirInfo const& )
+ {
+ ti.method = method_equal;
+ // Copy the SECOND intersection point
+ geometry::convert(intersection_info.intersections[1], ti.point);
+
+ int const side_pk_q2 = SideStrategy::apply(qj, qk, pk);
+ int const side_pk_p = SideStrategy::apply(pi, pj, pk);
+ int const side_qk_p = SideStrategy::apply(pi, pj, qk);
+
+ // If pk is collinear with qj-qk, they continue collinearly.
+ // This can be on either side of p1 (== q1), or collinear
+ // The second condition checks if they do not continue
+ // oppositely
+ if (side_pk_q2 == 0 && side_pk_p == side_qk_p)
+ {
+ both(ti, operation_continue);
+ return;
+ }
+
+
+ // If they turn to same side (not opposite sides)
+ if (! opposite(side_pk_p, side_qk_p))
+ {
+ int const side_pk_q2 = SideStrategy::apply(qj, qk, pk);
+
+ // If pk is left of q2 or collinear: p: union, q: intersection
+ ui_else_iu(side_pk_q2 != -1, ti);
+ }
+ else
+ {
+ // They turn opposite sides. If p turns left (or collinear),
+ // p: union, q: intersection
+ ui_else_iu(side_pk_p != -1, ti);
+ }
+ }
+};
+
+
+template
+<
+ typename TurnInfo,
+ typename AssignPolicy
+>
+struct equal_opposite : public base_turn_handler
+{
+ template
+ <
+ typename Point1,
+ typename Point2,
+ typename OutputIterator,
+ typename IntersectionInfo,
+ typename DirInfo
+ >
+ static inline void apply(Point1 const& pi, Point2 const& qi,
+ /* by value: */ TurnInfo tp,
+ OutputIterator& out,
+ IntersectionInfo const& intersection_info,
+ DirInfo const& dir_info)
+ {
+ // For equal-opposite segments, normally don't do anything.
+ if (AssignPolicy::include_opposite)
+ {
+ tp.method = method_equal;
+ for (int i = 0; i < 2; i++)
+ {
+ tp.operations[i].operation = operation_opposite;
+ }
+ for (unsigned int i = 0; i < intersection_info.count; i++)
+ {
+ geometry::convert(intersection_info.intersections[i], tp.point);
+ AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
+ *out++ = tp;
+ }
+ }
+ }
+};
+
+template
+<
+ typename TurnInfo,
+ typename SideStrategy
+>
+struct collinear : public base_turn_handler
+{
+ /*
+ arrival P pk//p1 qk//q1 product* case result
+ 1 1 1 CLL1 ui
+ -1 1 -1 CLL2 iu
+ 1 1 1 CLR1 ui
+ -1 -1 1 CLR2 ui
+
+ 1 -1 -1 CRL1 iu
+ -1 1 -1 CRL2 iu
+ 1 -1 -1 CRR1 iu
+ -1 -1 1 CRR2 ui
+
+ 1 0 0 CC1 cc
+ -1 0 0 CC2 cc
+
+ *product = arrival * (pk//p1 or qk//q1)
+
+ Stated otherwise:
+ - if P arrives: look at turn P
+ - if Q arrives: look at turn Q
+ - if P arrives and P turns left: union for P
+ - if P arrives and P turns right: intersection for P
+ - if Q arrives and Q turns left: union for Q (=intersection for P)
+ - if Q arrives and Q turns right: intersection for Q (=union for P)
+
+ ROBUSTNESS: p and q are collinear, so you would expect
+ that side qk//p1 == pk//q1. But that is not always the case
+ in near-epsilon ranges. Then decision logic is different.
+ If p arrives, q is further, so the angle qk//p1 is (normally)
+ more precise than pk//p1
+
+ */
+ template
+ <
+ typename Point1,
+ typename Point2,
+ typename IntersectionInfo,
+ typename DirInfo
+ >
+ static inline void apply(
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ TurnInfo& ti,
+ IntersectionInfo const& intersection_info,
+ DirInfo const& dir_info)
+ {
+ ti.method = method_collinear;
+ geometry::convert(intersection_info.intersections[1], ti.point);
+
+ int const arrival = dir_info.arrival[0];
+ // Should not be 0, this is checked before
+ BOOST_ASSERT(arrival != 0);
+
+ int const side_p = SideStrategy::apply(pi, pj, pk);
+ int const side_q = SideStrategy::apply(qi, qj, qk);
+
+ // If p arrives, use p, else use q
+ int const side_p_or_q = arrival == 1
+ ? side_p
+ : side_q
+ ;
+
+ int const side_pk = SideStrategy::apply(qi, qj, pk);
+ int const side_qk = SideStrategy::apply(pi, pj, qk);
+
+ // See comments above,
+ // resulting in a strange sort of mathematic rule here:
+ // The arrival-info multiplied by the relevant side
+ // delivers a consistent result.
+
+ int const product = arrival * side_p_or_q;
+
+ // Robustness: side_p is supposed to be equal to side_pk (because p/q are collinear)
+ // and side_q to side_qk
+ bool const robustness_issue = side_pk != side_p || side_qk != side_q;
+
+ if (robustness_issue)
+ {
+ handle_robustness(ti, arrival, side_p, side_q, side_pk, side_qk);
+ }
+ else if(product == 0)
+ {
+ both(ti, operation_continue);
+ }
+ else
+ {
+ ui_else_iu(product == 1, ti);
+ }
+ }
+
+ static inline void handle_robustness(TurnInfo& ti, int arrival,
+ int side_p, int side_q, int side_pk, int side_qk)
+ {
+ // We take the longer one, i.e. if q arrives in p (arrival == -1),
+ // then p exceeds q and we should take p for a union...
+
+ bool use_p_for_union = arrival == -1;
+
+ // ... unless one of the sides consistently directs to the other side
+ int const consistent_side_p = side_p == side_pk ? side_p : 0;
+ int const consistent_side_q = side_q == side_qk ? side_q : 0;
+ if (arrival == -1 && (consistent_side_p == -1 || consistent_side_q == 1))
+ {
+ use_p_for_union = false;
+ }
+ if (arrival == 1 && (consistent_side_p == 1 || consistent_side_q == -1))
+ {
+ use_p_for_union = true;
+ }
+
+ //std::cout << "ROBUSTNESS -> Collinear "
+ // << " arr: " << arrival
+ // << " dir: " << side_p << " " << side_q
+ // << " rev: " << side_pk << " " << side_qk
+ // << " cst: " << cside_p << " " << cside_q
+ // << std::boolalpha << " " << use_p_for_union
+ // << std::endl;
+
+ ui_else_iu(use_p_for_union, ti);
+ }
+
+};
+
+template
+<
+ typename TurnInfo,
+ typename SideStrategy,
+ typename AssignPolicy
+>
+struct collinear_opposite : public base_turn_handler
+{
+private :
+ /*
+ arrival P arrival Q pk//p1 qk//q1 case result2 result
+ --------------------------------------------------------------
+ 1 1 1 -1 CLO1 ix xu
+ 1 1 1 0 CLO2 ix (xx)
+ 1 1 1 1 CLO3 ix xi
+
+ 1 1 0 -1 CCO1 (xx) xu
+ 1 1 0 0 CCO2 (xx) (xx)
+ 1 1 0 1 CCO3 (xx) xi
+
+ 1 1 -1 -1 CRO1 ux xu
+ 1 1 -1 0 CRO2 ux (xx)
+ 1 1 -1 1 CRO3 ux xi
+
+ -1 1 -1 CXO1 xu
+ -1 1 0 CXO2 (xx)
+ -1 1 1 CXO3 xi
+
+ 1 -1 1 CXO1 ix
+ 1 -1 0 CXO2 (xx)
+ 1 -1 -1 CXO3 ux
+ */
+
+ template
+ <
+ int Index,
+ typename Point,
+ typename IntersectionInfo
+ >
+ static inline bool set_tp(Point const& ri, Point const& rj, Point const& rk,
+ bool const handle_robustness, Point const& si, Point const& sj,
+ TurnInfo& tp, IntersectionInfo const& intersection_info)
+ {
+ int side_rk_r = SideStrategy::apply(ri, rj, rk);
+
+ if (handle_robustness)
+ {
+ int const side_rk_s = SideStrategy::apply(si, sj, rk);
+
+ // For Robustness: also calculate rk w.r.t. the other line. Because they are collinear opposite, that direction should be the reverse of the first direction.
+ // If this is not the case, we make it all-collinear, so zero
+ if (side_rk_r != 0 && side_rk_r != -side_rk_s)
+ {
+#ifdef BOOST_GEOMETRY_DEBUG_ROBUSTNESS
+ std::cout << "Robustness correction: " << side_rk_r << " / " << side_rk_s << std::endl;
+#endif
+ side_rk_r = 0;
+ }
+ }
+
+ operation_type blocked = operation_blocked;
+ switch(side_rk_r)
+ {
+
+ case 1 :
+ // Turning left on opposite collinear: intersection
+ tp.operations[Index].operation = operation_intersection;
+ break;
+ case -1 :
+ // Turning right on opposite collinear: union
+ tp.operations[Index].operation = operation_union;
+ break;
+ case 0 :
+ // No turn on opposite collinear: block, do not traverse
+ // But this "xx" is usually ignored, it is useless to include
+ // two operations blocked, so the whole point does not need
+ // to be generated.
+ // So return false to indicate nothing is to be done.
+ if (AssignPolicy::include_opposite)
+ {
+ tp.operations[Index].operation = operation_opposite;
+ blocked = operation_opposite;
+ }
+ else
+ {
+ return false;
+ }
+ break;
+ }
+
+ // The other direction is always blocked when collinear opposite
+ tp.operations[1 - Index].operation = blocked;
+
+ // If P arrives within Q, set info on P (which is done above, index=0),
+ // this turn-info belongs to the second intersection point, index=1
+ // (see e.g. figure CLO1)
+ geometry::convert(intersection_info.intersections[1 - Index], tp.point);
+ return true;
+ }
+
+public:
+ template
+ <
+ typename Point1,
+ typename Point2,
+ typename OutputIterator,
+ typename IntersectionInfo,
+ typename DirInfo
+ >
+ static inline void apply(
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,
+
+ // Opposite collinear can deliver 2 intersection points,
+ TurnInfo const& tp_model,
+ OutputIterator& out,
+
+ IntersectionInfo const& intersection_info,
+ DirInfo const& dir_info)
+ {
+ TurnInfo tp = tp_model;
+
+ tp.method = method_collinear;
+
+ // If P arrives within Q, there is a turn dependent on P
+ if (dir_info.arrival[0] == 1
+ && set_tp<0>(pi, pj, pk, true, qi, qj, tp, intersection_info))
+ {
+ AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
+ *out++ = tp;
+ }
+
+ // If Q arrives within P, there is a turn dependent on Q
+ if (dir_info.arrival[1] == 1
+ && set_tp<1>(qi, qj, qk, false, pi, pj, tp, intersection_info))
+ {
+ AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
+ *out++ = tp;
+ }
+
+ if (AssignPolicy::include_opposite)
+ {
+ // Handle cases not yet handled above
+ if ((dir_info.arrival[1] == -1 && dir_info.arrival[0] == 0)
+ || (dir_info.arrival[0] == -1 && dir_info.arrival[1] == 0))
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ tp.operations[i].operation = operation_opposite;
+ }
+ for (unsigned int i = 0; i < intersection_info.count; i++)
+ {
+ geometry::convert(intersection_info.intersections[i], tp.point);
+ AssignPolicy::apply(tp, pi, qi, intersection_info, dir_info);
+ *out++ = tp;
+ }
+ }
+ }
+
+ }
+};
+
+
+template
+<
+ typename TurnInfo,
+ typename SideStrategy
+>
+struct crosses : public base_turn_handler
+{
+ template
+ <
+ typename Point1,
+ typename Point2,
+ typename IntersectionInfo,
+ typename DirInfo
+ >
+ static inline void apply(
+ Point1 const& , Point1 const& , Point1 const& ,
+ Point2 const& , Point2 const& , Point2 const& ,
+ TurnInfo& ti,
+ IntersectionInfo const& intersection_info,
+ DirInfo const& dir_info)
+ {
+ ti.method = method_crosses;
+ geometry::convert(intersection_info.intersections[0], ti.point);
+
+ // In all casees:
+ // If Q crosses P from left to right
+ // Union: take P
+ // Intersection: take Q
+ // Otherwise: vice versa
+ int const side_qi_p1 = dir_info.sides.template get<1, 0>();
+ int const index = side_qi_p1 == 1 ? 0 : 1;
+ ti.operations[index].operation = operation_union;
+ ti.operations[1 - index].operation = operation_intersection;
+ }
+};
+
+template<typename TurnInfo>
+struct only_convert
+{
+ template<typename IntersectionInfo>
+ static inline void apply(TurnInfo& ti, IntersectionInfo const& intersection_info)
+ {
+ ti.method = method_collinear;
+ geometry::convert(intersection_info.intersections[0], ti.point);
+ ti.operations[0].operation = operation_continue;
+ ti.operations[1].operation = operation_continue;
+ }
+};
+
+/*!
+\brief Policy doing nothing
+\details get_turn_info can have an optional policy to get/assign some
+ extra information. By default it does not, and this class
+ is that default.
+ */
+struct assign_null_policy
+{
+ static bool const include_no_turn = false;
+ static bool const include_degenerate = false;
+ static bool const include_opposite = false;
+
+ template
+ <
+ typename Info,
+ typename Point1,
+ typename Point2,
+ typename IntersectionInfo,
+ typename DirInfo
+ >
+ static inline void apply(Info& , Point1 const& , Point2 const&, IntersectionInfo const&, DirInfo const&)
+ {}
+
+};
+
+
+/*!
+ \brief Turn information: intersection point, method, and turn information
+ \details Information necessary for traversal phase (a phase
+ of the overlay process). The information is gathered during the
+ get_turns (segment intersection) phase.
+ \tparam Point1 point type of first segment
+ \tparam Point2 point type of second segment
+ \tparam TurnInfo type of class getting intersection and turn info
+ \tparam AssignPolicy policy to assign extra info,
+ e.g. to calculate distance from segment's first points
+ to intersection points.
+ It also defines if a certain class of points
+ (degenerate, non-turns) should be included.
+ */
+template
+<
+ typename Point1,
+ typename Point2,
+ typename TurnInfo,
+ typename AssignPolicy
+>
+struct get_turn_info
+{
+ typedef strategy_intersection
+ <
+ typename cs_tag<typename TurnInfo::point_type>::type,
+ Point1,
+ Point2,
+ typename TurnInfo::point_type
+ > si;
+
+ typedef typename si::segment_intersection_strategy_type strategy;
+
+ // Intersect pi-pj with qi-qj
+ // The points pk and qk are only used do determine more information
+ // about the turn.
+ template <typename OutputIterator>
+ static inline OutputIterator apply(
+ Point1 const& pi, Point1 const& pj, Point1 const& pk,
+ Point2 const& qi, Point2 const& qj, Point2 const& qk,
+ TurnInfo const& tp_model,
+ OutputIterator out)
+ {
+ typedef model::referring_segment<Point1 const> segment_type1;
+ typedef model::referring_segment<Point1 const> segment_type2;
+ segment_type1 p1(pi, pj), p2(pj, pk);
+ segment_type2 q1(qi, qj), q2(qj, qk);
+
+ typename strategy::return_type result = strategy::apply(p1, q1);
+
+ char const method = result.template get<1>().how;
+
+ // Copy, to copy possibly extended fields
+ TurnInfo tp = tp_model;
+
+
+ // Select method and apply
+ switch(method)
+ {
+ case 'a' : // collinear, "at"
+ case 'f' : // collinear, "from"
+ case 's' : // starts from the middle
+ if (AssignPolicy::include_no_turn
+ && result.template get<0>().count > 0)
+ {
+ only_convert<TurnInfo>::apply(tp,
+ result.template get<0>());
+ AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
+ *out++ = tp;
+ }
+ break;
+
+ case 'd' : // disjoint: never do anything
+ break;
+
+ case 'm' :
+ {
+ typedef touch_interior
+ <
+ TurnInfo,
+ typename si::side_strategy_type
+ > policy;
+
+ // If Q (1) arrives (1)
+ if (result.template get<1>().arrival[1] == 1)
+ {
+ policy::template apply<0>(pi, pj, pk, qi, qj, qk,
+ tp, result.template get<0>(), result.template get<1>());
+ }
+ else
+ {
+ // Swap p/q
+ policy::template apply<1>(qi, qj, qk, pi, pj, pk,
+ tp, result.template get<0>(), result.template get<1>());
+ }
+ AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
+ *out++ = tp;
+ }
+ break;
+ case 'i' :
+ {
+ typedef crosses
+ <
+ TurnInfo,
+ typename si::side_strategy_type
+ > policy;
+
+ policy::apply(pi, pj, pk, qi, qj, qk,
+ tp, result.template get<0>(), result.template get<1>());
+ AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
+ *out++ = tp;
+ }
+ break;
+ case 't' :
+ {
+ // Both touch (both arrive there)
+ typedef touch
+ <
+ TurnInfo,
+ typename si::side_strategy_type
+ > policy;
+
+ policy::apply(pi, pj, pk, qi, qj, qk,
+ tp, result.template get<0>(), result.template get<1>());
+ AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
+ *out++ = tp;
+ }
+ break;
+ case 'e':
+ {
+ if (! result.template get<1>().opposite)
+ {
+ // Both equal
+ // or collinear-and-ending at intersection point
+ typedef equal
+ <
+ TurnInfo,
+ typename si::side_strategy_type
+ > policy;
+
+ policy::apply(pi, pj, pk, qi, qj, qk,
+ tp, result.template get<0>(), result.template get<1>());
+ AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
+ *out++ = tp;
+ }
+ else
+ {
+ equal_opposite
+ <
+ TurnInfo,
+ AssignPolicy
+ >::apply(pi, qi,
+ tp, out, result.template get<0>(), result.template get<1>());
+ }
+ }
+ break;
+ case 'c' :
+ {
+ // Collinear
+ if (! result.template get<1>().opposite)
+ {
+
+ if (result.template get<1>().arrival[0] == 0)
+ {
+ // Collinear, but similar thus handled as equal
+ equal
+ <
+ TurnInfo,
+ typename si::side_strategy_type
+ >::apply(pi, pj, pk, qi, qj, qk,
+ tp, result.template get<0>(), result.template get<1>());
+
+ // override assigned method
+ tp.method = method_collinear;
+ }
+ else
+ {
+ collinear
+ <
+ TurnInfo,
+ typename si::side_strategy_type
+ >::apply(pi, pj, pk, qi, qj, qk,
+ tp, result.template get<0>(), result.template get<1>());
+ }
+
+ AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
+ *out++ = tp;
+ }
+ else
+ {
+ collinear_opposite
+ <
+ TurnInfo,
+ typename si::side_strategy_type,
+ AssignPolicy
+ >::apply(pi, pj, pk, qi, qj, qk,
+ tp, out, result.template get<0>(), result.template get<1>());
+ }
+ }
+ break;
+ case '0' :
+ {
+ // degenerate points
+ if (AssignPolicy::include_degenerate)
+ {
+ only_convert<TurnInfo>::apply(tp, result.template get<0>());
+ AssignPolicy::apply(tp, pi, qi, result.template get<0>(), result.template get<1>());
+ *out++ = tp;
+ }
+ }
+ break;
+ default :
+ {
+#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
+ throw turn_info_exception(method);
+#endif
+ }
+ break;
+ }
+
+ return out;
+ }
+};
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURN_INFO_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/boost/geometry/algorithms/detail/overlay/get_turns.hpp
new file mode 100644
index 000000000..782ea7fd2
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/get_turns.hpp
@@ -0,0 +1,890 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP
+
+
+#include <cstddef>
+#include <map>
+
+#include <boost/array.hpp>
+#include <boost/concept_check.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/reverse_dispatch.hpp>
+
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/views/closeable_view.hpp>
+#include <boost/geometry/views/reversible_view.hpp>
+#include <boost/geometry/views/detail/range_type.hpp>
+
+#include <boost/geometry/geometries/box.hpp>
+#include <boost/geometry/geometries/segment.hpp>
+
+#include <boost/geometry/iterators/ever_circling_iterator.hpp>
+
+#include <boost/geometry/strategies/cartesian/cart_intersect.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+#include <boost/geometry/strategies/intersection_result.hpp>
+
+#include <boost/geometry/algorithms/detail/disjoint.hpp>
+#include <boost/geometry/algorithms/detail/partition.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
+
+
+#include <boost/geometry/algorithms/detail/sections/range_by_section.hpp>
+
+#include <boost/geometry/algorithms/expand.hpp>
+#include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+# include <sstream>
+# include <boost/geometry/io/dsv/write.hpp>
+#endif
+
+
+namespace boost { namespace geometry
+{
+
+// Silence warning C4127: conditional expression is constant
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4127)
+#endif
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace get_turns
+{
+
+
+struct no_interrupt_policy
+{
+ static bool const enabled = false;
+
+ template <typename Range>
+ static inline bool apply(Range const&)
+ {
+ return false;
+ }
+};
+
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ bool Reverse1, bool Reverse2,
+ typename Section1, typename Section2,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+class get_turns_in_sections
+{
+ typedef typename closeable_view
+ <
+ typename range_type<Geometry1>::type const,
+ closure<Geometry1>::value
+ >::type cview_type1;
+ typedef typename closeable_view
+ <
+ typename range_type<Geometry2>::type const,
+ closure<Geometry2>::value
+ >::type cview_type2;
+
+ typedef typename reversible_view
+ <
+ cview_type1 const,
+ Reverse1 ? iterate_reverse : iterate_forward
+ >::type view_type1;
+ typedef typename reversible_view
+ <
+ cview_type2 const,
+ Reverse2 ? iterate_reverse : iterate_forward
+ >::type view_type2;
+
+ typedef typename boost::range_iterator
+ <
+ view_type1 const
+ >::type range1_iterator;
+
+ typedef typename boost::range_iterator
+ <
+ view_type2 const
+ >::type range2_iterator;
+
+
+ template <typename Geometry, typename Section>
+ static inline bool neighbouring(Section const& section,
+ int index1, int index2)
+ {
+ // About n-2:
+ // (square: range_count=5, indices 0,1,2,3
+ // -> 0-3 are adjacent, don't check on intersections)
+ // Also tested for open polygons, and/or duplicates
+ // About first condition: will be optimized by compiler (static)
+ // It checks if it is areal (box,ring,(multi)polygon
+ int const n = int(section.range_count);
+
+ boost::ignore_unused_variable_warning(n);
+ boost::ignore_unused_variable_warning(index1);
+ boost::ignore_unused_variable_warning(index2);
+
+ return boost::is_same
+ <
+ typename tag_cast
+ <
+ typename geometry::point_type<Geometry1>::type,
+ areal_tag
+ >::type,
+ areal_tag
+ >::value
+ && index1 == 0
+ && index2 >= n - 2
+ ;
+ }
+
+
+public :
+ // Returns true if terminated, false if interrupted
+ static inline bool apply(
+ int source_id1, Geometry1 const& geometry1, Section1 const& sec1,
+ int source_id2, Geometry2 const& geometry2, Section2 const& sec2,
+ bool skip_larger,
+ Turns& turns,
+ InterruptPolicy& interrupt_policy)
+ {
+ boost::ignore_unused_variable_warning(interrupt_policy);
+
+ cview_type1 cview1(range_by_section(geometry1, sec1));
+ cview_type2 cview2(range_by_section(geometry2, sec2));
+ view_type1 view1(cview1);
+ view_type2 view2(cview2);
+
+ range1_iterator begin_range_1 = boost::begin(view1);
+ range1_iterator end_range_1 = boost::end(view1);
+
+ range2_iterator begin_range_2 = boost::begin(view2);
+ range2_iterator end_range_2 = boost::end(view2);
+
+ 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.ring_id.multi_index == sec2.ring_id.multi_index
+ && sec1.ring_id.ring_index == sec2.ring_id.ring_index;
+
+ range1_iterator prev1, it1, end1;
+
+ get_start_point_iterator(sec1, view1, prev1, it1, end1,
+ index1, ndi1, dir1, sec2.bounding_box);
+
+ // We need a circular iterator because it might run through the closing point.
+ // One circle is actually enough but this one is just convenient.
+ ever_circling_iterator<range1_iterator> next1(begin_range_1, end_range_1, it1, true);
+ next1++;
+
+ // Walk through section and stop if we exceed the other box
+ // section 2: [--------------]
+ // section 1: |----|---|---|---|---|
+ for (prev1 = it1++, next1++;
+ it1 != end1 && ! exceeding<0>(dir1, *prev1, sec2.bounding_box);
+ ++prev1, ++it1, ++index1, ++next1, ++ndi1)
+ {
+ ever_circling_iterator<range1_iterator> nd_next1(
+ begin_range_1, end_range_1, next1, true);
+ advance_to_non_duplicate_next(nd_next1, it1, sec1);
+
+ int index2 = sec2.begin_index;
+ int ndi2 = sec2.non_duplicate_index;
+
+ range2_iterator prev2, it2, end2;
+
+ get_start_point_iterator(sec2, view2, prev2, it2, end2,
+ index2, ndi2, dir2, sec1.bounding_box);
+ ever_circling_iterator<range2_iterator> next2(begin_range_2, end_range_2, it2, true);
+ next2++;
+
+ for (prev2 = it2++, next2++;
+ it2 != end2 && ! exceeding<0>(dir2, *prev2, sec1.bounding_box);
+ ++prev2, ++it2, ++index2, ++next2, ++ndi2)
+ {
+ bool skip = same_source;
+ if (skip)
+ {
+ // If sources are the same (possibly self-intersecting):
+ // skip if it is a neighbouring segment.
+ // (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!)
+
+ skip = (skip_larger && index1 >= index2)
+ || ndi2 == ndi1 + 1
+ || neighbouring<Geometry1>(sec1, index1, index2)
+ ;
+ }
+
+ if (! skip)
+ {
+ // Move to the "non duplicate next"
+ ever_circling_iterator<range2_iterator> nd_next2(
+ begin_range_2, end_range_2, next2, true);
+ advance_to_non_duplicate_next(nd_next2, it2, sec2);
+
+ typedef typename boost::range_value<Turns>::type turn_info;
+ typedef typename turn_info::point_type ip;
+
+ turn_info ti;
+ ti.operations[0].seg_id = segment_identifier(source_id1,
+ sec1.ring_id.multi_index, sec1.ring_id.ring_index, index1),
+ ti.operations[1].seg_id = segment_identifier(source_id2,
+ sec2.ring_id.multi_index, sec2.ring_id.ring_index, index2),
+
+ ti.operations[0].other_id = ti.operations[1].seg_id;
+ ti.operations[1].other_id = ti.operations[0].seg_id;
+
+ std::size_t const size_before = boost::size(turns);
+
+ TurnPolicy::apply(*prev1, *it1, *nd_next1, *prev2, *it2, *nd_next2,
+ ti, std::back_inserter(turns));
+
+ if (InterruptPolicy::enabled)
+ {
+ if (interrupt_policy.apply(
+ std::make_pair(boost::begin(turns) + size_before,
+ boost::end(turns))))
+ {
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+
+private :
+ typedef typename geometry::point_type<Geometry1>::type point1_type;
+ typedef typename geometry::point_type<Geometry2>::type point2_type;
+ typedef typename model::referring_segment<point1_type const> segment1_type;
+ typedef typename model::referring_segment<point2_type const> segment2_type;
+
+
+ template <size_t Dim, typename Point, typename Box>
+ static inline bool preceding(int dir, Point const& point, Box const& box)
+ {
+ return (dir == 1 && get<Dim>(point) < get<min_corner, Dim>(box))
+ || (dir == -1 && get<Dim>(point) > get<max_corner, Dim>(box));
+ }
+
+ template <size_t Dim, typename Point, typename Box>
+ static inline bool exceeding(int dir, Point const& point, Box const& box)
+ {
+ return (dir == 1 && get<Dim>(point) > get<max_corner, Dim>(box))
+ || (dir == -1 && get<Dim>(point) < get<min_corner, Dim>(box));
+ }
+
+ template <typename Iterator, typename RangeIterator, typename Section>
+ static inline void advance_to_non_duplicate_next(Iterator& next,
+ RangeIterator const& it, Section const& section)
+ {
+ // To see where the next segments bend to, in case of touch/intersections
+ // on end points, we need (in case of degenerate/duplicate points) an extra
+ // iterator which moves to the REAL next point, so non duplicate.
+ // This needs an extra comparison (disjoint).
+ // (Note that within sections, non duplicate points are already asserted,
+ // by the sectionalize process).
+
+ // So advance to the "non duplicate next"
+ // (the check is defensive, to avoid endless loops)
+ std::size_t check = 0;
+ while(! detail::disjoint::disjoint_point_point(*it, *next)
+ && check++ < section.range_count)
+ {
+ next++;
+ }
+ }
+
+ // It is NOT possible to have section-iterators here
+ // because of the logistics of "index" (the section-iterator automatically
+ // skips to the begin-point, we loose the index or have to recalculate it)
+ // So we mimic it here
+ template <typename Range, typename Section, typename Box>
+ static inline void get_start_point_iterator(Section & section,
+ Range const& range,
+ typename boost::range_iterator<Range const>::type& it,
+ typename boost::range_iterator<Range const>::type& prev,
+ typename boost::range_iterator<Range const>::type& end,
+ int& index, int& ndi,
+ int dir, Box const& other_bounding_box)
+ {
+ it = boost::begin(range) + section.begin_index;
+ end = boost::begin(range) + section.end_index + 1;
+
+ // Mimic section-iterator:
+ // Skip to point such that section interects other box
+ prev = it++;
+ for(; it != end && preceding<0>(dir, *it, other_bounding_box);
+ prev = it++, index++, ndi++)
+ {}
+ // Go back one step because we want to start completely preceding
+ it = prev;
+ }
+};
+
+struct get_section_box
+{
+ template <typename Box, typename InputItem>
+ static inline void apply(Box& total, InputItem const& item)
+ {
+ geometry::expand(total, item.bounding_box);
+ }
+};
+
+struct ovelaps_section_box
+{
+ template <typename Box, typename InputItem>
+ static inline bool apply(Box const& box, InputItem const& item)
+ {
+ return ! detail::disjoint::disjoint_box_box(box, item.bounding_box);
+ }
+};
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ bool Reverse1, bool Reverse2,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+struct section_visitor
+{
+ int m_source_id1;
+ Geometry1 const& m_geometry1;
+ int m_source_id2;
+ Geometry2 const& m_geometry2;
+ Turns& m_turns;
+ InterruptPolicy& m_interrupt_policy;
+
+ section_visitor(int id1, Geometry1 const& g1,
+ int id2, Geometry2 const& g2,
+ Turns& turns, InterruptPolicy& ip)
+ : m_source_id1(id1), m_geometry1(g1)
+ , m_source_id2(id2), m_geometry2(g2)
+ , m_turns(turns)
+ , m_interrupt_policy(ip)
+ {}
+
+ template <typename Section>
+ inline bool apply(Section const& sec1, Section const& sec2)
+ {
+ if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, sec2.bounding_box))
+ {
+ return get_turns_in_sections
+ <
+ Geometry1,
+ Geometry2,
+ Reverse1, Reverse2,
+ Section, Section,
+ Turns,
+ TurnPolicy,
+ InterruptPolicy
+ >::apply(
+ m_source_id1, m_geometry1, sec1,
+ m_source_id2, m_geometry2, sec2,
+ false,
+ m_turns, m_interrupt_policy);
+ }
+ return true;
+ }
+
+};
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ bool Reverse1, bool Reverse2,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+class get_turns_generic
+{
+
+public:
+ static inline void apply(
+ int source_id1, Geometry1 const& geometry1,
+ int source_id2, Geometry2 const& geometry2,
+ Turns& turns, InterruptPolicy& interrupt_policy)
+ {
+ // First create monotonic sections...
+ typedef typename boost::range_value<Turns>::type ip_type;
+ typedef typename ip_type::point_type point_type;
+ typedef model::box<point_type> box_type;
+ typedef typename geometry::sections<box_type, 2> sections_type;
+
+ sections_type sec1, sec2;
+
+ geometry::sectionalize<Reverse1>(geometry1, sec1, 0);
+ geometry::sectionalize<Reverse2>(geometry2, sec2, 1);
+
+ // ... and then partition them, intersecting overlapping sections in visitor method
+ section_visitor
+ <
+ Geometry1, Geometry2,
+ Reverse1, Reverse2,
+ Turns, TurnPolicy, InterruptPolicy
+ > visitor(source_id1, geometry1, source_id2, geometry2, turns, interrupt_policy);
+
+ geometry::partition
+ <
+ box_type, get_section_box, ovelaps_section_box
+ >::apply(sec1, sec2, visitor);
+ }
+};
+
+
+// Get turns for a range with a box, following Cohen-Sutherland (cs) approach
+template
+<
+ typename Range, typename Box,
+ bool ReverseRange, bool ReverseBox,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+struct get_turns_cs
+{
+ typedef typename boost::range_value<Turns>::type turn_info;
+ typedef typename geometry::point_type<Range>::type point_type;
+ typedef typename geometry::point_type<Box>::type box_point_type;
+
+ typedef typename closeable_view
+ <
+ Range const,
+ closure<Range>::value
+ >::type cview_type;
+
+ typedef typename reversible_view
+ <
+ cview_type const,
+ ReverseRange ? iterate_reverse : iterate_forward
+ >::type view_type;
+
+ typedef typename boost::range_iterator
+ <
+ view_type const
+ >::type iterator_type;
+
+
+ static inline void apply(
+ int source_id1, Range const& range,
+ int source_id2, Box const& box,
+ Turns& turns,
+ InterruptPolicy& interrupt_policy,
+ int multi_index = -1, int ring_index = -1)
+ {
+ if (boost::size(range) <= 1)
+ {
+ return;
+ }
+
+ boost::array<box_point_type,4> bp;
+ assign_box_corners_oriented<ReverseBox>(box, bp);
+
+ cview_type cview(range);
+ view_type view(cview);
+
+ iterator_type it = boost::begin(view);
+
+ ever_circling_iterator<iterator_type> next(
+ boost::begin(view), boost::end(view), it, true);
+ next++;
+ next++;
+
+ //bool first = true;
+
+ //char previous_side[2] = {0, 0};
+
+ int index = 0;
+
+ for (iterator_type prev = it++;
+ it != boost::end(view);
+ prev = it++, next++, index++)
+ {
+ segment_identifier seg_id(source_id1,
+ multi_index, ring_index, index);
+
+ /*if (first)
+ {
+ previous_side[0] = get_side<0>(box, *prev);
+ previous_side[1] = get_side<1>(box, *prev);
+ }
+
+ char current_side[2];
+ current_side[0] = get_side<0>(box, *it);
+ current_side[1] = get_side<1>(box, *it);
+
+ // There can NOT be intersections if
+ // 1) EITHER the two points are lying on one side of the box (! 0 && the same)
+ // 2) OR same in Y-direction
+ // 3) OR all points are inside the box (0)
+ if (! (
+ (current_side[0] != 0 && current_side[0] == previous_side[0])
+ || (current_side[1] != 0 && current_side[1] == previous_side[1])
+ || (current_side[0] == 0
+ && current_side[1] == 0
+ && previous_side[0] == 0
+ && previous_side[1] == 0)
+ )
+ )*/
+ if (true)
+ {
+ get_turns_with_box(seg_id, source_id2,
+ *prev, *it, *next,
+ bp[0], bp[1], bp[2], bp[3],
+ turns, interrupt_policy);
+ // Future performance enhancement:
+ // return if told by the interrupt policy
+ }
+ }
+ }
+
+private:
+ template<std::size_t Index, typename Point>
+ static inline int get_side(Box const& box, Point const& point)
+ {
+ // Inside -> 0
+ // Outside -> -1 (left/below) or 1 (right/above)
+ // On border -> -2 (left/lower) or 2 (right/upper)
+ // The only purpose of the value is to not be the same,
+ // and to denote if it is inside (0)
+
+ typename coordinate_type<Point>::type const& c = get<Index>(point);
+ typename coordinate_type<Box>::type const& left = get<min_corner, Index>(box);
+ typename coordinate_type<Box>::type const& right = get<max_corner, Index>(box);
+
+ if (geometry::math::equals(c, left)) return -2;
+ else if (geometry::math::equals(c, right)) return 2;
+ else if (c < left) return -1;
+ else if (c > right) return 1;
+ else return 0;
+ }
+
+ static inline void get_turns_with_box(segment_identifier const& seg_id, int source_id2,
+ // Points from a range:
+ point_type const& rp0,
+ point_type const& rp1,
+ point_type const& rp2,
+ // Points from the box
+ box_point_type const& bp0,
+ box_point_type const& bp1,
+ box_point_type const& bp2,
+ box_point_type const& bp3,
+ // Output
+ Turns& turns,
+ InterruptPolicy& interrupt_policy)
+ {
+ boost::ignore_unused_variable_warning(interrupt_policy);
+
+ // Depending on code some relations can be left out
+
+ typedef typename boost::range_value<Turns>::type turn_info;
+
+ turn_info ti;
+ ti.operations[0].seg_id = seg_id;
+ ti.operations[0].other_id = ti.operations[1].seg_id;
+ ti.operations[1].other_id = seg_id;
+
+ ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 0);
+ TurnPolicy::apply(rp0, rp1, rp2, bp0, bp1, bp2,
+ ti, std::back_inserter(turns));
+
+ ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 1);
+ TurnPolicy::apply(rp0, rp1, rp2, bp1, bp2, bp3,
+ ti, std::back_inserter(turns));
+
+ ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 2);
+ TurnPolicy::apply(rp0, rp1, rp2, bp2, bp3, bp0,
+ ti, std::back_inserter(turns));
+
+ ti.operations[1].seg_id = segment_identifier(source_id2, -1, -1, 3);
+ TurnPolicy::apply(rp0, rp1, rp2, bp3, bp0, bp1,
+ ti, std::back_inserter(turns));
+
+ if (InterruptPolicy::enabled)
+ {
+ interrupt_policy.apply(turns);
+ }
+
+ }
+
+};
+
+
+template
+<
+ typename Polygon, typename Box,
+ bool Reverse, bool ReverseBox,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+struct get_turns_polygon_cs
+{
+ static inline void apply(
+ int source_id1, Polygon const& polygon,
+ int source_id2, Box const& box,
+ Turns& turns, InterruptPolicy& interrupt_policy,
+ int multi_index = -1)
+ {
+ typedef typename geometry::ring_type<Polygon>::type ring_type;
+
+ typedef detail::get_turns::get_turns_cs
+ <
+ ring_type, Box,
+ Reverse, ReverseBox,
+ Turns,
+ TurnPolicy,
+ InterruptPolicy
+ > intersector_type;
+
+ intersector_type::apply(
+ source_id1, geometry::exterior_ring(polygon),
+ source_id2, box, turns, interrupt_policy,
+ multi_index, -1);
+
+ int i = 0;
+
+ typename interior_return_type<Polygon const>::type rings
+ = interior_rings(polygon);
+ for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings);
+ ++it, ++i)
+ {
+ intersector_type::apply(
+ source_id1, *it,
+ source_id2, box, turns, interrupt_policy,
+ multi_index, i);
+ }
+
+ }
+};
+
+}} // namespace detail::get_turns
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// Because this is "detail" method, and most implementations will use "generic",
+// we take the freedom to derive it from "generic".
+template
+<
+ typename GeometryTag1, typename GeometryTag2,
+ typename Geometry1, typename Geometry2,
+ bool Reverse1, bool Reverse2,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+struct get_turns
+ : detail::get_turns::get_turns_generic
+ <
+ Geometry1, Geometry2,
+ Reverse1, Reverse2,
+ Turns,
+ TurnPolicy,
+ InterruptPolicy
+ >
+{};
+
+
+template
+<
+ typename Polygon, typename Box,
+ bool ReversePolygon, bool ReverseBox,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+struct get_turns
+ <
+ polygon_tag, box_tag,
+ Polygon, Box,
+ ReversePolygon, ReverseBox,
+ Turns,
+ TurnPolicy,
+ InterruptPolicy
+ > : detail::get_turns::get_turns_polygon_cs
+ <
+ Polygon, Box,
+ ReversePolygon, ReverseBox,
+ Turns, TurnPolicy, InterruptPolicy
+ >
+{};
+
+
+template
+<
+ typename Ring, typename Box,
+ bool ReverseRing, bool ReverseBox,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+struct get_turns
+ <
+ ring_tag, box_tag,
+ Ring, Box,
+ ReverseRing, ReverseBox,
+ Turns,
+ TurnPolicy,
+ InterruptPolicy
+ > : detail::get_turns::get_turns_cs
+ <
+ Ring, Box, ReverseRing, ReverseBox,
+ Turns, TurnPolicy, InterruptPolicy
+ >
+
+{};
+
+
+template
+<
+ typename GeometryTag1, typename GeometryTag2,
+ typename Geometry1, typename Geometry2,
+ bool Reverse1, bool Reverse2,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+struct get_turns_reversed
+{
+ static inline void apply(
+ int source_id1, Geometry1 const& g1,
+ int source_id2, Geometry2 const& g2,
+ Turns& turns, InterruptPolicy& interrupt_policy)
+ {
+ get_turns
+ <
+ GeometryTag2, GeometryTag1,
+ Geometry2, Geometry1,
+ Reverse2, Reverse1,
+ Turns, TurnPolicy,
+ InterruptPolicy
+ >::apply(source_id2, g2, source_id1, g1, turns, interrupt_policy);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+/*!
+\brief \brief_calc2{turn points}
+\ingroup overlay
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Turns type of turn-container (e.g. vector of "intersection/turn point"'s)
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param turns container which will contain turn points
+\param interrupt_policy policy determining if process is stopped
+ when intersection is found
+ */
+template
+<
+ bool Reverse1, bool Reverse2,
+ typename AssignPolicy,
+ typename Geometry1,
+ typename Geometry2,
+ typename Turns,
+ typename InterruptPolicy
+>
+inline void get_turns(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Turns& turns,
+ InterruptPolicy& interrupt_policy)
+{
+ concept::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2 const>();
+
+ typedef typename strategy_intersection
+ <
+ typename cs_tag<Geometry1>::type,
+ Geometry1,
+ Geometry2,
+ typename boost::range_value<Turns>::type
+ >::segment_intersection_strategy_type segment_intersection_strategy_type;
+
+ typedef detail::overlay::get_turn_info
+ <
+ typename point_type<Geometry1>::type,
+ typename point_type<Geometry2>::type,
+ typename boost::range_value<Turns>::type,
+ AssignPolicy
+ > TurnPolicy;
+
+ boost::mpl::if_c
+ <
+ reverse_dispatch<Geometry1, Geometry2>::type::value,
+ dispatch::get_turns_reversed
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ Geometry1, Geometry2,
+ Reverse1, Reverse2,
+ Turns, TurnPolicy,
+ InterruptPolicy
+ >,
+ dispatch::get_turns
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ Geometry1, Geometry2,
+ Reverse1, Reverse2,
+ Turns, TurnPolicy,
+ InterruptPolicy
+ >
+ >::type::apply(
+ 0, geometry1,
+ 1, geometry2,
+ turns, interrupt_policy);
+}
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp b/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp
new file mode 100644
index 000000000..84ec16f23
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/handle_tangencies.hpp
@@ -0,0 +1,703 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_TANGENCIES_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_TANGENCIES_HPP
+
+#include <algorithm>
+
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
+#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+
+#include <boost/geometry/geometries/segment.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+template
+<
+ typename TurnPoints,
+ typename Indexed,
+ typename Geometry1, typename Geometry2,
+ bool Reverse1, bool Reverse2,
+ typename Strategy
+>
+struct sort_in_cluster
+{
+ inline sort_in_cluster(TurnPoints const& turn_points
+ , Geometry1 const& geometry1
+ , Geometry2 const& geometry2
+ , Strategy const& strategy)
+ : m_turn_points(turn_points)
+ , m_geometry1(geometry1)
+ , m_geometry2(geometry2)
+ , m_strategy(strategy)
+ {}
+
+private :
+
+ TurnPoints const& m_turn_points;
+ Geometry1 const& m_geometry1;
+ Geometry2 const& m_geometry2;
+ Strategy const& m_strategy;
+
+ typedef typename Indexed::type turn_operation_type;
+ typedef typename geometry::point_type<Geometry1>::type point_type;
+ typedef model::referring_segment<point_type const> segment_type;
+
+ // Determine how p/r and p/s are located.
+ template <typename P>
+ static inline void overlap_info(P const& pi, P const& pj,
+ P const& ri, P const& rj,
+ P const& si, P const& sj,
+ bool& pr_overlap, bool& ps_overlap, bool& rs_overlap)
+ {
+ // Determine how p/r and p/s are located.
+ // One of them is coming from opposite direction.
+
+ typedef strategy::intersection::relate_cartesian_segments
+ <
+ policies::relate::segments_intersection_points
+ <
+ segment_type,
+ segment_type,
+ segment_intersection_points<point_type>
+ >
+ > policy;
+
+ segment_type p(pi, pj);
+ segment_type r(ri, rj);
+ segment_type s(si, sj);
+
+ // Get the intersection point (or two points)
+ segment_intersection_points<point_type> pr = policy::apply(p, r);
+ segment_intersection_points<point_type> ps = policy::apply(p, s);
+ segment_intersection_points<point_type> rs = policy::apply(r, s);
+
+ // Check on overlap
+ pr_overlap = pr.count == 2;
+ ps_overlap = ps.count == 2;
+ rs_overlap = rs.count == 2;
+ }
+
+
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ inline void debug_consider(int order, Indexed const& left,
+ Indexed const& right, std::string const& header,
+ bool skip = true,
+ std::string const& extra = "", bool ret = false
+ ) const
+ {
+ if (skip) return;
+
+ point_type pi, pj, ri, rj, si, sj;
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
+ left.subject.seg_id,
+ pi, pj);
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
+ left.subject.other_id,
+ ri, rj);
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
+ right.subject.other_id,
+ si, sj);
+
+ bool prc = false, psc = false, rsc = false;
+ overlap_info(pi, pj, ri, rj, si, sj, prc, psc, rsc);
+
+ int const side_ri_p = m_strategy.apply(pi, pj, ri);
+ int const side_rj_p = m_strategy.apply(pi, pj, rj);
+ int const side_si_p = m_strategy.apply(pi, pj, si);
+ int const side_sj_p = m_strategy.apply(pi, pj, sj);
+ int const side_si_r = m_strategy.apply(ri, rj, si);
+ int const side_sj_r = m_strategy.apply(ri, rj, sj);
+
+ std::cout << "Case: " << header << " for " << left.index << " / " << right.index << std::endl;
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH_MORE
+ std::cout << " Segment p:" << geometry::wkt(pi) << " .. " << geometry::wkt(pj) << std::endl;
+ std::cout << " Segment r:" << geometry::wkt(ri) << " .. " << geometry::wkt(rj) << std::endl;
+ std::cout << " Segment s:" << geometry::wkt(si) << " .. " << geometry::wkt(sj) << std::endl;
+
+ std::cout << " r//p: " << side_ri_p << " / " << side_rj_p << std::endl;
+ std::cout << " s//p: " << side_si_p << " / " << side_sj_p << std::endl;
+ std::cout << " s//r: " << side_si_r << " / " << side_sj_r << std::endl;
+#endif
+
+ std::cout << header
+ //<< " order: " << order
+ << " ops: " << operation_char(left.subject.operation)
+ << "/" << operation_char(right.subject.operation)
+ << " ri//p: " << side_ri_p
+ << " si//p: " << side_si_p
+ << " si//r: " << side_si_r
+ << " cnts: " << int(prc) << "," << int(psc) << "," << int(rsc)
+ //<< " idx: " << left.index << "/" << right.index
+ ;
+
+ if (! extra.empty())
+ {
+ std::cout << " " << extra << " " << (ret ? "true" : "false");
+ }
+ std::cout << std::endl;
+ }
+#else
+ inline void debug_consider(int, Indexed const& ,
+ Indexed const& , std::string const& ,
+ bool = true,
+ std::string const& = "", bool = false
+ ) const
+ {}
+#endif
+
+
+ // ux/ux
+ inline bool consider_ux_ux(Indexed const& left,
+ Indexed const& right
+ , std::string const& // header
+ ) const
+ {
+ bool ret = left.index < right.index;
+
+ // In combination of u/x, x/u: take first union, then blocked.
+ // Solves #88, #61, #56, #80
+ if (left.subject.operation == operation_union
+ && right.subject.operation == operation_blocked)
+ {
+ ret = true;
+ }
+ else if (left.subject.operation == operation_blocked
+ && right.subject.operation == operation_union)
+ {
+ ret = false;
+ }
+ else
+ {
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ std::cout << "ux/ux unhandled" << std::endl;
+#endif
+ }
+
+ //debug_consider(0, left, right, header, false, "-> return ", ret);
+
+ return ret;
+ }
+
+ inline bool consider_iu_ux(Indexed const& left,
+ Indexed const& right,
+ int order // 1: iu first, -1: ux first
+ , std::string const& // header
+ ) const
+ {
+ bool ret = false;
+
+ if (left.subject.operation == operation_union
+ && right.subject.operation == operation_union)
+ {
+ ret = order == 1;
+ }
+ else if (left.subject.operation == operation_union
+ && right.subject.operation == operation_blocked)
+ {
+ ret = true;
+ }
+ else if (right.subject.operation == operation_union
+ && left.subject.operation == operation_blocked)
+ {
+ ret = false;
+ }
+ else if (left.subject.operation == operation_union)
+ {
+ ret = true;
+ }
+ else if (right.subject.operation == operation_union)
+ {
+ ret = false;
+ }
+ else
+ {
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ // this still happens in the traverse.cpp test
+ std::cout << " iu/ux unhandled" << std::endl;
+#endif
+ ret = order == 1;
+ }
+
+ //debug_consider(0, left, right, header, false, "-> return", ret);
+ return ret;
+ }
+
+ inline bool consider_iu_ix(Indexed const& left,
+ Indexed const& right,
+ int order // 1: iu first, -1: ix first
+ , std::string const& // header
+ ) const
+ {
+ //debug_consider(order, left, right, header, false, "iu/ix");
+
+ return left.subject.operation == operation_intersection
+ && right.subject.operation == operation_intersection ? order == 1
+ : left.subject.operation == operation_intersection ? false
+ : right.subject.operation == operation_intersection ? true
+ : order == 1;
+ }
+
+ inline bool consider_ix_ix(Indexed const& left, Indexed const& right
+ , std::string const& // header
+ ) const
+ {
+ // Take first intersection, then blocked.
+ if (left.subject.operation == operation_intersection
+ && right.subject.operation == operation_blocked)
+ {
+ return true;
+ }
+ else if (left.subject.operation == operation_blocked
+ && right.subject.operation == operation_intersection)
+ {
+ return false;
+ }
+
+ // Default case, should not occur
+
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ std::cout << "ix/ix unhandled" << std::endl;
+#endif
+ //debug_consider(0, left, right, header, false, "-> return", ret);
+
+ return left.index < right.index;
+ }
+
+
+ inline bool consider_iu_iu(Indexed const& left, Indexed const& right,
+ std::string const& header) const
+ {
+ //debug_consider(0, left, right, header);
+
+ // In general, order it like "union, intersection".
+ if (left.subject.operation == operation_intersection
+ && right.subject.operation == operation_union)
+ {
+ //debug_consider(0, left, right, header, false, "i,u", false);
+ return false;
+ }
+ else if (left.subject.operation == operation_union
+ && right.subject.operation == operation_intersection)
+ {
+ //debug_consider(0, left, right, header, false, "u,i", true);
+ return true;
+ }
+
+ point_type pi, pj, ri, rj, si, sj;
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
+ left.subject.seg_id,
+ pi, pj);
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
+ left.subject.other_id,
+ ri, rj);
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
+ right.subject.other_id,
+ si, sj);
+
+ int const side_ri_p = m_strategy.apply(pi, pj, ri);
+ int const side_si_p = m_strategy.apply(pi, pj, si);
+ int const side_si_r = m_strategy.apply(ri, rj, si);
+
+ // Both located at same side (#58, pie_21_7_21_0_3)
+ if (side_ri_p * side_si_p == 1 && side_si_r != 0)
+ {
+ // Take the most left one
+ if (left.subject.operation == operation_union
+ && right.subject.operation == operation_union)
+ {
+ bool ret = side_si_r == 1;
+ //debug_consider(0, left, right, header, false, "same side", ret);
+ return ret;
+ }
+ }
+
+
+ // Coming from opposite sides (#59, #99)
+ if (side_ri_p * side_si_p == -1)
+ {
+ bool ret = false;
+
+ {
+ ret = side_ri_p == 1; // #100
+ debug_consider(0, left, right, header, false, "opp.", ret);
+ return ret;
+ }
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ std::cout << " iu/iu coming from opposite unhandled" << std::endl;
+#endif
+ }
+
+ // We need EXTRA information here: are p/r/s overlapping?
+ bool pr_ov = false, ps_ov = false, rs_ov = false;
+ overlap_info(pi, pj, ri, rj, si, sj, pr_ov, ps_ov, rs_ov);
+
+ // One coming from right (#83,#90)
+ // One coming from left (#90, #94, #95)
+ if (side_si_r != 0 && (side_ri_p != 0 || side_si_p != 0))
+ {
+ bool ret = false;
+
+ if (pr_ov || ps_ov)
+ {
+ int r = side_ri_p != 0 ? side_ri_p : side_si_p;
+ ret = r * side_si_r == 1;
+ }
+ else
+ {
+ ret = side_si_r == 1;
+ }
+
+ debug_consider(0, left, right, header, false, "left or right", ret);
+ return ret;
+ }
+
+ // All aligned (#92, #96)
+ if (side_ri_p == 0 && side_si_p == 0 && side_si_r == 0)
+ {
+ // One of them is coming from opposite direction.
+
+ // Take the one NOT overlapping
+ bool ret = false;
+ bool found = false;
+ if (pr_ov && ! ps_ov)
+ {
+ ret = true;
+ found = true;
+ }
+ else if (!pr_ov && ps_ov)
+ {
+ ret = false;
+ found = true;
+ }
+
+ debug_consider(0, left, right, header, false, "aligned", ret);
+ if (found)
+ {
+ return ret;
+ }
+ }
+
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ std::cout << " iu/iu unhandled" << std::endl;
+ debug_consider(0, left, right, header, false, "unhandled", left.index < right.index);
+#endif
+ return left.index < right.index;
+ }
+
+ inline bool consider_ii(Indexed const& left, Indexed const& right,
+ std::string const& header) const
+ {
+ debug_consider(0, left, right, header);
+
+ point_type pi, pj, ri, rj, si, sj;
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
+ left.subject.seg_id,
+ pi, pj);
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
+ left.subject.other_id,
+ ri, rj);
+ geometry::copy_segment_points<Reverse1, Reverse2>(m_geometry1, m_geometry2,
+ right.subject.other_id,
+ si, sj);
+
+ int const side_ri_p = m_strategy.apply(pi, pj, ri);
+ int const side_si_p = m_strategy.apply(pi, pj, si);
+
+ // Two other points are (mostly) lying both right of the considered segment
+ // Take the most left one
+ int const side_si_r = m_strategy.apply(ri, rj, si);
+ if (side_ri_p == -1
+ && side_si_p == -1
+ && side_si_r != 0)
+ {
+ bool const ret = side_si_r != 1;
+ return ret;
+ }
+ return left.index < right.index;
+ }
+
+
+public :
+ inline bool operator()(Indexed const& left, Indexed const& right) const
+ {
+ bool const default_order = left.index < right.index;
+
+ if ((m_turn_points[left.index].discarded || left.discarded)
+ && (m_turn_points[right.index].discarded || right.discarded))
+ {
+ return default_order;
+ }
+ else if (m_turn_points[left.index].discarded || left.discarded)
+ {
+ // Be careful to sort discarded first, then all others
+ return true;
+ }
+ else if (m_turn_points[right.index].discarded || right.discarded)
+ {
+ // See above so return false here such that right (discarded)
+ // is sorted before left (not discarded)
+ return false;
+ }
+ else if (m_turn_points[left.index].combination(operation_blocked, operation_union)
+ && m_turn_points[right.index].combination(operation_blocked, operation_union))
+ {
+ // ux/ux
+ return consider_ux_ux(left, right, "ux/ux");
+ }
+ else if (m_turn_points[left.index].both(operation_union)
+ && m_turn_points[right.index].both(operation_union))
+ {
+ // uu/uu, Order is arbitrary
+ // Note: uu/uu is discarded now before so this point will
+ // not be reached.
+ return default_order;
+ }
+ else if (m_turn_points[left.index].combination(operation_intersection, operation_union)
+ && m_turn_points[right.index].combination(operation_intersection, operation_union))
+ {
+ return consider_iu_iu(left, right, "iu/iu");
+ }
+ else if (m_turn_points[left.index].combination(operation_intersection, operation_blocked)
+ && m_turn_points[right.index].combination(operation_intersection, operation_blocked))
+ {
+ return consider_ix_ix(left, right, "ix/ix");
+ }
+ else if (m_turn_points[left.index].both(operation_intersection)
+ && m_turn_points[right.index].both(operation_intersection))
+ {
+ return consider_ii(left, right, "ii/ii");
+ }
+ else if (m_turn_points[left.index].combination(operation_union, operation_blocked)
+ && m_turn_points[right.index].combination(operation_intersection, operation_union))
+ {
+ return consider_iu_ux(left, right, -1, "ux/iu");
+ }
+ else if (m_turn_points[left.index].combination(operation_intersection, operation_union)
+ && m_turn_points[right.index].combination(operation_union, operation_blocked))
+ {
+ return consider_iu_ux(left, right, 1, "iu/ux");
+ }
+ else if (m_turn_points[left.index].combination(operation_intersection, operation_blocked)
+ && m_turn_points[right.index].combination(operation_intersection, operation_union))
+ {
+ return consider_iu_ix(left, right, 1, "ix/iu");
+ }
+ else if (m_turn_points[left.index].combination(operation_intersection, operation_union)
+ && m_turn_points[right.index].combination(operation_intersection, operation_blocked))
+ {
+ return consider_iu_ix(left, right, -1, "iu/ix");
+ }
+ else if (m_turn_points[left.index].method != method_equal
+ && m_turn_points[right.index].method == method_equal
+ )
+ {
+ // If one of them was EQUAL or CONTINUES, it should always come first
+ return false;
+ }
+ else if (m_turn_points[left.index].method == method_equal
+ && m_turn_points[right.index].method != method_equal
+ )
+ {
+ return true;
+ }
+
+ // Now we have no clue how to sort.
+
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ std::cout << " Consider: " << operation_char(m_turn_points[left.index].operations[0].operation)
+ << operation_char(m_turn_points[left.index].operations[1].operation)
+ << "/" << operation_char(m_turn_points[right.index].operations[0].operation)
+ << operation_char(m_turn_points[right.index].operations[1].operation)
+ << " " << " Take " << left.index << " < " << right.index
+ << std::endl;
+#endif
+
+ return default_order;
+ }
+};
+
+
+
+template
+<
+ typename IndexType,
+ typename Iterator,
+ typename TurnPoints,
+ typename Geometry1,
+ typename Geometry2,
+ typename Strategy
+>
+inline void inspect_cluster(Iterator begin_cluster, Iterator end_cluster,
+ TurnPoints& turn_points,
+ operation_type ,
+ Geometry1 const& , Geometry2 const& ,
+ Strategy const& )
+{
+ int count = 0;
+
+ // Make an analysis about all occuring cases here.
+ std::map<std::pair<operation_type, operation_type>, int> inspection;
+ for (Iterator it = begin_cluster; it != end_cluster; ++it)
+ {
+ operation_type first = turn_points[it->index].operations[0].operation;
+ operation_type second = turn_points[it->index].operations[1].operation;
+ if (first > second)
+ {
+ std::swap(first, second);
+ }
+ inspection[std::make_pair(first, second)]++;
+ count++;
+ }
+
+
+ bool keep_cc = false;
+
+ // Decide about which is going to be discarded here.
+ if (inspection[std::make_pair(operation_union, operation_union)] == 1
+ && inspection[std::make_pair(operation_continue, operation_continue)] == 1)
+ {
+ // In case of uu/cc, discard the uu, that indicates a tangency and
+ // inclusion would disturb the (e.g.) cc-cc-cc ordering
+ // NOTE: uu is now discarded anyhow.
+ keep_cc = true;
+ }
+ else if (count == 2
+ && inspection[std::make_pair(operation_intersection, operation_intersection)] == 1
+ && inspection[std::make_pair(operation_union, operation_intersection)] == 1)
+ {
+ // In case of ii/iu, discard the iu. The ii should always be visited,
+ // Because (in case of not discarding iu) correctly ordering of ii/iu appears impossible
+ for (Iterator it = begin_cluster; it != end_cluster; ++it)
+ {
+ if (turn_points[it->index].combination(operation_intersection, operation_union))
+ {
+ it->discarded = true;
+ }
+ }
+ }
+
+ // Discard any continue turn, unless it is the only thing left
+ // (necessary to avoid cc-only rings, all being discarded
+ // e.g. traversal case #75)
+ int nd_count= 0, cc_count = 0;
+ for (Iterator it = begin_cluster; it != end_cluster; ++it)
+ {
+ if (! it->discarded)
+ {
+ nd_count++;
+ if (turn_points[it->index].both(operation_continue))
+ {
+ cc_count++;
+ }
+ }
+ }
+
+ if (nd_count == cc_count)
+ {
+ keep_cc = true;
+ }
+
+ if (! keep_cc)
+ {
+ for (Iterator it = begin_cluster; it != end_cluster; ++it)
+ {
+ if (turn_points[it->index].both(operation_continue))
+ {
+ it->discarded = true;
+ }
+ }
+ }
+}
+
+
+template
+<
+ typename IndexType,
+ bool Reverse1, bool Reverse2,
+ typename Iterator,
+ typename TurnPoints,
+ typename Geometry1,
+ typename Geometry2,
+ typename Strategy
+>
+inline void handle_cluster(Iterator begin_cluster, Iterator end_cluster,
+ TurnPoints& turn_points,
+ operation_type for_operation,
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ // First inspect and (possibly) discard rows
+ inspect_cluster<IndexType>(begin_cluster, end_cluster, turn_points,
+ for_operation, geometry1, geometry2, strategy);
+
+
+ // Then sort this range (discard rows will be ordered first and will be removed in enrich_assign)
+ std::sort(begin_cluster, end_cluster,
+ sort_in_cluster
+ <
+ TurnPoints,
+ IndexType,
+ Geometry1, Geometry2,
+ Reverse1, Reverse2,
+ Strategy
+ >(turn_points, geometry1, geometry2, strategy));
+
+
+#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ typedef typename IndexType::type operations_type;
+ operations_type const& op = turn_points[begin_cluster->index].operations[begin_cluster->operation_index];
+ std::cout << "Clustered points on equal distance " << op.enriched.distance << std::endl;
+ std::cout << "->Indexes ";
+
+ for (Iterator it = begin_cluster; it != end_cluster; ++it)
+ {
+ std::cout << " " << it->index;
+ }
+ std::cout << std::endl << "->Methods: ";
+ for (Iterator it = begin_cluster; it != end_cluster; ++it)
+ {
+ std::cout << " " << method_char(turn_points[it->index].method);
+ }
+ std::cout << std::endl << "->Operations: ";
+ for (Iterator it = begin_cluster; it != end_cluster; ++it)
+ {
+ std::cout << " " << operation_char(turn_points[it->index].operations[0].operation)
+ << operation_char(turn_points[it->index].operations[1].operation);
+ }
+ std::cout << std::endl << "->Discarded: ";
+ for (Iterator it = begin_cluster; it != end_cluster; ++it)
+ {
+ std::cout << " " << (it->discarded ? "true" : "false");
+ }
+ std::cout << std::endl;
+ //<< "\tOn segments: " << prev_op.seg_id << " / " << prev_op.other_id
+ //<< " and " << op.seg_id << " / " << op.other_id
+ //<< geometry::distance(turn_points[prev->index].point, turn_points[it->index].point)
+#endif
+
+}
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_TANGENCIES_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
new file mode 100644
index 000000000..f0307eaf8
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
@@ -0,0 +1,646 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP
+
+
+#include <cstddef>
+
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <boost/geometry/core/is_areal.hpp>
+#include <boost/geometry/core/point_order.hpp>
+#include <boost/geometry/core/reverse_dispatch.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>
+#include <boost/geometry/algorithms/detail/overlay/clip_linestring.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp>
+#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
+#include <boost/geometry/algorithms/detail/overlay/follow.hpp>
+#include <boost/geometry/views/segment_view.hpp>
+
+#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
+#include <boost/foreach.hpp>
+#endif
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersection
+{
+
+template <typename PointOut>
+struct intersection_segment_segment_point
+{
+ template
+ <
+ typename Segment1, typename Segment2,
+ typename OutputIterator, typename Strategy
+ >
+ static inline OutputIterator apply(Segment1 const& segment1,
+ Segment2 const& segment2, OutputIterator out,
+ Strategy const& )
+ {
+ typedef typename point_type<PointOut>::type point_type;
+
+ // Get the intersection point (or two points)
+ segment_intersection_points<point_type> is
+ = strategy::intersection::relate_cartesian_segments
+ <
+ policies::relate::segments_intersection_points
+ <
+ Segment1,
+ Segment2,
+ segment_intersection_points<point_type>
+ >
+ >::apply(segment1, segment2);
+
+ for (std::size_t i = 0; i < is.count; i++)
+ {
+ PointOut p;
+ geometry::convert(is.intersections[i], p);
+ *out++ = p;
+ }
+ return out;
+ }
+};
+
+template <typename PointOut>
+struct intersection_linestring_linestring_point
+{
+ template
+ <
+ typename Linestring1, typename Linestring2,
+ typename OutputIterator, typename Strategy
+ >
+ static inline OutputIterator apply(Linestring1 const& linestring1,
+ Linestring2 const& linestring2, OutputIterator out,
+ Strategy const& )
+ {
+ typedef typename point_type<PointOut>::type point_type;
+
+ typedef detail::overlay::turn_info<point_type> turn_info;
+ std::deque<turn_info> turns;
+
+ geometry::get_intersection_points(linestring1, linestring2, turns);
+
+ for (typename boost::range_iterator<std::deque<turn_info> const>::type
+ it = boost::begin(turns); it != boost::end(turns); ++it)
+ {
+ PointOut p;
+ geometry::convert(it->point, p);
+ *out++ = p;
+ }
+ return out;
+ }
+};
+
+/*!
+\brief Version of linestring with an areal feature (polygon or multipolygon)
+*/
+template
+<
+ bool ReverseAreal,
+ typename LineStringOut,
+ overlay_type OverlayType
+>
+struct intersection_of_linestring_with_areal
+{
+#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
+ template <typename Turn, typename Operation>
+ static inline void debug_follow(Turn const& turn, Operation op,
+ int index)
+ {
+ std::cout << index
+ << " at " << op.seg_id
+ << " meth: " << method_char(turn.method)
+ << " op: " << operation_char(op.operation)
+ << " vis: " << visited_char(op.visited)
+ << " of: " << operation_char(turn.operations[0].operation)
+ << operation_char(turn.operations[1].operation)
+ << " " << geometry::wkt(turn.point)
+ << std::endl;
+ }
+#endif
+
+ template
+ <
+ typename LineString, typename Areal,
+ typename OutputIterator, typename Strategy
+ >
+ static inline OutputIterator apply(LineString const& linestring, Areal const& areal,
+ OutputIterator out,
+ Strategy const& )
+ {
+ if (boost::size(linestring) == 0)
+ {
+ return out;
+ }
+
+ typedef detail::overlay::follow
+ <
+ LineStringOut,
+ LineString,
+ Areal,
+ OverlayType
+ > follower;
+
+ typedef typename point_type<LineStringOut>::type point_type;
+
+ typedef detail::overlay::traversal_turn_info<point_type> turn_info;
+ std::deque<turn_info> turns;
+
+ detail::get_turns::no_interrupt_policy policy;
+ geometry::get_turns
+ <
+ false,
+ (OverlayType == overlay_intersection ? ReverseAreal : !ReverseAreal),
+ detail::overlay::calculate_distance_policy
+ >(linestring, areal, turns, policy);
+
+ if (turns.empty())
+ {
+ // No intersection points, it is either completely
+ // inside (interior + borders)
+ // or completely outside
+
+ // Use border point (on a segment) to check this
+ // (because turn points might skip some cases)
+ point_type border_point;
+ if (! geometry::point_on_border(border_point, linestring, true))
+ {
+ return out;
+ }
+
+
+ if (follower::included(border_point, areal))
+ {
+ LineStringOut copy;
+ geometry::convert(linestring, copy);
+ *out++ = copy;
+ }
+ return out;
+ }
+
+#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
+ int index = 0;
+ BOOST_FOREACH(turn_info const& turn, turns)
+ {
+ debug_follow(turn, turn.operations[0], index++);
+ }
+#endif
+
+ return follower::apply
+ (
+ linestring, areal,
+ geometry::detail::overlay::operation_intersection,
+ turns, out
+ );
+ }
+};
+
+
+}} // namespace detail::intersection
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ // real types
+ typename Geometry1, typename Geometry2,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ // orientation
+ bool Reverse1 = detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
+ bool Reverse2 = detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
+ bool ReverseOut = detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
+ // tag dispatching:
+ typename TagIn1 = typename geometry::tag<Geometry1>::type,
+ typename TagIn2 = typename geometry::tag<Geometry2>::type,
+ typename TagOut = typename geometry::tag<GeometryOut>::type,
+ // metafunction finetuning helpers:
+ bool Areal1 = geometry::is_areal<Geometry1>::value,
+ bool Areal2 = geometry::is_areal<Geometry2>::value,
+ bool ArealOut = geometry::is_areal<GeometryOut>::value
+>
+struct intersection_insert
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPES_OR_ORIENTATIONS
+ , (types<Geometry1, Geometry2, GeometryOut>)
+ );
+};
+
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ bool Reverse1, bool Reverse2, bool ReverseOut,
+ typename TagIn1, typename TagIn2, typename TagOut
+>
+struct intersection_insert
+ <
+ Geometry1, Geometry2,
+ GeometryOut,
+ OverlayType,
+ Reverse1, Reverse2, ReverseOut,
+ TagIn1, TagIn2, TagOut,
+ true, true, true
+ > : detail::overlay::overlay
+ <Geometry1, Geometry2, Reverse1, Reverse2, ReverseOut, GeometryOut, OverlayType>
+{};
+
+
+// Any areal type with box:
+template
+<
+ typename Geometry, typename Box,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ bool Reverse1, bool Reverse2, bool ReverseOut,
+ typename TagIn, typename TagOut
+>
+struct intersection_insert
+ <
+ Geometry, Box,
+ GeometryOut,
+ OverlayType,
+ Reverse1, Reverse2, ReverseOut,
+ TagIn, box_tag, TagOut,
+ true, true, true
+ > : detail::overlay::overlay
+ <Geometry, Box, Reverse1, Reverse2, ReverseOut, GeometryOut, OverlayType>
+{};
+
+
+template
+<
+ typename Segment1, typename Segment2,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ bool Reverse1, bool Reverse2, bool ReverseOut
+>
+struct intersection_insert
+ <
+ Segment1, Segment2,
+ GeometryOut,
+ OverlayType,
+ Reverse1, Reverse2, ReverseOut,
+ segment_tag, segment_tag, point_tag,
+ false, false, false
+ > : detail::intersection::intersection_segment_segment_point<GeometryOut>
+{};
+
+
+template
+<
+ typename Linestring1, typename Linestring2,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ bool Reverse1, bool Reverse2, bool ReverseOut
+>
+struct intersection_insert
+ <
+ Linestring1, Linestring2,
+ GeometryOut,
+ OverlayType,
+ Reverse1, Reverse2, ReverseOut,
+ linestring_tag, linestring_tag, point_tag,
+ false, false, false
+ > : detail::intersection::intersection_linestring_linestring_point<GeometryOut>
+{};
+
+
+template
+<
+ typename Linestring, typename Box,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ bool Reverse1, bool Reverse2, bool ReverseOut
+>
+struct intersection_insert
+ <
+ Linestring, Box,
+ GeometryOut,
+ OverlayType,
+ Reverse1, Reverse2, ReverseOut,
+ linestring_tag, box_tag, linestring_tag,
+ false, true, false
+ >
+{
+ template <typename OutputIterator, typename Strategy>
+ static inline OutputIterator apply(Linestring const& linestring,
+ Box const& box, OutputIterator out, Strategy const& )
+ {
+ typedef typename point_type<GeometryOut>::type point_type;
+ strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
+ return detail::intersection::clip_range_with_box
+ <GeometryOut>(box, linestring, out, lb_strategy);
+ }
+};
+
+
+template
+<
+ typename Linestring, typename Polygon,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ bool ReverseLinestring, bool ReversePolygon, bool ReverseOut
+>
+struct intersection_insert
+ <
+ Linestring, Polygon,
+ GeometryOut,
+ OverlayType,
+ ReverseLinestring, ReversePolygon, ReverseOut,
+ linestring_tag, polygon_tag, linestring_tag,
+ false, true, false
+ > : detail::intersection::intersection_of_linestring_with_areal
+ <
+ ReversePolygon,
+ GeometryOut,
+ OverlayType
+ >
+{};
+
+
+template
+<
+ typename Linestring, typename Ring,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ bool ReverseLinestring, bool ReverseRing, bool ReverseOut
+>
+struct intersection_insert
+ <
+ Linestring, Ring,
+ GeometryOut,
+ OverlayType,
+ ReverseLinestring, ReverseRing, ReverseOut,
+ linestring_tag, ring_tag, linestring_tag,
+ false, true, false
+ > : detail::intersection::intersection_of_linestring_with_areal
+ <
+ ReverseRing,
+ GeometryOut,
+ OverlayType
+ >
+{};
+
+template
+<
+ typename Segment, typename Box,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ bool Reverse1, bool Reverse2, bool ReverseOut
+>
+struct intersection_insert
+ <
+ Segment, Box,
+ GeometryOut,
+ OverlayType,
+ Reverse1, Reverse2, ReverseOut,
+ segment_tag, box_tag, linestring_tag,
+ false, true, false
+ >
+{
+ template <typename OutputIterator, typename Strategy>
+ static inline OutputIterator apply(Segment const& segment,
+ Box const& box, OutputIterator out, Strategy const& )
+ {
+ geometry::segment_view<Segment> range(segment);
+
+ typedef typename point_type<GeometryOut>::type point_type;
+ strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
+ return detail::intersection::clip_range_with_box
+ <GeometryOut>(box, range, out, lb_strategy);
+ }
+};
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename PointOut,
+ overlay_type OverlayType,
+ bool Reverse1, bool Reverse2, bool ReverseOut,
+ typename Tag1, typename Tag2,
+ bool Areal1, bool Areal2
+>
+struct intersection_insert
+ <
+ Geometry1, Geometry2,
+ PointOut,
+ OverlayType,
+ Reverse1, Reverse2, ReverseOut,
+ Tag1, Tag2, point_tag,
+ Areal1, Areal2, false
+ >
+{
+ template <typename OutputIterator, typename Strategy>
+ static inline OutputIterator apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2, OutputIterator out, Strategy const& )
+ {
+
+ typedef detail::overlay::turn_info<PointOut> turn_info;
+ std::vector<turn_info> turns;
+
+ detail::get_turns::no_interrupt_policy policy;
+ geometry::get_turns
+ <
+ false, false, detail::overlay::assign_null_policy
+ >(geometry1, geometry2, turns, policy);
+ for (typename std::vector<turn_info>::const_iterator it
+ = turns.begin(); it != turns.end(); ++it)
+ {
+ *out++ = it->point;
+ }
+
+ return out;
+ }
+};
+
+
+template
+<
+ typename Geometry1, typename Geometry2, typename GeometryOut,
+ overlay_type OverlayType,
+ bool Reverse1, bool Reverse2, bool ReverseOut
+>
+struct intersection_insert_reversed
+{
+ template <typename OutputIterator, typename Strategy>
+ static inline OutputIterator apply(Geometry1 const& g1,
+ Geometry2 const& g2, OutputIterator out,
+ Strategy const& strategy)
+ {
+ return intersection_insert
+ <
+ Geometry2, Geometry1, GeometryOut,
+ OverlayType,
+ Reverse2, Reverse1, ReverseOut
+ >::apply(g2, g1, out, strategy);
+ }
+};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersection
+{
+
+
+template
+<
+ typename GeometryOut,
+ bool ReverseSecond,
+ overlay_type OverlayType,
+ typename Geometry1, typename Geometry2,
+ typename OutputIterator,
+ typename Strategy
+>
+inline OutputIterator insert(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ OutputIterator out,
+ Strategy const& strategy)
+{
+ return boost::mpl::if_c
+ <
+ geometry::reverse_dispatch<Geometry1, Geometry2>::type::value,
+ geometry::dispatch::intersection_insert_reversed
+ <
+ Geometry1, Geometry2,
+ GeometryOut,
+ OverlayType,
+ overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
+ overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value,
+ overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value
+ >,
+ geometry::dispatch::intersection_insert
+ <
+ Geometry1, Geometry2,
+ GeometryOut,
+ OverlayType,
+ geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
+ geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, ReverseSecond>::value
+ >
+ >::type::apply(geometry1, geometry2, out, strategy);
+}
+
+
+/*!
+\brief \brief_calc2{intersection} \brief_strategy
+\ingroup intersection
+\details \details_calc2{intersection_insert, spatial set theoretic intersection}
+ \brief_strategy. \details_insert{intersection}
+\tparam GeometryOut \tparam_geometry{\p_l_or_c}
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam OutputIterator \tparam_out{\p_l_or_c}
+\tparam Strategy \tparam_strategy_overlay
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param out \param_out{intersection}
+\param strategy \param_strategy{intersection}
+\return \return_out
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/intersection.qbk]}
+*/
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename OutputIterator,
+ typename Strategy
+>
+inline OutputIterator intersection_insert(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ OutputIterator out,
+ Strategy const& strategy)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+
+ return detail::intersection::insert
+ <
+ GeometryOut, false, overlay_intersection
+ >(geometry1, geometry2, out, strategy);
+}
+
+
+/*!
+\brief \brief_calc2{intersection}
+\ingroup intersection
+\details \details_calc2{intersection_insert, spatial set theoretic intersection}.
+ \details_insert{intersection}
+\tparam GeometryOut \tparam_geometry{\p_l_or_c}
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam OutputIterator \tparam_out{\p_l_or_c}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param out \param_out{intersection}
+\return \return_out
+
+\qbk{[include reference/algorithms/intersection.qbk]}
+*/
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename OutputIterator
+>
+inline OutputIterator intersection_insert(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ OutputIterator out)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+
+ typedef strategy_intersection
+ <
+ typename cs_tag<GeometryOut>::type,
+ Geometry1,
+ Geometry2,
+ typename geometry::point_type<GeometryOut>::type
+ > strategy;
+
+ return intersection_insert<GeometryOut>(geometry1, geometry2, out,
+ strategy());
+}
+
+}} // namespace detail::intersection
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_INTERSECTION_INSERT_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/overlay.hpp b/boost/geometry/algorithms/detail/overlay/overlay.hpp
new file mode 100644
index 000000000..af9a8d991
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/overlay.hpp
@@ -0,0 +1,312 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_HPP
+
+
+#include <deque>
+#include <map>
+
+#include <boost/range.hpp>
+#include <boost/mpl/assert.hpp>
+
+
+#include <boost/geometry/algorithms/detail/overlay/calculate_distance_policy.hpp>
+#include <boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp>
+#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
+#include <boost/geometry/algorithms/detail/overlay/traverse.hpp>
+#include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+
+
+#include <boost/geometry/algorithms/num_points.hpp>
+#include <boost/geometry/algorithms/reverse.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/add_rings.hpp>
+#include <boost/geometry/algorithms/detail/overlay/assign_parents.hpp>
+#include <boost/geometry/algorithms/detail/overlay/ring_properties.hpp>
+#include <boost/geometry/algorithms/detail/overlay/select_rings.hpp>
+
+
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+# include <boost/geometry/io/dsv/write.hpp>
+#endif
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+// Skip for assemble process
+template <typename TurnInfo>
+inline bool skip(TurnInfo const& turn_info)
+{
+ return (turn_info.discarded || turn_info.both(operation_union))
+ && ! turn_info.any_blocked()
+ && ! turn_info.both(operation_intersection)
+ ;
+}
+
+
+template <typename TurnPoints, typename Map>
+inline void map_turns(Map& map, TurnPoints const& turn_points)
+{
+ typedef typename boost::range_value<TurnPoints>::type turn_point_type;
+ typedef typename turn_point_type::container_type container_type;
+
+ int index = 0;
+ for (typename boost::range_iterator<TurnPoints const>::type
+ it = boost::begin(turn_points);
+ it != boost::end(turn_points);
+ ++it, ++index)
+ {
+ if (! skip(*it))
+ {
+ int op_index = 0;
+ for (typename boost::range_iterator<container_type const>::type
+ op_it = boost::begin(it->operations);
+ op_it != boost::end(it->operations);
+ ++op_it, ++op_index)
+ {
+ ring_identifier ring_id
+ (
+ op_it->seg_id.source_index,
+ op_it->seg_id.multi_index,
+ op_it->seg_id.ring_index
+ );
+ map[ring_id]++;
+ }
+ }
+ }
+}
+
+
+template
+<
+ typename GeometryOut, overlay_type Direction, bool ReverseOut,
+ typename Geometry1, typename Geometry2,
+ typename OutputIterator
+>
+inline OutputIterator return_if_one_input_is_empty(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ OutputIterator out)
+{
+ typedef std::deque
+ <
+ typename geometry::ring_type<GeometryOut>::type
+ > ring_container_type;
+
+ typedef ring_properties<typename geometry::point_type<Geometry1>::type> properties;
+
+// Silence warning C4127: conditional expression is constant
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4127)
+#endif
+
+ // Union: return either of them
+ // Intersection: return nothing
+ // Difference: return first of them
+ if (Direction == overlay_intersection
+ || (Direction == overlay_difference
+ && geometry::num_points(geometry1) == 0))
+ {
+ return out;
+ }
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+
+ std::map<ring_identifier, int> empty;
+ std::map<ring_identifier, properties> all_of_one_of_them;
+
+ select_rings<Direction>(geometry1, geometry2, empty, all_of_one_of_them, false);
+ ring_container_type rings;
+ assign_parents(geometry1, geometry2, rings, all_of_one_of_them);
+ return add_rings<GeometryOut>(all_of_one_of_them, geometry1, geometry2, rings, out);
+}
+
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ bool Reverse1, bool Reverse2, bool ReverseOut,
+ typename GeometryOut,
+ overlay_type Direction
+>
+struct overlay
+{
+ template <typename OutputIterator, typename Strategy>
+ static inline OutputIterator apply(
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ OutputIterator out,
+ Strategy const& )
+ {
+ if (geometry::num_points(geometry1) == 0
+ && geometry::num_points(geometry2) == 0)
+ {
+ return out;
+ }
+
+ if (geometry::num_points(geometry1) == 0
+ || geometry::num_points(geometry2) == 0)
+ {
+ return return_if_one_input_is_empty
+ <
+ GeometryOut, Direction, ReverseOut
+ >(geometry1, geometry2, out);
+ }
+
+ typedef typename geometry::point_type<GeometryOut>::type point_type;
+ typedef detail::overlay::traversal_turn_info<point_type> turn_info;
+ typedef std::deque<turn_info> container_type;
+
+ typedef std::deque
+ <
+ typename geometry::ring_type<GeometryOut>::type
+ > ring_container_type;
+
+ container_type turn_points;
+
+#ifdef BOOST_GEOMETRY_TIME_OVERLAY
+ boost::timer timer;
+#endif
+
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+std::cout << "get turns" << std::endl;
+#endif
+ detail::get_turns::no_interrupt_policy policy;
+ geometry::get_turns
+ <
+ Reverse1, Reverse2,
+ detail::overlay::calculate_distance_policy
+ >(geometry1, geometry2, turn_points, policy);
+
+#ifdef BOOST_GEOMETRY_TIME_OVERLAY
+ std::cout << "get_turns: " << timer.elapsed() << std::endl;
+#endif
+
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+std::cout << "enrich" << std::endl;
+#endif
+ typename Strategy::side_strategy_type side_strategy;
+ geometry::enrich_intersection_points<Reverse1, Reverse2>(turn_points,
+ Direction == overlay_union
+ ? geometry::detail::overlay::operation_union
+ : geometry::detail::overlay::operation_intersection,
+ geometry1, geometry2,
+ side_strategy);
+
+#ifdef BOOST_GEOMETRY_TIME_OVERLAY
+ std::cout << "enrich_intersection_points: " << timer.elapsed() << std::endl;
+#endif
+
+
+#ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE
+std::cout << "traverse" << std::endl;
+#endif
+ // Traverse through intersection/turn points and create rings of them.
+ // Note that these rings are always in clockwise order, even in CCW polygons,
+ // and are marked as "to be reversed" below
+ ring_container_type rings;
+ traverse<Reverse1, Reverse2, Geometry1, Geometry2>::apply
+ (
+ geometry1, geometry2,
+ Direction == overlay_union
+ ? geometry::detail::overlay::operation_union
+ : geometry::detail::overlay::operation_intersection,
+ turn_points, rings
+ );
+
+#ifdef BOOST_GEOMETRY_TIME_OVERLAY
+ std::cout << "traverse: " << timer.elapsed() << std::endl;
+#endif
+
+
+ std::map<ring_identifier, int> map;
+ map_turns(map, turn_points);
+
+#ifdef BOOST_GEOMETRY_TIME_OVERLAY
+ std::cout << "map_turns: " << timer.elapsed() << std::endl;
+#endif
+
+ typedef ring_properties<typename geometry::point_type<GeometryOut>::type> properties;
+
+ std::map<ring_identifier, properties> selected;
+ select_rings<Direction>(geometry1, geometry2, map, selected, ! turn_points.empty());
+
+#ifdef BOOST_GEOMETRY_TIME_OVERLAY
+ std::cout << "select_rings: " << timer.elapsed() << std::endl;
+#endif
+
+
+ // Add rings created during traversal
+ {
+ ring_identifier id(2, 0, -1);
+ for (typename boost::range_iterator<ring_container_type>::type
+ it = boost::begin(rings);
+ it != boost::end(rings);
+ ++it)
+ {
+ selected[id] = properties(*it, true);
+ selected[id].reversed = ReverseOut;
+ id.multi_index++;
+ }
+ }
+
+#ifdef BOOST_GEOMETRY_TIME_OVERLAY
+ std::cout << "add traversal rings: " << timer.elapsed() << std::endl;
+#endif
+
+
+ assign_parents(geometry1, geometry2, rings, selected);
+
+#ifdef BOOST_GEOMETRY_TIME_OVERLAY
+ std::cout << "assign_parents: " << timer.elapsed() << std::endl;
+#endif
+
+ return add_rings<GeometryOut>(selected, geometry1, geometry2, rings, out);
+ }
+};
+
+
+// Metafunction helper for intersection and union
+template <order_selector Selector, bool Reverse = false>
+struct do_reverse {};
+
+template <>
+struct do_reverse<clockwise, false> : boost::false_type {};
+
+template <>
+struct do_reverse<clockwise, true> : boost::true_type {};
+
+template <>
+struct do_reverse<counterclockwise, false> : boost::true_type {};
+
+template <>
+struct do_reverse<counterclockwise, true> : boost::false_type {};
+
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/overlay_type.hpp b/boost/geometry/algorithms/detail/overlay/overlay_type.hpp
new file mode 100644
index 000000000..af62131f0
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/overlay_type.hpp
@@ -0,0 +1,29 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_TYPE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_TYPE_HPP
+
+
+
+namespace boost { namespace geometry
+{
+
+enum overlay_type
+{
+ overlay_union,
+ overlay_intersection,
+ overlay_difference,
+ overlay_dissolve
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_OVERLAY_TYPE_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/ring_properties.hpp b/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
new file mode 100644
index 000000000..a6088694d
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
@@ -0,0 +1,78 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RING_PROPERTIES_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RING_PROPERTIES_HPP
+
+
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/algorithms/within.hpp>
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+template <typename Point>
+struct ring_properties
+{
+ typedef Point point_type;
+ typedef typename default_area_result<Point>::type area_type;
+
+ // Filled by "select_rings"
+ Point point;
+ area_type area;
+
+ // Filled by "update_selection_map"
+ int within_code;
+ bool reversed;
+
+ // Filled/used by "assign_rings"
+ bool discarded;
+ ring_identifier parent;
+ area_type parent_area;
+ std::vector<ring_identifier> children;
+
+ inline ring_properties()
+ : area(area_type())
+ , within_code(-1)
+ , reversed(false)
+ , discarded(false)
+ , parent_area(-1)
+ {}
+
+ template <typename RingOrBox>
+ inline ring_properties(RingOrBox const& ring_or_box, bool midpoint)
+ : within_code(-1)
+ , reversed(false)
+ , discarded(false)
+ , parent_area(-1)
+ {
+ this->area = geometry::area(ring_or_box);
+ geometry::point_on_border(this->point, ring_or_box, midpoint);
+ }
+
+ inline area_type get_area() const
+ {
+ return reversed ? -area : area;
+ }
+};
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RING_PROPERTIES_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp b/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp
new file mode 100644
index 000000000..007113ffb
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/segment_identifier.hpp
@@ -0,0 +1,91 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SEGMENT_IDENTIFIER_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SEGMENT_IDENTIFIER_HPP
+
+
+#if defined(BOOST_GEOMETRY_DEBUG_OVERLAY)
+# define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER
+#endif
+
+
+#include <vector>
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+
+// Internal struct to uniquely identify a segment
+// on a linestring,ring
+// or polygon (needs ring_index)
+// or multi-geometry (needs multi_index)
+struct segment_identifier
+{
+ inline segment_identifier()
+ : source_index(-1)
+ , multi_index(-1)
+ , ring_index(-1)
+ , segment_index(-1)
+ {}
+
+ inline segment_identifier(int src, int mul, int rin, int seg)
+ : source_index(src)
+ , multi_index(mul)
+ , ring_index(rin)
+ , segment_index(seg)
+ {}
+
+ inline bool operator<(segment_identifier const& other) const
+ {
+ return source_index != other.source_index ? source_index < other.source_index
+ : multi_index !=other.multi_index ? multi_index < other.multi_index
+ : ring_index != other.ring_index ? ring_index < other.ring_index
+ : segment_index < other.segment_index
+ ;
+ }
+
+ inline bool operator==(segment_identifier const& other) const
+ {
+ return source_index == other.source_index
+ && segment_index == other.segment_index
+ && ring_index == other.ring_index
+ && multi_index == other.multi_index
+ ;
+ }
+
+#if defined(BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER)
+ friend std::ostream& operator<<(std::ostream &os, segment_identifier const& seg_id)
+ {
+ std::cout
+ << "s:" << seg_id.source_index
+ << ", v:" << seg_id.segment_index // ~vertex
+ ;
+ if (seg_id.ring_index >= 0) std::cout << ", r:" << seg_id.ring_index;
+ if (seg_id.multi_index >= 0) std::cout << ", m:" << seg_id.multi_index;
+ return os;
+ }
+#endif
+
+ int source_index;
+ int multi_index;
+ int ring_index;
+ int segment_index;
+};
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SEGMENT_IDENTIFIER_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/select_rings.hpp b/boost/geometry/algorithms/detail/overlay/select_rings.hpp
new file mode 100644
index 000000000..f664b1951
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/select_rings.hpp
@@ -0,0 +1,295 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP
+
+#include <map>
+
+
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/algorithms/within.hpp>
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
+#include <boost/geometry/algorithms/detail/overlay/ring_properties.hpp>
+#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+namespace dispatch
+{
+
+ template <typename Tag, typename Geometry>
+ struct select_rings
+ {};
+
+ template <typename Box>
+ struct select_rings<box_tag, Box>
+ {
+ template <typename Geometry, typename Map>
+ static inline void apply(Box const& box, Geometry const& ,
+ ring_identifier const& id, Map& map, bool midpoint)
+ {
+ map[id] = typename Map::mapped_type(box, midpoint);
+ }
+
+ template <typename Map>
+ static inline void apply(Box const& box,
+ ring_identifier const& id, Map& map, bool midpoint)
+ {
+ map[id] = typename Map::mapped_type(box, midpoint);
+ }
+ };
+
+ template <typename Ring>
+ struct select_rings<ring_tag, Ring>
+ {
+ template <typename Geometry, typename Map>
+ static inline void apply(Ring const& ring, Geometry const& ,
+ ring_identifier const& id, Map& map, bool midpoint)
+ {
+ if (boost::size(ring) > 0)
+ {
+ map[id] = typename Map::mapped_type(ring, midpoint);
+ }
+ }
+
+ template <typename Map>
+ static inline void apply(Ring const& ring,
+ ring_identifier const& id, Map& map, bool midpoint)
+ {
+ if (boost::size(ring) > 0)
+ {
+ map[id] = typename Map::mapped_type(ring, midpoint);
+ }
+ }
+ };
+
+
+ template <typename Polygon>
+ struct select_rings<polygon_tag, Polygon>
+ {
+ template <typename Geometry, typename Map>
+ static inline void apply(Polygon const& polygon, Geometry const& geometry,
+ ring_identifier id, Map& map, bool midpoint)
+ {
+ typedef typename geometry::ring_type<Polygon>::type ring_type;
+ typedef select_rings<ring_tag, ring_type> per_ring;
+
+ per_ring::apply(exterior_ring(polygon), geometry, id, map, midpoint);
+
+ typename interior_return_type<Polygon const>::type rings
+ = interior_rings(polygon);
+ for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
+ {
+ id.ring_index++;
+ per_ring::apply(*it, geometry, id, map, midpoint);
+ }
+ }
+
+ template <typename Map>
+ static inline void apply(Polygon const& polygon,
+ ring_identifier id, Map& map, bool midpoint)
+ {
+ typedef typename geometry::ring_type<Polygon>::type ring_type;
+ typedef select_rings<ring_tag, ring_type> per_ring;
+
+ per_ring::apply(exterior_ring(polygon), id, map, midpoint);
+
+ typename interior_return_type<Polygon const>::type rings
+ = interior_rings(polygon);
+ for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
+ {
+ id.ring_index++;
+ per_ring::apply(*it, id, map, midpoint);
+ }
+ }
+ };
+}
+
+
+template<overlay_type OverlayType>
+struct decide
+{};
+
+template<>
+struct decide<overlay_union>
+{
+ template <typename Code>
+ static bool include(ring_identifier const& , Code const& code)
+ {
+ return code.within_code * -1 == 1;
+ }
+
+ template <typename Code>
+ static bool reversed(ring_identifier const& , Code const& )
+ {
+ return false;
+ }
+};
+
+template<>
+struct decide<overlay_difference>
+{
+ template <typename Code>
+ static bool include(ring_identifier const& id, Code const& code)
+ {
+ bool is_first = id.source_index == 0;
+ return code.within_code * -1 * (is_first ? 1 : -1) == 1;
+ }
+
+ template <typename Code>
+ static bool reversed(ring_identifier const& id, Code const& code)
+ {
+ return include(id, code) && id.source_index == 1;
+ }
+};
+
+template<>
+struct decide<overlay_intersection>
+{
+ template <typename Code>
+ static bool include(ring_identifier const& , Code const& code)
+ {
+ return code.within_code * 1 == 1;
+ }
+
+ template <typename Code>
+ static bool reversed(ring_identifier const& , Code const& )
+ {
+ return false;
+ }
+};
+
+
+template
+<
+ overlay_type OverlayType,
+ typename Geometry1, typename Geometry2,
+ typename IntersectionMap, typename SelectionMap
+>
+inline void update_selection_map(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ IntersectionMap const& intersection_map,
+ SelectionMap const& map_with_all, SelectionMap& selection_map)
+{
+ selection_map.clear();
+
+ for (typename SelectionMap::const_iterator it = boost::begin(map_with_all);
+ it != boost::end(map_with_all);
+ ++it)
+ {
+ /*
+ int union_code = it->second.within_code * -1;
+ bool is_first = it->first.source_index == 0;
+ std::cout << it->first << " " << it->second.area
+ << ": " << it->second.within_code
+ << " union: " << union_code
+ << " intersection: " << (it->second.within_code * 1)
+ << " G1-G2: " << (union_code * (is_first ? 1 : -1))
+ << " G2-G1: " << (union_code * (is_first ? -1 : 1))
+ << " -> " << (decide<OverlayType>::include(it->first, it->second) ? "INC" : "")
+ << decide<OverlayType>::reverse(it->first, it->second)
+ << std::endl;
+ */
+
+ bool found = intersection_map.find(it->first) != intersection_map.end();
+ if (! found)
+ {
+ ring_identifier const id = it->first;
+ typename SelectionMap::mapped_type properties = it->second; // Copy by value
+
+ // Calculate the "within code" (previously this was done earlier but is
+ // must efficienter here - it can be even more efficient doing it all at once,
+ // using partition, TODO)
+ // So though this is less elegant than before, it avoids many unused point-in-poly calculations
+ switch(id.source_index)
+ {
+ case 0 :
+ properties.within_code
+ = geometry::within(properties.point, geometry2) ? 1 : -1;
+ break;
+ case 1 :
+ properties.within_code
+ = geometry::within(properties.point, geometry1) ? 1 : -1;
+ break;
+ }
+
+ if (decide<OverlayType>::include(id, properties))
+ {
+ properties.reversed = decide<OverlayType>::reversed(id, properties);
+ selection_map[id] = properties;
+ }
+ }
+ }
+}
+
+
+/*!
+\brief The function select_rings select rings based on the overlay-type (union,intersection)
+*/
+template
+<
+ overlay_type OverlayType,
+ typename Geometry1, typename Geometry2,
+ typename IntersectionMap, typename SelectionMap
+>
+inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ IntersectionMap const& intersection_map,
+ SelectionMap& selection_map, bool midpoint)
+{
+ typedef typename geometry::tag<Geometry1>::type tag1;
+ typedef typename geometry::tag<Geometry2>::type tag2;
+
+ SelectionMap map_with_all;
+ dispatch::select_rings<tag1, Geometry1>::apply(geometry1, geometry2,
+ ring_identifier(0, -1, -1), map_with_all, midpoint);
+ dispatch::select_rings<tag2, Geometry2>::apply(geometry2, geometry1,
+ ring_identifier(1, -1, -1), map_with_all, midpoint);
+
+ update_selection_map<OverlayType>(geometry1, geometry2, intersection_map,
+ map_with_all, selection_map);
+}
+
+template
+<
+ overlay_type OverlayType,
+ typename Geometry,
+ typename IntersectionMap, typename SelectionMap
+>
+inline void select_rings(Geometry const& geometry,
+ IntersectionMap const& intersection_map,
+ SelectionMap& selection_map, bool midpoint)
+{
+ typedef typename geometry::tag<Geometry>::type tag;
+
+ SelectionMap map_with_all;
+ dispatch::select_rings<tag, Geometry>::apply(geometry,
+ ring_identifier(0, -1, -1), map_with_all, midpoint);
+
+ update_selection_map<OverlayType>(geometry, geometry, intersection_map,
+ map_with_all, selection_map);
+}
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
new file mode 100644
index 000000000..9c4c99394
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
@@ -0,0 +1,308 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP
+
+#include <cstddef>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/detail/disjoint.hpp>
+#include <boost/geometry/algorithms/detail/partition.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
+
+#include <boost/geometry/geometries/box.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace self_get_turn_points
+{
+
+struct no_interrupt_policy
+{
+ static bool const enabled = false;
+ static bool const has_intersections = false;
+
+
+ template <typename Range>
+ static inline bool apply(Range const&)
+ {
+ return false;
+ }
+};
+
+
+
+
+class self_ip_exception : public geometry::exception {};
+
+template
+<
+ typename Geometry,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+struct self_section_visitor
+{
+ Geometry const& m_geometry;
+ Turns& m_turns;
+ InterruptPolicy& m_interrupt_policy;
+
+ inline self_section_visitor(Geometry const& g,
+ Turns& turns, InterruptPolicy& ip)
+ : m_geometry(g)
+ , m_turns(turns)
+ , m_interrupt_policy(ip)
+ {}
+
+ template <typename Section>
+ inline bool apply(Section const& sec1, Section const& sec2)
+ {
+ if (! detail::disjoint::disjoint_box_box(sec1.bounding_box, sec2.bounding_box)
+ && ! sec1.duplicate
+ && ! sec2.duplicate)
+ {
+ detail::get_turns::get_turns_in_sections
+ <
+ Geometry, Geometry,
+ false, false,
+ Section, Section,
+ Turns, TurnPolicy,
+ InterruptPolicy
+ >::apply(
+ 0, m_geometry, sec1,
+ 0, m_geometry, sec2,
+ false,
+ m_turns, m_interrupt_policy);
+ }
+ if (m_interrupt_policy.has_intersections)
+ {
+ // TODO: we should give partition an interrupt policy.
+ // Now we throw, and catch below, to stop the partition loop.
+ throw self_ip_exception();
+ }
+ return true;
+ }
+
+};
+
+
+
+template
+<
+ typename Geometry,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+struct get_turns
+{
+ static inline bool apply(
+ Geometry const& geometry,
+ Turns& turns,
+ InterruptPolicy& interrupt_policy)
+ {
+ typedef model::box
+ <
+ typename geometry::point_type<Geometry>::type
+ > box_type;
+ typedef typename geometry::sections
+ <
+ box_type, 1
+ > sections_type;
+
+ sections_type sec;
+ geometry::sectionalize<false>(geometry, sec);
+
+ self_section_visitor
+ <
+ Geometry,
+ Turns, TurnPolicy, InterruptPolicy
+ > visitor(geometry, turns, interrupt_policy);
+
+ try
+ {
+ geometry::partition
+ <
+ box_type,
+ detail::get_turns::get_section_box,
+ detail::get_turns::ovelaps_section_box
+ >::apply(sec, visitor);
+ }
+ catch(self_ip_exception const& )
+ {
+ return false;
+ }
+
+ return true;
+ }
+};
+
+
+}} // namespace detail::self_get_turn_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename GeometryTag,
+ typename Geometry,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+struct self_get_turn_points
+{
+};
+
+
+template
+<
+ typename Ring,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+struct self_get_turn_points
+ <
+ ring_tag, Ring,
+ Turns,
+ TurnPolicy,
+ InterruptPolicy
+ >
+ : detail::self_get_turn_points::get_turns
+ <
+ Ring,
+ Turns,
+ TurnPolicy,
+ InterruptPolicy
+ >
+{};
+
+
+template
+<
+ typename Box,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+struct self_get_turn_points
+ <
+ box_tag, Box,
+ Turns,
+ TurnPolicy,
+ InterruptPolicy
+ >
+{
+ static inline bool apply(
+ Box const& ,
+ Turns& ,
+ InterruptPolicy& )
+ {
+ return true;
+ }
+};
+
+
+template
+<
+ typename Polygon,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+struct self_get_turn_points
+ <
+ polygon_tag, Polygon,
+ Turns,
+ TurnPolicy,
+ InterruptPolicy
+ >
+ : detail::self_get_turn_points::get_turns
+ <
+ Polygon,
+ Turns,
+ TurnPolicy,
+ InterruptPolicy
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+ \brief Calculate self intersections of a geometry
+ \ingroup overlay
+ \tparam Geometry geometry type
+ \tparam Turns type of intersection container
+ (e.g. vector of "intersection/turn point"'s)
+ \param geometry geometry
+ \param turns container which will contain intersection points
+ \param interrupt_policy policy determining if process is stopped
+ when intersection is found
+ */
+template
+<
+ typename AssignPolicy,
+ typename Geometry,
+ typename Turns,
+ typename InterruptPolicy
+>
+inline void self_turns(Geometry const& geometry,
+ Turns& turns, InterruptPolicy& interrupt_policy)
+{
+ concept::check<Geometry const>();
+
+ typedef typename strategy_intersection
+ <
+ typename cs_tag<Geometry>::type,
+ Geometry,
+ Geometry,
+ typename boost::range_value<Turns>::type
+ >::segment_intersection_strategy_type strategy_type;
+
+ typedef detail::overlay::get_turn_info
+ <
+ typename point_type<Geometry>::type,
+ typename point_type<Geometry>::type,
+ typename boost::range_value<Turns>::type,
+ detail::overlay::assign_null_policy
+ > TurnPolicy;
+
+ dispatch::self_get_turn_points
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Turns,
+ TurnPolicy,
+ InterruptPolicy
+ >::apply(geometry, turns, interrupt_policy);
+}
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/stream_info.hpp b/boost/geometry/algorithms/detail/overlay/stream_info.hpp
new file mode 100644
index 000000000..eebe38194
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/stream_info.hpp
@@ -0,0 +1,75 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_STREAM_INFO_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_STREAM_INFO_HPP
+
+
+#include <string>
+
+#include <boost/array.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+ 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");
+ }
+
+ template <typename P>
+ std::ostream& operator<<(std::ostream &os, turn_info<P> const& info)
+ {
+ typename geometry::coordinate_type<P>::type d = info.distance;
+ os << "\t"
+ << " src " << info.seg_id.source_index
+ << " seg " << info.seg_id.segment_index
+ << " (// " << info.other_id.source_index
+ << "." << info.other_id.segment_index << ")"
+ << " how " << info.how
+ << "[" << how_str(info.arrival)
+ << " " << dir(info.direction)
+ << (info.opposite ? " o" : "")
+ << "]"
+ << " sd "
+ << dir(info.sides.get<0,0>())
+ << dir(info.sides.get<0,1>())
+ << dir(info.sides.get<1,0>())
+ << dir(info.sides.get<1,1>())
+ << " nxt seg " << info.travels_to_vertex_index
+ << " , ip " << info.travels_to_ip_index
+ << " , or " << info.next_ip_index
+ << " dst " << double(d)
+ << info.visit_state;
+ if (info.flagged)
+ {
+ os << " FLAGGED";
+ }
+ return os;
+ }
+
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_STREAM_INFO_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/traversal_info.hpp b/boost/geometry/algorithms/detail/overlay/traversal_info.hpp
new file mode 100644
index 000000000..810a27af0
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/traversal_info.hpp
@@ -0,0 +1,47 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_INFO_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_INFO_HPP
+
+
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+#include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
+#include <boost/geometry/algorithms/detail/overlay/visit_info.hpp>
+#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+template <typename P>
+struct traversal_turn_operation : public turn_operation
+{
+ enrichment_info<P> enriched;
+ visit_info visited;
+};
+
+template <typename P>
+struct traversal_turn_info : public turn_info<P, traversal_turn_operation<P> >
+{};
+
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_INFO_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/traverse.hpp b/boost/geometry/algorithms/detail/overlay/traverse.hpp
new file mode 100644
index 000000000..72665922b
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/traverse.hpp
@@ -0,0 +1,410 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSE_HPP
+
+#include <cstddef>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>
+#include <boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp>
+#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
+#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
+#include <boost/geometry/algorithms/num_points.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) \
+ || defined(BOOST_GEOMETRY_OVERLAY_REPORT_WKT) \
+ || defined(BOOST_GEOMETRY_DEBUG_TRAVERSE)
+# include <string>
+# include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
+# include <boost/geometry/io/wkt/wkt.hpp>
+#endif
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+template <typename Turn, typename Operation>
+#ifdef BOOST_GEOMETRY_DEBUG_TRAVERSE
+inline void debug_traverse(Turn const& turn, Operation op,
+ std::string const& header)
+{
+ std::cout << header
+ << " at " << op.seg_id
+ << " meth: " << method_char(turn.method)
+ << " op: " << operation_char(op.operation)
+ << " vis: " << visited_char(op.visited)
+ << " of: " << operation_char(turn.operations[0].operation)
+ << operation_char(turn.operations[1].operation)
+ << " " << geometry::wkt(turn.point)
+ << std::endl;
+
+ if (boost::contains(header, "Finished"))
+ {
+ std::cout << std::endl;
+ }
+}
+#else
+inline void debug_traverse(Turn const& , Operation, const char*)
+{
+}
+#endif
+
+
+template <typename Info, typename Turn>
+inline void set_visited_for_continue(Info& info, Turn const& turn)
+{
+ // On "continue", set "visited" for ALL directions
+ if (turn.operation == detail::overlay::operation_continue)
+ {
+ for (typename boost::range_iterator
+ <
+ typename Info::container_type
+ >::type it = boost::begin(info.operations);
+ it != boost::end(info.operations);
+ ++it)
+ {
+ if (it->visited.none())
+ {
+ it->visited.set_visited();
+ }
+ }
+ }
+}
+
+
+template
+<
+ bool Reverse1, bool Reverse2,
+ typename GeometryOut,
+ typename G1,
+ typename G2,
+ typename Turns,
+ typename IntersectionInfo
+>
+inline bool assign_next_ip(G1 const& g1, G2 const& g2,
+ Turns& turns,
+ typename boost::range_iterator<Turns>::type& ip,
+ GeometryOut& current_output,
+ IntersectionInfo& info,
+ segment_identifier& seg_id)
+{
+ info.visited.set_visited();
+ set_visited_for_continue(*ip, info);
+
+ // If there is no next IP on this segment
+ if (info.enriched.next_ip_index < 0)
+ {
+ if (info.enriched.travels_to_vertex_index < 0
+ || info.enriched.travels_to_ip_index < 0)
+ {
+ return false;
+ }
+
+ BOOST_ASSERT(info.enriched.travels_to_vertex_index >= 0);
+ BOOST_ASSERT(info.enriched.travels_to_ip_index >= 0);
+
+ if (info.seg_id.source_index == 0)
+ {
+ geometry::copy_segments<Reverse1>(g1, info.seg_id,
+ info.enriched.travels_to_vertex_index,
+ current_output);
+ }
+ else
+ {
+ geometry::copy_segments<Reverse2>(g2, info.seg_id,
+ info.enriched.travels_to_vertex_index,
+ current_output);
+ }
+ seg_id = info.seg_id;
+ ip = boost::begin(turns) + info.enriched.travels_to_ip_index;
+ }
+ else
+ {
+ ip = boost::begin(turns) + info.enriched.next_ip_index;
+ seg_id = info.seg_id;
+ }
+
+ detail::overlay::append_no_duplicates(current_output, ip->point);
+ return true;
+}
+
+
+inline bool select_source(operation_type operation, int source1, int source2)
+{
+ return (operation == operation_intersection && source1 != source2)
+ || (operation == operation_union && source1 == source2)
+ ;
+}
+
+
+template
+<
+ typename Turn,
+ typename Iterator
+>
+inline bool select_next_ip(operation_type operation,
+ Turn& turn,
+ segment_identifier const& seg_id,
+ Iterator& selected)
+{
+ if (turn.discarded)
+ {
+ return false;
+ }
+ bool has_tp = false;
+ selected = boost::end(turn.operations);
+ for (Iterator it = boost::begin(turn.operations);
+ it != boost::end(turn.operations);
+ ++it)
+ {
+ if (it->visited.started())
+ {
+ selected = it;
+ //std::cout << " RETURN";
+ return true;
+ }
+
+ // In some cases there are two alternatives.
+ // For "ii", take the other one (alternate)
+ // UNLESS the other one is already visited
+ // For "uu", take the same one (see above);
+ // For "cc", take either one, but if there is a starting one,
+ // take that one.
+ if ( (it->operation == operation_continue
+ && (! has_tp || it->visited.started()
+ )
+ )
+ || (it->operation == operation
+ && ! it->visited.finished()
+ && (! has_tp
+ || select_source(operation,
+ it->seg_id.source_index, seg_id.source_index)
+ )
+ )
+ )
+ {
+ selected = it;
+ debug_traverse(turn, *it, " Candidate");
+ has_tp = true;
+ }
+ }
+
+ if (has_tp)
+ {
+ debug_traverse(turn, *selected, " Accepted");
+ }
+
+
+ return has_tp;
+}
+
+
+
+/*!
+ \brief Traverses through intersection points / geometries
+ \ingroup overlay
+ */
+template
+<
+ bool Reverse1, bool Reverse2,
+ typename Geometry1,
+ typename Geometry2,
+ typename Backtrack = backtrack_check_self_intersections<Geometry1, Geometry2>
+>
+class traverse
+{
+public :
+ template <typename Turns, typename Rings>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ detail::overlay::operation_type operation,
+ Turns& turns, Rings& rings)
+ {
+ typedef typename boost::range_value<Rings>::type ring_type;
+ typedef typename boost::range_iterator<Turns>::type turn_iterator;
+ typedef typename boost::range_value<Turns>::type turn_type;
+ typedef typename boost::range_iterator
+ <
+ typename turn_type::container_type
+ >::type turn_operation_iterator_type;
+
+ std::size_t const min_num_points
+ = core_detail::closure::minimum_ring_size
+ <
+ geometry::closure<ring_type>::value
+ >::value;
+
+ std::size_t size_at_start = boost::size(rings);
+
+ typename Backtrack::state_type state;
+ do
+ {
+ state.reset();
+
+ // Iterate through all unvisited points
+ for (turn_iterator it = boost::begin(turns);
+ state.good() && it != boost::end(turns);
+ ++it)
+ {
+ // Skip discarded ones
+ if (! (it->is_discarded() || it->blocked()))
+ {
+ for (turn_operation_iterator_type iit = boost::begin(it->operations);
+ state.good() && iit != boost::end(it->operations);
+ ++iit)
+ {
+ if (iit->visited.none()
+ && ! iit->visited.rejected()
+ && (iit->operation == operation
+ || iit->operation == detail::overlay::operation_continue)
+ )
+ {
+ set_visited_for_continue(*it, *iit);
+
+ ring_type current_output;
+ detail::overlay::append_no_duplicates(current_output,
+ it->point, true);
+
+ turn_iterator current = it;
+ turn_operation_iterator_type current_iit = iit;
+ segment_identifier current_seg_id;
+
+ if (! detail::overlay::assign_next_ip<Reverse1, Reverse2>(
+ geometry1, geometry2,
+ turns,
+ current, current_output,
+ *iit, current_seg_id))
+ {
+ Backtrack::apply(
+ size_at_start,
+ rings, current_output, turns, *current_iit,
+ "No next IP",
+ geometry1, geometry2, state);
+ }
+
+ if (! detail::overlay::select_next_ip(
+ operation,
+ *current,
+ current_seg_id,
+ current_iit))
+ {
+ Backtrack::apply(
+ size_at_start,
+ rings, current_output, turns, *iit,
+ "Dead end at start",
+ geometry1, geometry2, state);
+ }
+ else
+ {
+
+ iit->visited.set_started();
+ detail::overlay::debug_traverse(*it, *iit, "-> Started");
+ detail::overlay::debug_traverse(*current, *current_iit, "Selected ");
+
+
+ unsigned int i = 0;
+
+ while (current_iit != iit && state.good())
+ {
+ if (current_iit->visited.visited())
+ {
+ // It visits a visited node again, without passing the start node.
+ // This makes it suspicious for endless loops
+ Backtrack::apply(
+ size_at_start,
+ rings, current_output, turns, *iit,
+ "Visit again",
+ geometry1, geometry2, state);
+ }
+ else
+ {
+
+
+ // 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.
+ detail::overlay::assign_next_ip<Reverse1, Reverse2>(
+ geometry1, geometry2,
+ turns, current, current_output,
+ *current_iit, current_seg_id);
+
+ if (! detail::overlay::select_next_ip(
+ operation,
+ *current,
+ current_seg_id,
+ current_iit))
+ {
+ // Should not occur in valid (non-self-intersecting) polygons
+ // Should not occur in self-intersecting polygons without spikes
+ // Might occur in polygons with spikes
+ Backtrack::apply(
+ size_at_start,
+ rings, current_output, turns, *iit,
+ "Dead end",
+ geometry1, geometry2, state);
+ }
+ else
+ {
+ detail::overlay::debug_traverse(*current, *current_iit, "Selected ");
+ }
+
+ if (i++ > 2 + 2 * turns.size())
+ {
+ // Sanity check: there may be never more loops
+ // than turn points.
+ // Turn points marked as "ii" can be visited twice.
+ Backtrack::apply(
+ size_at_start,
+ rings, current_output, turns, *iit,
+ "Endless loop",
+ geometry1, geometry2, state);
+ }
+ }
+ }
+
+ if (state.good())
+ {
+ iit->visited.set_finished();
+ detail::overlay::debug_traverse(*current, *iit, "->Finished");
+ if (geometry::num_points(current_output) >= min_num_points)
+ {
+ rings.push_back(current_output);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } while (! state.good());
+ }
+};
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSE_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/turn_info.hpp b/boost/geometry/algorithms/detail/overlay/turn_info.hpp
new file mode 100644
index 000000000..89a60b21a
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/turn_info.hpp
@@ -0,0 +1,152 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TURN_INFO_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TURN_INFO_HPP
+
+
+#include <boost/array.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+enum operation_type
+{
+ operation_none,
+ operation_union,
+ operation_intersection,
+ operation_blocked,
+ operation_continue,
+ operation_opposite
+};
+
+
+enum method_type
+{
+ method_none,
+ method_disjoint,
+ method_crosses,
+ method_touch,
+ method_touch_interior,
+ method_collinear,
+ method_equal,
+ method_error
+};
+
+
+/*!
+ \brief Turn operation: operation
+ \details Information necessary for traversal phase (a phase
+ of the overlay process). The information is gathered during the
+ get_turns (segment intersection) phase.
+ The class is to be included in the turn_info class, either direct
+ or a derived or similar class with more (e.g. enrichment) information.
+ */
+struct turn_operation
+{
+ operation_type operation;
+ segment_identifier seg_id;
+ segment_identifier other_id;
+
+ inline turn_operation()
+ : operation(operation_none)
+ {}
+};
+
+
+/*!
+ \brief Turn information: intersection point, method, and turn information
+ \details Information necessary for traversal phase (a phase
+ of the overlay process). The information is gathered during the
+ get_turns (segment intersection) phase.
+ \tparam Point point type of intersection point
+ \tparam Operation gives classes opportunity to add additional info
+ \tparam Container gives classes opportunity to define how operations are stored
+ */
+template
+<
+ typename Point,
+ typename Operation = turn_operation,
+ typename Container = boost::array<Operation, 2>
+>
+struct turn_info
+{
+ typedef Point point_type;
+ typedef Operation turn_operation_type;
+ typedef Container container_type;
+
+ Point point;
+ method_type method;
+ bool discarded;
+
+
+ Container operations;
+
+ inline turn_info()
+ : method(method_none)
+ , discarded(false)
+ {}
+
+ inline bool both(operation_type type) const
+ {
+ return has12(type, type);
+ }
+
+ inline bool has(operation_type type) const
+ {
+ return this->operations[0].operation == type
+ || this->operations[1].operation == type;
+ }
+
+ inline bool combination(operation_type type1, operation_type type2) const
+ {
+ return has12(type1, type2) || has12(type2, type1);
+ }
+
+
+ inline bool is_discarded() const { return discarded; }
+ inline bool blocked() const
+ {
+ return both(operation_blocked);
+ }
+ inline bool opposite() const
+ {
+ return both(operation_opposite);
+ }
+ inline bool any_blocked() const
+ {
+ return has(operation_blocked);
+ }
+
+
+private :
+ inline bool has12(operation_type type1, operation_type type2) const
+ {
+ return this->operations[0].operation == type1
+ && this->operations[1].operation == type2
+ ;
+ }
+
+};
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TURN_INFO_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/visit_info.hpp b/boost/geometry/algorithms/detail/overlay/visit_info.hpp
new file mode 100644
index 000000000..6be63f42b
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/visit_info.hpp
@@ -0,0 +1,136 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_VISIT_INFO_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_VISIT_INFO_HPP
+
+
+#ifdef BOOST_GEOMETRY_USE_MSM
+# include <boost/geometry/algorithms/detail/overlay/msm_state.hpp>
+#endif
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+
+#if ! defined(BOOST_GEOMETRY_USE_MSM)
+
+class visit_info
+{
+private :
+ static const int NONE = 0;
+ static const int STARTED = 1;
+ static const int VISITED = 2;
+ static const int FINISHED = 3;
+ static const int REJECTED = 4;
+
+ int m_visit_code;
+ bool m_rejected;
+
+public:
+ inline visit_info()
+ : m_visit_code(0)
+ , m_rejected(false)
+ {}
+
+ inline void set_visited() { m_visit_code = VISITED; }
+ inline void set_started() { m_visit_code = STARTED; }
+ inline void set_finished() { m_visit_code = FINISHED; }
+ inline void set_rejected()
+ {
+ m_visit_code = REJECTED;
+ m_rejected = true;
+ }
+
+ inline bool none() const { return m_visit_code == NONE; }
+ inline bool visited() const { return m_visit_code == VISITED; }
+ inline bool started() const { return m_visit_code == STARTED; }
+ inline bool finished() const { return m_visit_code == FINISHED; }
+ inline bool rejected() const { return m_rejected; }
+
+ inline void clear()
+ {
+ if (! rejected())
+ {
+ m_visit_code = NONE;
+ }
+ }
+
+
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ friend std::ostream& operator<<(std::ostream &os, visit_info const& v)
+ {
+ if (v.m_visit_code != 0)
+ {
+ os << " VIS: " << int(v.m_visit_code);
+ }
+ return os;
+ }
+#endif
+
+};
+
+
+#else
+
+
+class visit_info
+{
+
+private :
+
+#ifndef USE_MSM_MINI
+ mutable
+#endif
+ traverse_state state;
+
+public :
+ inline visit_info()
+ {
+ state.start();
+ }
+
+ inline void set_none() { state.process_event(none()); } // Not Yet Implemented!
+ inline void set_visited() { state.process_event(visit()); }
+ inline void set_started() { state.process_event(starting()); }
+ inline void set_finished() { state.process_event(finish()); }
+
+#ifdef USE_MSM_MINI
+ inline bool none() const { return state.flag_none(); }
+ inline bool visited() const { return state.flag_visited(); }
+ inline bool started() const { return state.flag_started(); }
+#else
+ inline bool none() const { return state.is_flag_active<is_init>(); }
+ inline bool visited() const { return state.is_flag_active<is_visited>(); }
+ inline bool started() const { return state.is_flag_active<is_started>(); }
+#endif
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ friend std::ostream& operator<<(std::ostream &os, visit_info const& v)
+ {
+ return os;
+ }
+#endif
+};
+#endif
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_VISIT_INFO_HPP
diff --git a/boost/geometry/algorithms/detail/partition.hpp b/boost/geometry/algorithms/detail/partition.hpp
new file mode 100644
index 000000000..45ff52ccb
--- /dev/null
+++ b/boost/geometry/algorithms/detail/partition.hpp
@@ -0,0 +1,425 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP
+
+#include <vector>
+#include <boost/range/algorithm/copy.hpp>
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace detail { namespace partition
+{
+
+typedef std::vector<std::size_t> index_vector_type;
+
+template <int Dimension, typename Box>
+inline void divide_box(Box const& box, Box& lower_box, Box& upper_box)
+{
+ typedef typename coordinate_type<Box>::type ctype;
+
+ // Divide input box into two parts, e.g. left/right
+ ctype two = 2;
+ ctype mid = (geometry::get<min_corner, Dimension>(box)
+ + geometry::get<max_corner, Dimension>(box)) / two;
+
+ lower_box = box;
+ upper_box = box;
+ geometry::set<max_corner, Dimension>(lower_box, mid);
+ geometry::set<min_corner, Dimension>(upper_box, mid);
+}
+
+// Divide collection into three subsets: lower, upper and oversized
+// (not-fitting)
+// (lower == left or bottom, upper == right or top)
+template <typename OverlapsPolicy, typename InputCollection, typename Box>
+static inline void divide_into_subsets(Box const& lower_box,
+ Box const& upper_box,
+ InputCollection const& collection,
+ index_vector_type const& input,
+ index_vector_type& lower,
+ index_vector_type& upper,
+ index_vector_type& exceeding)
+{
+ typedef boost::range_iterator
+ <
+ index_vector_type const
+ >::type index_iterator_type;
+
+ for(index_iterator_type it = boost::begin(input);
+ it != boost::end(input);
+ ++it)
+ {
+ bool const lower_overlapping = OverlapsPolicy::apply(lower_box,
+ collection[*it]);
+ bool const upper_overlapping = OverlapsPolicy::apply(upper_box,
+ collection[*it]);
+
+ if (lower_overlapping && upper_overlapping)
+ {
+ exceeding.push_back(*it);
+ }
+ else if (lower_overlapping)
+ {
+ lower.push_back(*it);
+ }
+ else if (upper_overlapping)
+ {
+ upper.push_back(*it);
+ }
+ else
+ {
+ // Is nowhere! Should not occur!
+ BOOST_ASSERT(true);
+ }
+ }
+}
+
+// Match collection with itself
+template <typename InputCollection, typename Policy>
+static inline void handle_one(InputCollection const& collection,
+ index_vector_type const& input,
+ Policy& policy)
+{
+ typedef boost::range_iterator<index_vector_type const>::type
+ index_iterator_type;
+ // Quadratic behaviour at lowest level (lowest quad, or all exceeding)
+ for(index_iterator_type it1 = boost::begin(input);
+ it1 != boost::end(input);
+ ++it1)
+ {
+ index_iterator_type it2 = it1;
+ for(++it2; it2 != boost::end(input); ++it2)
+ {
+ policy.apply(collection[*it1], collection[*it2]);
+ }
+ }
+}
+
+// Match collection 1 with collection 2
+template <typename InputCollection, typename Policy>
+static inline void handle_two(
+ InputCollection const& collection1, index_vector_type const& input1,
+ InputCollection const& collection2, index_vector_type const& input2,
+ Policy& policy)
+{
+ typedef boost::range_iterator
+ <
+ index_vector_type const
+ >::type index_iterator_type;
+
+ for(index_iterator_type it1 = boost::begin(input1);
+ it1 != boost::end(input1);
+ ++it1)
+ {
+ for(index_iterator_type it2 = boost::begin(input2);
+ it2 != boost::end(input2);
+ ++it2)
+ {
+ policy.apply(collection1[*it1], collection2[*it2]);
+ }
+ }
+}
+
+template
+<
+ int Dimension,
+ typename Box,
+ typename OverlapsPolicy,
+ typename VisitBoxPolicy
+>
+class partition_one_collection
+{
+ typedef std::vector<std::size_t> index_vector_type;
+ typedef typename coordinate_type<Box>::type ctype;
+ typedef partition_one_collection
+ <
+ 1 - Dimension,
+ Box,
+ OverlapsPolicy,
+ VisitBoxPolicy
+ > sub_divide;
+
+ template <typename InputCollection, typename Policy>
+ static inline void next_level(Box const& box,
+ InputCollection const& collection,
+ index_vector_type const& input,
+ int level, std::size_t min_elements,
+ Policy& policy, VisitBoxPolicy& box_policy)
+ {
+ if (boost::size(input) > 0)
+ {
+ if (std::size_t(boost::size(input)) > min_elements && level < 100)
+ {
+ sub_divide::apply(box, collection, input, level + 1,
+ min_elements, policy, box_policy);
+ }
+ else
+ {
+ handle_one(collection, input, policy);
+ }
+ }
+ }
+
+public :
+ template <typename InputCollection, typename Policy>
+ static inline void apply(Box const& box,
+ InputCollection const& collection,
+ index_vector_type const& input,
+ int level,
+ std::size_t min_elements,
+ Policy& policy, VisitBoxPolicy& box_policy)
+ {
+ box_policy.apply(box, level);
+
+ Box lower_box, upper_box;
+ divide_box<Dimension>(box, lower_box, upper_box);
+
+ index_vector_type lower, upper, exceeding;
+ divide_into_subsets<OverlapsPolicy>(lower_box, upper_box, collection,
+ input, lower, upper, exceeding);
+
+ if (boost::size(exceeding) > 0)
+ {
+ // All what is not fitting a partition should be combined
+ // with each other, and with all which is fitting.
+ handle_one(collection, exceeding, policy);
+ handle_two(collection, exceeding, collection, lower, policy);
+ handle_two(collection, exceeding, collection, upper, policy);
+ }
+
+ // Recursively call operation both parts
+ next_level(lower_box, collection, lower, level, min_elements,
+ policy, box_policy);
+ next_level(upper_box, collection, upper, level, min_elements,
+ policy, box_policy);
+ }
+};
+
+template
+<
+ int Dimension,
+ typename Box,
+ typename OverlapsPolicy,
+ typename VisitBoxPolicy
+>
+class partition_two_collections
+{
+ typedef std::vector<std::size_t> index_vector_type;
+ typedef typename coordinate_type<Box>::type ctype;
+ typedef partition_two_collections
+ <
+ 1 - Dimension,
+ Box,
+ OverlapsPolicy,
+ VisitBoxPolicy
+ > sub_divide;
+
+ template <typename InputCollection, typename Policy>
+ static inline void next_level(Box const& box,
+ InputCollection const& collection1,
+ index_vector_type const& input1,
+ InputCollection const& collection2,
+ index_vector_type const& input2,
+ int level, std::size_t min_elements,
+ Policy& policy, VisitBoxPolicy& box_policy)
+ {
+ if (boost::size(input1) > 0 && boost::size(input2) > 0)
+ {
+ if (std::size_t(boost::size(input1)) > min_elements
+ && std::size_t(boost::size(input2)) > min_elements
+ && level < 100)
+ {
+ sub_divide::apply(box, collection1, input1, collection2,
+ input2, level + 1, min_elements,
+ policy, box_policy);
+ }
+ else
+ {
+ box_policy.apply(box, level + 1);
+ handle_two(collection1, input1, collection2, input2, policy);
+ }
+ }
+ }
+
+public :
+ template <typename InputCollection, typename Policy>
+ static inline void apply(Box const& box,
+ InputCollection const& collection1, index_vector_type const& input1,
+ InputCollection const& collection2, index_vector_type const& input2,
+ int level,
+ std::size_t min_elements,
+ Policy& policy, VisitBoxPolicy& box_policy)
+ {
+ box_policy.apply(box, level);
+
+ Box lower_box, upper_box;
+ divide_box<Dimension>(box, lower_box, upper_box);
+
+ index_vector_type lower1, upper1, exceeding1;
+ index_vector_type lower2, upper2, exceeding2;
+ divide_into_subsets<OverlapsPolicy>(lower_box, upper_box, collection1,
+ input1, lower1, upper1, exceeding1);
+ divide_into_subsets<OverlapsPolicy>(lower_box, upper_box, collection2,
+ input2, lower2, upper2, exceeding2);
+
+ if (boost::size(exceeding1) > 0)
+ {
+ // All exceeding from 1 with 2:
+ handle_two(collection1, exceeding1, collection2, exceeding2,
+ policy);
+
+ // All exceeding from 1 with lower and upper of 2:
+ handle_two(collection1, exceeding1, collection2, lower2, policy);
+ handle_two(collection1, exceeding1, collection2, upper2, policy);
+ }
+ if (boost::size(exceeding2) > 0)
+ {
+ // All exceeding from 2 with lower and upper of 1:
+ handle_two(collection1, lower1, collection2, exceeding2, policy);
+ handle_two(collection1, upper1, collection2, exceeding2, policy);
+ }
+
+ next_level(lower_box, collection1, lower1, collection2, lower2, level,
+ min_elements, policy, box_policy);
+ next_level(upper_box, collection1, upper1, collection2, upper2, level,
+ min_elements, policy, box_policy);
+ }
+};
+
+}} // namespace detail::partition
+
+struct visit_no_policy
+{
+ template <typename Box>
+ static inline void apply(Box const&, int )
+ {}
+};
+
+template
+<
+ typename Box,
+ typename ExpandPolicy,
+ typename OverlapsPolicy,
+ typename VisitBoxPolicy = visit_no_policy
+>
+class partition
+{
+ typedef std::vector<std::size_t> index_vector_type;
+
+ template <typename InputCollection>
+ static inline void expand_to_collection(InputCollection const& collection,
+ Box& total, index_vector_type& index_vector)
+ {
+ std::size_t index = 0;
+ for(typename boost::range_iterator<InputCollection const>::type it
+ = boost::begin(collection);
+ it != boost::end(collection);
+ ++it, ++index)
+ {
+ ExpandPolicy::apply(total, *it);
+ index_vector.push_back(index);
+ }
+ }
+
+public :
+ template <typename InputCollection, typename VisitPolicy>
+ static inline void apply(InputCollection const& collection,
+ VisitPolicy& visitor,
+ std::size_t min_elements = 16,
+ VisitBoxPolicy box_visitor = visit_no_policy()
+ )
+ {
+ if (std::size_t(boost::size(collection)) > min_elements)
+ {
+ index_vector_type index_vector;
+ Box total;
+ assign_inverse(total);
+ expand_to_collection(collection, total, index_vector);
+
+ detail::partition::partition_one_collection
+ <
+ 0, Box,
+ OverlapsPolicy,
+ VisitBoxPolicy
+ >::apply(total, collection, index_vector, 0, min_elements,
+ visitor, box_visitor);
+ }
+ else
+ {
+ typedef typename boost::range_iterator
+ <
+ InputCollection const
+ >::type iterator_type;
+ for(iterator_type it1 = boost::begin(collection);
+ it1 != boost::end(collection);
+ ++it1)
+ {
+ iterator_type it2 = it1;
+ for(++it2; it2 != boost::end(collection); ++it2)
+ {
+ visitor.apply(*it1, *it2);
+ }
+ }
+ }
+ }
+
+ template <typename InputCollection, typename VisitPolicy>
+ static inline void apply(InputCollection const& collection1,
+ InputCollection const& collection2,
+ VisitPolicy& visitor,
+ std::size_t min_elements = 16,
+ VisitBoxPolicy box_visitor = visit_no_policy()
+ )
+ {
+ if (std::size_t(boost::size(collection1)) > min_elements
+ && std::size_t(boost::size(collection2)) > min_elements)
+ {
+ index_vector_type index_vector1, index_vector2;
+ Box total;
+ assign_inverse(total);
+ expand_to_collection(collection1, total, index_vector1);
+ expand_to_collection(collection2, total, index_vector2);
+
+ detail::partition::partition_two_collections
+ <
+ 0, Box, OverlapsPolicy, VisitBoxPolicy
+ >::apply(total,
+ collection1, index_vector1,
+ collection2, index_vector2,
+ 0, min_elements, visitor, box_visitor);
+ }
+ else
+ {
+ typedef typename boost::range_iterator
+ <
+ InputCollection const
+ >::type iterator_type;
+ for(iterator_type it1 = boost::begin(collection1);
+ it1 != boost::end(collection1);
+ ++it1)
+ {
+ for(iterator_type it2 = boost::begin(collection2);
+ it2 != boost::end(collection2);
+ ++it2)
+ {
+ visitor.apply(*it1, *it2);
+ }
+ }
+ }
+ }
+
+};
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_PARTITION_HPP
diff --git a/boost/geometry/algorithms/detail/point_on_border.hpp b/boost/geometry/algorithms/detail/point_on_border.hpp
new file mode 100644
index 000000000..b7e15ba3f
--- /dev/null
+++ b/boost/geometry/algorithms/detail/point_on_border.hpp
@@ -0,0 +1,246 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.Dimension. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
+
+
+#include <cstddef>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
+#include <boost/geometry/algorithms/detail/disjoint.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace point_on_border
+{
+
+
+template<typename Point>
+struct get_point
+{
+ static inline bool apply(Point& destination, Point const& source, bool)
+ {
+ destination = source;
+ return true;
+ }
+};
+
+template<typename Point, std::size_t Dimension, std::size_t DimensionCount>
+struct midpoint_helper
+{
+ template <typename InputPoint>
+ static inline bool apply(Point& p, InputPoint const& p1, InputPoint const& p2)
+ {
+ typename coordinate_type<Point>::type const two = 2;
+ set<Dimension>(p,
+ (get<Dimension>(p1) + get<Dimension>(p2)) / two);
+ return midpoint_helper<Point, Dimension + 1, DimensionCount>::apply(p, p1, p2);
+ }
+};
+
+
+template <typename Point, std::size_t DimensionCount>
+struct midpoint_helper<Point, DimensionCount, DimensionCount>
+{
+ template <typename InputPoint>
+ static inline bool apply(Point& , InputPoint const& , InputPoint const& )
+ {
+ return true;
+ }
+};
+
+
+template<typename Point, typename Range>
+struct point_on_range
+{
+ static inline bool apply(Point& point, Range const& range, bool midpoint)
+ {
+ const std::size_t n = boost::size(range);
+ if (midpoint && n > 1)
+ {
+ typedef typename boost::range_iterator
+ <
+ Range const
+ >::type iterator;
+
+ iterator it = boost::begin(range);
+ iterator prev = it++;
+ while (it != boost::end(range)
+ && detail::equals::equals_point_point(*it, *prev))
+ {
+ prev = it++;
+ }
+ if (it != boost::end(range))
+ {
+ return midpoint_helper
+ <
+ Point,
+ 0, dimension<Point>::value
+ >::apply(point, *prev, *it);
+ }
+ }
+
+ if (n > 0)
+ {
+ geometry::detail::conversion::convert_point_to_point(*boost::begin(range), point);
+ return true;
+ }
+ return false;
+ }
+};
+
+
+template<typename Point, typename Polygon>
+struct point_on_polygon
+{
+ static inline bool apply(Point& point, Polygon const& polygon, bool midpoint)
+ {
+ return point_on_range
+ <
+ Point,
+ typename ring_type<Polygon>::type
+ >::apply(point, exterior_ring(polygon), midpoint);
+ }
+};
+
+
+template<typename Point, typename Box>
+struct point_on_box
+{
+ static inline bool apply(Point& point, Box const& box, bool midpoint)
+ {
+ if (midpoint)
+ {
+ Point p1, p2;
+ detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, p1);
+ detail::assign::assign_box_2d_corner<max_corner, min_corner>(box, p2);
+ midpoint_helper
+ <
+ Point,
+ 0, dimension<Point>::value
+ >::apply(point, p1, p2);
+ }
+ else
+ {
+ detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, point);
+ }
+
+ return true;
+ }
+};
+
+
+}} // namespace detail::point_on_border
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename GeometryTag,
+ typename Point,
+ typename Geometry
+
+>
+struct point_on_border
+{};
+
+
+template<typename Point>
+struct point_on_border<point_tag, Point, Point>
+ : detail::point_on_border::get_point<Point>
+{};
+
+
+template<typename Point, typename Linestring>
+struct point_on_border<linestring_tag, Point, Linestring>
+ : detail::point_on_border::point_on_range<Point, Linestring>
+{};
+
+
+template<typename Point, typename Ring>
+struct point_on_border<ring_tag, Point, Ring>
+ : detail::point_on_border::point_on_range<Point, Ring>
+{};
+
+
+template<typename Point, typename Polygon>
+struct point_on_border<polygon_tag, Point, Polygon>
+ : detail::point_on_border::point_on_polygon<Point, Polygon>
+{};
+
+
+template<typename Point, typename Box>
+struct point_on_border<box_tag, Point, Box>
+ : detail::point_on_border::point_on_box<Point, Box>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Take point on a border
+\ingroup overlay
+\tparam Geometry geometry type. This also defines the type of the output point
+\param point to assign
+\param geometry geometry to take point from
+\param midpoint boolean flag, true if the point should not be a vertex, but some point
+ in between of two vertices
+\return TRUE if successful, else false.
+ It is only false if polygon/line have no points
+\note for a polygon, it is always a point on the exterior ring
+\note for take_midpoint, it is not taken from two consecutive duplicate vertices,
+ (unless there are no other).
+ */
+template <typename Point, typename Geometry>
+inline bool point_on_border(Point& point,
+ Geometry const& geometry,
+ bool midpoint = false)
+{
+ concept::check<Point>();
+ concept::check<Geometry const>();
+
+ typedef typename point_type<Geometry>::type point_type;
+
+ return dispatch::point_on_border
+ <
+ typename tag<Geometry>::type,
+ Point,
+ Geometry
+ >::apply(point, geometry, midpoint);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
diff --git a/boost/geometry/algorithms/detail/ring_identifier.hpp b/boost/geometry/algorithms/detail/ring_identifier.hpp
new file mode 100644
index 000000000..9209ee030
--- /dev/null
+++ b/boost/geometry/algorithms/detail/ring_identifier.hpp
@@ -0,0 +1,70 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RING_IDENTIFIER_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RING_IDENTIFIER_HPP
+
+
+namespace boost { namespace geometry
+{
+
+
+// Ring Identifier. It is currently: source,multi,ring
+struct ring_identifier
+{
+
+ inline ring_identifier()
+ : source_index(-1)
+ , multi_index(-1)
+ , ring_index(-1)
+ {}
+
+ inline ring_identifier(int src, int mul, int rin)
+ : source_index(src)
+ , multi_index(mul)
+ , ring_index(rin)
+ {}
+
+ inline bool operator<(ring_identifier const& other) const
+ {
+ return source_index != other.source_index ? source_index < other.source_index
+ : multi_index !=other.multi_index ? multi_index < other.multi_index
+ : ring_index < other.ring_index
+ ;
+ }
+
+ inline bool operator==(ring_identifier const& other) const
+ {
+ return source_index == other.source_index
+ && ring_index == other.ring_index
+ && multi_index == other.multi_index
+ ;
+ }
+
+#if defined(BOOST_GEOMETRY_DEBUG_IDENTIFIER)
+ friend std::ostream& operator<<(std::ostream &os, ring_identifier const& ring_id)
+ {
+ os << "(s:" << ring_id.source_index;
+ if (ring_id.ring_index >= 0) os << ", r:" << ring_id.ring_index;
+ if (ring_id.multi_index >= 0) os << ", m:" << ring_id.multi_index;
+ os << ")";
+ return os;
+ }
+#endif
+
+
+ int source_index;
+ int multi_index;
+ int ring_index;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RING_IDENTIFIER_HPP
diff --git a/boost/geometry/algorithms/detail/sections/range_by_section.hpp b/boost/geometry/algorithms/detail/sections/range_by_section.hpp
new file mode 100644
index 000000000..ad62f232b
--- /dev/null
+++ b/boost/geometry/algorithms/detail/sections/range_by_section.hpp
@@ -0,0 +1,131 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace section
+{
+
+
+template <typename Range, typename Section>
+struct full_section_range
+{
+ static inline Range const& apply(Range const& range, Section const& )
+ {
+ return range;
+ }
+};
+
+
+template <typename Polygon, typename Section>
+struct full_section_polygon
+{
+ static inline typename ring_return_type<Polygon const>::type apply(Polygon const& polygon, Section const& section)
+ {
+ return section.ring_id.ring_index < 0
+ ? geometry::exterior_ring(polygon)
+ : geometry::interior_rings(polygon)[section.ring_id.ring_index];
+ }
+};
+
+
+}} // namespace detail::section
+#endif
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Tag,
+ typename Geometry,
+ typename Section
+>
+struct range_by_section
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<Geometry>)
+ );
+};
+
+
+template <typename LineString, typename Section>
+struct range_by_section<linestring_tag, LineString, Section>
+ : detail::section::full_section_range<LineString, Section>
+{};
+
+
+template <typename Ring, typename Section>
+struct range_by_section<ring_tag, Ring, Section>
+ : detail::section::full_section_range<Ring, Section>
+{};
+
+
+template <typename Polygon, typename Section>
+struct range_by_section<polygon_tag, Polygon, Section>
+ : detail::section::full_section_polygon<Polygon, Section>
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+/*!
+ \brief Get full ring (exterior, one of interiors, one from multi)
+ indicated by the specified section
+ \ingroup sectionalize
+ \tparam Geometry type
+ \tparam Section type of section to get from
+ \param geometry geometry to take section of
+ \param section structure with section
+ */
+template <typename Geometry, typename Section>
+inline typename ring_return_type<Geometry const>::type
+ range_by_section(Geometry const& geometry, Section const& section)
+{
+ concept::check<Geometry const>();
+
+ return dispatch::range_by_section
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Section
+ >::apply(geometry, section);
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP
diff --git a/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/boost/geometry/algorithms/detail/sections/sectionalize.hpp
new file mode 100644
index 000000000..2ec63aa42
--- /dev/null
+++ b/boost/geometry/algorithms/detail/sections/sectionalize.hpp
@@ -0,0 +1,672 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP
+
+#include <cstddef>
+#include <vector>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/expand.hpp>
+
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/point_order.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/views/closeable_view.hpp>
+#include <boost/geometry/views/reversible_view.hpp>
+#include <boost/geometry/geometries/segment.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Structure containing section information
+ \details Section information consists of a bounding box, direction
+ information (if it is increasing or decreasing, per dimension),
+ index information (begin-end, ring, multi) and the number of
+ segments in this section
+
+ \tparam Box box-type
+ \tparam DimensionCount number of dimensions for this section
+ \ingroup sectionalize
+ */
+template <typename Box, std::size_t DimensionCount>
+struct section
+{
+ typedef Box box_type;
+
+ int id; // might be obsolete now, BSG 14-03-2011 TODO decide about this
+
+ int directions[DimensionCount];
+ ring_identifier ring_id;
+ Box bounding_box;
+
+ int begin_index;
+ int end_index;
+ std::size_t count;
+ std::size_t range_count;
+ bool duplicate;
+ int non_duplicate_index;
+
+ inline section()
+ : id(-1)
+ , 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 std::size_t const value = DimensionCount;
+};
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace sectionalize
+{
+
+template <typename Segment, std::size_t Dimension, std::size_t DimensionCount>
+struct get_direction_loop
+{
+ typedef typename coordinate_type<Segment>::type coordinate_type;
+
+ static inline void apply(Segment const& seg,
+ int directions[DimensionCount])
+ {
+ coordinate_type const diff =
+ geometry::get<1, Dimension>(seg) - geometry::get<0, Dimension>(seg);
+
+ coordinate_type zero = coordinate_type();
+ directions[Dimension] = diff > zero ? 1 : diff < zero ? -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&, int [DimensionCount])
+ {}
+};
+
+template <typename T, std::size_t Dimension, std::size_t DimensionCount>
+struct copy_loop
+{
+ static inline void apply(T const 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(T const [DimensionCount], T [DimensionCount])
+ {}
+};
+
+template <typename T, std::size_t Dimension, std::size_t DimensionCount>
+struct compare_loop
+{
+ static inline bool apply(T const source[DimensionCount],
+ T const 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(T const [DimensionCount],
+ T const [DimensionCount])
+ {
+
+ 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)
+ {
+ if (! geometry::math::equals
+ (
+ geometry::get<0, Dimension>(seg),
+ geometry::get<1, Dimension>(seg)
+ )
+ )
+ {
+ 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 [DimensionCount], int const)
+ {
+ }
+};
+
+/// @brief Helper class to create sections of a part of a range, on the fly
+template
+<
+ typename Range, // Can be closeable_view
+ typename Point,
+ typename Sections,
+ std::size_t DimensionCount,
+ std::size_t MaxCount
+>
+struct sectionalize_part
+{
+ typedef model::referring_segment<Point const> segment_type;
+ typedef typename boost::range_value<Sections>::type section_type;
+
+ typedef typename boost::range_iterator<Range const>::type iterator_type;
+
+ static inline void apply(Sections& sections, section_type& section,
+ int& index, int& ndi,
+ Range const& range,
+ ring_identifier ring_id)
+ {
+ if (int(boost::size(range)) <= index)
+ {
+ return;
+ }
+
+ if (index == 0)
+ {
+ ndi = 0;
+ }
+
+ iterator_type it = boost::begin(range);
+ it += index;
+
+ for(iterator_type previous = it++;
+ it != boost::end(range);
+ ++previous, ++it, index++)
+ {
+ segment_type segment(*previous, *it);
+
+ int direction_classes[DimensionCount] = {0};
+ get_direction_loop
+ <
+ segment_type, 0, DimensionCount
+ >::apply(segment, direction_classes);
+
+ // if "dir" == 0 for all point-dimensions, it is duplicate.
+ // Those sections might be omitted, if wished, lateron
+ bool duplicate = false;
+
+ if (direction_classes[0] == 0)
+ {
+ // Recheck because ALL dimensions should be checked,
+ // not only first one.
+ // (DimensionCount might be < dimension<P>::value)
+ if (check_duplicate_loop
+ <
+ segment_type, 0, geometry::dimension<Point>::type::value
+ >::apply(segment)
+ )
+ {
+ 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 = section_type();
+ }
+
+ if (section.count == 0)
+ {
+ section.begin_index = index;
+ section.ring_id = ring_id;
+ section.duplicate = duplicate;
+ section.non_duplicate_index = ndi;
+ section.range_count = boost::size(range);
+
+ copy_loop
+ <
+ int, 0, DimensionCount
+ >::apply(direction_classes, section.directions);
+ geometry::expand(section.bounding_box, *previous);
+ }
+
+ geometry::expand(section.bounding_box, *it);
+ section.end_index = index + 1;
+ section.count++;
+ if (! duplicate)
+ {
+ ndi++;
+ }
+ }
+ }
+};
+
+
+template
+<
+ typename Range, closure_selector Closure, bool Reverse,
+ typename Point,
+ typename Sections,
+ std::size_t DimensionCount,
+ std::size_t MaxCount
+>
+struct sectionalize_range
+{
+ typedef typename closeable_view<Range const, Closure>::type cview_type;
+ typedef typename reversible_view
+ <
+ cview_type const,
+ Reverse ? iterate_reverse : iterate_forward
+ >::type view_type;
+
+ static inline void apply(Range const& range, Sections& sections,
+ ring_identifier ring_id)
+ {
+ typedef model::referring_segment<Point const> segment_type;
+
+ cview_type cview(range);
+ view_type view(cview);
+
+ std::size_t const n = boost::size(view);
+ if (n == 0)
+ {
+ // Zero points, no section
+ return;
+ }
+
+ if (n == 1)
+ {
+ // Line with one point ==> no sections
+ return;
+ }
+
+ int index = 0;
+ int ndi = 0; // non duplicate index
+
+ typedef typename boost::range_value<Sections>::type section_type;
+ section_type section;
+
+ sectionalize_part
+ <
+ view_type, Point, Sections,
+ DimensionCount, MaxCount
+ >::apply(sections, section, index, ndi,
+ view, ring_id);
+
+ // Add last section if applicable
+ if (section.count > 0)
+ {
+ sections.push_back(section);
+ }
+ }
+};
+
+template
+<
+ typename Polygon,
+ bool Reverse,
+ typename Sections,
+ std::size_t DimensionCount,
+ std::size_t MaxCount
+>
+struct sectionalize_polygon
+{
+ static inline void apply(Polygon const& poly, Sections& sections,
+ ring_identifier ring_id)
+ {
+ typedef typename point_type<Polygon>::type point_type;
+ typedef typename ring_type<Polygon>::type ring_type;
+ typedef sectionalize_range
+ <
+ ring_type, closure<Polygon>::value, Reverse,
+ point_type, Sections, DimensionCount, MaxCount
+ > sectionalizer_type;
+
+ ring_id.ring_index = -1;
+ sectionalizer_type::apply(exterior_ring(poly), sections, ring_id);//-1, multi_index);
+
+ ring_id.ring_index++;
+ typename interior_return_type<Polygon const>::type rings
+ = interior_rings(poly);
+ for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings);
+ ++it, ++ring_id.ring_index)
+ {
+ sectionalizer_type::apply(*it, sections, ring_id);
+ }
+ }
+};
+
+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, ring_identifier const& ring_id)
+ {
+ 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
+
+ // TODO: might be replaced by assign_box_corners_oriented
+ // or just "convert"
+ point_type ll, lr, ul, ur;
+ geometry::detail::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>, closed, false,
+ point_type,
+ Sections,
+ DimensionCount,
+ MaxCount
+ >::apply(points, sections, ring_id);
+ }
+};
+
+template <typename Sections>
+inline void set_section_unique_ids(Sections& sections)
+{
+ // Set ID's.
+ int index = 0;
+ for (typename boost::range_iterator<Sections>::type it = boost::begin(sections);
+ it != boost::end(sections);
+ ++it)
+ {
+ it->id = index++;
+ }
+}
+
+template <typename Sections>
+inline void enlargeSections(Sections& sections)
+{
+ // Robustness issue. Increase sections a tiny bit such that all points are really within (and not on border)
+ // Reason: turns might, rarely, be missed otherwise (case: "buffer_mp1")
+ // Drawback: not really, range is now completely inside the section. Section is a tiny bit too large,
+ // which might cause (a small number) of more comparisons
+ // TODO: make dimension-agnostic
+ for (typename boost::range_iterator<Sections>::type it = boost::begin(sections);
+ it != boost::end(sections);
+ ++it)
+ {
+ typedef typename boost::range_value<Sections>::type section_type;
+ typedef typename section_type::box_type box_type;
+ typedef typename geometry::coordinate_type<box_type>::type coordinate_type;
+ coordinate_type const reps = math::relaxed_epsilon(10.0);
+ geometry::set<0, 0>(it->bounding_box, geometry::get<0, 0>(it->bounding_box) - reps);
+ geometry::set<0, 1>(it->bounding_box, geometry::get<0, 1>(it->bounding_box) - reps);
+ geometry::set<1, 0>(it->bounding_box, geometry::get<1, 0>(it->bounding_box) + reps);
+ geometry::set<1, 1>(it->bounding_box, geometry::get<1, 1>(it->bounding_box) + reps);
+ }
+}
+
+
+}} // namespace detail::sectionalize
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Tag,
+ typename Geometry,
+ bool Reverse,
+ typename Sections,
+ std::size_t DimensionCount,
+ std::size_t MaxCount
+>
+struct sectionalize
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<Geometry>)
+ );
+};
+
+template
+<
+ typename Box,
+ bool Reverse,
+ typename Sections,
+ std::size_t DimensionCount,
+ std::size_t MaxCount
+>
+struct sectionalize<box_tag, Box, Reverse, 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,
+ false,
+ Sections,
+ DimensionCount,
+ MaxCount
+ >
+ : detail::sectionalize::sectionalize_range
+ <
+ LineString, closed, false,
+ typename point_type<LineString>::type,
+ Sections,
+ DimensionCount,
+ MaxCount
+ >
+{};
+
+template
+<
+ typename Ring,
+ bool Reverse,
+ typename Sections,
+ std::size_t DimensionCount,
+ std::size_t MaxCount
+>
+struct sectionalize<ring_tag, Ring, Reverse, Sections, DimensionCount, MaxCount>
+ : detail::sectionalize::sectionalize_range
+ <
+ Ring, geometry::closure<Ring>::value, Reverse,
+ typename point_type<Ring>::type,
+ Sections,
+ DimensionCount,
+ MaxCount
+ >
+{};
+
+template
+<
+ typename Polygon,
+ bool Reverse,
+ typename Sections,
+ std::size_t DimensionCount,
+ std::size_t MaxCount
+>
+struct sectionalize<polygon_tag, Polygon, Reverse, Sections, DimensionCount, MaxCount>
+ : detail::sectionalize::sectionalize_polygon
+ <
+ Polygon, Reverse, 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
+ \param source_index index to assign to the ring_identifiers
+ */
+template<bool Reverse, typename Geometry, typename Sections>
+inline void sectionalize(Geometry const& geometry, Sections& sections, int source_index = 0)
+{
+ concept::check<Geometry const>();
+
+ // TODO: review use of this constant (see below) as causing problems with GCC 4.6 --mloskot
+ // A maximum of 10 segments per section seems to give the fastest results
+ //static std::size_t const max_segments_per_section = 10;
+ typedef dispatch::sectionalize
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ Reverse,
+ Sections,
+ Sections::value,
+ 10 // TODO: max_segments_per_section
+ > sectionalizer_type;
+
+ sections.clear();
+ ring_identifier ring_id;
+ ring_id.source_index = source_index;
+ sectionalizer_type::apply(geometry, sections, ring_id);
+ detail::sectionalize::set_section_unique_ids(sections);
+ detail::sectionalize::enlargeSections(sections);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP
diff --git a/boost/geometry/algorithms/detail/throw_on_empty_input.hpp b/boost/geometry/algorithms/detail/throw_on_empty_input.hpp
new file mode 100644
index 000000000..62328a0d8
--- /dev/null
+++ b/boost/geometry/algorithms/detail/throw_on_empty_input.hpp
@@ -0,0 +1,53 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP
+
+#include <boost/geometry/core/exception.hpp>
+#include <boost/geometry/algorithms/num_points.hpp>
+
+// BSG 2012-02-06: we use this currently only for distance.
+// For other scalar results area,length,perimeter it is commented on purpose.
+// Reason is that for distance there is no other choice. distance of two
+// empty geometries (or one empty) should NOT return any value.
+// But for area it is no problem to be 0.
+// Suppose: area(intersection(a,b)). We (probably) don't want a throw there...
+
+// So decided that at least for Boost 1.49 this is commented for
+// scalar results, except distance.
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Geometry>
+inline void throw_on_empty_input(Geometry const& geometry)
+{
+#if ! defined(BOOST_GEOMETRY_EMPTY_INPUT_NO_THROW)
+ if (geometry::num_points(geometry) == 0)
+ {
+ throw empty_input_exception();
+ }
+#endif
+}
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_THROW_ON_EMPTY_INPUT_HPP
+
diff --git a/boost/geometry/algorithms/difference.hpp b/boost/geometry/algorithms/difference.hpp
new file mode 100644
index 000000000..2f32b344c
--- /dev/null
+++ b/boost/geometry/algorithms/difference.hpp
@@ -0,0 +1,152 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP
+
+#include <algorithm>
+
+#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace difference
+{
+
+/*!
+\brief_calc2{difference} \brief_strategy
+\ingroup difference
+\details \details_calc2{difference_insert, spatial set theoretic difference}
+ \brief_strategy. \details_inserter{difference}
+\tparam GeometryOut output geometry type, must be specified
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam OutputIterator output iterator
+\tparam Strategy \tparam_strategy_overlay
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param out \param_out{difference}
+\param strategy \param_strategy{difference}
+\return \return_out
+
+\qbk{distinguish,with strategy}
+*/
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename OutputIterator,
+ typename Strategy
+>
+inline OutputIterator difference_insert(Geometry1 const& geometry1,
+ Geometry2 const& geometry2, OutputIterator out,
+ Strategy const& strategy)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+ concept::check<GeometryOut>();
+
+ return geometry::dispatch::intersection_insert
+ <
+ Geometry1, Geometry2,
+ GeometryOut,
+ overlay_difference,
+ geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
+ geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, true>::value
+ >::apply(geometry1, geometry2, out, strategy);
+}
+
+/*!
+\brief_calc2{difference}
+\ingroup difference
+\details \details_calc2{difference_insert, spatial set theoretic difference}.
+ \details_insert{difference}
+\tparam GeometryOut output geometry type, must be specified
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam OutputIterator output iterator
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param out \param_out{difference}
+\return \return_out
+
+\qbk{[include reference/algorithms/difference_insert.qbk]}
+*/
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename OutputIterator
+>
+inline OutputIterator difference_insert(Geometry1 const& geometry1,
+ Geometry2 const& geometry2, OutputIterator out)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+ concept::check<GeometryOut>();
+
+ typedef strategy_intersection
+ <
+ typename cs_tag<GeometryOut>::type,
+ Geometry1,
+ Geometry2,
+ typename geometry::point_type<GeometryOut>::type
+ > strategy;
+
+ return difference_insert<GeometryOut>(geometry1, geometry2,
+ out, strategy());
+}
+
+
+}} // namespace detail::difference
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+/*!
+\brief_calc2{difference}
+\ingroup difference
+\details \details_calc2{difference, spatial set theoretic difference}.
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Collection \tparam_output_collection
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param output_collection the output collection
+
+\qbk{[include reference/algorithms/difference.qbk]}
+*/
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Collection
+>
+inline void difference(Geometry1 const& geometry1,
+ Geometry2 const& geometry2, Collection& output_collection)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+
+ typedef typename boost::range_value<Collection>::type geometry_out;
+ concept::check<geometry_out>();
+
+ detail::difference::difference_insert<geometry_out>(
+ geometry1, geometry2,
+ std::back_inserter(output_collection));
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP
diff --git a/boost/geometry/algorithms/disjoint.hpp b/boost/geometry/algorithms/disjoint.hpp
new file mode 100644
index 000000000..ade4e57d5
--- /dev/null
+++ b/boost/geometry/algorithms/disjoint.hpp
@@ -0,0 +1,296 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DISJOINT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DISJOINT_HPP
+
+#include <cstddef>
+#include <deque>
+
+#include <boost/mpl/if.hpp>
+#include <boost/range.hpp>
+
+#include <boost/static_assert.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/reverse_dispatch.hpp>
+
+#include <boost/geometry/algorithms/detail/disjoint.hpp>
+#include <boost/geometry/algorithms/detail/for_each_range.hpp>
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
+#include <boost/geometry/algorithms/within.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/util/math.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace disjoint
+{
+
+template<typename Geometry>
+struct check_each_ring_for_within
+{
+ bool has_within;
+ Geometry const& m_geometry;
+
+ inline check_each_ring_for_within(Geometry const& g)
+ : has_within(false)
+ , m_geometry(g)
+ {}
+
+ template <typename Range>
+ inline void apply(Range const& range)
+ {
+ typename geometry::point_type<Range>::type p;
+ geometry::point_on_border(p, range);
+ if (geometry::within(p, m_geometry))
+ {
+ has_within = true;
+ }
+ }
+};
+
+template <typename FirstGeometry, typename SecondGeometry>
+inline bool rings_containing(FirstGeometry const& geometry1,
+ SecondGeometry const& geometry2)
+{
+ check_each_ring_for_within<FirstGeometry> checker(geometry1);
+ geometry::detail::for_each_range(geometry2, checker);
+ return checker.has_within;
+}
+
+
+struct assign_disjoint_policy
+{
+ // We want to include all points:
+ static bool const include_no_turn = true;
+ static bool const include_degenerate = true;
+ static bool const include_opposite = true;
+
+ // We don't assign extra info:
+ template
+ <
+ typename Info,
+ typename Point1,
+ typename Point2,
+ typename IntersectionInfo,
+ typename DirInfo
+ >
+ static inline void apply(Info& , Point1 const& , Point2 const&,
+ IntersectionInfo const&, DirInfo const&)
+ {}
+};
+
+
+template <typename Geometry1, typename Geometry2>
+struct disjoint_linear
+{
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ {
+ typedef typename geometry::point_type<Geometry1>::type point_type;
+
+ typedef overlay::turn_info<point_type> turn_info;
+ std::deque<turn_info> turns;
+
+ // Specify two policies:
+ // 1) Stop at any intersection
+ // 2) In assignment, include also degenerate points (which are normally skipped)
+ disjoint_interrupt_policy policy;
+ geometry::get_turns
+ <
+ false, false,
+ assign_disjoint_policy
+ >(geometry1, geometry2, turns, policy);
+ if (policy.has_intersections)
+ {
+ return false;
+ }
+
+ return true;
+ }
+};
+
+template <typename Segment1, typename Segment2>
+struct disjoint_segment
+{
+ static inline bool apply(Segment1 const& segment1, Segment2 const& segment2)
+ {
+ typedef typename point_type<Segment1>::type point_type;
+
+ segment_intersection_points<point_type> is
+ = strategy::intersection::relate_cartesian_segments
+ <
+ policies::relate::segments_intersection_points
+ <
+ Segment1,
+ Segment2,
+ segment_intersection_points<point_type>
+ >
+ >::apply(segment1, segment2);
+
+ return is.count == 0;
+ }
+};
+
+template <typename Geometry1, typename Geometry2>
+struct general_areal
+{
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ {
+ if (! disjoint_linear<Geometry1, Geometry2>::apply(geometry1, geometry2))
+ {
+ return false;
+ }
+
+ // If there is no intersection of segments, they might located
+ // inside each other
+ if (rings_containing(geometry1, geometry2)
+ || rings_containing(geometry2, geometry1))
+ {
+ return false;
+ }
+
+ return true;
+ }
+};
+
+
+}} // namespace detail::disjoint
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ std::size_t DimensionCount = dimension<Geometry1>::type::value,
+ typename Tag1 = typename tag<Geometry1>::type,
+ typename Tag2 = typename tag<Geometry2>::type,
+ bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
+>
+struct disjoint
+ : detail::disjoint::general_areal<Geometry1, Geometry2>
+{};
+
+
+// If reversal is needed, perform it
+template
+<
+ typename Geometry1, typename Geometry2,
+ std::size_t DimensionCount,
+ typename Tag1, typename Tag2
+>
+struct disjoint<Geometry1, Geometry2, DimensionCount, Tag1, Tag2, true>
+ : disjoint<Geometry2, Geometry1, DimensionCount, Tag2, Tag1, false>
+{
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ {
+ return disjoint
+ <
+ Geometry2, Geometry1,
+ DimensionCount,
+ Tag2, Tag1
+ >::apply(g2, g1);
+ }
+};
+
+
+template <typename Point1, typename Point2, std::size_t DimensionCount, bool Reverse>
+struct disjoint<Point1, Point2, DimensionCount, point_tag, point_tag, Reverse>
+ : detail::disjoint::point_point<Point1, Point2, 0, DimensionCount>
+{};
+
+
+template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
+struct disjoint<Box1, Box2, DimensionCount, box_tag, box_tag, Reverse>
+ : detail::disjoint::box_box<Box1, Box2, 0, DimensionCount>
+{};
+
+
+template <typename Point, typename Box, std::size_t DimensionCount, bool Reverse>
+struct disjoint<Point, Box, DimensionCount, point_tag, box_tag, Reverse>
+ : detail::disjoint::point_box<Point, Box, 0, DimensionCount>
+{};
+
+template <typename Point, typename Ring, std::size_t DimensionCount, bool Reverse>
+struct disjoint<Point, Ring, DimensionCount, point_tag, ring_tag, Reverse>
+ : detail::disjoint::reverse_covered_by<Point, Ring>
+{};
+
+template <typename Point, typename Polygon, std::size_t DimensionCount, bool Reverse>
+struct disjoint<Point, Polygon, DimensionCount, point_tag, polygon_tag, Reverse>
+ : detail::disjoint::reverse_covered_by<Point, Polygon>
+{};
+
+template <typename Linestring1, typename Linestring2, bool Reverse>
+struct disjoint<Linestring1, Linestring2, 2, linestring_tag, linestring_tag, Reverse>
+ : detail::disjoint::disjoint_linear<Linestring1, Linestring2>
+{};
+
+template <typename Linestring1, typename Linestring2, bool Reverse>
+struct disjoint<Linestring1, Linestring2, 2, segment_tag, segment_tag, Reverse>
+ : detail::disjoint::disjoint_segment<Linestring1, Linestring2>
+{};
+
+template <typename Linestring, typename Segment, bool Reverse>
+struct disjoint<Linestring, Segment, 2, linestring_tag, segment_tag, Reverse>
+ : detail::disjoint::disjoint_linear<Linestring, Segment>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+/*!
+\brief \brief_check2{are disjoint}
+\ingroup disjoint
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\return \return_check2{are disjoint}
+
+\qbk{[include reference/algorithms/disjoint.qbk]}
+*/
+template <typename Geometry1, typename Geometry2>
+inline bool disjoint(Geometry1 const& geometry1,
+ Geometry2 const& geometry2)
+{
+ concept::check_concepts_and_equal_dimensions
+ <
+ Geometry1 const,
+ Geometry2 const
+ >();
+
+ return dispatch::disjoint<Geometry1, Geometry2>::apply(geometry1, geometry2);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DISJOINT_HPP
diff --git a/boost/geometry/algorithms/distance.hpp b/boost/geometry/algorithms/distance.hpp
new file mode 100644
index 000000000..0fd5c43f4
--- /dev/null
+++ b/boost/geometry/algorithms/distance.hpp
@@ -0,0 +1,596 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DISTANCE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DISTANCE_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/reverse_dispatch.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
+
+#include <boost/geometry/geometries/segment.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/default_distance_result.hpp>
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/within.hpp>
+
+#include <boost/geometry/views/closeable_view.hpp>
+#include <boost/geometry/util/math.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace distance
+{
+
+// To avoid spurious namespaces here:
+using strategy::distance::services::return_type;
+
+template <typename P1, typename P2, typename Strategy>
+struct point_to_point
+{
+ static inline typename return_type<Strategy>::type apply(P1 const& p1,
+ P2 const& p2, Strategy const& strategy)
+ {
+ boost::ignore_unused_variable_warning(strategy);
+ return strategy.apply(p1, p2);
+ }
+};
+
+
+template<typename Point, typename Segment, typename Strategy>
+struct point_to_segment
+{
+ static inline typename return_type<Strategy>::type apply(Point const& point,
+ Segment const& segment, Strategy const& )
+ {
+ typename strategy::distance::services::default_strategy
+ <
+ segment_tag,
+ Point,
+ typename point_type<Segment>::type,
+ typename cs_tag<Point>::type,
+ typename cs_tag<typename point_type<Segment>::type>::type,
+ Strategy
+ >::type segment_strategy;
+
+ typename point_type<Segment>::type p[2];
+ geometry::detail::assign_point_from_index<0>(segment, p[0]);
+ geometry::detail::assign_point_from_index<1>(segment, p[1]);
+ return segment_strategy.apply(point, p[0], p[1]);
+ }
+};
+
+
+template
+<
+ typename Point,
+ typename Range,
+ closure_selector Closure,
+ typename PPStrategy,
+ typename PSStrategy
+>
+struct point_to_range
+{
+ typedef typename return_type<PSStrategy>::type return_type;
+
+ static inline return_type apply(Point const& point, Range const& range,
+ PPStrategy const& pp_strategy, PSStrategy const& ps_strategy)
+ {
+ return_type const zero = return_type(0);
+
+ if (boost::size(range) == 0)
+ {
+ return zero;
+ }
+
+ typedef typename closeable_view<Range const, Closure>::type view_type;
+
+ view_type view(range);
+
+ // line of one point: return point distance
+ typedef typename boost::range_iterator<view_type const>::type iterator_type;
+ iterator_type it = boost::begin(view);
+ iterator_type prev = it++;
+ if (it == boost::end(view))
+ {
+ return pp_strategy.apply(point, *boost::begin(view));
+ }
+
+ // Create comparable (more efficient) strategy
+ typedef typename strategy::distance::services::comparable_type<PSStrategy>::type eps_strategy_type;
+ eps_strategy_type eps_strategy = strategy::distance::services::get_comparable<PSStrategy>::apply(ps_strategy);
+
+ // start with first segment distance
+ return_type d = eps_strategy.apply(point, *prev, *it);
+ return_type rd = ps_strategy.apply(point, *prev, *it);
+
+ // check if other segments are closer
+ for (++prev, ++it; it != boost::end(view); ++prev, ++it)
+ {
+ return_type const ds = eps_strategy.apply(point, *prev, *it);
+ if (geometry::math::equals(ds, zero))
+ {
+ return ds;
+ }
+ else if (ds < d)
+ {
+ d = ds;
+ rd = ps_strategy.apply(point, *prev, *it);
+ }
+ }
+
+ return rd;
+ }
+};
+
+
+template
+<
+ typename Point,
+ typename Ring,
+ closure_selector Closure,
+ typename PPStrategy,
+ typename PSStrategy
+>
+struct point_to_ring
+{
+ typedef std::pair
+ <
+ typename return_type<PPStrategy>::type, bool
+ > distance_containment;
+
+ static inline distance_containment apply(Point const& point,
+ Ring const& ring,
+ PPStrategy const& pp_strategy, PSStrategy const& ps_strategy)
+ {
+ return distance_containment
+ (
+ point_to_range
+ <
+ Point,
+ Ring,
+ Closure,
+ PPStrategy,
+ PSStrategy
+ >::apply(point, ring, pp_strategy, ps_strategy),
+ geometry::within(point, ring)
+ );
+ }
+};
+
+
+
+template
+<
+ typename Point,
+ typename Polygon,
+ closure_selector Closure,
+ typename PPStrategy,
+ typename PSStrategy
+>
+struct point_to_polygon
+{
+ typedef typename return_type<PPStrategy>::type return_type;
+ typedef std::pair<return_type, bool> distance_containment;
+
+ static inline distance_containment apply(Point const& point,
+ Polygon const& polygon,
+ PPStrategy const& pp_strategy, PSStrategy const& ps_strategy)
+ {
+ // Check distance to all rings
+ typedef point_to_ring
+ <
+ Point,
+ typename ring_type<Polygon>::type,
+ Closure,
+ PPStrategy,
+ PSStrategy
+ > per_ring;
+
+ distance_containment dc = per_ring::apply(point,
+ exterior_ring(polygon), pp_strategy, ps_strategy);
+
+ typename interior_return_type<Polygon const>::type rings
+ = interior_rings(polygon);
+ for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
+ {
+ distance_containment dcr = per_ring::apply(point,
+ *it, pp_strategy, ps_strategy);
+ if (dcr.first < dc.first)
+ {
+ dc.first = dcr.first;
+ }
+ // If it was inside, and also inside inner ring,
+ // turn off the inside-flag, it is outside the polygon
+ if (dc.second && dcr.second)
+ {
+ dc.second = false;
+ }
+ }
+ return dc;
+ }
+};
+
+
+// Helper metafunction for default strategy retrieval
+template <typename Geometry1, typename Geometry2>
+struct default_strategy
+ : strategy::distance::services::default_strategy
+ <
+ point_tag,
+ typename point_type<Geometry1>::type,
+ typename point_type<Geometry2>::type
+ >
+{};
+
+
+}} // namespace detail::distance
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+using strategy::distance::services::return_type;
+
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Strategy = typename detail::distance::default_strategy<Geometry1, Geometry2>::type,
+ typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,
+ typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type,
+ typename StrategyTag = typename strategy::distance::services::tag<Strategy>::type,
+ bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
+>
+struct distance: not_implemented<Tag1, Tag2>
+{};
+
+
+// If reversal is needed, perform it
+template
+<
+ typename Geometry1, typename Geometry2, typename Strategy,
+ typename Tag1, typename Tag2, typename StrategyTag
+>
+struct distance
+<
+ Geometry1, Geometry2, Strategy,
+ Tag1, Tag2, StrategyTag,
+ true
+>
+ : distance<Geometry2, Geometry1, Strategy, Tag2, Tag1, StrategyTag, false>
+{
+ static inline typename return_type<Strategy>::type apply(
+ Geometry1 const& g1,
+ Geometry2 const& g2,
+ Strategy const& strategy)
+ {
+ return distance
+ <
+ Geometry2, Geometry1, Strategy,
+ Tag2, Tag1, StrategyTag,
+ false
+ >::apply(g2, g1, strategy);
+ }
+};
+
+// If reversal is needed and we got the strategy by default, invert it before
+// proceeding to the reversal.
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1, typename Tag2, typename StrategyTag
+>
+struct distance
+<
+ Geometry1, Geometry2,
+ typename detail::distance::default_strategy<Geometry1, Geometry2>::type,
+ Tag1, Tag2, StrategyTag,
+ true
+>
+ : distance
+ <
+ Geometry2, Geometry1,
+ typename detail::distance::default_strategy<Geometry2, Geometry1>::type,
+ Tag2, Tag1, StrategyTag,
+ false
+ >
+{
+ typedef typename detail::distance::default_strategy<Geometry2, Geometry1>::type reversed_strategy;
+
+ static inline typename strategy::distance::services::return_type<reversed_strategy>::type apply(
+ Geometry1 const& g1,
+ Geometry2 const& g2,
+ typename detail::distance::default_strategy<Geometry1, Geometry2>::type const&)
+ {
+ return distance
+ <
+ Geometry2, Geometry1, reversed_strategy,
+ Tag2, Tag1, StrategyTag,
+ false
+ >::apply(g2, g1, reversed_strategy());
+ }
+};
+
+
+// Point-point
+template <typename P1, typename P2, typename Strategy>
+struct distance
+ <
+ P1, P2, Strategy,
+ point_tag, point_tag, strategy_tag_distance_point_point,
+ 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, Linestring, Strategy,
+ point_tag, linestring_tag, strategy_tag_distance_point_point,
+ false
+>
+{
+
+ static inline typename return_type<Strategy>::type apply(Point const& point,
+ Linestring const& linestring,
+ Strategy const& strategy)
+ {
+ typedef typename strategy::distance::services::default_strategy
+ <
+ segment_tag,
+ Point,
+ typename point_type<Linestring>::type,
+ typename cs_tag<Point>::type,
+ typename cs_tag<typename point_type<Linestring>::type>::type,
+ Strategy
+ >::type ps_strategy_type;
+
+ return detail::distance::point_to_range
+ <
+ Point, Linestring, closed, 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, Linestring, Strategy,
+ point_tag, linestring_tag, strategy_tag_distance_point_segment,
+ false
+>
+{
+ static inline typename return_type<Strategy>::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_range
+ <
+ Point, Linestring, closed, pp_strategy_type, Strategy
+ >::apply(point, linestring, pp_strategy_type(), strategy);
+ }
+};
+
+// Point-ring , where point-segment strategy is specified
+template <typename Point, typename Ring, typename Strategy>
+struct distance
+<
+ Point, Ring, Strategy,
+ point_tag, ring_tag, strategy_tag_distance_point_point,
+ false
+>
+{
+ typedef typename return_type<Strategy>::type return_type;
+
+ static inline return_type apply(Point const& point,
+ Ring const& ring,
+ Strategy const& strategy)
+ {
+ typedef typename strategy::distance::services::default_strategy
+ <
+ segment_tag,
+ Point,
+ typename point_type<Ring>::type
+ >::type ps_strategy_type;
+
+ std::pair<return_type, bool>
+ dc = detail::distance::point_to_ring
+ <
+ Point, Ring,
+ geometry::closure<Ring>::value,
+ Strategy, ps_strategy_type
+ >::apply(point, ring, strategy, ps_strategy_type());
+
+ return dc.second ? return_type(0) : dc.first;
+ }
+};
+
+
+// Point-polygon , where point-segment strategy is specified
+template <typename Point, typename Polygon, typename Strategy>
+struct distance
+<
+ Point, Polygon, Strategy,
+ point_tag, polygon_tag, strategy_tag_distance_point_point,
+ false
+>
+{
+ typedef typename return_type<Strategy>::type return_type;
+
+ static inline return_type apply(Point const& point,
+ Polygon const& polygon,
+ Strategy const& strategy)
+ {
+ typedef typename strategy::distance::services::default_strategy
+ <
+ segment_tag,
+ Point,
+ typename point_type<Polygon>::type
+ >::type ps_strategy_type;
+
+ std::pair<return_type, bool>
+ dc = detail::distance::point_to_polygon
+ <
+ Point, Polygon,
+ geometry::closure<Polygon>::value,
+ Strategy, ps_strategy_type
+ >::apply(point, polygon, strategy, ps_strategy_type());
+
+ return dc.second ? return_type(0) : dc.first;
+ }
+};
+
+
+
+// Point-segment version 1, with point-point strategy
+template <typename Point, typename Segment, typename Strategy>
+struct distance
+<
+ Point, Segment, Strategy,
+ point_tag, segment_tag, strategy_tag_distance_point_point,
+ false
+> : detail::distance::point_to_segment<Point, Segment, Strategy>
+{};
+
+// Point-segment version 2, with point-segment strategy
+template <typename Point, typename Segment, typename Strategy>
+struct distance
+<
+ Point, Segment, Strategy,
+ point_tag, segment_tag, strategy_tag_distance_point_segment,
+ false
+>
+{
+ static inline typename return_type<Strategy>::type apply(Point const& point,
+ Segment const& segment, Strategy const& strategy)
+ {
+
+ typename point_type<Segment>::type p[2];
+ geometry::detail::assign_point_from_index<0>(segment, p[0]);
+ geometry::detail::assign_point_from_index<1>(segment, p[1]);
+ return strategy.apply(point, p[0], p[1]);
+ }
+};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+/*!
+\brief \brief_calc2{distance} \brief_strategy
+\ingroup distance
+\details
+\details \details_calc{area}. \brief_strategy. \details_strategy_reasons
+
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Strategy \tparam_strategy{Distance}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param strategy \param_strategy{distance}
+\return \return_calc{distance}
+\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.
+
+\qbk{distinguish,with strategy}
+
+\qbk{
+[heading Available Strategies]
+\* [link geometry.reference.strategies.strategy_distance_pythagoras Pythagoras (cartesian)]
+\* [link geometry.reference.strategies.strategy_distance_haversine Haversine (spherical)]
+\* [link geometry.reference.strategies.strategy_distance_cross_track Cross track (spherical\, point-to-segment)]
+\* [link geometry.reference.strategies.strategy_distance_projected_point Projected point (cartesian\, point-to-segment)]
+\* more (currently extensions): Vincenty\, Andoyer (geographic)
+}
+ */
+
+/*
+Note, in case of a Compilation Error:
+if you get:
+ - "Failed to specialize function template ..."
+ - "error: no matching function for call to ..."
+for distance, it is probably so that there is no specialization
+for return_type<...> for your strategy.
+*/
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline typename strategy::distance::services::return_type<Strategy>::type distance(
+ Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+
+ detail::throw_on_empty_input(geometry1);
+ detail::throw_on_empty_input(geometry2);
+
+ return dispatch::distance
+ <
+ Geometry1,
+ Geometry2,
+ Strategy
+ >::apply(geometry1, geometry2, strategy);
+}
+
+
+/*!
+\brief \brief_calc2{distance}
+\ingroup distance
+\details The default strategy is used, corresponding to the coordinate system of the geometries
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\return \return_calc{distance}
+
+\qbk{[include reference/algorithms/distance.qbk]}
+ */
+template <typename Geometry1, typename Geometry2>
+inline typename default_distance_result<Geometry1, Geometry2>::type distance(
+ Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+
+ return distance(geometry1, geometry2,
+ typename detail::distance::default_strategy<Geometry1, Geometry2>::type());
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DISTANCE_HPP
diff --git a/boost/geometry/algorithms/envelope.hpp b/boost/geometry/algorithms/envelope.hpp
new file mode 100644
index 000000000..ee88fe888
--- /dev/null
+++ b/boost/geometry/algorithms/envelope.hpp
@@ -0,0 +1,195 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_ENVELOPE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_ENVELOPE_HPP
+
+#include <boost/range.hpp>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/expand.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace envelope
+{
+
+
+/// Calculate envelope of an 2D or 3D segment
+struct envelope_expand_one
+{
+ template<typename Geometry, typename Box>
+ static inline void apply(Geometry const& geometry, Box& mbr)
+ {
+ assign_inverse(mbr);
+ geometry::expand(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_iterator<Range const>::type iterator_type;
+
+ for (iterator_type it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ geometry::expand(mbr, *it);
+ }
+}
+
+
+
+/// Generic range dispatching struct
+struct envelope_range
+{
+ /// Calculate envelope of range using a strategy
+ template <typename Range, typename Box>
+ 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
+{
+
+
+template
+<
+ typename Geometry,
+ typename Tag = typename tag<Geometry>::type
+>
+struct envelope: not_implemented<Tag>
+{};
+
+
+template <typename Point>
+struct envelope<Point, point_tag>
+ : detail::envelope::envelope_expand_one
+{};
+
+
+template <typename Box>
+struct envelope<Box, box_tag>
+ : detail::envelope::envelope_expand_one
+{};
+
+
+template <typename Segment>
+struct envelope<Segment, segment_tag>
+ : detail::envelope::envelope_expand_one
+{};
+
+
+template <typename Linestring>
+struct envelope<Linestring, linestring_tag>
+ : detail::envelope::envelope_range
+{};
+
+
+template <typename Ring>
+struct envelope<Ring, ring_tag>
+ : detail::envelope::envelope_range
+{};
+
+
+template <typename Polygon>
+struct envelope<Polygon, polygon_tag>
+ : detail::envelope::envelope_range
+{
+ template <typename Box>
+ static inline void apply(Polygon const& poly, Box& mbr)
+ {
+ // For polygon, inspecting outer ring is sufficient
+ detail::envelope::envelope_range::apply(exterior_ring(poly), mbr);
+ }
+
+};
+
+
+} // namespace dispatch
+#endif
+
+
+/*!
+\brief \brief_calc{envelope}
+\ingroup envelope
+\details \details_calc{envelope,\det_envelope}.
+\tparam Geometry \tparam_geometry
+\tparam Box \tparam_box
+\param geometry \param_geometry
+\param mbr \param_box \param_set{envelope}
+
+\qbk{[include reference/algorithms/envelope.qbk]}
+\qbk{
+[heading Example]
+[envelope] [envelope_output]
+}
+*/
+template<typename Geometry, typename Box>
+inline void envelope(Geometry const& geometry, Box& mbr)
+{
+ concept::check<Geometry const>();
+ concept::check<Box>();
+
+ dispatch::envelope<Geometry>::apply(geometry, mbr);
+}
+
+
+/*!
+\brief \brief_calc{envelope}
+\ingroup envelope
+\details \details_calc{return_envelope,\det_envelope}. \details_return{envelope}
+\tparam Box \tparam_box
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\return \return_calc{envelope}
+
+\qbk{[include reference/algorithms/envelope.qbk]}
+\qbk{
+[heading Example]
+[return_envelope] [return_envelope_output]
+}
+*/
+template<typename Box, typename Geometry>
+inline Box return_envelope(Geometry const& geometry)
+{
+ concept::check<Geometry const>();
+ concept::check<Box>();
+
+ Box mbr;
+ dispatch::envelope<Geometry>::apply(geometry, mbr);
+ return mbr;
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_ENVELOPE_HPP
diff --git a/boost/geometry/algorithms/equals.hpp b/boost/geometry/algorithms/equals.hpp
new file mode 100644
index 000000000..60175d456
--- /dev/null
+++ b/boost/geometry/algorithms/equals.hpp
@@ -0,0 +1,382 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP
+
+
+#include <cstddef>
+#include <vector>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/reverse_dispatch.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/detail/disjoint.hpp>
+#include <boost/geometry/algorithms/detail/not.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+// For trivial checks
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/algorithms/length.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+#include <boost/geometry/algorithms/detail/equals/collect_vectors.hpp>
+
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/apply_visitor.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace equals
+{
+
+
+template
+<
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct box_box
+{
+ template <typename Box1, typename Box2>
+ static inline bool apply(Box1 const& box1, Box2 const& box2)
+ {
+ if (!geometry::math::equals(get<min_corner, Dimension>(box1), get<min_corner, Dimension>(box2))
+ || !geometry::math::equals(get<max_corner, Dimension>(box1), get<max_corner, Dimension>(box2)))
+ {
+ return false;
+ }
+ return box_box<Dimension + 1, DimensionCount>::apply(box1, box2);
+ }
+};
+
+template <std::size_t DimensionCount>
+struct box_box<DimensionCount, DimensionCount>
+{
+ template <typename Box1, typename Box2>
+ static inline bool apply(Box1 const& , Box2 const& )
+ {
+ return true;
+ }
+};
+
+
+struct area_check
+{
+ template <typename Geometry1, typename Geometry2>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ {
+ return geometry::math::equals(
+ geometry::area(geometry1),
+ geometry::area(geometry2));
+ }
+};
+
+
+struct length_check
+{
+ template <typename Geometry1, typename Geometry2>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ {
+ return geometry::math::equals(
+ geometry::length(geometry1),
+ geometry::length(geometry2));
+ }
+};
+
+
+template <typename TrivialCheck>
+struct equals_by_collection
+{
+ template <typename Geometry1, typename Geometry2>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2)
+ {
+ if (! TrivialCheck::apply(geometry1, geometry2))
+ {
+ return false;
+ }
+
+ typedef typename geometry::select_most_precise
+ <
+ typename select_coordinate_type
+ <
+ Geometry1, Geometry2
+ >::type,
+ double
+ >::type calculation_type;
+
+ typedef std::vector<collected_vector<calculation_type> > v;
+ v c1, c2;
+
+ geometry::collect_vectors(c1, geometry1);
+ geometry::collect_vectors(c2, geometry2);
+
+ if (boost::size(c1) != boost::size(c2))
+ {
+ return false;
+ }
+
+ std::sort(c1.begin(), c1.end());
+ std::sort(c2.begin(), c2.end());
+
+ // Just check if these vectors are equal.
+ return std::equal(c1.begin(), c1.end(), c2.begin());
+ }
+};
+
+
+}} // namespace detail::equals
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Tag1 = typename tag<Geometry1>::type,
+ typename Tag2 = typename tag<Geometry2>::type,
+ std::size_t DimensionCount = dimension<Geometry1>::type::value,
+ bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
+>
+struct equals: not_implemented<Tag1, Tag2>
+{};
+
+
+// If reversal is needed, perform it
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1, typename Tag2,
+ std::size_t DimensionCount
+>
+struct equals<Geometry1, Geometry2, Tag1, Tag2, DimensionCount, true>
+ : equals<Geometry2, Geometry1, Tag2, Tag1, DimensionCount, false>
+{
+ static inline bool apply(Geometry1 const& g1, Geometry2 const& g2)
+ {
+ return equals
+ <
+ Geometry2, Geometry1,
+ Tag2, Tag1,
+ DimensionCount,
+ false
+ >::apply(g2, g1);
+ }
+};
+
+
+template <typename P1, typename P2, std::size_t DimensionCount, bool Reverse>
+struct equals<P1, P2, point_tag, point_tag, DimensionCount, Reverse>
+ : geometry::detail::not_
+ <
+ P1,
+ P2,
+ detail::disjoint::point_point<P1, P2, 0, DimensionCount>
+ >
+{};
+
+
+template <typename Box1, typename Box2, std::size_t DimensionCount, bool Reverse>
+struct equals<Box1, Box2, box_tag, box_tag, DimensionCount, Reverse>
+ : detail::equals::box_box<0, DimensionCount>
+{};
+
+
+template <typename Ring1, typename Ring2, bool Reverse>
+struct equals<Ring1, Ring2, ring_tag, ring_tag, 2, Reverse>
+ : detail::equals::equals_by_collection<detail::equals::area_check>
+{};
+
+
+template <typename Polygon1, typename Polygon2, bool Reverse>
+struct equals<Polygon1, Polygon2, polygon_tag, polygon_tag, 2, Reverse>
+ : detail::equals::equals_by_collection<detail::equals::area_check>
+{};
+
+
+template <typename LineString1, typename LineString2, bool Reverse>
+struct equals<LineString1, LineString2, linestring_tag, linestring_tag, 2, Reverse>
+ : detail::equals::equals_by_collection<detail::equals::length_check>
+{};
+
+
+template <typename Polygon, typename Ring, bool Reverse>
+struct equals<Polygon, Ring, polygon_tag, ring_tag, 2, Reverse>
+ : detail::equals::equals_by_collection<detail::equals::area_check>
+{};
+
+
+template <typename Ring, typename Box, bool Reverse>
+struct equals<Ring, Box, ring_tag, box_tag, 2, Reverse>
+ : detail::equals::equals_by_collection<detail::equals::area_check>
+{};
+
+
+template <typename Polygon, typename Box, bool Reverse>
+struct equals<Polygon, Box, polygon_tag, box_tag, 2, Reverse>
+ : detail::equals::equals_by_collection<detail::equals::area_check>
+{};
+
+
+template <typename Geometry1, typename Geometry2>
+struct devarianted_equals
+{
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2)
+ {
+ concept::check_concepts_and_equal_dimensions
+ <
+ Geometry1 const,
+ Geometry2 const
+ >();
+ return equals<Geometry1, Geometry2>::apply(geometry1, geometry2);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
+struct devarianted_equals<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+{
+ struct visitor: static_visitor<bool>
+ {
+ Geometry2 const& m_geometry2;
+
+ visitor(Geometry2 const& geometry2)
+ : m_geometry2(geometry2)
+ {}
+
+ template <typename Geometry1>
+ inline bool operator()(Geometry1 const& geometry1) const
+ {
+ return devarianted_equals<Geometry1, Geometry2>
+ ::apply(geometry1, m_geometry2);
+ }
+
+ };
+
+ static inline bool apply(
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
+ Geometry2 const& geometry2
+ )
+ {
+ return apply_visitor(visitor(geometry2), geometry1);
+ }
+};
+
+template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct devarianted_equals<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ struct visitor: static_visitor<bool>
+ {
+ Geometry1 const& m_geometry1;
+
+ visitor(Geometry1 const& geometry1)
+ : m_geometry1(geometry1)
+ {}
+
+ template <typename Geometry2>
+ inline bool operator()(Geometry2 const& geometry2) const
+ {
+ return devarianted_equals<Geometry1, Geometry2>
+ ::apply(m_geometry1, geometry2);
+ }
+
+ };
+
+ static inline bool apply(
+ Geometry1 const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2
+ )
+ {
+ return apply_visitor(visitor(geometry1), geometry2);
+ }
+};
+
+template <
+ BOOST_VARIANT_ENUM_PARAMS(typename T1),
+ BOOST_VARIANT_ENUM_PARAMS(typename T2)
+>
+struct devarianted_equals<
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
+>
+{
+ struct visitor: static_visitor<bool>
+ {
+ template <typename Geometry1, typename Geometry2>
+ inline bool operator()(Geometry1 const& geometry1,
+ Geometry2 const& geometry2) const
+ {
+ return devarianted_equals<Geometry1, Geometry2>
+ ::apply(geometry1, geometry2);
+ }
+
+ };
+
+ static inline bool apply(
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
+ boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2
+ )
+ {
+ return apply_visitor(visitor(), geometry1, geometry2);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief \brief_check{are spatially equal}
+\details \details_check12{equals, is spatially equal}. Spatially equal means
+ that the same point set is included. A box can therefore be spatially equal
+ to a ring or a polygon, or a linestring can be spatially equal to a
+ multi-linestring or a segment. This only works theoretically, not all
+ combinations are implemented yet.
+\ingroup equals
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\return \return_check2{are spatially equal}
+
+\qbk{[include reference/algorithms/equals.qbk]}
+
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ return dispatch::devarianted_equals<Geometry1, Geometry2>
+ ::apply(geometry1, geometry2);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP
+
diff --git a/boost/geometry/algorithms/expand.hpp b/boost/geometry/algorithms/expand.hpp
new file mode 100644
index 000000000..2e1531bf0
--- /dev/null
+++ b/boost/geometry/algorithms/expand.hpp
@@ -0,0 +1,300 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_EXPAND_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_EXPAND_HPP
+
+
+#include <cstddef>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+#include <boost/geometry/strategies/compare.hpp>
+#include <boost/geometry/policies/compare.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace expand
+{
+
+
+template
+<
+ typename StrategyLess, typename StrategyGreater,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct point_loop
+{
+ template <typename Box, typename Point>
+ static inline void apply(Box& box, Point const& source)
+ {
+ 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;
+
+ 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
+ <
+ StrategyLess, StrategyGreater,
+ Dimension + 1, DimensionCount
+ >::apply(box, source);
+ }
+};
+
+
+template
+<
+ typename StrategyLess, typename StrategyGreater,
+ std::size_t DimensionCount
+>
+struct point_loop
+ <
+ StrategyLess, StrategyGreater,
+ DimensionCount, DimensionCount
+ >
+{
+ template <typename Box, typename Point>
+ static inline void apply(Box&, Point const&) {}
+};
+
+
+template
+<
+ typename StrategyLess, typename StrategyGreater,
+ std::size_t Index,
+ std::size_t Dimension, std::size_t DimensionCount
+>
+struct indexed_loop
+{
+ template <typename Box, typename Geometry>
+ static inline void apply(Box& box, Geometry const& source)
+ {
+ 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;
+
+ 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
+ <
+ StrategyLess, StrategyGreater,
+ Index, Dimension + 1, DimensionCount
+ >::apply(box, source);
+ }
+};
+
+
+template
+<
+ typename StrategyLess, typename StrategyGreater,
+ std::size_t Index, std::size_t DimensionCount
+>
+struct indexed_loop
+ <
+ StrategyLess, StrategyGreater,
+ Index, DimensionCount, DimensionCount
+ >
+{
+ template <typename Box, typename Geometry>
+ static inline void apply(Box&, Geometry const&) {}
+};
+
+
+
+// Changes a box such that the other box is also contained by the box
+template
+<
+ typename StrategyLess, typename StrategyGreater
+>
+struct expand_indexed
+{
+ template <typename Box, typename Geometry>
+ static inline void apply(Box& box, Geometry const& geometry)
+ {
+ indexed_loop
+ <
+ StrategyLess, StrategyGreater,
+ 0, 0, dimension<Geometry>::type::value
+ >::apply(box, geometry);
+
+ indexed_loop
+ <
+ StrategyLess, StrategyGreater,
+ 1, 0, dimension<Geometry>::type::value
+ >::apply(box, geometry);
+ }
+};
+
+}} // namespace detail::expand
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename GeometryOut, typename Geometry,
+ typename StrategyLess = strategy::compare::default_strategy,
+ typename StrategyGreater = strategy::compare::default_strategy,
+ typename TagOut = typename tag<GeometryOut>::type,
+ typename Tag = typename tag<Geometry>::type
+>
+struct expand: not_implemented<TagOut, Tag>
+{};
+
+
+// Box + point -> new box containing also point
+template
+<
+ typename BoxOut, typename Point,
+ typename StrategyLess, typename StrategyGreater
+>
+struct expand<BoxOut, Point, StrategyLess, StrategyGreater, box_tag, point_tag>
+ : detail::expand::point_loop
+ <
+ 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 expand<BoxOut, BoxIn, StrategyLess, StrategyGreater, box_tag, box_tag>
+ : detail::expand::expand_indexed<StrategyLess, StrategyGreater>
+{};
+
+template
+<
+ typename Box, typename Segment,
+ typename StrategyLess, typename StrategyGreater
+>
+struct expand<Box, Segment, StrategyLess, StrategyGreater, box_tag, segment_tag>
+ : detail::expand::expand_indexed<StrategyLess, StrategyGreater>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/***
+*!
+\brief Expands a box using the extend (envelope) of another geometry (box, point)
+\ingroup expand
+\tparam Box type of the box
+\tparam Geometry of second geometry, to be expanded with the box
+\param box box to expand another geometry with, might be changed
+\param geometry other geometry
+\param strategy_less
+\param strategy_greater
+\note Strategy is currently ignored
+ *
+template
+<
+ typename Box, typename Geometry,
+ typename StrategyLess, typename StrategyGreater
+>
+inline void expand(Box& box, Geometry const& geometry,
+ StrategyLess const& strategy_less,
+ StrategyGreater const& strategy_greater)
+{
+ concept::check_concepts_and_equal_dimensions<Box, Geometry const>();
+
+ dispatch::expand<Box, Geometry>::apply(box, geometry);
+}
+***/
+
+
+/*!
+\brief Expands a box using the bounding box (envelope) of another geometry (box, point)
+\ingroup expand
+\tparam Box type of the box
+\tparam Geometry \tparam_geometry
+\param box box to be expanded using another geometry, mutable
+\param geometry \param_geometry geometry which envelope (bounding box) will be added to the box
+
+\qbk{[include reference/algorithms/expand.qbk]}
+ */
+template <typename Box, typename Geometry>
+inline void expand(Box& box, Geometry const& geometry)
+{
+ concept::check_concepts_and_equal_dimensions<Box, Geometry const>();
+
+ dispatch::expand<Box, Geometry>::apply(box, geometry);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_EXPAND_HPP
diff --git a/boost/geometry/algorithms/for_each.hpp b/boost/geometry/algorithms/for_each.hpp
new file mode 100644
index 000000000..24d38d3d8
--- /dev/null
+++ b/boost/geometry/algorithms/for_each.hpp
@@ -0,0 +1,271 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_FOR_EACH_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_FOR_EACH_HPP
+
+
+#include <algorithm>
+
+#include <boost/range.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/geometries/segment.hpp>
+
+#include <boost/geometry/util/add_const_if_c.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace for_each
+{
+
+
+struct fe_point_per_point
+{
+ template <typename Point, typename Functor>
+ static inline void apply(Point& point, Functor& f)
+ {
+ f(point);
+ }
+};
+
+
+struct fe_point_per_segment
+{
+ template <typename Point, typename Functor>
+ static inline void apply(Point& , Functor& f)
+ {
+ // TODO: if non-const, we should extract the points from the segment
+ // and call the functor on those two points
+ }
+};
+
+
+struct fe_range_per_point
+{
+ template <typename Range, typename Functor>
+ static inline void apply(Range& range, Functor& f)
+ {
+ // The previous implementation called the std library:
+ // return (std::for_each(boost::begin(range), boost::end(range), f));
+ // But that is not accepted for capturing lambda's.
+ // It needs to do it like that to return the state of Functor f (f is passed by value in std::for_each).
+
+ // So we now loop manually.
+
+ for (typename boost::range_iterator<Range>::type it = boost::begin(range); it != boost::end(range); ++it)
+ {
+ f(*it);
+ }
+ }
+};
+
+
+struct fe_range_per_segment
+{
+ template <typename Range, typename Functor>
+ static inline void apply(Range& range, Functor& f)
+ {
+ typedef typename add_const_if_c
+ <
+ is_const<Range>::value,
+ typename point_type<Range>::type
+ >::type point_type;
+
+ BOOST_AUTO_TPL(it, boost::begin(range));
+ BOOST_AUTO_TPL(previous, it++);
+ while(it != boost::end(range))
+ {
+ model::referring_segment<point_type> s(*previous, *it);
+ f(s);
+ previous = it++;
+ }
+ }
+};
+
+
+struct fe_polygon_per_point
+{
+ template <typename Polygon, typename Functor>
+ static inline void apply(Polygon& poly, Functor& f)
+ {
+ fe_range_per_point::apply(exterior_ring(poly), f);
+
+ typename interior_return_type<Polygon>::type rings
+ = interior_rings(poly);
+ for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
+ {
+ fe_range_per_point::apply(*it, f);
+ }
+ }
+
+};
+
+
+struct fe_polygon_per_segment
+{
+ template <typename Polygon, typename Functor>
+ static inline void apply(Polygon& poly, Functor& f)
+ {
+ fe_range_per_segment::apply(exterior_ring(poly), f);
+
+ typename interior_return_type<Polygon>::type rings
+ = interior_rings(poly);
+ for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
+ {
+ fe_range_per_segment::apply(*it, f);
+ }
+ }
+
+};
+
+
+}} // namespace detail::for_each
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry,
+ typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type
+>
+struct for_each_point: not_implemented<Tag>
+{};
+
+
+template <typename Point>
+struct for_each_point<Point, point_tag>
+ : detail::for_each::fe_point_per_point
+{};
+
+
+template <typename Linestring>
+struct for_each_point<Linestring, linestring_tag>
+ : detail::for_each::fe_range_per_point
+{};
+
+
+template <typename Ring>
+struct for_each_point<Ring, ring_tag>
+ : detail::for_each::fe_range_per_point
+{};
+
+
+template <typename Polygon>
+struct for_each_point<Polygon, polygon_tag>
+ : detail::for_each::fe_polygon_per_point
+{};
+
+
+template
+<
+ typename Geometry,
+ typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type
+>
+struct for_each_segment: not_implemented<Tag>
+{};
+
+template <typename Point>
+struct for_each_segment<Point, point_tag>
+ : detail::for_each::fe_point_per_segment
+{};
+
+
+template <typename Linestring>
+struct for_each_segment<Linestring, linestring_tag>
+ : detail::for_each::fe_range_per_segment
+{};
+
+
+template <typename Ring>
+struct for_each_segment<Ring, ring_tag>
+ : detail::for_each::fe_range_per_segment
+{};
+
+
+template <typename Polygon>
+struct for_each_segment<Polygon, polygon_tag>
+ : detail::for_each::fe_polygon_per_segment
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief \brf_for_each{point}
+\details \det_for_each{point}
+\ingroup for_each
+\param geometry \param_geometry
+\param f \par_for_each_f{point}
+\tparam Geometry \tparam_geometry
+\tparam Functor \tparam_functor
+
+\qbk{[include reference/algorithms/for_each_point.qbk]}
+\qbk{[heading Example]}
+\qbk{[for_each_point] [for_each_point_output]}
+\qbk{[for_each_point_const] [for_each_point_const_output]}
+*/
+template<typename Geometry, typename Functor>
+inline Functor for_each_point(Geometry& geometry, Functor f)
+{
+ concept::check<Geometry>();
+
+ dispatch::for_each_point<Geometry>::apply(geometry, f);
+ return f;
+}
+
+
+/*!
+\brief \brf_for_each{segment}
+\details \det_for_each{segment}
+\ingroup for_each
+\param geometry \param_geometry
+\param f \par_for_each_f{segment}
+\tparam Geometry \tparam_geometry
+\tparam Functor \tparam_functor
+
+\qbk{[include reference/algorithms/for_each_segment.qbk]}
+\qbk{[heading Example]}
+\qbk{[for_each_segment_const] [for_each_segment_const_output]}
+*/
+template<typename Geometry, typename Functor>
+inline Functor for_each_segment(Geometry& geometry, Functor f)
+{
+ concept::check<Geometry>();
+
+ dispatch::for_each_segment<Geometry>::apply(geometry, f);
+ return f;
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_FOR_EACH_HPP
diff --git a/boost/geometry/algorithms/intersection.hpp b/boost/geometry/algorithms/intersection.hpp
new file mode 100644
index 000000000..3125752db
--- /dev/null
+++ b/boost/geometry/algorithms/intersection.hpp
@@ -0,0 +1,208 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_INTERSECTION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_INTERSECTION_HPP
+
+
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
+#include <boost/geometry/algorithms/intersects.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersection
+{
+
+template <std::size_t Dimension, std::size_t DimensionCount>
+struct intersection_box_box
+{
+ template
+ <
+ typename Box1, typename Box2, typename BoxOut,
+ typename Strategy
+ >
+ static inline bool apply(Box1 const& box1,
+ Box2 const& box2, BoxOut& box_out,
+ Strategy const& strategy)
+ {
+ typedef typename coordinate_type<BoxOut>::type ct;
+
+ ct min1 = get<min_corner, Dimension>(box1);
+ ct min2 = get<min_corner, Dimension>(box2);
+ ct max1 = get<max_corner, Dimension>(box1);
+ ct max2 = get<max_corner, Dimension>(box2);
+
+ if (max1 < min2 || max2 < min1)
+ {
+ return false;
+ }
+ // Set dimensions of output coordinate
+ set<min_corner, Dimension>(box_out, min1 < min2 ? min2 : min1);
+ set<max_corner, Dimension>(box_out, max1 > max2 ? max2 : max1);
+
+ return intersection_box_box<Dimension + 1, DimensionCount>
+ ::apply(box1, box2, box_out, strategy);
+ }
+};
+
+template <std::size_t DimensionCount>
+struct intersection_box_box<DimensionCount, DimensionCount>
+{
+ template
+ <
+ typename Box1, typename Box2, typename BoxOut,
+ typename Strategy
+ >
+ static inline bool apply(Box1 const&, Box2 const&, BoxOut&, Strategy const&)
+ {
+ return true;
+ }
+};
+
+
+}} // namespace detail::intersection
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// By default, all is forwarded to the intersection_insert-dispatcher
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type,
+ bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
+>
+struct intersection
+{
+ template <typename GeometryOut, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
+ {
+ typedef typename boost::range_value<GeometryOut>::type OneOut;
+
+ intersection_insert
+ <
+ Geometry1, Geometry2, OneOut,
+ overlay_intersection
+ >::apply(geometry1, geometry2, std::back_inserter(geometry_out), strategy);
+
+ return true;
+ }
+
+};
+
+
+// If reversal is needed, perform it
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1, typename Tag2
+>
+struct intersection
+<
+ Geometry1, Geometry2,
+ Tag1, Tag2,
+ true
+>
+ : intersection<Geometry2, Geometry1, Tag2, Tag1, false>
+{
+ template <typename GeometryOut, typename Strategy>
+ static inline bool apply(
+ Geometry1 const& g1,
+ Geometry2 const& g2,
+ GeometryOut& out,
+ Strategy const& strategy)
+ {
+ return intersection<
+ Geometry2, Geometry1,
+ Tag2, Tag1,
+ false
+ >::apply(g2, g1, out, strategy);
+ }
+};
+
+
+template
+<
+ typename Box1, typename Box2, bool Reverse
+>
+struct intersection
+ <
+ Box1, Box2,
+ box_tag, box_tag,
+ Reverse
+ > : public detail::intersection::intersection_box_box
+ <
+ 0, geometry::dimension<Box1>::value
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief \brief_calc2{intersection}
+\ingroup intersection
+\details \details_calc2{intersection, spatial set theoretic intersection}.
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam GeometryOut Collection of geometries (e.g. std::vector, std::deque, boost::geometry::multi*) of which
+ the value_type fulfills a \p_l_or_c concept, or it is the output geometry (e.g. for a box)
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param geometry_out The output geometry, either a multi_point, multi_polygon,
+ multi_linestring, or a box (for intersection of two boxes)
+
+\qbk{[include reference/algorithms/intersection.qbk]}
+*/
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename GeometryOut
+>
+inline bool intersection(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+
+ typedef strategy_intersection
+ <
+ typename cs_tag<Geometry1>::type,
+ Geometry1,
+ Geometry2,
+ typename geometry::point_type<Geometry1>::type
+ > strategy;
+
+
+ return dispatch::intersection<
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, geometry_out, strategy());
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_INTERSECTION_HPP
diff --git a/boost/geometry/algorithms/intersects.hpp b/boost/geometry/algorithms/intersects.hpp
new file mode 100644
index 000000000..f367f2e25
--- /dev/null
+++ b/boost/geometry/algorithms/intersects.hpp
@@ -0,0 +1,106 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_INTERSECTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_INTERSECTS_HPP
+
+
+#include <deque>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
+#include <boost/geometry/algorithms/disjoint.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+/*!
+\brief \brief_check{has 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 \tparam_geometry
+\param geometry \param_geometry
+\return \return_check{is self-intersecting}
+
+\qbk{distinguish,one geometry}
+\qbk{[def __one_parameter__]}
+\qbk{[include reference/algorithms/intersects.qbk]}
+*/
+template <typename Geometry>
+inline bool intersects(Geometry const& geometry)
+{
+ concept::check<Geometry const>();
+
+
+ typedef detail::overlay::turn_info
+ <
+ typename geometry::point_type<Geometry>::type
+ > turn_info;
+ std::deque<turn_info> turns;
+
+ typedef typename strategy_intersection
+ <
+ typename cs_tag<Geometry>::type,
+ Geometry,
+ Geometry,
+ typename geometry::point_type<Geometry>::type
+ >::segment_intersection_strategy_type segment_intersection_strategy_type;
+
+ typedef detail::overlay::get_turn_info
+ <
+ typename point_type<Geometry>::type,
+ typename point_type<Geometry>::type,
+ turn_info,
+ detail::overlay::assign_null_policy
+ > TurnPolicy;
+
+ detail::disjoint::disjoint_interrupt_policy policy;
+ detail::self_get_turn_points::get_turns
+ <
+ Geometry,
+ std::deque<turn_info>,
+ TurnPolicy,
+ detail::disjoint::disjoint_interrupt_policy
+ >::apply(geometry, turns, policy);
+ return policy.has_intersections;
+}
+
+
+/*!
+\brief \brief_check2{have at least one intersection}
+\ingroup intersects
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\return \return_check2{intersect each other}
+
+\qbk{distinguish,two geometries}
+\qbk{[include reference/algorithms/intersects.qbk]}
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool intersects(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+
+ return ! geometry::disjoint(geometry1, geometry2);
+}
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_INTERSECTS_HPP
diff --git a/boost/geometry/algorithms/length.hpp b/boost/geometry/algorithms/length.hpp
new file mode 100644
index 000000000..2051e41a9
--- /dev/null
+++ b/boost/geometry/algorithms/length.hpp
@@ -0,0 +1,275 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_LENGTH_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_LENGTH_HPP
+
+#include <iterator>
+
+#include <boost/concept_check.hpp>
+#include <boost/range.hpp>
+
+#include <boost/mpl/fold.hpp>
+#include <boost/mpl/greater.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/insert.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/set.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/transform.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/closure.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/detail/calculate_null.hpp>
+// #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
+#include <boost/geometry/views/closeable_view.hpp>
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/default_length_result.hpp>
+
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace length
+{
+
+
+template<typename Segment>
+struct segment_length
+{
+ template <typename Strategy>
+ static inline typename default_length_result<Segment>::type apply(
+ Segment const& segment, Strategy const& strategy)
+ {
+ typedef typename point_type<Segment>::type point_type;
+ point_type p1, p2;
+ geometry::detail::assign_point_from_index<0>(segment, p1);
+ geometry::detail::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, closure_selector Closure>
+struct range_length
+{
+ typedef typename default_length_result<Range>::type return_type;
+
+ template <typename Strategy>
+ static inline return_type apply(
+ Range const& range, Strategy const& strategy)
+ {
+ boost::ignore_unused_variable_warning(strategy);
+ typedef typename closeable_view<Range const, Closure>::type view_type;
+ typedef typename boost::range_iterator
+ <
+ view_type const
+ >::type iterator_type;
+
+ return_type sum = return_type();
+ view_type view(range);
+ iterator_type it = boost::begin(view), end = boost::end(view);
+ if(it != end)
+ {
+ for(iterator_type previous = it++;
+ it != end;
+ ++previous, ++it)
+ {
+ // Add point-point distance using the return type belonging
+ // to strategy
+ sum += strategy.apply(*previous, *it);
+ }
+ }
+
+ return sum;
+ }
+};
+
+
+}} // namespace detail::length
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct length : detail::calculate_null
+{
+ typedef typename default_length_result<Geometry>::type return_type;
+
+ template <typename Strategy>
+ static inline return_type apply(Geometry const& geometry, Strategy const& strategy)
+ {
+ return calculate_null::apply<return_type>(geometry, strategy);
+ }
+};
+
+
+template <typename Geometry>
+struct length<Geometry, linestring_tag>
+ : detail::length::range_length<Geometry, closed>
+{};
+
+
+// RING: length is currently 0; it might be argued that it is the "perimeter"
+
+
+template <typename Geometry>
+struct length<Geometry, segment_tag>
+ : detail::length::segment_length<Geometry>
+{};
+
+
+template <typename Geometry>
+struct devarianted_length
+{
+ typedef typename default_length_result<Geometry>::type result_type;
+
+ template <typename Strategy>
+ static inline result_type apply(Geometry const& geometry,
+ Strategy const& strategy)
+ {
+ return length<Geometry>::apply(geometry, strategy);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct devarianted_length<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ typedef typename mpl::fold<
+ typename mpl::transform<
+ typename variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types,
+ default_length_result<mpl::_>
+ >::type,
+ mpl::set0<>,
+ mpl::insert<mpl::_1, mpl::_2>
+ >::type possible_result_types;
+
+ typedef typename mpl::if_<
+ mpl::greater<
+ mpl::size<possible_result_types>,
+ mpl::int_<1>
+ >,
+ typename make_variant_over<possible_result_types>::type,
+ typename mpl::front<possible_result_types>::type
+ >::type result_type;
+
+ template <typename Strategy>
+ struct visitor
+ : static_visitor<result_type>
+ {
+ Strategy const& m_strategy;
+
+ visitor(Strategy const& strategy)
+ : m_strategy(strategy)
+ {}
+
+ template <typename Geometry>
+ inline typename devarianted_length<Geometry>::result_type
+ operator()(Geometry const& geometry) const
+ {
+ return devarianted_length<Geometry>::apply(geometry, m_strategy);
+ }
+ };
+
+ template <typename Strategy>
+ static inline result_type apply(
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
+ Strategy const& strategy
+ )
+ {
+ return apply_visitor(visitor<Strategy>(strategy), geometry);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief \brief_calc{length}
+\ingroup length
+\details \details_calc{length, length (the sum of distances between consecutive points)}. \details_default_strategy
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\return \return_calc{length}
+
+\qbk{[include reference/algorithms/length.qbk]}
+\qbk{[length] [length_output]}
+ */
+template<typename Geometry>
+inline typename dispatch::devarianted_length<Geometry>::result_type
+length(Geometry const& geometry)
+{
+ concept::check<Geometry const>();
+
+ // detail::throw_on_empty_input(geometry);
+
+ typedef typename strategy::distance::services::default_strategy
+ <
+ point_tag, typename point_type<Geometry>::type
+ >::type strategy_type;
+
+ return dispatch::devarianted_length<Geometry>::apply(geometry, strategy_type());
+}
+
+
+/*!
+\brief \brief_calc{length} \brief_strategy
+\ingroup length
+\details \details_calc{length, length (the sum of distances between consecutive points)} \brief_strategy. \details_strategy_reasons
+\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{distance}
+\param geometry \param_geometry
+\param strategy \param_strategy{distance}
+\return \return_calc{length}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/length.qbk]}
+\qbk{[length_with_strategy] [length_with_strategy_output]}
+ */
+template<typename Geometry, typename Strategy>
+inline typename dispatch::devarianted_length<Geometry>::result_type
+length(Geometry const& geometry, Strategy const& strategy)
+{
+ concept::check<Geometry const>();
+
+ // detail::throw_on_empty_input(geometry);
+
+ return dispatch::devarianted_length<Geometry>::apply(geometry, strategy);
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_LENGTH_HPP
diff --git a/boost/geometry/algorithms/make.hpp b/boost/geometry/algorithms/make.hpp
new file mode 100644
index 000000000..d0e309249
--- /dev/null
+++ b/boost/geometry/algorithms/make.hpp
@@ -0,0 +1,200 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_MAKE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_MAKE_HPP
+
+#include <boost/geometry/algorithms/assign.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace make
+{
+
+/*!
+\brief Construct a geometry
+\ingroup make
+\tparam Geometry \tparam_geometry
+\tparam Range \tparam_range_point
+\param range \param_range_point
+\return The constructed geometry, here: a linestring or a ring
+
+\qbk{distinguish, with a range}
+\qbk{
+[heading Example]
+[make_with_range] [make_with_range_output]
+
+[heading See also]
+\* [link geometry.reference.algorithms.assign.assign_points assign]
+}
+ */
+template <typename Geometry, typename Range>
+inline Geometry make_points(Range const& range)
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ geometry::append(geometry, range);
+ return geometry;
+}
+
+}} // namespace detail::make
+#endif // DOXYGEN_NO_DETAIL
+
+/*!
+\brief Construct a geometry
+\ingroup make
+\details
+\note It does not work with array-point types, like int[2]
+\tparam Geometry \tparam_geometry
+\tparam Type \tparam_numeric to specify the coordinates
+\param c1 \param_x
+\param c2 \param_y
+\return The constructed geometry, here: a 2D point
+
+\qbk{distinguish, 2 coordinate values}
+\qbk{
+[heading Example]
+[make_2d_point] [make_2d_point_output]
+
+[heading See also]
+\* [link geometry.reference.algorithms.assign.assign_values_3_2_coordinate_values assign]
+}
+*/
+template <typename Geometry, typename Type>
+inline Geometry make(Type const& c1, Type const& c2)
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ geometry::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2);
+ return geometry;
+}
+
+/*!
+\brief Construct a geometry
+\ingroup make
+\tparam Geometry \tparam_geometry
+\tparam Type \tparam_numeric to specify the coordinates
+\param c1 \param_x
+\param c2 \param_y
+\param c3 \param_z
+\return The constructed geometry, here: a 3D point
+
+\qbk{distinguish, 3 coordinate values}
+\qbk{
+[heading Example]
+[make_3d_point] [make_3d_point_output]
+
+[heading See also]
+\* [link geometry.reference.algorithms.assign.assign_values_4_3_coordinate_values assign]
+}
+ */
+template <typename Geometry, typename Type>
+inline Geometry make(Type const& c1, Type const& c2, Type const& c3)
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ geometry::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2, c3);
+ return geometry;
+}
+
+template <typename Geometry, typename Type>
+inline Geometry make(Type const& c1, Type const& c2, Type const& c3, Type const& c4)
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ dispatch::assign
+ <
+ typename tag<Geometry>::type,
+ Geometry,
+ geometry::dimension<Geometry>::type::value
+ >::apply(geometry, c1, c2, c3, c4);
+ return geometry;
+}
+
+
+
+
+
+/*!
+\brief Construct a box with inverse infinite coordinates
+\ingroup make
+\details The make_inverse function initializes a 2D or 3D box with large coordinates, the
+ min corner is very large, the max corner is very small. This is useful e.g. in combination
+ with the expand function, to determine the bounding box of a series of geometries.
+\tparam Geometry \tparam_geometry
+\return The constructed geometry, here: a box
+
+\qbk{
+[heading Example]
+[make_inverse] [make_inverse_output]
+
+[heading See also]
+\* [link geometry.reference.algorithms.assign.assign_inverse assign_inverse]
+}
+ */
+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 Construct a geometry with its coordinates initialized to zero
+\ingroup make
+\details The make_zero function initializes a 2D or 3D point or box with coordinates of zero
+\tparam Geometry \tparam_geometry
+\return The constructed and zero-initialized geometry
+ */
+template <typename Geometry>
+inline Geometry make_zero()
+{
+ concept::check<Geometry>();
+
+ Geometry geometry;
+ dispatch::assign_zero
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::apply(geometry);
+ return geometry;
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_MAKE_HPP
diff --git a/boost/geometry/algorithms/not_implemented.hpp b/boost/geometry/algorithms/not_implemented.hpp
new file mode 100644
index 000000000..008f111cc
--- /dev/null
+++ b/boost/geometry/algorithms/not_implemented.hpp
@@ -0,0 +1,117 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_NOT_IMPLEMENTED_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_NOT_IMPLEMENTED_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace info
+{
+ struct UNRECOGNIZED_GEOMETRY_TYPE {};
+ struct POINT {};
+ struct LINESTRING {};
+ struct POLYGON {};
+ struct RING {};
+ struct BOX {};
+ struct SEGMENT {};
+ struct MULTI_POINT {};
+ struct MULTI_LINESTRING {};
+ struct MULTI_POLYGON {};
+ struct GEOMETRY_COLLECTION {};
+ template <size_t D> struct DIMENSION {};
+}
+
+
+namespace nyi
+{
+
+
+struct not_implemented_tag {};
+
+template
+<
+ typename Term1,
+ typename Term2,
+ typename Term3
+>
+struct not_implemented_error
+{
+
+#ifndef BOOST_GEOMETRY_IMPLEMENTATION_STATUS_BUILD
+# define BOOST_GEOMETRY_IMPLEMENTATION_STATUS_BUILD false
+#endif
+
+ BOOST_MPL_ASSERT_MSG
+ (
+ BOOST_GEOMETRY_IMPLEMENTATION_STATUS_BUILD,
+ THIS_OPERATION_IS_NOT_OR_NOT_YET_IMPLEMENTED,
+ (
+ types<Term1, Term2, Term3>
+ )
+ );
+};
+
+template <typename Tag>
+struct tag_to_term
+{
+ typedef Tag type;
+};
+
+template <> struct tag_to_term<geometry_not_recognized_tag> { typedef info::UNRECOGNIZED_GEOMETRY_TYPE type; };
+template <> struct tag_to_term<point_tag> { typedef info::POINT type; };
+template <> struct tag_to_term<linestring_tag> { typedef info::LINESTRING type; };
+template <> struct tag_to_term<polygon_tag> { typedef info::POLYGON type; };
+template <> struct tag_to_term<ring_tag> { typedef info::RING type; };
+template <> struct tag_to_term<box_tag> { typedef info::BOX type; };
+template <> struct tag_to_term<segment_tag> { typedef info::SEGMENT type; };
+template <> struct tag_to_term<multi_point_tag> { typedef info::MULTI_POINT type; };
+template <> struct tag_to_term<multi_linestring_tag> { typedef info::MULTI_LINESTRING type; };
+template <> struct tag_to_term<multi_polygon_tag> { typedef info::MULTI_POLYGON type; };
+template <> struct tag_to_term<geometry_collection_tag> { typedef info::GEOMETRY_COLLECTION type; };
+template <int D> struct tag_to_term<mpl::int_<D> > { typedef info::DIMENSION<D> type; };
+
+
+}
+
+
+template
+<
+ typename Term1 = void,
+ typename Term2 = void,
+ typename Term3 = void
+>
+struct not_implemented
+ : nyi::not_implemented_tag,
+ nyi::not_implemented_error
+ <
+ typename mpl::identity<typename nyi::tag_to_term<Term1>::type>::type,
+ typename mpl::identity<typename nyi::tag_to_term<Term2>::type>::type,
+ typename mpl::identity<typename nyi::tag_to_term<Term3>::type>::type
+ >
+{};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_NOT_IMPLEMENTED_HPP
diff --git a/boost/geometry/algorithms/num_geometries.hpp b/boost/geometry/algorithms/num_geometries.hpp
new file mode 100644
index 000000000..58afe4b97
--- /dev/null
+++ b/boost/geometry/algorithms/num_geometries.hpp
@@ -0,0 +1,89 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_NUM_GEOMETRIES_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_NUM_GEOMETRIES_HPP
+
+#include <cstddef>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Geometry,
+ typename Tag = typename tag_cast
+ <
+ typename tag<Geometry>::type,
+ single_tag,
+ multi_tag
+ >::type
+>
+struct num_geometries: not_implemented<Tag>
+{};
+
+
+template <typename Geometry>
+struct num_geometries<Geometry, single_tag>
+{
+ static inline std::size_t apply(Geometry const&)
+ {
+ return 1;
+ }
+};
+
+
+
+} // namespace dispatch
+#endif
+
+
+/*!
+\brief \brief_calc{number of geometries}
+\ingroup num_geometries
+\details \details_calc{num_geometries, number of geometries}.
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\return \return_calc{number of geometries}
+
+\qbk{[include reference/algorithms/num_geometries.qbk]}
+*/
+template <typename Geometry>
+inline std::size_t num_geometries(Geometry const& geometry)
+{
+ concept::check<Geometry const>();
+
+ return dispatch::num_geometries<Geometry>::apply(geometry);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_NUM_GEOMETRIES_HPP
diff --git a/boost/geometry/algorithms/num_interior_rings.hpp b/boost/geometry/algorithms/num_interior_rings.hpp
new file mode 100644
index 000000000..e815f5981
--- /dev/null
+++ b/boost/geometry/algorithms/num_interior_rings.hpp
@@ -0,0 +1,84 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_NUM_INTERIOR_RINGS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_NUM_INTERIOR_RINGS_HPP
+
+#include <cstddef>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/core/interior_rings.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct num_interior_rings
+{
+ static inline std::size_t apply(Geometry const& )
+ {
+ return 0;
+ }
+};
+
+
+
+template <typename Polygon>
+struct num_interior_rings<Polygon, polygon_tag>
+{
+ static inline std::size_t apply(Polygon const& polygon)
+ {
+ return boost::size(geometry::interior_rings(polygon));
+ }
+
+};
+
+
+} // namespace dispatch
+#endif
+
+
+/*!
+\brief \brief_calc{number of interior rings}
+\ingroup num_interior_rings
+\details \details_calc{num_interior_rings, number of interior rings}.
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\return \return_calc{number of interior rings}
+
+\qbk{[include reference/algorithms/num_interior_rings.qbk]}
+
+\note Defined by OGC as "numInteriorRing". To be consistent with "numPoints"
+ letter "s" is appended
+*/
+template <typename Geometry>
+inline std::size_t num_interior_rings(Geometry const& geometry)
+{
+ return dispatch::num_interior_rings<Geometry>::apply(geometry);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_NUM_INTERIOR_RINGS_HPP
diff --git a/boost/geometry/algorithms/num_points.hpp b/boost/geometry/algorithms/num_points.hpp
new file mode 100644
index 000000000..923ae8297
--- /dev/null
+++ b/boost/geometry/algorithms/num_points.hpp
@@ -0,0 +1,212 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_NUM_POINTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_NUM_POINTS_HPP
+
+#include <cstddef>
+
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+#include <boost/geometry/algorithms/disjoint.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+// Silence warning C4127: conditional expression is constant
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4127)
+#endif
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace num_points
+{
+
+
+struct range_count
+{
+ template <typename Range>
+ static inline std::size_t apply(Range const& range, bool add_for_open)
+ {
+ std::size_t n = boost::size(range);
+ if (add_for_open && n > 0)
+ {
+ if (geometry::closure<Range>::value == open)
+ {
+ if (geometry::disjoint(*boost::begin(range), *(boost::begin(range) + n - 1)))
+ {
+ return n + 1;
+ }
+ }
+ }
+ return n;
+ }
+};
+
+template <std::size_t D>
+struct other_count
+{
+ template <typename Geometry>
+ static inline std::size_t apply(Geometry const&, bool)
+ {
+ return D;
+ }
+};
+
+struct polygon_count: private range_count
+{
+ template <typename Polygon>
+ static inline std::size_t apply(Polygon const& poly, bool add_for_open)
+ {
+ typedef typename geometry::ring_type<Polygon>::type ring_type;
+
+ std::size_t n = range_count::apply(
+ exterior_ring(poly), add_for_open);
+
+ typename interior_return_type<Polygon const>::type rings
+ = interior_rings(poly);
+ for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
+ {
+ n += range_count::apply(*it, add_for_open);
+ }
+
+ return n;
+ }
+};
+
+}} // namespace detail::num_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry,
+ typename Tag = typename tag_cast<typename tag<Geometry>::type, multi_tag>::type
+>
+struct num_points: not_implemented<Tag>
+{};
+
+template <typename Geometry>
+struct num_points<Geometry, point_tag>
+ : detail::num_points::other_count<1>
+{};
+
+template <typename Geometry>
+struct num_points<Geometry, box_tag>
+ : detail::num_points::other_count<4>
+{};
+
+template <typename Geometry>
+struct num_points<Geometry, segment_tag>
+ : detail::num_points::other_count<2>
+{};
+
+template <typename Geometry>
+struct num_points<Geometry, linestring_tag>
+ : detail::num_points::range_count
+{};
+
+template <typename Geometry>
+struct num_points<Geometry, ring_tag>
+ : detail::num_points::range_count
+{};
+
+template <typename Geometry>
+struct num_points<Geometry, polygon_tag>
+ : detail::num_points::polygon_count
+{};
+
+template <typename Geometry>
+struct devarianted_num_points
+{
+ static inline std::size_t apply(Geometry const& geometry,
+ bool add_for_open)
+ {
+ return num_points<Geometry>::apply(geometry, add_for_open);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct devarianted_num_points<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ struct visitor: boost::static_visitor<std::size_t>
+ {
+ bool m_add_for_open;
+
+ visitor(bool add_for_open): m_add_for_open(add_for_open) {}
+
+ template <typename Geometry>
+ typename std::size_t operator()(Geometry const& geometry) const
+ {
+ return dispatch::num_points<Geometry>::apply(geometry, m_add_for_open);
+ }
+ };
+
+ static inline std::size_t
+ apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
+ bool add_for_open)
+ {
+ return boost::apply_visitor(visitor(add_for_open), geometry);
+ }
+};
+
+
+} // namespace dispatch
+#endif
+
+
+/*!
+\brief \brief_calc{number of points}
+\ingroup num_points
+\details \details_calc{num_points, number of points}.
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\param add_for_open add one for open geometries (i.e. polygon types which are not closed)
+\return \return_calc{number of points}
+
+\qbk{[include reference/algorithms/num_points.qbk]}
+*/
+template <typename Geometry>
+inline std::size_t num_points(Geometry const& geometry, bool add_for_open = false)
+{
+ concept::check<Geometry const>();
+
+ return dispatch::devarianted_num_points<Geometry>::apply(geometry, add_for_open);
+}
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_NUM_POINTS_HPP
diff --git a/boost/geometry/algorithms/overlaps.hpp b/boost/geometry/algorithms/overlaps.hpp
new file mode 100644
index 000000000..d417a4b1f
--- /dev/null
+++ b/boost/geometry/algorithms/overlaps.hpp
@@ -0,0 +1,184 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_OVERLAPS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_OVERLAPS_HPP
+
+
+#include <cstddef>
+
+#include <boost/geometry/core/access.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlaps
+{
+
+template
+<
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct box_box_loop
+{
+ template <typename Box1, typename Box2>
+ 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
+ <
+ Dimension + 1,
+ DimensionCount
+ >::apply(b1, b2, overlaps, one_in_two, two_in_one);
+ }
+};
+
+template
+<
+ std::size_t DimensionCount
+>
+struct box_box_loop<DimensionCount, DimensionCount>
+{
+ template <typename Box1, typename Box2>
+ static inline void apply(Box1 const& , Box2 const&, bool&, bool&, bool&)
+ {
+ }
+};
+
+struct box_box
+{
+ template <typename Box1, typename Box2>
+ static inline bool apply(Box1 const& b1, Box2 const& b2)
+ {
+ bool overlaps = true;
+ bool within1 = true;
+ bool within2 = true;
+ box_box_loop
+ <
+ 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
+
+//struct not_implemented_for_this_geometry_type : public boost::false_type {};
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Tag1 = typename tag<Geometry1>::type,
+ typename Tag2 = typename tag<Geometry2>::type
+>
+struct overlaps: not_implemented<Tag1, Tag2>
+{};
+
+
+template <typename Box1, typename Box2>
+struct overlaps<Box1, Box2, box_tag, box_tag>
+ : detail::overlaps::box_box
+{};
+
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief \brief_check2{overlap}
+\ingroup overlaps
+\return \return_check2{overlap}
+
+\qbk{[include reference/algorithms/overlaps.qbk]}
+*/
+template <typename Geometry1, typename Geometry2>
+inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+
+ return dispatch::overlaps
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_OVERLAPS_HPP
diff --git a/boost/geometry/algorithms/perimeter.hpp b/boost/geometry/algorithms/perimeter.hpp
new file mode 100644
index 000000000..b70517e3e
--- /dev/null
+++ b/boost/geometry/algorithms/perimeter.hpp
@@ -0,0 +1,137 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_PERIMETER_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_PERIMETER_HPP
+
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/strategies/default_length_result.hpp>
+#include <boost/geometry/algorithms/length.hpp>
+#include <boost/geometry/algorithms/detail/calculate_null.hpp>
+#include <boost/geometry/algorithms/detail/calculate_sum.hpp>
+// #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// Default perimeter is 0.0, specializations implement calculated values
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct perimeter : detail::calculate_null
+{
+ typedef typename default_length_result<Geometry>::type return_type;
+
+ template <typename Strategy>
+ static inline return_type apply(Geometry const& geometry, Strategy const& strategy)
+ {
+ return calculate_null::apply<return_type>(geometry, strategy);
+ }
+};
+
+template <typename Geometry>
+struct perimeter<Geometry, ring_tag>
+ : detail::length::range_length
+ <
+ Geometry,
+ closure<Geometry>::value
+ >
+{};
+
+template <typename Polygon>
+struct perimeter<Polygon, polygon_tag> : detail::calculate_polygon_sum
+{
+ typedef typename default_length_result<Polygon>::type return_type;
+ typedef detail::length::range_length
+ <
+ typename ring_type<Polygon>::type,
+ closure<Polygon>::value
+ > policy;
+
+ template <typename Strategy>
+ static inline return_type apply(Polygon const& polygon, Strategy const& strategy)
+ {
+ return calculate_polygon_sum::apply<return_type, policy>(polygon, strategy);
+ }
+};
+
+
+// box,n-sphere: to be implemented
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief \brief_calc{perimeter}
+\ingroup perimeter
+\details The function perimeter returns the perimeter of a geometry,
+ using the default distance-calculation-strategy
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\return \return_calc{perimeter}
+
+\qbk{[include reference/algorithms/perimeter.qbk]}
+ */
+template<typename Geometry>
+inline typename default_length_result<Geometry>::type perimeter(
+ Geometry const& geometry)
+{
+ concept::check<Geometry const>();
+
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename strategy::distance::services::default_strategy
+ <
+ point_tag, point_type
+ >::type strategy_type;
+
+ // detail::throw_on_empty_input(geometry);
+
+ return dispatch::perimeter<Geometry>::apply(geometry, strategy_type());
+}
+
+/*!
+\brief \brief_calc{perimeter} \brief_strategy
+\ingroup perimeter
+\details The function perimeter returns the perimeter of a geometry,
+ using specified strategy
+\tparam Geometry \tparam_geometry
+\tparam Strategy \tparam_strategy{distance}
+\param geometry \param_geometry
+\param strategy strategy to be used for distance calculations.
+\return \return_calc{perimeter}
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/perimeter.qbk]}
+ */
+template<typename Geometry, typename Strategy>
+inline typename default_length_result<Geometry>::type perimeter(
+ Geometry const& geometry, Strategy const& strategy)
+{
+ concept::check<Geometry const>();
+
+ // detail::throw_on_empty_input(geometry);
+
+ return dispatch::perimeter<Geometry>::apply(geometry, strategy);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_PERIMETER_HPP
+
diff --git a/boost/geometry/algorithms/reverse.hpp b/boost/geometry/algorithms/reverse.hpp
new file mode 100644
index 000000000..1e1168a5a
--- /dev/null
+++ b/boost/geometry/algorithms/reverse.hpp
@@ -0,0 +1,125 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_REVERSE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_REVERSE_HPP
+
+#include <algorithm>
+
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace reverse
+{
+
+
+struct range_reverse
+{
+ template <typename Range>
+ static inline void apply(Range& range)
+ {
+ std::reverse(boost::begin(range), boost::end(range));
+ }
+};
+
+
+struct polygon_reverse: private range_reverse
+{
+ template <typename Polygon>
+ static inline void apply(Polygon& polygon)
+ {
+ typedef typename geometry::ring_type<Polygon>::type ring_type;
+
+ range_reverse::apply(exterior_ring(polygon));
+
+ typename interior_return_type<Polygon>::type rings
+ = interior_rings(polygon);
+ for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
+ {
+ range_reverse::apply(*it);
+ }
+ }
+};
+
+
+}} // namespace detail::reverse
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct reverse
+{
+ static inline void apply(Geometry&)
+ {}
+};
+
+
+template <typename Ring>
+struct reverse<Ring, ring_tag>
+ : detail::reverse::range_reverse
+{};
+
+
+template <typename LineString>
+struct reverse<LineString, linestring_tag>
+ : detail::reverse::range_reverse
+{};
+
+
+template <typename Polygon>
+struct reverse<Polygon, polygon_tag>
+ : detail::reverse::polygon_reverse
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+/*!
+\brief Reverses the points within a geometry
+\details Generic function to reverse a geometry. It resembles the std::reverse
+ functionality, but it takes the geometry type into account. Only for a ring
+ or for a linestring it is the same as the std::reverse.
+\ingroup reverse
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry which will be reversed
+
+\qbk{[include reference/algorithms/reverse.qbk]}
+*/
+template <typename Geometry>
+inline void reverse(Geometry& geometry)
+{
+ concept::check<Geometry>();
+
+ dispatch::reverse<Geometry>::apply(geometry);
+}
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_REVERSE_HPP
diff --git a/boost/geometry/algorithms/simplify.hpp b/boost/geometry/algorithms/simplify.hpp
new file mode 100644
index 000000000..7e3aca401
--- /dev/null
+++ b/boost/geometry/algorithms/simplify.hpp
@@ -0,0 +1,371 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_SIMPLIFY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_SIMPLIFY_HPP
+
+
+#include <cstddef>
+
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/mutable_range.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp>
+#include <boost/geometry/strategies/concepts/simplify_concept.hpp>
+
+#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/algorithms/num_interior_rings.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace simplify
+{
+
+struct simplify_range_insert
+{
+ template<typename Range, typename Strategy, typename OutputIterator, typename Distance>
+ static inline void apply(Range const& range, OutputIterator out,
+ Distance const& 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);
+ }
+ }
+};
+
+
+struct simplify_copy
+{
+ template <typename Range, typename Strategy, typename Distance>
+ static inline void apply(Range const& range, Range& out,
+ Distance const& , Strategy const& )
+ {
+ std::copy
+ (
+ boost::begin(range), boost::end(range), std::back_inserter(out)
+ );
+ }
+};
+
+
+template<std::size_t Minimum>
+struct simplify_range
+{
+ template <typename Range, typename Strategy, typename Distance>
+ static inline void apply(Range const& range, Range& out,
+ Distance const& 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 3 (open) or 4 (closed) points (=correct),
+ the output < 3 or 4(=wrong)
+ */
+
+ if (boost::size(range) <= int(Minimum) || max_distance < 0.0)
+ {
+ simplify_copy::apply(range, out, max_distance, strategy);
+ }
+ else
+ {
+ simplify_range_insert::apply
+ (
+ range, std::back_inserter(out), max_distance, strategy
+ );
+ }
+ }
+};
+
+struct simplify_polygon
+{
+ template <typename Polygon, typename Strategy, typename Distance>
+ static inline void apply(Polygon const& poly_in, Polygon& poly_out,
+ Distance const& max_distance, Strategy const& strategy)
+ {
+ typedef typename ring_type<Polygon>::type ring_type;
+
+ int const Minimum = core_detail::closure::minimum_ring_size
+ <
+ geometry::closure<Polygon>::value
+ >::value;
+
+ // 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<Minimum>::apply(exterior_ring(poly_in),
+ exterior_ring(poly_out),
+ max_distance, strategy);
+
+ traits::resize
+ <
+ typename boost::remove_reference
+ <
+ typename traits::interior_mutable_type<Polygon>::type
+ >::type
+ >::apply(interior_rings(poly_out), num_interior_rings(poly_in));
+
+ typename interior_return_type<Polygon const>::type rings_in
+ = interior_rings(poly_in);
+ typename interior_return_type<Polygon>::type rings_out
+ = interior_rings(poly_out);
+ BOOST_AUTO_TPL(it_out, boost::begin(rings_out));
+ for (BOOST_AUTO_TPL(it_in, boost::begin(rings_in));
+ it_in != boost::end(rings_in);
+ ++it_in, ++it_out)
+ {
+ simplify_range<Minimum>::apply(*it_in, *it_out, max_distance, strategy);
+ }
+ }
+};
+
+
+}} // namespace detail::simplify
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry,
+ typename Tag = typename tag<Geometry>::type
+>
+struct simplify: not_implemented<Tag>
+{};
+
+template <typename Point>
+struct simplify<Point, point_tag>
+{
+ template <typename Distance, typename Strategy>
+ static inline void apply(Point const& point, Point& out,
+ Distance const& , Strategy const& )
+ {
+ geometry::convert(point, out);
+ }
+};
+
+
+template <typename Linestring>
+struct simplify<Linestring, linestring_tag>
+ : detail::simplify::simplify_range<2>
+{};
+
+template <typename Ring>
+struct simplify<Ring, ring_tag>
+ : detail::simplify::simplify_range
+ <
+ core_detail::closure::minimum_ring_size
+ <
+ geometry::closure<Ring>::value
+ >::value
+ >
+{};
+
+template <typename Polygon>
+struct simplify<Polygon, polygon_tag>
+ : detail::simplify::simplify_polygon
+{};
+
+
+template
+<
+ typename Geometry,
+ typename Tag = typename tag<Geometry>::type
+>
+struct simplify_insert: not_implemented<Tag>
+{};
+
+
+template <typename Linestring>
+struct simplify_insert<Linestring, linestring_tag>
+ : detail::simplify::simplify_range_insert
+{};
+
+template <typename Ring>
+struct simplify_insert<Ring, ring_tag>
+ : detail::simplify::simplify_range_insert
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Simplify a geometry using a specified strategy
+\ingroup simplify
+\tparam Geometry \tparam_geometry
+\tparam Distance A numerical distance measure
+\tparam Strategy A type fulfilling a SimplifyStrategy concept
+\param strategy A strategy to calculate simplification
+\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
+
+\image html svg_simplify_country.png "The image below presents the simplified country"
+\qbk{distinguish,with strategy}
+*/
+template<typename Geometry, typename Distance, typename Strategy>
+inline void simplify(Geometry const& geometry, Geometry& out,
+ Distance const& max_distance, Strategy const& strategy)
+{
+ concept::check<Geometry>();
+
+ BOOST_CONCEPT_ASSERT( (geometry::concept::SimplifyStrategy<Strategy>) );
+
+ geometry::clear(out);
+
+ dispatch::simplify<Geometry>::apply(geometry, out, max_distance, strategy);
+}
+
+
+
+
+/*!
+\brief Simplify a geometry
+\ingroup simplify
+\tparam Geometry \tparam_geometry
+\tparam Distance \tparam_numeric
+\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
+
+\qbk{[include reference/algorithms/simplify.qbk]}
+ */
+template<typename Geometry, typename Distance>
+inline void simplify(Geometry const& geometry, Geometry& out,
+ Distance const& max_distance)
+{
+ concept::check<Geometry>();
+
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename strategy::distance::services::default_strategy
+ <
+ segment_tag, 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());
+}
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace simplify
+{
+
+
+/*!
+\brief Simplify a geometry, using an output iterator
+ and a specified strategy
+\ingroup simplify
+\tparam Geometry \tparam_geometry
+\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
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/simplify.qbk]}
+*/
+template<typename Geometry, typename OutputIterator, typename Distance, typename Strategy>
+inline void simplify_insert(Geometry const& geometry, OutputIterator out,
+ Distance const& max_distance, Strategy const& strategy)
+{
+ concept::check<Geometry const>();
+ BOOST_CONCEPT_ASSERT( (geometry::concept::SimplifyStrategy<Strategy>) );
+
+ dispatch::simplify_insert<Geometry>::apply(geometry, out, max_distance, strategy);
+}
+
+/*!
+\brief Simplify a geometry, using an output iterator
+\ingroup simplify
+\tparam Geometry \tparam_geometry
+\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
+
+\qbk{[include reference/algorithms/simplify_insert.qbk]}
+ */
+template<typename Geometry, typename OutputIterator, typename Distance>
+inline void simplify_insert(Geometry const& geometry, OutputIterator out,
+ Distance const& max_distance)
+{
+ typedef typename point_type<Geometry>::type point_type;
+
+ // Concept: output point type = point type of input geometry
+ concept::check<Geometry const>();
+ concept::check<point_type>();
+
+ typedef typename strategy::distance::services::default_strategy
+ <
+ segment_tag, point_type
+ >::type ds_strategy_type;
+
+ typedef strategy::simplify::douglas_peucker
+ <
+ point_type, ds_strategy_type
+ > strategy_type;
+
+ dispatch::simplify_insert<Geometry>::apply(geometry, out, max_distance, strategy_type());
+}
+
+}} // namespace detail::simplify
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_SIMPLIFY_HPP
diff --git a/boost/geometry/algorithms/sym_difference.hpp b/boost/geometry/algorithms/sym_difference.hpp
new file mode 100644
index 000000000..28affc43c
--- /dev/null
+++ b/boost/geometry/algorithms/sym_difference.hpp
@@ -0,0 +1,162 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP
+
+#include <algorithm>
+
+
+#include <boost/geometry/algorithms/intersection.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace sym_difference
+{
+
+
+
+/*!
+\brief \brief_calc2{symmetric difference} \brief_strategy
+\ingroup sym_difference
+\details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}
+ \brief_strategy. \details_insert{sym_difference}
+\tparam GeometryOut output geometry type, must be specified
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Strategy \tparam_strategy_overlay
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param out \param_out{difference}
+\param strategy \param_strategy{difference}
+\return \return_out
+
+\qbk{distinguish,with strategy}
+*/
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename OutputIterator,
+ typename Strategy
+>
+inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
+ Geometry2 const& geometry2, OutputIterator out,
+ Strategy const& strategy)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+ concept::check<GeometryOut>();
+
+ out = geometry::dispatch::intersection_insert
+ <
+ Geometry1, Geometry2,
+ GeometryOut,
+ overlay_difference,
+ geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
+ geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value, true>::value
+ >::apply(geometry1, geometry2, out, strategy);
+ out = geometry::dispatch::intersection_insert
+ <
+ Geometry2, Geometry1,
+ GeometryOut,
+ overlay_difference,
+ geometry::detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
+ geometry::detail::overlay::do_reverse<geometry::point_order<Geometry1>::value, true>::value,
+ geometry::detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value
+ >::apply(geometry2, geometry1, out, strategy);
+ return out;
+}
+
+
+/*!
+\brief \brief_calc2{symmetric difference}
+\ingroup sym_difference
+\details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}
+ \details_insert{sym_difference}
+\tparam GeometryOut output geometry type, must be specified
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param out \param_out{difference}
+\return \return_out
+
+*/
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename OutputIterator
+>
+inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
+ Geometry2 const& geometry2, OutputIterator out)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+ concept::check<GeometryOut>();
+
+ typedef strategy_intersection
+ <
+ typename cs_tag<GeometryOut>::type,
+ Geometry1,
+ Geometry2,
+ typename geometry::point_type<GeometryOut>::type
+ > strategy_type;
+
+ return sym_difference_insert<GeometryOut>(geometry1, geometry2, out, strategy_type());
+}
+
+}} // namespace detail::sym_difference
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+\brief \brief_calc2{symmetric difference}
+\ingroup sym_difference
+\details \details_calc2{symmetric difference, spatial set theoretic symmetric difference (XOR)}.
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Collection output collection, either a multi-geometry,
+ or a std::vector<Geometry> / std::deque<Geometry> etc
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param output_collection the output collection
+
+\qbk{[include reference/algorithms/sym_difference.qbk]}
+*/
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Collection
+>
+inline void sym_difference(Geometry1 const& geometry1,
+ Geometry2 const& geometry2, Collection& output_collection)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+
+ typedef typename boost::range_value<Collection>::type geometry_out;
+ concept::check<geometry_out>();
+
+ detail::sym_difference::sym_difference_insert<geometry_out>(
+ geometry1, geometry2,
+ std::back_inserter(output_collection));
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP
diff --git a/boost/geometry/algorithms/touches.hpp b/boost/geometry/algorithms/touches.hpp
new file mode 100644
index 000000000..7d424af42
--- /dev/null
+++ b/boost/geometry/algorithms/touches.hpp
@@ -0,0 +1,181 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_TOUCHES_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_TOUCHES_HPP
+
+
+#include <deque>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
+#include <boost/geometry/algorithms/disjoint.hpp>
+#include <boost/geometry/algorithms/intersects.hpp>
+#include <boost/geometry/algorithms/num_geometries.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace detail { namespace touches
+{
+
+template <typename Turn>
+inline bool ok_for_touch(Turn const& turn)
+{
+ return turn.both(detail::overlay::operation_union)
+ || turn.both(detail::overlay::operation_blocked)
+ || turn.combination(detail::overlay::operation_union, detail::overlay::operation_blocked)
+ ;
+}
+
+template <typename Turns>
+inline bool has_only_turns(Turns const& turns)
+{
+ bool has_touch = false;
+ typedef typename boost::range_iterator<Turns const>::type iterator_type;
+ for (iterator_type it = boost::begin(turns); it != boost::end(turns); ++it)
+ {
+ if (it->has(detail::overlay::operation_intersection))
+ {
+ return false;
+ }
+
+ switch(it->method)
+ {
+ case detail::overlay::method_crosses:
+ return false;
+ case detail::overlay::method_equal:
+ // Segment spatially equal means: at the right side
+ // the polygon internally overlaps. So return false.
+ return false;
+ case detail::overlay::method_touch:
+ case detail::overlay::method_touch_interior:
+ case detail::overlay::method_collinear:
+ if (ok_for_touch(*it))
+ {
+ has_touch = true;
+ }
+ else
+ {
+ return false;
+ }
+ break;
+ case detail::overlay::method_none :
+ case detail::overlay::method_disjoint :
+ case detail::overlay::method_error :
+ break;
+ }
+ }
+ return has_touch;
+}
+
+}}
+
+/*!
+\brief \brief_check{has at least one touching point (self-tangency)}
+\note This function can be called for one geometry (self-tangency) and
+ also for two geometries (touch)
+\ingroup touches
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\return \return_check{is self-touching}
+
+\qbk{distinguish,one geometry}
+\qbk{[def __one_parameter__]}
+\qbk{[include reference/algorithms/touches.qbk]}
+*/
+template <typename Geometry>
+inline bool touches(Geometry const& geometry)
+{
+ concept::check<Geometry const>();
+
+ typedef detail::overlay::turn_info
+ <
+ typename geometry::point_type<Geometry>::type
+ > turn_info;
+
+ typedef detail::overlay::get_turn_info
+ <
+ typename point_type<Geometry>::type,
+ typename point_type<Geometry>::type,
+ turn_info,
+ detail::overlay::assign_null_policy
+ > policy_type;
+
+ std::deque<turn_info> turns;
+ detail::self_get_turn_points::no_interrupt_policy policy;
+ detail::self_get_turn_points::get_turns
+ <
+ Geometry,
+ std::deque<turn_info>,
+ policy_type,
+ detail::self_get_turn_points::no_interrupt_policy
+ >::apply(geometry, turns, policy);
+
+ return detail::touches::has_only_turns(turns);
+}
+
+
+/*!
+\brief \brief_check2{have at least one touching point (tangent - non overlapping)}
+\ingroup touches
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\return \return_check2{touch each other}
+
+\qbk{distinguish,two geometries}
+\qbk{[include reference/algorithms/touches.qbk]}
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool touches(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+
+
+ typedef detail::overlay::turn_info
+ <
+ typename geometry::point_type<Geometry1>::type
+ > turn_info;
+
+ typedef detail::overlay::get_turn_info
+ <
+ typename point_type<Geometry1>::type,
+ typename point_type<Geometry2>::type,
+ turn_info,
+ detail::overlay::assign_null_policy
+ > policy_type;
+
+ std::deque<turn_info> turns;
+ detail::get_turns::no_interrupt_policy policy;
+ boost::geometry::get_turns
+ <
+ false, false,
+ detail::overlay::assign_null_policy
+ >(geometry1, geometry2, turns, policy);
+
+ return detail::touches::has_only_turns(turns)
+ && ! geometry::detail::disjoint::rings_containing(geometry1, geometry2)
+ && ! geometry::detail::disjoint::rings_containing(geometry2, geometry1)
+ ;
+}
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_TOUCHES_HPP
diff --git a/boost/geometry/algorithms/transform.hpp b/boost/geometry/algorithms/transform.hpp
new file mode 100644
index 000000000..52d195fe8
--- /dev/null
+++ b/boost/geometry/algorithms/transform.hpp
@@ -0,0 +1,339 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP
+
+#include <cmath>
+#include <iterator>
+
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/num_interior_rings.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/mutable_range.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/strategies/transform.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace transform
+{
+
+struct transform_point
+{
+ template <typename Point1, typename Point2, typename Strategy>
+ static inline bool apply(Point1 const& p1, Point2& p2,
+ Strategy const& strategy)
+ {
+ return strategy.apply(p1, p2);
+ }
+};
+
+
+struct transform_box
+{
+ template <typename Box1, typename Box2, typename Strategy>
+ static inline bool apply(Box1 const& b1, Box2& b2,
+ Strategy const& strategy)
+ {
+ typedef typename point_type<Box1>::type point_type1;
+ typedef typename point_type<Box2>::type point_type2;
+
+ point_type1 lower_left, upper_right;
+ detail::assign::assign_box_2d_corner<min_corner, min_corner>(
+ b1, lower_left);
+ detail::assign::assign_box_2d_corner<max_corner, max_corner>(
+ b1, upper_right);
+
+ point_type2 p1, p2;
+ if (strategy.apply(lower_left, p1) && strategy.apply(upper_right, p2))
+ {
+ // Create a valid box and therefore swap if necessary
+ typedef typename coordinate_type<point_type2>::type coordinate_type;
+ coordinate_type x1 = geometry::get<0>(p1)
+ , y1 = geometry::get<1>(p1)
+ , x2 = geometry::get<0>(p2)
+ , y2 = geometry::get<1>(p2);
+
+ if (x1 > x2) { std::swap(x1, x2); }
+ if (y1 > y2) { std::swap(y1, y2); }
+
+ set<min_corner, 0>(b2, x1);
+ set<min_corner, 1>(b2, y1);
+ set<max_corner, 0>(b2, x2);
+ set<max_corner, 1>(b2, y2);
+
+ return true;
+ }
+ return false;
+ }
+};
+
+struct transform_box_or_segment
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& source, Geometry2& target,
+ Strategy const& strategy)
+ {
+ typedef typename point_type<Geometry1>::type point_type1;
+ typedef typename point_type<Geometry2>::type point_type2;
+
+ point_type1 source_point[2];
+ geometry::detail::assign_point_from_index<0>(source, source_point[0]);
+ geometry::detail::assign_point_from_index<1>(source, source_point[1]);
+
+ point_type2 target_point[2];
+ if (strategy.apply(source_point[0], target_point[0])
+ && strategy.apply(source_point[1], target_point[1]))
+ {
+ geometry::detail::assign_point_to_index<0>(target_point[0], target);
+ geometry::detail::assign_point_to_index<1>(target_point[1], target);
+ 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_iterator<Range const>::type
+ it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ if (! transform_point::apply(*it, point_out, strategy))
+ {
+ return false;
+ }
+ *out++ = point_out;
+ }
+ return true;
+}
+
+
+struct transform_polygon
+{
+ template <typename Polygon1, typename Polygon2, typename Strategy>
+ static inline bool apply(Polygon1 const& poly1, Polygon2& poly2,
+ Strategy const& strategy)
+ {
+ typedef typename ring_type<Polygon1>::type ring1_type;
+ typedef typename ring_type<Polygon2>::type ring2_type;
+ typedef typename point_type<Polygon2>::type point2_type;
+
+ geometry::clear(poly2);
+
+ if (!transform_range_out<point2_type>(exterior_ring(poly1),
+ std::back_inserter(exterior_ring(poly2)), strategy))
+ {
+ return false;
+ }
+
+ // Note: here a resizeable container is assumed.
+ traits::resize
+ <
+ typename boost::remove_reference
+ <
+ typename traits::interior_mutable_type<Polygon2>::type
+ >::type
+ >::apply(interior_rings(poly2), num_interior_rings(poly1));
+
+ typename interior_return_type<Polygon1 const>::type rings1
+ = interior_rings(poly1);
+ typename interior_return_type<Polygon2>::type rings2
+ = interior_rings(poly2);
+ BOOST_AUTO_TPL(it1, boost::begin(rings1));
+ BOOST_AUTO_TPL(it2, boost::begin(rings2));
+ 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::services::default_strategy
+ <
+ 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;
+};
+
+struct transform_range
+{
+ template <typename Range1, typename Range2, typename Strategy>
+ static inline bool apply(Range1 const& range1,
+ Range2& range2, Strategy const& strategy)
+ {
+ typedef typename point_type<Range2>::type point_type;
+
+ // Should NOT be done here!
+ // geometry::clear(range2);
+ return transform_range_out<point_type>(range1,
+ std::back_inserter(range2), strategy);
+ }
+};
+
+}} // namespace detail::transform
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,
+ typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type
+>
+struct transform {};
+
+template <typename Point1, typename Point2>
+struct transform<Point1, Point2, point_tag, point_tag>
+ : detail::transform::transform_point
+{
+};
+
+
+template <typename Linestring1, typename Linestring2>
+struct transform
+ <
+ Linestring1, Linestring2,
+ linestring_tag, linestring_tag
+ >
+ : detail::transform::transform_range
+{
+};
+
+template <typename Range1, typename Range2>
+struct transform<Range1, Range2, ring_tag, ring_tag>
+ : detail::transform::transform_range
+{
+};
+
+template <typename Polygon1, typename Polygon2>
+struct transform<Polygon1, Polygon2, polygon_tag, polygon_tag>
+ : detail::transform::transform_polygon
+{
+};
+
+template <typename Box1, typename Box2>
+struct transform<Box1, Box2, box_tag, box_tag>
+ : detail::transform::transform_box
+{
+};
+
+template <typename Segment1, typename Segment2>
+struct transform<Segment1, Segment2, segment_tag, segment_tag>
+ : detail::transform::transform_box_or_segment
+{
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Transforms from one geometry to another geometry \brief_strategy
+\ingroup transform
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Strategy strategy
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param strategy The strategy to be used for transformation
+\return True if the transformation could be done
+
+\qbk{distinguish,with strategy}
+
+\qbk{[include reference/algorithms/transform_with_strategy.qbk]}
+ */
+template <typename Geometry1, typename Geometry2, typename Strategy>
+inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2,
+ Strategy const& strategy)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2>();
+
+ typedef dispatch::transform<Geometry1, Geometry2> transform_type;
+
+ return transform_type::apply(geometry1, geometry2, strategy);
+}
+
+
+/*!
+\brief Transforms from one geometry to another geometry using a strategy
+\ingroup transform
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\return True if the transformation could be done
+
+\qbk{[include reference/algorithms/transform.qbk]}
+ */
+template <typename Geometry1, typename Geometry2>
+inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2>();
+
+ typename detail::transform::select_strategy<Geometry1, Geometry2>::type strategy;
+ return transform(geometry1, geometry2, strategy);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP
diff --git a/boost/geometry/algorithms/union.hpp b/boost/geometry/algorithms/union.hpp
new file mode 100644
index 000000000..479f556a1
--- /dev/null
+++ b/boost/geometry/algorithms/union.hpp
@@ -0,0 +1,245 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_UNION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_UNION_HPP
+
+
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/core/is_areal.hpp>
+#include <boost/geometry/core/point_order.hpp>
+#include <boost/geometry/core/reverse_dispatch.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry1, typename Geometry2, typename GeometryOut,
+ typename TagIn1 = typename tag<Geometry1>::type,
+ typename TagIn2 = typename tag<Geometry2>::type,
+ typename TagOut = typename tag<GeometryOut>::type,
+ bool Areal1 = geometry::is_areal<Geometry1>::value,
+ bool Areal2 = geometry::is_areal<Geometry2>::value,
+ bool ArealOut = geometry::is_areal<GeometryOut>::value,
+ bool Reverse1 = detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
+ bool Reverse2 = detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
+ bool ReverseOut = detail::overlay::do_reverse<geometry::point_order<GeometryOut>::value>::value,
+ bool Reverse = geometry::reverse_dispatch<Geometry1, Geometry2>::type::value
+>
+struct union_insert: not_implemented<TagIn1, TagIn2, TagOut>
+{};
+
+
+// If reversal is needed, perform it first
+
+template
+<
+ typename Geometry1, typename Geometry2, typename GeometryOut,
+ typename TagIn1, typename TagIn2, typename TagOut,
+ bool Reverse1, bool Reverse2, bool ReverseOut
+>
+struct union_insert
+ <
+ Geometry1, Geometry2, GeometryOut,
+ TagIn1, TagIn2, TagOut,
+ true, true, true,
+ Reverse1, Reverse2, ReverseOut,
+ true
+ >: union_insert<Geometry2, Geometry1, GeometryOut>
+{
+ template <typename OutputIterator, typename Strategy>
+ static inline OutputIterator apply(Geometry1 const& g1,
+ Geometry2 const& g2, OutputIterator out,
+ Strategy const& strategy)
+ {
+ return union_insert
+ <
+ Geometry2, Geometry1, GeometryOut
+ >::apply(g2, g1, out, strategy);
+ }
+};
+
+
+template
+<
+ typename Geometry1, typename Geometry2, typename GeometryOut,
+ typename TagIn1, typename TagIn2, typename TagOut,
+ bool Reverse1, bool Reverse2, bool ReverseOut
+>
+struct union_insert
+ <
+ Geometry1, Geometry2, GeometryOut,
+ TagIn1, TagIn2, TagOut,
+ true, true, true,
+ Reverse1, Reverse2, ReverseOut,
+ false
+ > : detail::overlay::overlay
+ <Geometry1, Geometry2, Reverse1, Reverse2, ReverseOut, GeometryOut, overlay_union>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace union_
+{
+
+template
+<
+ typename GeometryOut,
+ typename Geometry1, typename Geometry2,
+ typename OutputIterator,
+ typename Strategy
+>
+inline OutputIterator insert(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ OutputIterator out,
+ Strategy const& strategy)
+{
+ return dispatch::union_insert
+ <
+ Geometry1, Geometry2, GeometryOut
+ >::apply(geometry1, geometry2, out, strategy);
+}
+
+/*!
+\brief_calc2{union} \brief_strategy
+\ingroup union
+\details \details_calc2{union_insert, spatial set theoretic union}
+ \brief_strategy. details_insert{union}
+\tparam GeometryOut output geometry type, must be specified
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam OutputIterator output iterator
+\tparam Strategy \tparam_strategy_overlay
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param out \param_out{union}
+\param strategy \param_strategy{union}
+\return \return_out
+
+\qbk{distinguish,with strategy}
+*/
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename OutputIterator,
+ typename Strategy
+>
+inline OutputIterator union_insert(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ OutputIterator out,
+ Strategy const& strategy)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+ concept::check<GeometryOut>();
+
+ return detail::union_::insert<GeometryOut>(geometry1, geometry2, out, strategy);
+}
+
+/*!
+\brief_calc2{union}
+\ingroup union
+\details \details_calc2{union_insert, spatial set theoretic union}.
+ \details_insert{union}
+\tparam GeometryOut output geometry type, must be specified
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam OutputIterator output iterator
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param out \param_out{union}
+\return \return_out
+*/
+template
+<
+ typename GeometryOut,
+ typename Geometry1,
+ typename Geometry2,
+ typename OutputIterator
+>
+inline OutputIterator union_insert(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ OutputIterator out)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+ concept::check<GeometryOut>();
+
+ typedef strategy_intersection
+ <
+ typename cs_tag<GeometryOut>::type,
+ Geometry1,
+ Geometry2,
+ typename geometry::point_type<GeometryOut>::type
+ > strategy;
+
+ return union_insert<GeometryOut>(geometry1, geometry2, out, strategy());
+}
+
+
+}} // namespace detail::union_
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+
+/*!
+\brief Combines two geometries which each other
+\ingroup union
+\details \details_calc2{union, spatial set theoretic union}.
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Collection output collection, either a multi-geometry,
+ or a std::vector<Geometry> / std::deque<Geometry> etc
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param output_collection the output collection
+\note Called union_ because union is a reserved word.
+
+\qbk{[include reference/algorithms/union.qbk]}
+*/
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Collection
+>
+inline void union_(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+
+ typedef typename boost::range_value<Collection>::type geometry_out;
+ concept::check<geometry_out>();
+
+ detail::union_::union_insert<geometry_out>(geometry1, geometry2,
+ std::back_inserter(output_collection));
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_UNION_HPP
diff --git a/boost/geometry/algorithms/unique.hpp b/boost/geometry/algorithms/unique.hpp
new file mode 100644
index 000000000..e11dc13c4
--- /dev/null
+++ b/boost/geometry/algorithms/unique.hpp
@@ -0,0 +1,147 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_UNIQUE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_UNIQUE_HPP
+
+#include <algorithm>
+
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/mutable_range.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/policies/compare.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace unique
+{
+
+
+struct range_unique
+{
+ template <typename Range, typename ComparePolicy>
+ static inline void apply(Range& range, ComparePolicy const& policy)
+ {
+ typename boost::range_iterator<Range>::type it
+ = std::unique
+ (
+ boost::begin(range),
+ boost::end(range),
+ policy
+ );
+
+ traits::resize<Range>::apply(range, it - boost::begin(range));
+ }
+};
+
+
+struct polygon_unique
+{
+ template <typename Polygon, typename ComparePolicy>
+ static inline void apply(Polygon& polygon, ComparePolicy const& policy)
+ {
+ typedef typename geometry::ring_type<Polygon>::type ring_type;
+
+ range_unique::apply(exterior_ring(polygon), policy);
+
+ typename interior_return_type<Polygon>::type rings
+ = interior_rings(polygon);
+ for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
+ {
+ range_unique::apply(*it, policy);
+ }
+ }
+};
+
+
+
+}} // namespace detail::unique
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Geometry,
+ typename Tag = typename tag<Geometry>::type
+>
+struct unique
+{
+ template <typename ComparePolicy>
+ static inline void apply(Geometry&, ComparePolicy const& )
+ {}
+};
+
+
+template <typename Ring>
+struct unique<Ring, ring_tag>
+ : detail::unique::range_unique
+{};
+
+
+template <typename LineString>
+struct unique<LineString, linestring_tag>
+ : detail::unique::range_unique
+{};
+
+
+template <typename Polygon>
+struct unique<Polygon, polygon_tag>
+ : detail::unique::polygon_unique
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+/*!
+\brief \brief_calc{minimal set}
+\ingroup unique
+\details \details_calc{unique,minimal set (where duplicate consecutive points are removed)}.
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry which will be made unique
+
+\qbk{[include reference/algorithms/unique.qbk]}
+*/
+template <typename Geometry>
+inline void unique(Geometry& geometry)
+{
+ concept::check<Geometry>();
+
+ // Default strategy is the default point-comparison policy
+ typedef geometry::equal_to
+ <
+ typename geometry::point_type<Geometry>::type
+ > policy;
+
+
+ dispatch::unique<Geometry>::apply(geometry, policy());
+}
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_UNIQUE_HPP
diff --git a/boost/geometry/algorithms/within.hpp b/boost/geometry/algorithms/within.hpp
new file mode 100644
index 000000000..b024bd9fa
--- /dev/null
+++ b/boost/geometry/algorithms/within.hpp
@@ -0,0 +1,348 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP
+
+
+#include <cstddef>
+
+#include <boost/concept_check.hpp>
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/algorithms/make.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/point_order.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/strategies/within.hpp>
+#include <boost/geometry/strategies/concepts/within_concept.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/order_as_direction.hpp>
+#include <boost/geometry/views/closeable_view.hpp>
+#include <boost/geometry/views/reversible_view.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace within
+{
+
+
+template
+<
+ typename Point,
+ typename Ring,
+ iterate_direction Direction,
+ closure_selector Closure,
+ typename Strategy
+>
+struct point_in_ring
+{
+ BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategyPolygonal<Strategy>) );
+
+ static inline int apply(Point const& point, Ring const& ring,
+ Strategy const& strategy)
+ {
+ boost::ignore_unused_variable_warning(strategy);
+ if (int(boost::size(ring))
+ < core_detail::closure::minimum_ring_size<Closure>::value)
+ {
+ return -1;
+ }
+
+ typedef typename reversible_view<Ring const, Direction>::type rev_view_type;
+ typedef typename closeable_view
+ <
+ rev_view_type const, Closure
+ >::type cl_view_type;
+ typedef typename boost::range_iterator<cl_view_type const>::type iterator_type;
+
+ rev_view_type rev_view(ring);
+ cl_view_type view(rev_view);
+ typename Strategy::state_type state;
+ iterator_type it = boost::begin(view);
+ iterator_type end = boost::end(view);
+
+ bool stop = false;
+ for (iterator_type previous = it++;
+ it != end && ! stop;
+ ++previous, ++it)
+ {
+ if (! strategy.apply(point, *previous, *it, state))
+ {
+ stop = true;
+ }
+ }
+
+ return strategy.result(state);
+ }
+};
+
+
+// Polygon: in exterior ring, and if so, not within interior ring(s)
+template
+<
+ typename Point,
+ typename Polygon,
+ iterate_direction Direction,
+ closure_selector Closure,
+ typename Strategy
+>
+struct point_in_polygon
+{
+ BOOST_CONCEPT_ASSERT( (geometry::concept::WithinStrategyPolygonal<Strategy>) );
+
+ static inline int apply(Point const& point, Polygon const& poly,
+ Strategy const& strategy)
+ {
+ int const code = point_in_ring
+ <
+ Point,
+ typename ring_type<Polygon>::type,
+ Direction,
+ Closure,
+ Strategy
+ >::apply(point, exterior_ring(poly), strategy);
+
+ if (code == 1)
+ {
+ typename interior_return_type<Polygon const>::type rings
+ = interior_rings(poly);
+ for (BOOST_AUTO_TPL(it, boost::begin(rings));
+ it != boost::end(rings);
+ ++it)
+ {
+ int const interior_code = point_in_ring
+ <
+ Point,
+ typename ring_type<Polygon>::type,
+ Direction,
+ Closure,
+ Strategy
+ >::apply(point, *it, strategy);
+
+ if (interior_code != -1)
+ {
+ // If 0, return 0 (touch)
+ // If 1 (inside hole) return -1 (outside polygon)
+ // If -1 (outside hole) check other holes if any
+ return -interior_code;
+ }
+ }
+ }
+ return code;
+ }
+};
+
+}} // namespace detail::within
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Tag1 = typename tag<Geometry1>::type,
+ typename Tag2 = typename tag<Geometry2>::type
+>
+struct within: not_implemented<Tag1, Tag2>
+{};
+
+
+template <typename Point, typename Box>
+struct within<Point, Box, point_tag, box_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
+ {
+ boost::ignore_unused_variable_warning(strategy);
+ return strategy.apply(point, box);
+ }
+};
+
+template <typename Box1, typename Box2>
+struct within<Box1, Box2, box_tag, box_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Box1 const& box1, Box2 const& box2, Strategy const& strategy)
+ {
+ assert_dimension_equal<Box1, Box2>();
+ boost::ignore_unused_variable_warning(strategy);
+ return strategy.apply(box1, box2);
+ }
+};
+
+
+
+template <typename Point, typename Ring>
+struct within<Point, Ring, point_tag, ring_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Point const& point, Ring const& ring, Strategy const& strategy)
+ {
+ return detail::within::point_in_ring
+ <
+ Point,
+ Ring,
+ order_as_direction<geometry::point_order<Ring>::value>::value,
+ geometry::closure<Ring>::value,
+ Strategy
+ >::apply(point, ring, strategy) == 1;
+ }
+};
+
+template <typename Point, typename Polygon>
+struct within<Point, Polygon, point_tag, polygon_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Point const& point, Polygon const& polygon, Strategy const& strategy)
+ {
+ return detail::within::point_in_polygon
+ <
+ Point,
+ Polygon,
+ order_as_direction<geometry::point_order<Polygon>::value>::value,
+ geometry::closure<Polygon>::value,
+ Strategy
+ >::apply(point, polygon, strategy) == 1;
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief \brief_check12{is completely inside}
+\ingroup within
+\details \details_check12{within, is completely inside}.
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry which might be within the second geometry
+\param geometry2 \param_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
+
+
+\qbk{[include reference/algorithms/within.qbk]}
+
+\qbk{
+[heading Example]
+[within]
+[within_output]
+}
+ */
+template<typename Geometry1, typename Geometry2>
+inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2)
+{
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+ assert_dimension_equal<Geometry1, Geometry2>();
+
+ typedef typename point_type<Geometry1>::type point_type1;
+ typedef typename point_type<Geometry2>::type point_type2;
+
+ typedef typename strategy::within::services::default_strategy
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ typename tag<Geometry1>::type,
+ typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
+ typename tag_cast
+ <
+ typename cs_tag<point_type1>::type, spherical_tag
+ >::type,
+ typename tag_cast
+ <
+ typename cs_tag<point_type2>::type, spherical_tag
+ >::type,
+ Geometry1,
+ Geometry2
+ >::type strategy_type;
+
+ return dispatch::within
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy_type());
+}
+
+/*!
+\brief \brief_check12{is completely inside} \brief_strategy
+\ingroup within
+\details \details_check12{within, is completely inside}, \brief_strategy. \details_strategy_reasons
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\param geometry1 \param_geometry which might be within the second geometry
+\param geometry2 \param_geometry which might contain the first geometry
+\param strategy strategy to be used
+\return true if geometry1 is completely contained within geometry2,
+ else false
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/within.qbk]}
+\qbk{
+[heading Available Strategies]
+\* [link geometry.reference.strategies.strategy_within_winding Winding (coordinate system agnostic)]
+\* [link geometry.reference.strategies.strategy_within_franklin Franklin (cartesian)]
+\* [link geometry.reference.strategies.strategy_within_crossings_multiply Crossings Multiply (cartesian)]
+
+[heading Example]
+[within_strategy]
+[within_strategy_output]
+
+}
+*/
+template<typename Geometry1, typename Geometry2, typename Strategy>
+inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+{
+ concept::within::check
+ <
+ typename tag<Geometry1>::type,
+ typename tag<Geometry2>::type,
+ typename tag_cast<typename tag<Geometry2>::type, areal_tag>::type,
+ Strategy
+ >();
+ concept::check<Geometry1 const>();
+ concept::check<Geometry2 const>();
+ assert_dimension_equal<Geometry1, Geometry2>();
+
+ return dispatch::within
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP
diff --git a/boost/geometry/arithmetic/arithmetic.hpp b/boost/geometry/arithmetic/arithmetic.hpp
new file mode 100644
index 000000000..6479ecc4a
--- /dev/null
+++ b/boost/geometry/arithmetic/arithmetic.hpp
@@ -0,0 +1,281 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ARITHMETIC_ARITHMETIC_HPP
+#define BOOST_GEOMETRY_ARITHMETIC_ARITHMETIC_HPP
+
+#include <functional>
+
+#include <boost/call_traits.hpp>
+#include <boost/concept/requires.hpp>
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/util/for_each_coordinate.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template <typename P>
+struct param
+{
+ typedef typename boost::call_traits
+ <
+ typename coordinate_type<P>::type
+ >::param_type type;
+};
+
+
+template <typename C, template <typename> class Function>
+struct value_operation
+{
+ C m_value;
+
+ inline value_operation(C const &value)
+ : m_value(value)
+ {}
+
+ template <typename P, int I>
+ inline void apply(P& point) const
+ {
+ set<I>(point, Function<C>()(get<I>(point), m_value));
+ }
+};
+
+template <typename PointSrc, template <typename> class Function>
+struct point_operation
+{
+ typedef typename coordinate_type<PointSrc>::type coordinate_type;
+ PointSrc const& m_source_point;
+
+ inline point_operation(PointSrc const& point)
+ : m_source_point(point)
+ {}
+
+ template <typename PointDst, int I>
+ inline void apply(PointDst& dest_point) const
+ {
+ set<I>(dest_point,
+ Function<coordinate_type>()(get<I>(dest_point), get<I>(m_source_point)));
+ }
+};
+
+
+template <typename C>
+struct value_assignment
+{
+ C m_value;
+
+ inline value_assignment(C const &value)
+ : m_value(value)
+ {}
+
+ template <typename P, int I>
+ inline void apply(P& point) const
+ {
+ set<I>(point, m_value);
+ }
+};
+
+template <typename PointSrc>
+struct point_assignment
+{
+ PointSrc const& m_source_point;
+
+ inline point_assignment(PointSrc const& point)
+ : m_source_point(point)
+ {}
+
+ template <typename PointDst, int I>
+ inline void apply(PointDst& dest_point) const
+ {
+ set<I>(dest_point, get<I>(m_source_point));
+ }
+};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+/*!
+ \brief Adds the same 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 the same 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 the same 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 first point will be multiplied by those of the second 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 the same 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 first point will be divided by those of the second 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));
+}
+
+/*!
+ \brief Assign each coordinate of a point the same value
+ \ingroup arithmetic
+ \details
+ \param p point
+ \param value value to assign
+ */
+template <typename Point>
+inline void assign_value(Point& p, typename detail::param<Point>::type value)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+ for_each_coordinate(p, detail::value_assignment<typename coordinate_type<Point>::type>(value));
+}
+
+/*!
+ \brief Assign a point with another
+ \ingroup arithmetic
+ \details The coordinates of the first point will be assigned those of the second point.
+ The second point is not modified.
+ \param p1 first point
+ \param p2 second point
+ */
+template <typename Point1, typename Point2>
+inline void assign_point(Point1& p1, const Point2& p2)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point2>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
+
+ for_each_coordinate(p1, detail::point_assignment<Point2>(p2));
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ARITHMETIC_ARITHMETIC_HPP
diff --git a/boost/geometry/arithmetic/determinant.hpp b/boost/geometry/arithmetic/determinant.hpp
new file mode 100644
index 000000000..db3b86709
--- /dev/null
+++ b/boost/geometry/arithmetic/determinant.hpp
@@ -0,0 +1,76 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ARITHMETIC_DETERMINANT_HPP
+#define BOOST_GEOMETRY_ARITHMETIC_DETERMINANT_HPP
+
+
+#include <cstddef>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename ReturnType, typename U, typename V>
+class calculate_determinant
+{
+ template <typename T>
+ static inline ReturnType rt(T const& v)
+ {
+ return boost::numeric_cast<ReturnType>(v);
+ }
+
+public :
+
+ static inline ReturnType apply(U const& ux, U const& uy
+ , V const& vx, V const& vy)
+ {
+ return rt(ux) * rt(vy) - rt(uy) * rt(vx);
+ }
+};
+
+template <typename ReturnType, typename U, typename V>
+inline ReturnType determinant(U const& ux, U const& uy
+ , V const& vx, V const& vy)
+{
+ return calculate_determinant
+ <
+ ReturnType, U, V
+ >::apply(ux, uy, vx, vy);
+}
+
+
+template <typename ReturnType, typename U, typename V>
+inline ReturnType determinant(U const& u, V const& v)
+{
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<U>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<V>) );
+
+ return calculate_determinant
+ <
+ ReturnType,
+ typename geometry::coordinate_type<U>::type,
+ typename geometry::coordinate_type<V>::type
+ >::apply(get<0>(u), get<1>(u), get<0>(v), get<1>(v));
+}
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ARITHMETIC_DETERMINANT_HPP
diff --git a/boost/geometry/arithmetic/dot_product.hpp b/boost/geometry/arithmetic/dot_product.hpp
new file mode 100644
index 000000000..13fe96877
--- /dev/null
+++ b/boost/geometry/arithmetic/dot_product.hpp
@@ -0,0 +1,82 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ARITHMETIC_DOT_PRODUCT_HPP
+#define BOOST_GEOMETRY_ARITHMETIC_DOT_PRODUCT_HPP
+
+
+#include <cstddef>
+
+#include <boost/concept/requires.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename P1, typename P2, std::size_t Dimension, std::size_t DimensionCount>
+struct dot_product_maker
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+
+ static inline coordinate_type apply(P1 const& p1, P2 const& p2)
+ {
+ return get<Dimension>(p1) * get<Dimension>(p2)
+ + dot_product_maker<P1, P2, Dimension+1, DimensionCount>::apply(p1, p2);
+ }
+};
+
+template <typename P1, typename P2, std::size_t DimensionCount>
+struct dot_product_maker<P1, P2, DimensionCount, DimensionCount>
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+
+ static inline coordinate_type apply(P1 const& p1, P2 const& p2)
+ {
+ return get<DimensionCount>(p1) * get<DimensionCount>(p2);
+ }
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief Computes the dot product (or scalar product) of 2 vectors (points).
+ \ingroup arithmetic
+ \param p1 first point
+ \param p2 second point
+ \return the dot product
+ */
+template <typename P1, typename P2>
+inline typename select_coordinate_type<P1, P2>::type dot_product(
+ P1 const& p1, P2 const& p2)
+{
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<P1>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<P2>) );
+
+ return detail::dot_product_maker
+ <
+ P1, P2,
+ 0, dimension<P1>::type::value - 1
+ >::apply(p1, p2);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ARITHMETIC_DOT_PRODUCT_HPP
diff --git a/boost/geometry/core/access.hpp b/boost/geometry/core/access.hpp
new file mode 100644
index 000000000..9ee33cd64
--- /dev/null
+++ b/boost/geometry/core/access.hpp
@@ -0,0 +1,398 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_ACCESS_HPP
+#define BOOST_GEOMETRY_CORE_ACCESS_HPP
+
+
+#include <cstddef>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/concept_check.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/util/bare_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+/// Index of minimum corner of the box.
+int const min_corner = 0;
+
+/// Index of maximum corner of the box.
+int const max_corner = 1;
+
+namespace traits
+{
+
+/*!
+\brief Traits class which gives access (get,set) to points.
+\ingroup traits
+\par Geometries:
+/// @li point
+\par Specializations should provide, per Dimension
+/// @li static inline T get(G const&)
+/// @li static inline void set(G&, T const&)
+\tparam Geometry geometry-type
+\tparam Dimension dimension to access
+*/
+template <typename Geometry, std::size_t Dimension, typename Enable = void>
+struct access
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE, (types<Geometry>)
+ );
+};
+
+
+/*!
+\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(G const&)
+ - static inline void set(G&, T const&)
+\ingroup traits
+*/
+template <typename Geometry, std::size_t Index, std::size_t Dimension>
+struct indexed_access {};
+
+
+} // namespace traits
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template
+<
+ typename Geometry,
+ typename CoordinateType,
+ std::size_t Index,
+ std::size_t Dimension
+>
+struct indexed_access_non_pointer
+{
+ static inline CoordinateType get(Geometry const& geometry)
+ {
+ return traits::indexed_access<Geometry, Index, Dimension>::get(geometry);
+ }
+ static inline void set(Geometry& b, CoordinateType const& value)
+ {
+ traits::indexed_access<Geometry, Index, Dimension>::set(b, value);
+ }
+};
+
+template
+<
+ typename Geometry,
+ typename CoordinateType,
+ std::size_t Index,
+ std::size_t Dimension
+>
+struct indexed_access_pointer
+{
+ static inline CoordinateType get(Geometry const* geometry)
+ {
+ return traits::indexed_access<typename boost::remove_pointer<Geometry>::type, Index, Dimension>::get(*geometry);
+ }
+ static inline void set(Geometry* geometry, CoordinateType const& value)
+ {
+ traits::indexed_access<typename boost::remove_pointer<Geometry>::type, Index, Dimension>::set(*geometry, value);
+ }
+};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template
+<
+ typename Tag,
+ typename Geometry,
+ typename
+ CoordinateType,
+ std::size_t Dimension,
+ typename IsPointer
+>
+struct access
+{
+ //static inline T get(G const&) {}
+ //static inline void set(G& g, T const& value) {}
+};
+
+template
+<
+ typename Tag,
+ typename Geometry,
+ typename CoordinateType,
+ std::size_t Index,
+ std::size_t Dimension,
+ typename IsPointer
+>
+struct indexed_access
+{
+ //static inline T get(G const&) {}
+ //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, boost::false_type>
+{
+ 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 Point, typename CoordinateType, std::size_t Dimension>
+struct access<point_tag, Point, CoordinateType, Dimension, boost::true_type>
+{
+ static inline CoordinateType get(Point const* point)
+ {
+ return traits::access<typename boost::remove_pointer<Point>::type, Dimension>::get(*point);
+ }
+ static inline void set(Point* p, CoordinateType const& value)
+ {
+ traits::access<typename boost::remove_pointer<Point>::type, 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, boost::false_type>
+ : detail::indexed_access_non_pointer<Box, CoordinateType, Index, Dimension>
+{};
+
+template
+<
+ typename Box,
+ typename CoordinateType,
+ std::size_t Index,
+ std::size_t Dimension
+>
+struct indexed_access<box_tag, Box, CoordinateType, Index, Dimension, boost::true_type>
+ : detail::indexed_access_pointer<Box, CoordinateType, Index, Dimension>
+{};
+
+
+template
+<
+ typename Segment,
+ typename CoordinateType,
+ std::size_t Index,
+ std::size_t Dimension
+>
+struct indexed_access<segment_tag, Segment, CoordinateType, Index, Dimension, boost::false_type>
+ : detail::indexed_access_non_pointer<Segment, CoordinateType, Index, Dimension>
+{};
+
+
+template
+<
+ typename Segment,
+ typename CoordinateType,
+ std::size_t Index,
+ std::size_t Dimension
+>
+struct indexed_access<segment_tag, Segment, CoordinateType, Index, Dimension, boost::true_type>
+ : detail::indexed_access_pointer<Segment, CoordinateType, Index, Dimension>
+{};
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+// Two dummy tags to distinguish get/set variants below.
+// They don't have to be specified by the user. The functions are distinguished
+// by template signature also, but for e.g. GCC this is not enough. So give them
+// a different signature.
+struct signature_getset_dimension {};
+struct signature_getset_index_dimension {};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+\brief Get coordinate value of a geometry (usually a point)
+\details \details_get_set
+\ingroup get
+\tparam Dimension \tparam_dimension_required
+\tparam Geometry \tparam_geometry (usually a Point Concept)
+\param geometry \param_geometry (usually a point)
+\return The coordinate value of specified dimension of specified geometry
+
+\qbk{[include reference/core/get_point.qbk]}
+*/
+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 core_dispatch::access
+ <
+ typename tag<Geometry>::type,
+ typename geometry::util::bare_type<Geometry>::type,
+ typename coordinate_type<Geometry>::type,
+ Dimension,
+ typename boost::is_pointer<Geometry>::type
+ > coord_access_type;
+
+ return coord_access_type::get(geometry);
+}
+
+
+/*!
+\brief Set coordinate value of a geometry (usually a point)
+\details \details_get_set
+\tparam Dimension \tparam_dimension_required
+\tparam Geometry \tparam_geometry (usually a Point Concept)
+\param geometry geometry to assign coordinate to
+\param geometry \param_geometry (usually a point)
+\param value The coordinate value to set
+\ingroup set
+
+\qbk{[include reference/core/set_point.qbk]}
+*/
+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 core_dispatch::access
+ <
+ typename tag<Geometry>::type,
+ typename geometry::util::bare_type<Geometry>::type,
+ typename coordinate_type<Geometry>::type,
+ Dimension,
+ typename boost::is_pointer<Geometry>::type
+ > coord_access_type;
+
+ coord_access_type::set(geometry, value);
+}
+
+
+/*!
+\brief get coordinate value of a Box or Segment
+\details \details_get_set
+\tparam Index \tparam_index_required
+\tparam Dimension \tparam_dimension_required
+\tparam Geometry \tparam_box_or_segment
+\param geometry \param_geometry
+\return coordinate value
+\ingroup get
+
+\qbk{distinguish,with index}
+\qbk{[include reference/core/get_box.qbk]}
+*/
+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 core_dispatch::indexed_access
+ <
+ typename tag<Geometry>::type,
+ typename geometry::util::bare_type<Geometry>::type,
+ typename coordinate_type<Geometry>::type,
+ Index,
+ Dimension,
+ typename boost::is_pointer<Geometry>::type
+ > coord_access_type;
+
+ return coord_access_type::get(geometry);
+}
+
+/*!
+\brief set coordinate value of a Box / Segment
+\details \details_get_set
+\tparam Index \tparam_index_required
+\tparam Dimension \tparam_dimension_required
+\tparam Geometry \tparam_box_or_segment
+\param geometry geometry to assign coordinate to
+\param geometry \param_geometry
+\param value The coordinate value to set
+\ingroup set
+
+\qbk{distinguish,with index}
+\qbk{[include reference/core/set_box.qbk]}
+*/
+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 core_dispatch::indexed_access
+ <
+ typename tag<Geometry>::type,
+ typename geometry::util::bare_type<Geometry>::type,
+ typename coordinate_type<Geometry>::type,
+ Index,
+ Dimension,
+ typename boost::is_pointer<Geometry>::type
+ > coord_access_type;
+
+ coord_access_type::set(geometry, value);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_ACCESS_HPP
diff --git a/boost/geometry/core/closure.hpp b/boost/geometry/core/closure.hpp
new file mode 100644
index 000000000..aab02e787
--- /dev/null
+++ b/boost/geometry/core/closure.hpp
@@ -0,0 +1,180 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_CLOSURE_HPP
+#define BOOST_GEOMETRY_CORE_CLOSURE_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/range.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+\brief Enumerates options for defining if polygons are open or closed
+\ingroup enum
+\details The enumeration closure_selector describes options for if a polygon is
+ open or closed. In a closed polygon the very first point (per ring) should
+ be equal to the very last point.
+ The specific closing property of a polygon type is defined by the closure
+ metafunction. The closure metafunction defines a value, which is one of the
+ values enumerated in the closure_selector
+
+\qbk{
+[heading See also]
+[link geometry.reference.core.closure The closure metafunction]
+}
+*/
+enum closure_selector
+{
+ /// Rings are open: first point and last point are different, algorithms
+ /// close them explicitly on the fly
+ open = 0,
+ /// Rings are closed: first point and last point must be the same
+ closed = 1,
+ /// (Not yet implemented): algorithms first figure out if ring must be
+ /// closed on the fly
+ closure_undertermined = -1
+};
+
+namespace traits
+{
+
+/*!
+ \brief Traits class indicating if points within a
+ ring or (multi)polygon are closed (last point == first point),
+ open or not known.
+ \ingroup traits
+ \par Geometries:
+ - ring
+ \tparam G geometry
+*/
+template <typename G>
+struct closure
+{
+ static const closure_selector value = closed;
+};
+
+
+} // namespace traits
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace core_detail { namespace closure
+{
+
+struct closed
+{
+ static const closure_selector value = geometry::closed;
+};
+
+
+/// Metafunction to define the minimum size of a ring:
+/// 3 for open rings, 4 for closed rings
+template <closure_selector Closure>
+struct minimum_ring_size {};
+
+template <>
+struct minimum_ring_size<geometry::closed> : boost::mpl::int_<4> {};
+
+template <>
+struct minimum_ring_size<geometry::open> : boost::mpl::int_<3> {};
+
+
+}} // namespace detail::point_order
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename Tag, typename Geometry>
+struct closure
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<Geometry>)
+ );
+};
+
+template <typename Box>
+struct closure<point_tag, Box> : public core_detail::closure::closed {};
+
+template <typename Box>
+struct closure<box_tag, Box> : public core_detail::closure::closed {};
+
+template <typename Box>
+struct closure<segment_tag, Box> : public core_detail::closure::closed {};
+
+template <typename LineString>
+struct closure<linestring_tag, LineString>
+ : public core_detail::closure::closed {};
+
+
+template <typename Ring>
+struct closure<ring_tag, Ring>
+{
+ static const closure_selector value
+ = geometry::traits::closure<Ring>::value;
+};
+
+// Specialization for polygon: the closure is the closure of its rings
+template <typename Polygon>
+struct closure<polygon_tag, Polygon>
+{
+ static const closure_selector value = core_dispatch::closure
+ <
+ ring_tag,
+ typename ring_type<polygon_tag, Polygon>::type
+ >::value ;
+};
+
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief \brief_meta{value, closure (clockwise\, counterclockwise),
+ \meta_geometry_type}
+\tparam Geometry \tparam_geometry
+\ingroup core
+
+\qbk{[include reference/core/closure.qbk]}
+*/
+template <typename Geometry>
+struct closure
+{
+ static const closure_selector value = core_dispatch::closure
+ <
+ typename tag<Geometry>::type,
+ typename boost::remove_const<Geometry>::type
+ >::value;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_CLOSURE_HPP
diff --git a/boost/geometry/core/coordinate_dimension.hpp b/boost/geometry/core/coordinate_dimension.hpp
new file mode 100644
index 000000000..15df129de
--- /dev/null
+++ b/boost/geometry/core/coordinate_dimension.hpp
@@ -0,0 +1,126 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_COORDINATE_DIMENSION_HPP
+#define BOOST_GEOMETRY_CORE_COORDINATE_DIMENSION_HPP
+
+
+#include <cstddef>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/util/bare_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+/*!
+\brief Traits class indicating the number of dimensions of a point
+\par Geometries:
+ - point
+\par Specializations should provide:
+ - value (should be derived from boost::mpl::int_<D>
+\ingroup traits
+*/
+template <typename Point, typename Enable = void>
+struct dimension
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE, (types<Point>)
+ );
+};
+
+} // 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<typename geometry::util::bare_type<P>::type> {};
+
+} // namespace core_dispatch
+#endif
+
+/*!
+\brief \brief_meta{value, number of coordinates (the number of axes of any geometry), \meta_point_type}
+\tparam Geometry \tparam_geometry
+\ingroup core
+
+\qbk{[include reference/core/coordinate_dimension.qbk]}
+*/
+template <typename Geometry>
+struct dimension
+ : core_dispatch::dimension
+ <
+ typename tag<Geometry>::type,
+ typename geometry::util::bare_type<Geometry>::type
+ >
+{};
+
+/*!
+\brief assert_dimension, enables compile-time checking if coordinate dimensions are as expected
+\ingroup utility
+*/
+template <typename Geometry, int Dimensions>
+inline void assert_dimension()
+{
+ BOOST_STATIC_ASSERT((
+ boost::mpl::equal_to
+ <
+ geometry::dimension<Geometry>,
+ boost::mpl::int_<Dimensions>
+ >::type::value
+ ));
+}
+
+/*!
+\brief assert_dimension, enables compile-time checking if coordinate dimensions are as expected
+\ingroup utility
+*/
+template <typename Geometry, int Dimensions>
+inline void assert_dimension_less_equal()
+{
+ BOOST_STATIC_ASSERT(( dimension<Geometry>::type::value <= Dimensions ));
+}
+
+template <typename Geometry, int Dimensions>
+inline void assert_dimension_greater_equal()
+{
+ BOOST_STATIC_ASSERT(( dimension<Geometry>::type::value >= Dimensions ));
+}
+
+/*!
+\brief assert_dimension_equal, enables compile-time checking if coordinate dimensions of two geometries are equal
+\ingroup utility
+*/
+template <typename G1, typename G2>
+inline void assert_dimension_equal()
+{
+ BOOST_STATIC_ASSERT(( dimension<G1>::type::value == dimension<G2>::type::value ));
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_COORDINATE_DIMENSION_HPP
diff --git a/boost/geometry/core/coordinate_system.hpp b/boost/geometry/core/coordinate_system.hpp
new file mode 100644
index 000000000..d33353f4b
--- /dev/null
+++ b/boost/geometry/core/coordinate_system.hpp
@@ -0,0 +1,100 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_COORDINATE_SYSTEM_HPP
+#define BOOST_GEOMETRY_CORE_COORDINATE_SYSTEM_HPP
+
+
+#include <boost/mpl/assert.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/util/bare_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace traits
+{
+
+/*!
+\brief Traits class defining the coordinate system of a point, important for strategy selection
+\ingroup traits
+\par Geometries:
+ - point
+\par Specializations should provide:
+ - typedef CS type; (cs::cartesian, cs::spherical, etc)
+*/
+template <typename Point, typename Enable = void>
+struct coordinate_system
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE, (types<Point>)
+ );
+};
+
+} // 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 Point>
+ struct coordinate_system<point_tag, Point>
+ {
+ typedef typename traits::coordinate_system
+ <
+ typename geometry::util::bare_type<Point>::type
+ >::type type;
+ };
+
+
+} // namespace core_dispatch
+#endif
+
+
+/*!
+\brief \brief_meta{type, coordinate system (cartesian\, spherical\, etc), \meta_point_type}
+\tparam Geometry \tparam_geometry
+\ingroup core
+
+\qbk{[include reference/core/coordinate_system.qbk]}
+*/
+template <typename Geometry>
+struct coordinate_system
+{
+ typedef typename core_dispatch::coordinate_system
+ <
+ typename tag<Geometry>::type,
+ typename geometry::util::bare_type<Geometry>::type
+ >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_COORDINATE_SYSTEM_HPP
diff --git a/boost/geometry/core/coordinate_type.hpp b/boost/geometry/core/coordinate_type.hpp
new file mode 100644
index 000000000..f138d59c8
--- /dev/null
+++ b/boost/geometry/core/coordinate_type.hpp
@@ -0,0 +1,108 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_COORDINATE_TYPE_HPP
+#define BOOST_GEOMETRY_CORE_COORDINATE_TYPE_HPP
+
+
+#include <boost/mpl/assert.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/util/bare_type.hpp>
+#include <boost/geometry/util/promote_floating_point.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+/*!
+\brief Traits class which indicate the coordinate type (double,float,...) of a point
+\ingroup traits
+\par Geometries:
+ - point
+\par Specializations should provide:
+ - typedef T type; (double,float,int,etc)
+*/
+template <typename Point, typename Enable = void>
+struct coordinate_type
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE, (types<Point>)
+ );
+};
+
+} // namespace traits
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename GeometryTag, typename Geometry>
+struct coordinate_type
+{
+ typedef typename point_type<GeometryTag, Geometry>::type point_type;
+
+ // Call its own specialization on point-tag
+ typedef typename coordinate_type<point_tag, point_type>::type type;
+};
+
+template <typename Point>
+struct coordinate_type<point_tag, Point>
+{
+ typedef typename traits::coordinate_type
+ <
+ typename geometry::util::bare_type<Point>::type
+ >::type type;
+};
+
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief \brief_meta{type, coordinate type (int\, float\, double\, etc), \meta_point_type}
+\tparam Geometry \tparam_geometry
+\ingroup core
+
+\qbk{[include reference/core/coordinate_type.qbk]}
+*/
+template <typename Geometry>
+struct coordinate_type
+{
+ typedef typename core_dispatch::coordinate_type
+ <
+ typename tag<Geometry>::type,
+ typename geometry::util::bare_type<Geometry>::type
+ >::type type;
+};
+
+template <typename Geometry>
+struct fp_coordinate_type
+{
+ typedef typename promote_floating_point
+ <
+ typename coordinate_type<Geometry>::type
+ >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_COORDINATE_TYPE_HPP
diff --git a/boost/geometry/core/cs.hpp b/boost/geometry/core/cs.hpp
new file mode 100644
index 000000000..3588ed1a8
--- /dev/null
+++ b/boost/geometry/core/cs.hpp
@@ -0,0 +1,220 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_CS_HPP
+#define BOOST_GEOMETRY_CORE_CS_HPP
+
+#include <cstddef>
+
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+/*!
+\brief Unit of plane angle: Degrees
+\details Tag defining the unit of plane angle for spherical coordinate systems.
+ This tag specifies that coordinates are defined in degrees (-180 .. 180).
+ It has to be specified for some coordinate systems.
+\qbk{[include reference/core/degree_radian.qbk]}
+*/
+struct degree {};
+
+
+/*!
+\brief Unit of plane angle: Radians
+\details Tag defining the unit of plane angle for spherical coordinate systems.
+ This tag specifies that coordinates are defined in radians (-PI .. PI).
+ It has to be specified for some coordinate systems.
+\qbk{[include reference/core/degree_radian.qbk]}
+*/
+struct 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 (polar) 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 Spherical equatorial coordinate system, in degree or in radian
+\details This one resembles the geographic coordinate system, and has latitude
+ up from zero at the equator, to 90 at the pole
+ (opposite to the spherical(polar) coordinate system).
+ Used in astronomy and in GIS (but there is also the geographic)
+
+\see http://en.wikipedia.org/wiki/Spherical_coordinates
+\ingroup cs
+*/
+template<typename DegreeOrRadian>
+struct spherical_equatorial
+{
+ 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_polar_tag type;
+};
+
+template<typename DegreeOrRadian>
+struct cs_tag<cs::spherical_equatorial<DegreeOrRadian> >
+{
+ typedef spherical_equatorial_tag type;
+};
+
+
+template<>
+struct cs_tag<cs::cartesian>
+{
+ typedef cartesian_tag type;
+};
+
+
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+} // namespace traits
+
+/*!
+\brief Meta-function returning coordinate system tag (cs family) of any geometry
+\ingroup core
+*/
+template <typename G>
+struct cs_tag
+{
+ typedef typename traits::cs_tag
+ <
+ typename geometry::coordinate_system<G>::type
+ >::type type;
+};
+
+
+/*!
+\brief Meta-function to verify if a coordinate system is radian
+\ingroup core
+*/
+template <typename CoordinateSystem>
+struct is_radian : boost::true_type {};
+
+
+#ifndef DOXYGEN_NO_SPECIALIZATIONS
+
+// Specialization for any degree coordinate systems
+template <template<typename> class CoordinateSystem>
+struct is_radian< CoordinateSystem<degree> > : boost::false_type
+{
+};
+
+#endif // DOXYGEN_NO_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_CS_HPP
diff --git a/boost/geometry/core/exception.hpp b/boost/geometry/core/exception.hpp
new file mode 100644
index 000000000..97d249e93
--- /dev/null
+++ b/boost/geometry/core/exception.hpp
@@ -0,0 +1,60 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_EXCEPTION_HPP
+#define BOOST_GEOMETRY_CORE_EXCEPTION_HPP
+
+#include <exception>
+
+namespace boost { namespace geometry
+{
+
+/*!
+\brief Base exception class for Boost.Geometry algorithms
+\ingroup core
+\details This class is never thrown. All exceptions thrown in Boost.Geometry
+ are derived from exception, so it might be convenient to catch it.
+*/
+class exception : public std::exception
+{};
+
+
+/*!
+\brief Empty Input Exception
+\ingroup core
+\details The empty_input_exception is thrown if free functions, e.g. distance,
+ are called with empty geometries, e.g. a linestring
+ without points, a polygon without points, an empty multi-geometry.
+\qbk{
+[heading See also]
+\* [link geometry.reference.algorithms.area the area function]
+\* [link geometry.reference.algorithms.distance the distance function]
+\* [link geometry.reference.algorithms.length the length function]
+}
+ */
+class empty_input_exception : public geometry::exception
+{
+public:
+
+ inline empty_input_exception() {}
+
+ virtual char const* what() const throw()
+ {
+ return "Boost.Geometry Empty-Input exception";
+ }
+};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_EXCEPTION_HPP
diff --git a/boost/geometry/core/exterior_ring.hpp b/boost/geometry/core/exterior_ring.hpp
new file mode 100644
index 000000000..e5c97dd30
--- /dev/null
+++ b/boost/geometry/core/exterior_ring.hpp
@@ -0,0 +1,144 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_EXTERIOR_RING_HPP
+#define BOOST_GEOMETRY_CORE_EXTERIOR_RING_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/add_const_if_c.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+
+/*!
+ \brief Traits class defining access to exterior_ring of a polygon
+ \details Should define const and non const access
+ \ingroup traits
+ \tparam Polygon the polygon type
+ \par Geometries:
+ - polygon
+ \par Specializations should provide:
+ - static inline RING& get(POLY& )
+ - static inline RING const& get(POLY const& )
+*/
+template <typename Polygon>
+struct exterior_ring
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_POLYGON_TYPE
+ , (types<Polygon>)
+ );
+};
+
+
+} // namespace traits
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+
+template <typename Tag, typename Geometry>
+struct exterior_ring
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<Geometry>)
+ );
+};
+
+
+template <typename Polygon>
+struct exterior_ring<polygon_tag, Polygon>
+{
+ static
+ typename geometry::ring_return_type<Polygon>::type
+ apply(typename add_const_if_c
+ <
+ boost::is_const<Polygon>::type::value,
+ 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 exterior_ring
+ \note OGC compliance: instead of ExteriorRing
+ \tparam Polygon 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_return_type<Polygon>::type exterior_ring(Polygon& polygon)
+{
+ return core_dispatch::exterior_ring
+ <
+ typename tag<Polygon>::type,
+ Polygon
+ >::apply(polygon);
+}
+
+
+/*!
+\brief Function to get the exterior ring of a polygon (const version)
+\ingroup exterior_ring
+\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
+
+\qbk{distinguish,const version}
+*/
+template <typename Polygon>
+inline typename ring_return_type<Polygon const>::type exterior_ring(
+ Polygon const& polygon)
+{
+ return core_dispatch::exterior_ring
+ <
+ typename tag<Polygon>::type,
+ Polygon const
+ >::apply(polygon);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_EXTERIOR_RING_HPP
diff --git a/boost/geometry/core/geometry_id.hpp b/boost/geometry/core/geometry_id.hpp
new file mode 100644
index 000000000..369c5cfa1
--- /dev/null
+++ b/boost/geometry/core/geometry_id.hpp
@@ -0,0 +1,94 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_GEOMETRY_ID_HPP
+#define BOOST_GEOMETRY_CORE_GEOMETRY_ID_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/type_traits.hpp>
+
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename GeometryTag>
+struct geometry_id
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<GeometryTag>)
+ );
+};
+
+
+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 returning the id of a geometry type
+\details The meta-function geometry_id defines a numerical ID (based on
+ boost::mpl::int_<...> ) for each geometry concept. A numerical ID is
+ sometimes useful, and within Boost.Geometry it is used for the
+ reverse_dispatch metafuntion.
+\note Used for e.g. reverse meta-function
+\ingroup core
+*/
+template <typename Geometry>
+struct geometry_id : core_dispatch::geometry_id<typename tag<Geometry>::type>
+{};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_GEOMETRY_ID_HPP
diff --git a/boost/geometry/core/interior_rings.hpp b/boost/geometry/core/interior_rings.hpp
new file mode 100644
index 000000000..10af2ae4e
--- /dev/null
+++ b/boost/geometry/core/interior_rings.hpp
@@ -0,0 +1,139 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_INTERIOR_RINGS_HPP
+#define BOOST_GEOMETRY_CORE_INTERIOR_RINGS_HPP
+
+#include <cstddef>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/range.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/interior_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+
+/*!
+ \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(POLY const&)
+ \tparam Geometry geometry
+*/
+template <typename Geometry>
+struct interior_rings
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<Geometry>)
+ );
+};
+
+
+} // namespace traits
+
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template
+<
+ typename GeometryTag,
+ typename Geometry
+>
+struct interior_rings {};
+
+
+template <typename Polygon>
+struct interior_rings<polygon_tag, Polygon>
+{
+ static inline
+ typename geometry::interior_return_type<Polygon>::type
+ apply(Polygon& polygon)
+ {
+ return traits::interior_rings
+ <
+ typename boost::remove_const<Polygon>::type
+ >::get(polygon);
+ }
+};
+
+
+} // namespace core_dispatch
+#endif
+
+
+
+/*!
+\brief Function to get the interior rings of a polygon (non const version)
+\ingroup interior_rings
+\note OGC compliance: instead of InteriorRingN
+\tparam Polygon polygon type
+\param polygon the polygon to get the interior rings from
+\return the interior rings (possibly a reference)
+*/
+
+template <typename Polygon>
+inline typename interior_return_type<Polygon>::type interior_rings(Polygon& polygon)
+{
+ return core_dispatch::interior_rings
+ <
+ typename tag<Polygon>::type,
+ Polygon
+ >::apply(polygon);
+}
+
+
+/*!
+\brief Function to get the interior rings of a polygon (const version)
+\ingroup interior_rings
+\note OGC compliance: instead of InteriorRingN
+\tparam Polygon polygon type
+\param polygon the polygon to get the interior rings from
+\return the interior rings (possibly a const reference)
+
+\qbk{distinguish,const version}
+*/
+template <typename Polygon>
+inline typename interior_return_type<Polygon const>::type interior_rings(
+ Polygon const& polygon)
+{
+ return core_dispatch::interior_rings
+ <
+ typename tag<Polygon>::type,
+ Polygon const
+ >::apply(polygon);
+}
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_INTERIOR_RINGS_HPP
diff --git a/boost/geometry/core/interior_type.hpp b/boost/geometry/core/interior_type.hpp
new file mode 100644
index 000000000..02328372f
--- /dev/null
+++ b/boost/geometry/core/interior_type.hpp
@@ -0,0 +1,161 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_INTERIOR_TYPE_HPP
+#define BOOST_GEOMETRY_CORE_INTERIOR_TYPE_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+/*!
+\brief Traits class 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_const_type
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<Geometry>)
+ );
+};
+
+template <typename Geometry>
+struct interior_mutable_type
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<Geometry>)
+ );
+};
+
+
+} // namespace traits
+
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+
+template <typename GeometryTag, typename Geometry>
+struct interior_return_type
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<Geometry>)
+ );
+};
+
+
+template <typename Polygon>
+struct interior_return_type<polygon_tag, Polygon>
+{
+ typedef typename boost::remove_const<Polygon>::type nc_polygon_type;
+
+ typedef typename mpl::if_
+ <
+ boost::is_const<Polygon>,
+ typename traits::interior_const_type<nc_polygon_type>::type,
+ typename traits::interior_mutable_type<nc_polygon_type>::type
+ >::type type;
+};
+
+
+
+
+template <typename GeometryTag, typename Geometry>
+struct interior_type
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<Geometry>)
+ );
+};
+
+
+template <typename Polygon>
+struct interior_type<polygon_tag, Polygon>
+{
+ typedef typename boost::remove_reference
+ <
+ typename interior_return_type<polygon_tag, Polygon>::type
+ >::type type;
+};
+
+
+} // namespace core_dispatch
+#endif
+
+
+/*!
+\brief \brief_meta{type, interior_type (container type
+ of inner rings), \meta_geometry_type}
+\details Interior rings should be organized as a container
+ (std::vector, std::deque, boost::array) with
+ Boost.Range support. This metafunction defines the type
+ of the container.
+\tparam Geometry A type fullfilling the Polygon or MultiPolygon concept.
+\ingroup core
+
+\qbk{[include reference/core/interior_type.qbk]}
+*/
+template <typename Geometry>
+struct interior_type
+{
+ typedef typename core_dispatch::interior_type
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::type type;
+};
+
+template <typename Geometry>
+struct interior_return_type
+{
+ typedef typename core_dispatch::interior_return_type
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_INTERIOR_TYPE_HPP
diff --git a/boost/geometry/core/is_areal.hpp b/boost/geometry/core/is_areal.hpp
new file mode 100644
index 000000000..5ddfa753b
--- /dev/null
+++ b/boost/geometry/core/is_areal.hpp
@@ -0,0 +1,60 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_IS_AREAL_HPP
+#define BOOST_GEOMETRY_CORE_IS_AREAL_HPP
+
+
+#include <boost/type_traits.hpp>
+
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename GeometryTag> struct is_areal : boost::false_type {};
+
+template <> struct is_areal<ring_tag> : boost::true_type {};
+template <> struct is_areal<box_tag> : boost::true_type {};
+template <> struct is_areal<polygon_tag> : boost::true_type {};
+
+
+} // namespace core_dispatch
+#endif
+
+
+
+/*!
+ \brief Meta-function defining "true" for areal types (box, (multi)polygon, ring),
+ \note Used for tag dispatching and meta-function finetuning
+ \note Also a "ring" has areal properties within Boost.Geometry
+ \ingroup core
+*/
+template <typename Geometry>
+struct is_areal : core_dispatch::is_areal<typename tag<Geometry>::type>
+{};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_IS_AREAL_HPP
diff --git a/boost/geometry/core/mutable_range.hpp b/boost/geometry/core/mutable_range.hpp
new file mode 100644
index 000000000..9b53e4057
--- /dev/null
+++ b/boost/geometry/core/mutable_range.hpp
@@ -0,0 +1,98 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_MUTABLE_RANGE_HPP
+#define BOOST_GEOMETRY_CORE_MUTABLE_RANGE_HPP
+
+
+#include <cstddef>
+
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/range.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace traits
+{
+
+/*!
+\brief Metafunction to define the argument passed to the three
+ traits classes clear, push_back and resize
+\ingroup mutable_range
+ */
+template <typename Range>
+struct rvalue_type
+{
+ typedef typename boost::remove_reference<Range>::type& type;
+};
+
+
+/*!
+\brief Traits class to clear a geometry
+\ingroup mutable_range
+ */
+template <typename Range>
+struct clear
+{
+ static inline void apply(typename rvalue_type<Range>::type range)
+ {
+ range.clear();
+ }
+};
+
+
+/*!
+\brief Traits class to append a point to a range (ring, linestring, multi*)
+\ingroup mutable_range
+ */
+template <typename Range>
+struct push_back
+{
+ typedef typename boost::range_value
+ <
+ typename boost::remove_reference<Range>::type
+ >::type item_type;
+
+ static inline void apply(typename rvalue_type<Range>::type range,
+ item_type const& item)
+ {
+ range.push_back(item);
+ }
+};
+
+
+/*!
+\brief Traits class to append a point to a range (ring, linestring, multi*)
+\ingroup mutable_range
+ */
+template <typename Range>
+struct resize
+{
+ static inline void apply(typename rvalue_type<Range>::type range,
+ std::size_t new_size)
+ {
+ range.resize(new_size);
+ }
+};
+
+
+} // namespace traits
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_MUTABLE_RANGE_HPP
diff --git a/boost/geometry/core/point_order.hpp b/boost/geometry/core/point_order.hpp
new file mode 100644
index 000000000..f09086a9d
--- /dev/null
+++ b/boost/geometry/core/point_order.hpp
@@ -0,0 +1,162 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_POINT_ORDER_HPP
+#define BOOST_GEOMETRY_CORE_POINT_ORDER_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/range.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+\brief Enumerates options for the order of points within polygons
+\ingroup enum
+\details The enumeration order_selector describes options for the order of
+ points within a polygon. Polygons can be ordered either clockwise or
+ counterclockwise. The specific order of a polygon type is defined by the
+ point_order metafunction. The point_order metafunction defines a value,
+ which is one of the values enumerated in the order_selector
+
+\qbk{
+[heading See also]
+[link geometry.reference.core.point_order The point_order metafunction]
+}
+*/
+enum order_selector
+{
+ /// Points are ordered clockwise
+ clockwise = 1,
+ /// Points are ordered counter clockwise
+ counterclockwise = 2,
+ /// Points might be stored in any order, algorithms will determine it on the
+ /// fly (not yet supported)
+ 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
+\tparam Ring ring
+*/
+template <typename Ring>
+struct point_order
+{
+ static const order_selector value = clockwise;
+};
+
+
+} // namespace traits
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace point_order
+{
+
+struct clockwise
+{
+ static const order_selector value = geometry::clockwise;
+};
+
+
+}} // namespace detail::point_order
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename Tag, typename Geometry>
+struct point_order
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<Geometry>)
+ );
+};
+
+template <typename Point>
+struct point_order<point_tag, Point>
+ : public detail::point_order::clockwise {};
+
+template <typename Segment>
+struct point_order<segment_tag, Segment>
+ : public detail::point_order::clockwise {};
+
+
+template <typename Box>
+struct point_order<box_tag, Box>
+ : public detail::point_order::clockwise {};
+
+template <typename LineString>
+struct point_order<linestring_tag, LineString>
+ : public detail::point_order::clockwise {};
+
+
+template <typename Ring>
+struct point_order<ring_tag, Ring>
+{
+ static const order_selector value
+ = geometry::traits::point_order<Ring>::value;
+};
+
+// Specialization for polygon: the order is the order of its rings
+template <typename Polygon>
+struct point_order<polygon_tag, Polygon>
+{
+ static const order_selector value = core_dispatch::point_order
+ <
+ ring_tag,
+ typename ring_type<polygon_tag, Polygon>::type
+ >::value ;
+};
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief \brief_meta{value, point order (clockwise\, counterclockwise),
+ \meta_geometry_type}
+\tparam Geometry \tparam_geometry
+\ingroup core
+
+\qbk{[include reference/core/point_order.qbk]}
+*/
+template <typename Geometry>
+struct point_order
+{
+ static const order_selector value = core_dispatch::point_order
+ <
+ typename tag<Geometry>::type,
+ typename boost::remove_const<Geometry>::type
+ >::value;
+};
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_POINT_ORDER_HPP
diff --git a/boost/geometry/core/point_type.hpp b/boost/geometry/core/point_type.hpp
new file mode 100644
index 000000000..e148c84a5
--- /dev/null
+++ b/boost/geometry/core/point_type.hpp
@@ -0,0 +1,130 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_POINT_TYPE_HPP
+#define BOOST_GEOMETRY_CORE_POINT_TYPE_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/range.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/bare_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+/*!
+\brief Traits class indicating the type of contained points
+\ingroup traits
+\par Geometries:
+ - all geometries except point
+\par Specializations should provide:
+ - typedef P type (where P should fulfil the Point concept)
+\tparam Geometry geometry
+*/
+template <typename Geometry>
+struct point_type
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE, (types<Geometry>)
+ );
+};
+
+
+} // 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/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 \brief_meta{type, point_type, \meta_geometry_type}
+\tparam Geometry \tparam_geometry
+\ingroup core
+
+\qbk{[include reference/core/point_type.qbk]}
+*/
+template <typename Geometry>
+struct point_type
+{
+ typedef typename core_dispatch::point_type
+ <
+ typename tag<Geometry>::type,
+ typename boost::geometry::util::bare_type<Geometry>::type
+ >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_POINT_TYPE_HPP
diff --git a/boost/geometry/core/radian_access.hpp b/boost/geometry/core/radian_access.hpp
new file mode 100644
index 000000000..bac77d7bc
--- /dev/null
+++ b/boost/geometry/core/radian_access.hpp
@@ -0,0 +1,152 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_RADIAN_ACCESS_HPP
+#define BOOST_GEOMETRY_CORE_RADIAN_ACCESS_HPP
+
+
+#include <cstddef>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+
+
+#include <boost/geometry/util/math.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template<std::size_t Dimension, typename Geometry>
+struct degree_radian_converter
+{
+ typedef typename fp_coordinate_type<Geometry>::type coordinate_type;
+
+ static inline coordinate_type get(Geometry const& geometry)
+ {
+ return boost::numeric_cast
+ <
+ coordinate_type
+ >(geometry::get<Dimension>(geometry) * geometry::math::d2r);
+ }
+
+ static inline void set(Geometry& geometry, coordinate_type const& radians)
+ {
+ geometry::set<Dimension>(geometry, boost::numeric_cast
+ <
+ coordinate_type
+ >(radians * geometry::math::r2d));
+ }
+
+};
+
+
+// Default, radian (or any other coordinate system) just works like "get"
+template <std::size_t Dimension, typename Geometry, typename DegreeOrRadian>
+struct radian_access
+{
+ typedef typename fp_coordinate_type<Geometry>::type coordinate_type;
+
+ static inline coordinate_type get(Geometry const& geometry)
+ {
+ return geometry::get<Dimension>(geometry);
+ }
+
+ static inline void set(Geometry& geometry, coordinate_type const& radians)
+ {
+ geometry::set<Dimension>(geometry, radians);
+ }
+};
+
+// Specialize, any "degree" coordinate system will be converted to radian
+// but only for dimension 0,1 (so: dimension 2 and heigher are untouched)
+
+template
+<
+ typename Geometry,
+ template<typename> class CoordinateSystem
+>
+struct radian_access<0, Geometry, CoordinateSystem<degree> >
+ : degree_radian_converter<0, Geometry>
+{};
+
+
+template
+<
+ typename Geometry,
+ template<typename> class CoordinateSystem
+>
+struct radian_access<1, Geometry, CoordinateSystem<degree> >
+ : degree_radian_converter<1, Geometry>
+{};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+\brief get coordinate value of a point, result is in Radian
+\details Result is in Radian, even if source coordinate system
+ is in Degrees
+\return coordinate value
+\ingroup get
+\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 fp_coordinate_type<Geometry>::type get_as_radian(Geometry const& 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 set
+\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,
+ typename fp_coordinate_type<Geometry>::type const& radians)
+{
+ detail::radian_access<Dimension, Geometry,
+ typename coordinate_system<Geometry>::type>::set(geometry, radians);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_RADIAN_ACCESS_HPP
diff --git a/boost/geometry/core/reverse_dispatch.hpp b/boost/geometry/core/reverse_dispatch.hpp
new file mode 100644
index 000000000..2e4fb8005
--- /dev/null
+++ b/boost/geometry/core/reverse_dispatch.hpp
@@ -0,0 +1,67 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_REVERSE_DISPATCH_HPP
+#define BOOST_GEOMETRY_CORE_REVERSE_DISPATCH_HPP
+
+
+#include <cstddef>
+
+#include <boost/type_traits.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/greater.hpp>
+
+#include <boost/geometry/core/geometry_id.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+// Different geometries: reverse_dispatch if second ID < first ID
+template <std::size_t GeometryId1, std::size_t GeometryId2>
+struct reverse_dispatch : boost::mpl::if_c
+ <
+ (GeometryId1 > GeometryId2),
+ boost::true_type,
+ boost::false_type
+ >
+{};
+
+
+// Same geometry: never reverse_dispatch
+template <std::size_t GeometryId>
+struct reverse_dispatch<GeometryId, GeometryId> : boost::false_type {};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+template <typename Geometry1, typename Geometry2>
+struct reverse_dispatch : detail::reverse_dispatch
+ <
+ geometry_id<Geometry1>::type::value,
+ geometry_id<Geometry2>::type::value
+ >
+{};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_REVERSE_DISPATCH_HPP
diff --git a/boost/geometry/core/ring_type.hpp b/boost/geometry/core/ring_type.hpp
new file mode 100644
index 000000000..9b984faf3
--- /dev/null
+++ b/boost/geometry/core/ring_type.hpp
@@ -0,0 +1,170 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_RING_TYPE_HPP
+#define BOOST_GEOMETRY_CORE_RING_TYPE_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+
+/*!
+\brief Traits class to indicate ring-type of a polygon's exterior ring/interior rings
+\ingroup traits
+\par Geometries:
+ - polygon
+\par Specializations should provide:
+ - typedef XXX type ( e.g. ring<P> )
+\tparam Geometry geometry
+*/
+template <typename Geometry>
+struct ring_const_type
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<Geometry>)
+ );
+};
+
+template <typename Geometry>
+struct ring_mutable_type
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<Geometry>)
+ );
+};
+
+
+} // namespace traits
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename GeometryTag, typename Geometry>
+struct ring_return_type
+{};
+
+
+template <typename LineString>
+struct ring_return_type<linestring_tag, LineString>
+{
+ typedef LineString& type;
+};
+
+
+template <typename Ring>
+struct ring_return_type<ring_tag, Ring>
+{
+ typedef Ring& type;
+};
+
+
+template <typename Polygon>
+struct ring_return_type<polygon_tag, Polygon>
+{
+ typedef typename boost::remove_const<Polygon>::type nc_polygon_type;
+
+ typedef typename mpl::if_
+ <
+ boost::is_const<Polygon>,
+ typename traits::ring_const_type<nc_polygon_type>::type,
+ typename traits::ring_mutable_type<nc_polygon_type>::type
+ >::type type;
+};
+
+
+template <typename GeometryTag, typename Geometry>
+struct ring_type
+{};
+
+
+template <typename Ring>
+struct ring_type<ring_tag, Ring>
+{
+ typedef Ring type;
+};
+
+
+template <typename Polygon>
+struct ring_type<polygon_tag, Polygon>
+{
+ typedef typename boost::remove_reference
+ <
+ typename ring_return_type<polygon_tag, Polygon>::type
+ >::type type;
+};
+
+
+
+
+
+} // namespace core_dispatch
+#endif
+
+
+/*!
+\brief \brief_meta{type, ring_type, \meta_geometry_type}
+\details A polygon contains one exterior ring
+ and zero or more interior rings (holes).
+ This metafunction retrieves the type of the rings.
+ Exterior ring and each of the interior rings all have the same ring_type.
+\tparam Geometry A type fullfilling the Ring, Polygon or MultiPolygon concept.
+\ingroup core
+
+\qbk{[include reference/core/ring_type.qbk]}
+*/
+template <typename Geometry>
+struct ring_type
+{
+ typedef typename core_dispatch::ring_type
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::type type;
+};
+
+
+template <typename Geometry>
+struct ring_return_type
+{
+ typedef typename core_dispatch::ring_return_type
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_RING_TYPE_HPP
diff --git a/boost/geometry/core/tag.hpp b/boost/geometry/core/tag.hpp
new file mode 100644
index 000000000..1687085a7
--- /dev/null
+++ b/boost/geometry/core/tag.hpp
@@ -0,0 +1,71 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_TAG_HPP
+#define BOOST_GEOMETRY_CORE_TAG_HPP
+
+
+#include <boost/mpl/assert.hpp>
+
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/bare_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+/*!
+\brief Traits class to attach a tag to a geometry
+\details All geometries should implement a traits::tag<G>::type metafunction to indicate their
+ own geometry type.
+\ingroup traits
+\par Geometries:
+ - all geometries
+\par Specializations should provide:
+ - typedef XXX_tag type; (point_tag, box_tag, ...)
+\tparam Geometry geometry
+*/
+template <typename Geometry, typename Enable = void>
+struct tag
+{
+ typedef void type;
+};
+
+} // namespace traits
+
+
+
+/*!
+\brief \brief_meta{type, tag, \meta_geometry_type}
+\details With Boost.Geometry, tags are the driving force of the tag dispatching
+ mechanism. The tag metafunction is therefore used in every free function.
+\tparam Geometry \tparam_geometry
+\ingroup core
+
+\qbk{[include reference/core/tag.qbk]}
+*/
+template <typename Geometry>
+struct tag
+{
+ typedef typename traits::tag
+ <
+ typename geometry::util::bare_type<Geometry>::type
+ >::type type;
+};
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_TAG_HPP
diff --git a/boost/geometry/core/tag_cast.hpp b/boost/geometry/core/tag_cast.hpp
new file mode 100644
index 000000000..47a2e834f
--- /dev/null
+++ b/boost/geometry/core/tag_cast.hpp
@@ -0,0 +1,84 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_TAG_CAST_HPP
+#define BOOST_GEOMETRY_CORE_TAG_CAST_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+\brief Metafunction defining a type being either the specified tag, or one
+ of the specified basetags if the type inherits from them.
+\details Tags can inherit each other. A multi_point inherits, for example,
+ both the multi_tag and the pointlike tag. Often behaviour can be shared
+ between different geometry types. A tag, found by the metafunction tag,
+ can be casted to a more basic tag, and then dispatched by that tag.
+\ingroup core
+\tparam Tag The tag to be casted to one of the base tags
+\tparam BaseTag First base tag
+\tparam BaseTag2 Optional second base tag
+\tparam BaseTag3 Optional third base tag
+\tparam BaseTag4 Optional fourth base tag
+\tparam BaseTag5 Optional fifth base tag
+\tparam BaseTag6 Optional sixth base tag
+\tparam BaseTag7 Optional seventh base tag
+
+\qbk{[include reference/core/tag_cast.qbk]}
+*/
+template
+<
+ typename Tag,
+ typename BaseTag,
+ typename BaseTag2 = void,
+ typename BaseTag3 = void,
+ typename BaseTag4 = void,
+ typename BaseTag5 = void,
+ typename BaseTag6 = void,
+ typename BaseTag7 = void
+>
+struct tag_cast
+{
+ typedef typename boost::mpl::if_
+ <
+ typename boost::is_base_of<BaseTag, Tag>::type,
+ BaseTag,
+ // Try next one in line:
+ typename tag_cast
+ <
+ Tag, BaseTag2, BaseTag3, BaseTag4,
+ BaseTag5, BaseTag6, BaseTag7, void
+ >::type
+ >::type type;
+};
+
+#ifndef DOXYGEN_NO_SPECIALIZATIONS
+
+// Specialization for last one
+template <typename Tag>
+struct tag_cast<Tag, void, void, void, void, void, void, void>
+{
+ // If not found, take specified tag, so do not cast
+ typedef Tag type;
+};
+
+#endif // DOXYGEN_NO_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_TAG_CAST_HPP
diff --git a/boost/geometry/core/tags.hpp b/boost/geometry/core/tags.hpp
new file mode 100644
index 000000000..9272858ed
--- /dev/null
+++ b/boost/geometry/core/tags.hpp
@@ -0,0 +1,94 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_CORE_TAGS_HPP
+#define BOOST_GEOMETRY_CORE_TAGS_HPP
+
+
+namespace boost { namespace geometry
+{
+
+// Tags defining strategies linked to coordinate systems
+
+/// Tag used for casting spherical/geographic coordinate systems
+struct spherical_tag {};
+
+
+/// Tag indicating Cartesian coordinate system family (cartesian,epsg)
+struct cartesian_tag {};
+
+/// Tag indicating Spherical polar coordinate system family
+struct spherical_polar_tag : spherical_tag {};
+
+/// Tag indicating Spherical equatorial coordinate system family
+struct spherical_equatorial_tag : spherical_tag {};
+
+/// Tag indicating Geographic coordinate system family (geographic)
+struct geographic_tag : spherical_tag {};
+
+
+
+// Tags defining tag hierarchy
+
+/// For single-geometries (point, linestring, polygon, box, ring, segment)
+struct single_tag {};
+
+
+/// For multiple-geometries (multi_point, multi_linestring, multi_polygon)
+struct multi_tag {};
+
+/// For point-like types (point, multi_point)
+struct pointlike_tag {};
+
+/// For linear types (linestring, multi-linestring, segment)
+struct linear_tag {};
+
+/// For areal types (polygon, multi_polygon, box, ring)
+struct areal_tag {};
+
+// Subset of areal types (polygon, multi_polygon, ring)
+struct polygonal_tag : areal_tag {};
+
+/// For volume types (also box (?), polyhedron)
+struct volumetric_tag {};
+
+
+// Tags defining geometry types
+
+
+/// "default" tag
+struct geometry_not_recognized_tag {};
+
+/// OGC Point identifying tag
+struct point_tag : single_tag, pointlike_tag {};
+
+/// OGC Linestring identifying tag
+struct linestring_tag : single_tag, linear_tag {};
+
+/// OGC Polygon identifying tag
+struct polygon_tag : single_tag, polygonal_tag {};
+
+/// Convenience (linear) ring identifying tag
+struct ring_tag : single_tag, polygonal_tag {};
+
+/// Convenience 2D or 3D box (mbr / aabb) identifying tag
+struct box_tag : single_tag, areal_tag {};
+
+/// Convenience segment (2-points) identifying tag
+struct segment_tag : single_tag, linear_tag {};
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_CORE_TAGS_HPP
diff --git a/boost/geometry/core/topological_dimension.hpp b/boost/geometry/core/topological_dimension.hpp
new file mode 100644
index 000000000..02f1ed341
--- /dev/null
+++ b/boost/geometry/core/topological_dimension.hpp
@@ -0,0 +1,88 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_CORE_TOPOLOGICAL_DIMENSION_HPP
+#define BOOST_GEOMETRY_CORE_TOPOLOGICAL_DIMENSION_HPP
+
+
+#include <boost/mpl/int.hpp>
+
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+
+template <typename GeometryTag>
+struct top_dim {};
+
+
+template <>
+struct top_dim<point_tag> : boost::mpl::int_<0> {};
+
+
+template <>
+struct top_dim<linestring_tag> : boost::mpl::int_<1> {};
+
+
+template <>
+struct top_dim<segment_tag> : boost::mpl::int_<1> {};
+
+
+// ring: topological dimension of two, but some people say: 1 !!
+template <>
+struct top_dim<ring_tag> : boost::mpl::int_<2> {};
+
+
+template <>
+struct top_dim<box_tag> : boost::mpl::int_<2> {};
+
+
+template <>
+struct top_dim<polygon_tag> : boost::mpl::int_<2> {};
+
+
+
+} // namespace core_dispatch
+#endif
+
+
+
+
+
+/*!
+ \brief Meta-function returning the topological dimension of a geometry
+ \details The topological dimension defines a point as 0-dimensional,
+ a linestring as 1-dimensional,
+ and a ring or polygon as 2-dimensional.
+ \see http://www.math.okstate.edu/mathdept/dynamics/lecnotes/node36.html
+ \ingroup core
+*/
+template <typename Geometry>
+struct topological_dimension
+ : core_dispatch::top_dim<typename tag<Geometry>::type> {};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_TOPOLOGICAL_DIMENSION_HPP
diff --git a/boost/geometry/geometries/adapted/boost_array.hpp b/boost/geometry/geometries/adapted/boost_array.hpp
new file mode 100644
index 000000000..275ccb5c2
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_array.hpp
@@ -0,0 +1,120 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2010 Alfredo Correa
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_ARRAY_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_ARRAY_HPP
+
+
+#ifdef BOOST_GEOMETRY_ADAPTED_BOOST_ARRAY_TAG_DEFINED
+#error Include either "boost_array_as_point" or \
+ "boost_array_as_linestring" or "boost_array_as_ring" \
+ or "boost_array_as_multi_point" to adapt a boost_array
+#endif
+
+#define BOOST_GEOMETRY_ADAPTED_BOOST_ARRAY_TAG_DEFINED
+
+
+#include <cstddef>
+
+#include <boost/type_traits/is_arithmetic.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/array.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+// Create class and specialization to indicate the tag
+// for normal cases and the case that the type of the c-array is arithmetic
+template <bool>
+struct boost_array_tag
+{
+ typedef geometry_not_recognized_tag type;
+};
+
+
+template <>
+struct boost_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<boost::array<CoordinateType, DimensionCount> >
+ : detail::boost_array_tag<boost::is_arithmetic<CoordinateType>::value> {};
+
+
+template <typename CoordinateType, std::size_t DimensionCount>
+struct coordinate_type<boost::array<CoordinateType, DimensionCount> >
+{
+ typedef CoordinateType type;
+};
+
+
+template <typename CoordinateType, std::size_t DimensionCount>
+struct dimension<boost::array<CoordinateType, DimensionCount> >: boost::mpl::int_<DimensionCount> {};
+
+
+template <typename CoordinateType, std::size_t DimensionCount, std::size_t Dimension>
+struct access<boost::array<CoordinateType, DimensionCount>, Dimension>
+{
+ static inline CoordinateType get(boost::array<CoordinateType, DimensionCount> const& a)
+ {
+ return a[Dimension];
+ }
+
+ static inline void set(boost::array<CoordinateType, DimensionCount>& a,
+ CoordinateType const& value)
+ {
+ a[Dimension] = value;
+ }
+};
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+
+#define BOOST_GEOMETRY_REGISTER_BOOST_ARRAY_CS(CoordinateSystem) \
+ namespace boost { namespace geometry { namespace traits { \
+ template <class T, std::size_t N> \
+ struct coordinate_system<boost::array<T, N> > \
+ { \
+ typedef CoordinateSystem type; \
+ }; \
+ }}}
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_ARRAY_HPP
+
diff --git a/boost/geometry/geometries/adapted/boost_fusion.hpp b/boost/geometry/geometries/adapted/boost_fusion.hpp
new file mode 100644
index 000000000..a9aba916a
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_fusion.hpp
@@ -0,0 +1,172 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2011-2012 Akira Takahashi
+// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_FUSION_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_FUSION_HPP
+
+
+#include <cstddef>
+
+#include <boost/fusion/include/is_sequence.hpp>
+#include <boost/fusion/include/size.hpp>
+#include <boost/fusion/include/tag_of.hpp>
+#include <boost/fusion/include/front.hpp>
+#include <boost/fusion/include/at.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/fusion/mpl.hpp>
+#include <boost/mpl/front.hpp>
+#include <boost/mpl/count_if.hpp>
+#include <boost/mpl/pop_front.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/front.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace fusion_adapt_detail
+{
+
+template <class Sequence>
+struct all_same :
+ boost::mpl::bool_<
+ boost::mpl::count_if<
+ Sequence,
+ boost::is_same<
+ typename boost::mpl::front<Sequence>::type,
+ boost::mpl::_
+ >
+ >::value == boost::mpl::size<Sequence>::value
+ >
+{};
+
+template <class Sequence>
+struct is_coordinate_size : boost::mpl::bool_<
+ boost::fusion::result_of::size<Sequence>::value == 2 ||
+ boost::fusion::result_of::size<Sequence>::value == 3> {};
+
+template<typename Sequence>
+struct is_fusion_sequence
+ : mpl::and_<boost::fusion::traits::is_sequence<Sequence>,
+ fusion_adapt_detail::is_coordinate_size<Sequence>,
+ fusion_adapt_detail::all_same<Sequence> >
+{};
+
+
+} // namespace fusion_adapt_detail
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+// Boost Fusion Sequence, 2D or 3D
+template <typename Sequence>
+struct coordinate_type
+ <
+ Sequence,
+ typename boost::enable_if
+ <
+ fusion_adapt_detail::is_fusion_sequence<Sequence>
+ >::type
+ >
+{
+ typedef typename boost::mpl::front<Sequence>::type type;
+};
+
+
+template <typename Sequence>
+struct dimension
+ <
+ Sequence,
+ typename boost::enable_if
+ <
+ fusion_adapt_detail::is_fusion_sequence<Sequence>
+ >::type
+ > : boost::mpl::size<Sequence>
+{};
+
+
+template <typename Sequence, std::size_t Dimension>
+struct access
+ <
+ Sequence,
+ Dimension,
+ typename boost::enable_if
+ <
+ fusion_adapt_detail::is_fusion_sequence<Sequence>
+ >::type
+ >
+{
+ typedef typename coordinate_type<Sequence>::type ctype;
+
+ static inline ctype get(Sequence const& point)
+ {
+ return boost::fusion::at_c<Dimension>(point);
+ }
+
+ template <class CoordinateType>
+ static inline void set(Sequence& point, CoordinateType const& value)
+ {
+ boost::fusion::at_c<Dimension>(point) = value;
+ }
+};
+
+
+template <typename Sequence>
+struct tag
+ <
+ Sequence,
+ typename boost::enable_if
+ <
+ fusion_adapt_detail::is_fusion_sequence<Sequence>
+ >::type
+ >
+{
+ typedef point_tag type;
+};
+
+
+} // namespace traits
+
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+
+// Convenience registration macro to bind a Fusion sequence to a CS
+#define BOOST_GEOMETRY_REGISTER_BOOST_FUSION_CS(CoordinateSystem) \
+ namespace boost { namespace geometry { namespace traits { \
+ template <typename Sequence> \
+ struct coordinate_system \
+ < \
+ Sequence, \
+ typename boost::enable_if \
+ < \
+ fusion_adapt_detail::is_fusion_sequence<Sequence> \
+ >::type \
+ > \
+ { typedef CoordinateSystem type; }; \
+ }}}
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_FUSION_HPP
diff --git a/boost/geometry/geometries/adapted/boost_polygon.hpp b/boost/geometry/geometries/adapted/boost_polygon.hpp
new file mode 100644
index 000000000..fed2362b6
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_polygon.hpp
@@ -0,0 +1,18 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HPP
+
+#include <boost/geometry/geometries/adapted/boost_polygon/point.hpp>
+#include <boost/geometry/geometries/adapted/boost_polygon/box.hpp>
+#include <boost/geometry/geometries/adapted/boost_polygon/ring.hpp>
+#include <boost/geometry/geometries/adapted/boost_polygon/polygon.hpp>
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HPP
+
diff --git a/boost/geometry/geometries/adapted/boost_polygon/box.hpp b/boost/geometry/geometries/adapted/boost_polygon/box.hpp
new file mode 100644
index 000000000..87c3b6065
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_polygon/box.hpp
@@ -0,0 +1,141 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_BOX_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_BOX_HPP
+
+// Adapts Geometries from Boost.Polygon for usage in Boost.Geometry
+// boost::polygon::rectangle_data -> boost::geometry::box
+
+
+#include <boost/polygon/polygon.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+
+template <typename CoordinateType>
+struct tag<boost::polygon::rectangle_data<CoordinateType> >
+{
+ typedef box_tag type;
+};
+
+
+template <typename CoordinateType>
+struct point_type<boost::polygon::rectangle_data<CoordinateType> >
+{
+ // Not sure what to do here. Boost.Polygon's rectangle does NOT define its
+ // point_type (but uses it...)
+ typedef boost::polygon::point_data<CoordinateType> type;
+};
+
+
+template <typename CoordinateType>
+struct indexed_access
+<
+ boost::polygon::rectangle_data<CoordinateType>,
+ min_corner, 0
+>
+{
+ typedef boost::polygon::rectangle_data<CoordinateType> box_type;
+
+ static inline CoordinateType get(box_type const& b)
+ {
+ return boost::polygon::xl(b);
+ }
+
+ static inline void set(box_type& b, CoordinateType const& value)
+ {
+ boost::polygon::xl(b, value);
+ }
+};
+
+
+template <typename CoordinateType>
+struct indexed_access
+<
+ boost::polygon::rectangle_data<CoordinateType>,
+ min_corner, 1
+>
+{
+ typedef boost::polygon::rectangle_data<CoordinateType> box_type;
+
+ static inline CoordinateType get(box_type const& b)
+ {
+ return boost::polygon::yl(b);
+ }
+
+ static inline void set(box_type& b, CoordinateType const& value)
+ {
+ boost::polygon::yl(b, value);
+ }
+};
+
+
+template <typename CoordinateType>
+struct indexed_access
+<
+ boost::polygon::rectangle_data<CoordinateType>,
+ max_corner, 0
+>
+{
+ typedef boost::polygon::rectangle_data<CoordinateType> box_type;
+
+ static inline CoordinateType get(box_type const& b)
+ {
+ return boost::polygon::xh(b);
+ }
+
+ static inline void set(box_type& b, CoordinateType const& value)
+ {
+ boost::polygon::xh(b, value);
+ }
+};
+
+
+template <typename CoordinateType>
+struct indexed_access
+<
+ boost::polygon::rectangle_data<CoordinateType>,
+ max_corner, 1
+>
+{
+ typedef boost::polygon::rectangle_data<CoordinateType> box_type;
+
+ static inline CoordinateType get(box_type const& b)
+ {
+ return boost::polygon::yh(b);
+ }
+
+ static inline void set(box_type& b, CoordinateType const& value)
+ {
+ boost::polygon::yh(b, value);
+ }
+};
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_BOX_HPP
diff --git a/boost/geometry/geometries/adapted/boost_polygon/hole_iterator.hpp b/boost/geometry/geometries/adapted/boost_polygon/hole_iterator.hpp
new file mode 100644
index 000000000..c9c1bc7b6
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_polygon/hole_iterator.hpp
@@ -0,0 +1,84 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HOLE_ITERATOR_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HOLE_ITERATOR_HPP
+
+// Adapts Geometries from Boost.Polygon for usage in Boost.Geometry
+// boost::polygon::polygon_with_holes_data -> boost::geometry::polygon
+// hole_iterator -> returning ring_proxy's instead of normal polygon_data
+
+#include <boost/polygon/polygon.hpp>
+
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace adapt { namespace bp
+{
+
+
+template <typename Polygon, typename RingProxy>
+class hole_iterator
+ : public ::boost::iterator_facade
+ <
+ hole_iterator<Polygon, RingProxy>,
+ RingProxy, // value type
+ boost::forward_traversal_tag,
+ RingProxy // reference type
+ >
+{
+public :
+ typedef typename boost::polygon::polygon_with_holes_traits
+ <
+ Polygon
+ >::iterator_holes_type ith_type;
+
+ explicit inline hole_iterator(Polygon& polygon, ith_type const it)
+ : m_polygon(polygon)
+ , m_base(it)
+ {
+ }
+
+ typedef std::ptrdiff_t difference_type;
+
+private:
+ friend class boost::iterator_core_access;
+
+ inline RingProxy dereference() const
+ {
+ return RingProxy(m_polygon, this->m_base);
+ }
+
+ inline void increment() { ++m_base; }
+ inline void decrement() { --m_base; }
+ inline void advance(difference_type n)
+ {
+ for (int i = 0; i < n; i++)
+ {
+ ++m_base;
+ }
+ }
+
+ inline bool equal(hole_iterator<Polygon, RingProxy> const& other) const
+ {
+ return this->m_base == other.m_base;
+ }
+
+ Polygon& m_polygon;
+ ith_type m_base;
+};
+
+
+}}}}
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HOLE_ITERATOR_HPP
+
diff --git a/boost/geometry/geometries/adapted/boost_polygon/holes_proxy.hpp b/boost/geometry/geometries/adapted/boost_polygon/holes_proxy.hpp
new file mode 100644
index 000000000..c2a6a44db
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_polygon/holes_proxy.hpp
@@ -0,0 +1,204 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HOLES_PROXY_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HOLES_PROXY_HPP
+
+// Adapts Geometries from Boost.Polygon for usage in Boost.Geometry
+// boost::polygon::polygon_with_holes_data -> boost::geometry::polygon
+// pair{begin_holes, begin_holes} -> interior_proxy
+
+#include <boost/polygon/polygon.hpp>
+
+#include <boost/geometry/geometries/adapted/boost_polygon/hole_iterator.hpp>
+#include <boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace adapt { namespace bp
+{
+
+
+// Polygon should implement the boost::polygon::polygon_with_holes_concept
+// Specify constness in the template parameter if necessary
+template<typename Polygon>
+struct holes_proxy
+{
+ typedef ring_proxy
+ <
+ typename boost::mpl::if_
+ <
+ typename boost::is_const<Polygon>,
+ Polygon const,
+ Polygon
+ >::type
+ > proxy_type;
+ typedef hole_iterator<Polygon, proxy_type> iterator_type;
+
+ // The next line does not work probably because coordinate_type is part of the
+ // polygon_traits, but not of the polygon_with_holes_traits
+ // typedef typename boost::polygon::polygon_traits<Polygon>::coordinate_type coordinate_type;
+
+ // So we use:
+ typedef typename Polygon::coordinate_type coordinate_type;
+
+ inline holes_proxy(Polygon& p)
+ : polygon(p)
+ {}
+
+ inline void clear()
+ {
+ Polygon empty;
+ // Clear the holes
+ polygon.set_holes
+ (
+ boost::polygon::begin_holes(empty),
+ boost::polygon::end_holes(empty)
+ );
+ }
+
+ inline void resize(std::size_t new_size)
+ {
+ std::vector<boost::polygon::polygon_data<coordinate_type> > temporary_copy
+ (
+ boost::polygon::begin_holes(polygon),
+ boost::polygon::end_holes(polygon)
+ );
+ temporary_copy.resize(new_size);
+ polygon.set_holes(temporary_copy.begin(), temporary_copy.end());
+ }
+
+ template <typename Ring>
+ inline void push_back(Ring const& ring)
+ {
+ std::vector<boost::polygon::polygon_data<coordinate_type> > temporary_copy
+ (
+ boost::polygon::begin_holes(polygon),
+ boost::polygon::end_holes(polygon)
+ );
+ boost::polygon::polygon_data<coordinate_type> added;
+ boost::polygon::set_points(added, ring.begin(), ring.end());
+ temporary_copy.push_back(added);
+ polygon.set_holes(temporary_copy.begin(), temporary_copy.end());
+ }
+
+
+ Polygon& polygon;
+};
+
+
+// Support holes_proxy for Boost.Range ADP
+
+// Const versions
+template<typename Polygon>
+inline typename boost::geometry::adapt::bp::holes_proxy<Polygon const>::iterator_type
+ range_begin(boost::geometry::adapt::bp::holes_proxy<Polygon const> const& proxy)
+{
+ typename boost::geometry::adapt::bp::holes_proxy<Polygon const>::iterator_type
+ begin(proxy.polygon, boost::polygon::begin_holes(proxy.polygon));
+ return begin;
+}
+
+template<typename Polygon>
+inline typename boost::geometry::adapt::bp::holes_proxy<Polygon const>::iterator_type
+ range_end(boost::geometry::adapt::bp::holes_proxy<Polygon const> const& proxy)
+{
+ typename boost::geometry::adapt::bp::holes_proxy<Polygon const>::iterator_type
+ end(proxy.polygon, boost::polygon::end_holes(proxy.polygon));
+ return end;
+}
+
+// Mutable versions
+template<typename Polygon>
+inline typename boost::geometry::adapt::bp::holes_proxy<Polygon>::iterator_type
+ range_begin(boost::geometry::adapt::bp::holes_proxy<Polygon>& proxy)
+{
+ typename boost::geometry::adapt::bp::holes_proxy<Polygon>::iterator_type
+ begin(proxy.polygon, boost::polygon::begin_holes(proxy.polygon));
+ return begin;
+}
+
+template<typename Polygon>
+inline typename boost::geometry::adapt::bp::holes_proxy<Polygon>::iterator_type
+ range_end(boost::geometry::adapt::bp::holes_proxy<Polygon>& proxy)
+{
+ typename boost::geometry::adapt::bp::holes_proxy<Polygon>::iterator_type
+ end(proxy.polygon, boost::polygon::end_holes(proxy.polygon));
+ return end;
+}
+
+
+}}
+
+namespace traits
+{
+
+template <typename Polygon>
+struct rvalue_type<adapt::bp::holes_proxy<Polygon> >
+{
+ typedef adapt::bp::holes_proxy<Polygon> type;
+};
+
+
+template <typename Polygon>
+struct clear<adapt::bp::holes_proxy<Polygon> >
+{
+ static inline void apply(adapt::bp::holes_proxy<Polygon> proxy)
+ {
+ proxy.clear();
+ }
+};
+
+template <typename Polygon>
+struct resize<adapt::bp::holes_proxy<Polygon> >
+{
+ static inline void apply(adapt::bp::holes_proxy<Polygon> proxy, std::size_t new_size)
+ {
+ proxy.resize(new_size);
+ }
+};
+
+template <typename Polygon>
+struct push_back<adapt::bp::holes_proxy<Polygon> >
+{
+ template <typename Ring>
+ static inline void apply(adapt::bp::holes_proxy<Polygon> proxy, Ring const& ring)
+ {
+ proxy.push_back(ring);
+ }
+};
+
+
+
+} // namespace traits
+
+
+}}
+
+
+// Specialize holes_proxy for Boost.Range
+namespace boost
+{
+ template<typename Polygon>
+ struct range_mutable_iterator<geometry::adapt::bp::holes_proxy<Polygon> >
+ {
+ typedef typename geometry::adapt::bp::holes_proxy<Polygon>::iterator_type type;
+ };
+
+ template<typename Polygon>
+ struct range_const_iterator<geometry::adapt::bp::holes_proxy<Polygon> >
+ {
+ typedef typename geometry::adapt::bp::holes_proxy<Polygon const>::iterator_type type;
+ };
+
+} // namespace boost
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_HOLES_PROXY_HPP
diff --git a/boost/geometry/geometries/adapted/boost_polygon/point.hpp b/boost/geometry/geometries/adapted/boost_polygon/point.hpp
new file mode 100644
index 000000000..2aabb5663
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_polygon/point.hpp
@@ -0,0 +1,102 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_POINT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_POINT_HPP
+
+// Adapts Geometries from Boost.Polygon for usage in Boost.Geometry
+// boost::polygon::point_data -> boost::geometry::point
+
+
+#include <boost/polygon/polygon.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+
+template <typename CoordinateType>
+struct tag<boost::polygon::point_data<CoordinateType> >
+{
+ typedef point_tag type;
+};
+
+
+template <typename CoordinateType>
+struct coordinate_type<boost::polygon::point_data<CoordinateType> >
+{
+ typedef CoordinateType type;
+};
+
+
+template <typename CoordinateType>
+struct coordinate_system<boost::polygon::point_data<CoordinateType> >
+{
+ typedef cs::cartesian type;
+};
+
+
+template <typename CoordinateType>
+struct dimension<boost::polygon::point_data<CoordinateType> >
+ : boost::mpl::int_<2>
+{};
+
+
+template <typename CoordinateType>
+struct access<boost::polygon::point_data<CoordinateType>, 0>
+{
+ typedef boost::polygon::point_data<CoordinateType> point_type;
+
+ static inline CoordinateType get(point_type const& p)
+ {
+ return p.x();
+ }
+
+ static inline void set(point_type& p, CoordinateType const& value)
+ {
+ p.x(value);
+ }
+};
+
+
+template <typename CoordinateType>
+struct access<boost::polygon::point_data<CoordinateType>, 1>
+{
+ typedef boost::polygon::point_data<CoordinateType> point_type;
+
+ static inline CoordinateType get(point_type const& p)
+ {
+ return p.y();
+ }
+
+ static inline void set(point_type& p, CoordinateType const& value)
+ {
+ p.y(value);
+ }
+};
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_POINT_HPP
diff --git a/boost/geometry/geometries/adapted/boost_polygon/polygon.hpp b/boost/geometry/geometries/adapted/boost_polygon/polygon.hpp
new file mode 100644
index 000000000..5703601e0
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_polygon/polygon.hpp
@@ -0,0 +1,111 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_POLYGON_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_POLYGON_HPP
+
+// Adapts Geometries from Boost.Polygon for usage in Boost.Geometry
+// boost::polygon::polygon_with_holes_data -> boost::geometry::polygon
+
+#include <boost/polygon/polygon.hpp>
+
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+
+#include <boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp>
+#include <boost/geometry/geometries/adapted/boost_polygon/hole_iterator.hpp>
+#include <boost/geometry/geometries/adapted/boost_polygon/holes_proxy.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename CoordinateType>
+struct tag<boost::polygon::polygon_with_holes_data<CoordinateType> >
+{
+ typedef polygon_tag type;
+};
+
+template <typename CoordinateType>
+struct ring_const_type<boost::polygon::polygon_with_holes_data<CoordinateType> >
+{
+ typedef adapt::bp::ring_proxy<boost::polygon::polygon_with_holes_data<CoordinateType> const> type;
+};
+
+template <typename CoordinateType>
+struct ring_mutable_type<boost::polygon::polygon_with_holes_data<CoordinateType> >
+{
+ typedef adapt::bp::ring_proxy<boost::polygon::polygon_with_holes_data<CoordinateType> > type;
+};
+
+template <typename CoordinateType>
+struct interior_const_type<boost::polygon::polygon_with_holes_data<CoordinateType> >
+{
+ typedef adapt::bp::holes_proxy<boost::polygon::polygon_with_holes_data<CoordinateType> const> type;
+};
+
+template <typename CoordinateType>
+struct interior_mutable_type<boost::polygon::polygon_with_holes_data<CoordinateType> >
+{
+ typedef adapt::bp::holes_proxy<boost::polygon::polygon_with_holes_data<CoordinateType> > type;
+};
+
+
+template <typename CoordinateType>
+struct exterior_ring<boost::polygon::polygon_with_holes_data<CoordinateType> >
+{
+ typedef boost::polygon::polygon_with_holes_data<CoordinateType> polygon_type;
+ typedef adapt::bp::ring_proxy<polygon_type> proxy;
+ typedef adapt::bp::ring_proxy<polygon_type const> const_proxy;
+
+ static inline proxy get(polygon_type& p)
+ {
+ return proxy(p);
+ }
+
+ static inline const_proxy get(polygon_type const& p)
+ {
+ return const_proxy(p);
+ }
+};
+
+template <typename CoordinateType>
+struct interior_rings<boost::polygon::polygon_with_holes_data<CoordinateType> >
+{
+ typedef boost::polygon::polygon_with_holes_data<CoordinateType> polygon_type;
+ typedef adapt::bp::holes_proxy<polygon_type> proxy;
+ typedef adapt::bp::holes_proxy<polygon_type const> const_proxy;
+
+ static inline proxy get(polygon_type& p)
+ {
+ return proxy(p);
+ }
+
+ static inline const_proxy get(polygon_type const& p)
+ {
+ return const_proxy(p);
+ }
+};
+
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_POLYGON_HPP
+
diff --git a/boost/geometry/geometries/adapted/boost_polygon/ring.hpp b/boost/geometry/geometries/adapted/boost_polygon/ring.hpp
new file mode 100644
index 000000000..93b21fee9
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_polygon/ring.hpp
@@ -0,0 +1,163 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_RING_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_RING_HPP
+
+// Adapts Geometries from Boost.Polygon for usage in Boost.Geometry
+// boost::polygon::polygon_data -> boost::geometry::ring
+
+#include <cstddef>
+#include <boost/polygon/polygon.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/mutable_range.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+template <typename CoordinateType>
+struct tag<boost::polygon::polygon_data<CoordinateType> >
+{
+ typedef ring_tag type;
+};
+
+template <typename CoordinateType>
+struct clear<boost::polygon::polygon_data<CoordinateType> >
+{
+ static inline void apply(boost::polygon::polygon_data<CoordinateType>& data)
+ {
+ // There is no "clear" function but we can assign
+ // a newly (and therefore empty) constructed polygon
+ boost::polygon::assign(data, boost::polygon::polygon_data<CoordinateType>());
+ }
+};
+
+template <typename CoordinateType>
+struct push_back<boost::polygon::polygon_data<CoordinateType> >
+{
+ typedef boost::polygon::point_data<CoordinateType> point_type;
+
+ static inline void apply(boost::polygon::polygon_data<CoordinateType>& data,
+ point_type const& point)
+ {
+ // Boost.Polygon's polygons are not appendable. So create a temporary vector,
+ // add a record and set it to the original. Of course: this is not efficient.
+ // But there seems no other way (without using a wrapper)
+ std::vector<point_type> temporary_vector
+ (
+ boost::polygon::begin_points(data),
+ boost::polygon::end_points(data)
+ );
+ temporary_vector.push_back(point);
+ data.set(temporary_vector.begin(), temporary_vector.end());
+ }
+};
+
+
+
+
+} // namespace traits
+
+}} // namespace boost::geometry
+
+
+// Adapt Boost.Polygon's polygon_data to Boost.Range
+// This just translates to
+// polygon_data.begin() and polygon_data.end()
+namespace boost
+{
+ template<typename CoordinateType>
+ struct range_mutable_iterator<boost::polygon::polygon_data<CoordinateType> >
+ {
+ typedef typename boost::polygon::polygon_traits
+ <
+ boost::polygon::polygon_data<CoordinateType>
+ >::iterator_type type;
+ };
+
+ template<typename CoordinateType>
+ struct range_const_iterator<boost::polygon::polygon_data<CoordinateType> >
+ {
+ typedef typename boost::polygon::polygon_traits
+ <
+ boost::polygon::polygon_data<CoordinateType>
+ >::iterator_type type;
+ };
+
+ template<typename CoordinateType>
+ struct range_size<boost::polygon::polygon_data<CoordinateType> >
+ {
+ typedef std::size_t type;
+ };
+
+} // namespace boost
+
+
+// Support Boost.Polygon's polygon_data for Boost.Range ADP
+namespace boost { namespace polygon
+{
+
+template<typename CoordinateType>
+inline typename polygon_traits
+ <
+ polygon_data<CoordinateType>
+ >::iterator_type range_begin(polygon_data<CoordinateType>& polygon)
+{
+ return polygon.begin();
+}
+
+template<typename CoordinateType>
+inline typename polygon_traits
+ <
+ polygon_data<CoordinateType>
+ >::iterator_type range_begin(polygon_data<CoordinateType> const& polygon)
+{
+ return polygon.begin();
+}
+
+template<typename CoordinateType>
+inline typename polygon_traits
+ <
+ polygon_data<CoordinateType>
+ >::iterator_type range_end(polygon_data<CoordinateType>& polygon)
+{
+ return polygon.end();
+}
+
+template<typename CoordinateType>
+inline typename polygon_traits
+ <
+ polygon_data<CoordinateType>
+ >::iterator_type range_end(polygon_data<CoordinateType> const& polygon)
+{
+ return polygon.end();
+}
+
+template<typename CoordinateType>
+inline std::size_t range_calculate_size(polygon_data<CoordinateType> const& polygon)
+{
+ return polygon.size();
+}
+
+}}
+
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_RING_HPP
diff --git a/boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp b/boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp
new file mode 100644
index 000000000..825ef8061
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_polygon/ring_proxy.hpp
@@ -0,0 +1,301 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_RING_PROXY_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_RING_PROXY_HPP
+
+// Adapts Geometries from Boost.Polygon for usage in Boost.Geometry
+// boost::polygon::polygon_with_holes_data -> boost::geometry::polygon
+// pair{begin_points, end_points} -> ring_proxy
+
+#include <boost/polygon/polygon.hpp>
+#include <boost/range.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+namespace adapt { namespace bp
+{
+
+namespace detail
+{
+
+template <bool Mutable>
+struct modify
+{};
+
+template <>
+struct modify<true>
+{
+ template <typename Ring, typename Point>
+ static inline void push_back(Ring& ring, Point const& point)
+ {
+ // Boost.Polygon's polygons are not appendable. So create a temporary vector,
+ // add a record and set it to the original. Of course: this is not efficient.
+ // But there seems no other way (without using a wrapper)
+ std::vector<Point> temporary_vector
+ (
+ boost::polygon::begin_points(ring),
+ boost::polygon::end_points(ring)
+ );
+ temporary_vector.push_back(point);
+ boost::polygon::set_points(ring, temporary_vector.begin(), temporary_vector.end());
+ }
+
+};
+
+template <>
+struct modify<false>
+{
+ template <typename Ring, typename Point>
+ static inline void push_back(Ring& ring, Point const& point)
+ {
+ }
+
+};
+
+
+}
+
+
+// Polygon should implement the boost::polygon::polygon_with_holes_concept
+// Specify constness in the template parameter if necessary
+template<typename Polygon>
+class ring_proxy
+{
+public :
+ typedef typename boost::polygon::polygon_traits
+ <
+ typename boost::remove_const<Polygon>::type
+ >::iterator_type iterator_type;
+
+ typedef typename boost::polygon::polygon_with_holes_traits
+ <
+ typename boost::remove_const<Polygon>::type
+ >::iterator_holes_type hole_iterator_type;
+
+ static const bool is_mutable = !boost::is_const<Polygon>::type::value;
+
+ inline ring_proxy(Polygon& p)
+ : m_polygon_pointer(&p)
+ , m_do_hole(false)
+ {}
+
+ // Constructor used from hole_iterator
+ inline ring_proxy(Polygon& p, hole_iterator_type hole_it)
+ : m_polygon_pointer(&p)
+ , m_do_hole(true)
+ , m_hole_it(hole_it)
+ {}
+
+ // Default constructor, for mutable polygons / appending (interior) rings
+ inline ring_proxy()
+ : m_polygon_pointer(&m_polygon_for_default_constructor)
+ , m_do_hole(false)
+ {}
+
+
+ iterator_type begin() const
+ {
+ return m_do_hole
+ ? boost::polygon::begin_points(*m_hole_it)
+ : boost::polygon::begin_points(*m_polygon_pointer)
+ ;
+ }
+
+ iterator_type begin()
+ {
+ return m_do_hole
+ ? boost::polygon::begin_points(*m_hole_it)
+ : boost::polygon::begin_points(*m_polygon_pointer)
+ ;
+ }
+
+ iterator_type end() const
+ {
+ return m_do_hole
+ ? boost::polygon::end_points(*m_hole_it)
+ : boost::polygon::end_points(*m_polygon_pointer)
+ ;
+ }
+
+ iterator_type end()
+ {
+ return m_do_hole
+ ? boost::polygon::end_points(*m_hole_it)
+ : boost::polygon::end_points(*m_polygon_pointer)
+ ;
+ }
+
+ // Mutable
+ void clear()
+ {
+ Polygon p;
+ if (m_do_hole)
+ {
+ // Does NOT work see comment above
+ }
+ else
+ {
+ boost::polygon::set_points(*m_polygon_pointer,
+ boost::polygon::begin_points(p),
+ boost::polygon::end_points(p));
+ }
+ }
+
+ void resize(std::size_t new_size)
+ {
+ if (m_do_hole)
+ {
+ // Does NOT work see comment above
+ }
+ else
+ {
+ // TODO: implement this by resizing the container
+ }
+ }
+
+
+
+ template <typename Point>
+ void push_back(Point const& point)
+ {
+ if (m_do_hole)
+ {
+ //detail::modify<is_mutable>::push_back(*m_hole_it, point);
+ //std::cout << "HOLE: " << typeid(*m_hole_it).name() << std::endl;
+ //std::cout << "HOLE: " << typeid(m_hole_it).name() << std::endl;
+ //std::cout << "HOLE: " << typeid(hole_iterator_type).name() << std::endl;
+
+ // Note, ths does NOT work because hole_iterator_type is defined
+ // as a const_iterator by Boost.Polygon
+
+ }
+ else
+ {
+ detail::modify<is_mutable>::push_back(*m_polygon_pointer, point);
+ }
+ }
+
+private :
+ Polygon* m_polygon_pointer;
+ bool m_do_hole;
+ hole_iterator_type m_hole_it;
+
+ Polygon m_polygon_for_default_constructor;
+};
+
+
+
+
+// Support geometry::adapt::bp::ring_proxy for Boost.Range ADP
+template<typename Polygon>
+inline typename boost::geometry::adapt::bp::ring_proxy<Polygon>::iterator_type
+ range_begin(boost::geometry::adapt::bp::ring_proxy<Polygon>& proxy)
+{
+ return proxy.begin();
+}
+
+template<typename Polygon>
+inline typename boost::geometry::adapt::bp::ring_proxy<Polygon const>::iterator_type
+ range_begin(boost::geometry::adapt::bp::ring_proxy<Polygon const> const& proxy)
+{
+ return proxy.begin();
+}
+
+template<typename Polygon>
+inline typename boost::geometry::adapt::bp::ring_proxy<Polygon>::iterator_type
+ range_end(boost::geometry::adapt::bp::ring_proxy<Polygon>& proxy)
+{
+ return proxy.end();
+}
+
+template<typename Polygon>
+inline typename boost::geometry::adapt::bp::ring_proxy<Polygon const>::iterator_type
+ range_end(boost::geometry::adapt::bp::ring_proxy<Polygon const> const& proxy)
+{
+ return proxy.end();
+}
+
+
+
+
+}} // namespace adapt::bp
+
+
+namespace traits
+{
+
+template <typename Polygon>
+struct tag<adapt::bp::ring_proxy<Polygon> >
+{
+ typedef ring_tag type;
+};
+
+
+template <typename Polygon>
+struct rvalue_type<adapt::bp::ring_proxy<Polygon> >
+{
+ typedef adapt::bp::ring_proxy<Polygon> type;
+};
+
+template <typename Polygon>
+struct clear<adapt::bp::ring_proxy<Polygon> >
+{
+ static inline void apply(adapt::bp::ring_proxy<Polygon> proxy)
+ {
+ proxy.clear();
+ }
+};
+
+
+template <typename Polygon>
+struct resize<adapt::bp::ring_proxy<Polygon> >
+{
+ static inline void apply(adapt::bp::ring_proxy<Polygon> proxy, std::size_t new_size)
+ {
+ proxy.resize(new_size);
+ }
+};
+
+template <typename Polygon>
+struct push_back<adapt::bp::ring_proxy<Polygon> >
+{
+ static inline void apply(adapt::bp::ring_proxy<Polygon> proxy,
+ typename boost::polygon::polygon_traits<Polygon>::point_type const& point)
+ {
+ proxy.push_back(point);
+ }
+};
+
+
+} // namespace traits
+
+}} // namespace boost::geometry
+
+// Specialize ring_proxy for Boost.Range
+namespace boost
+{
+ template<typename Polygon>
+ struct range_mutable_iterator<geometry::adapt::bp::ring_proxy<Polygon> >
+ {
+ typedef typename geometry::adapt::bp::ring_proxy<Polygon>::iterator_type type;
+ };
+
+ template<typename Polygon>
+ struct range_const_iterator<geometry::adapt::bp::ring_proxy<Polygon> >
+ {
+ typedef typename geometry::adapt::bp::ring_proxy<Polygon const>::iterator_type type;
+ };
+
+} // namespace boost
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_POLYGON_RING_PROXY_HPP
diff --git a/boost/geometry/geometries/adapted/boost_range/adjacent_filtered.hpp b/boost/geometry/geometries/adapted/boost_range/adjacent_filtered.hpp
new file mode 100644
index 000000000..496dbeaec
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_range/adjacent_filtered.hpp
@@ -0,0 +1,40 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_ADJACENT_FILTERED_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_ADJACENT_FILTERED_HPP
+
+
+#include <boost/range/adaptor/adjacent_filtered.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+template<typename Filter, typename Geometry, bool DefaultPass>
+#if BOOST_VERSION > 104500
+struct tag<boost::adjacent_filtered_range<Filter, Geometry, DefaultPass> >
+#else
+struct tag<boost::range_detail::adjacent_filter_range<Filter, Geometry, DefaultPass> >
+#endif
+{
+ typedef typename geometry::tag<Geometry>::type type;
+};
+
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_ADJACENT_FILTERED_HPP
+
diff --git a/boost/geometry/geometries/adapted/boost_range/filtered.hpp b/boost/geometry/geometries/adapted/boost_range/filtered.hpp
new file mode 100644
index 000000000..990d60846
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_range/filtered.hpp
@@ -0,0 +1,40 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_FILTERED_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_FILTERED_HPP
+
+
+#include <boost/range/adaptor/filtered.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+template<typename Filter, typename Geometry>
+#if BOOST_VERSION > 104500
+struct tag<boost::filtered_range<Filter, Geometry> >
+#else
+struct tag<boost::range_detail::filter_range<Filter, Geometry> >
+#endif
+{
+ typedef typename geometry::tag<Geometry>::type type;
+};
+
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_FILTERED_HPP
+
diff --git a/boost/geometry/geometries/adapted/boost_range/reversed.hpp b/boost/geometry/geometries/adapted/boost_range/reversed.hpp
new file mode 100644
index 000000000..3c8601fe1
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_range/reversed.hpp
@@ -0,0 +1,40 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_REVERSED_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_REVERSED_HPP
+
+
+#include <boost/range/adaptor/reversed.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+template<typename Geometry>
+#if BOOST_VERSION > 104500
+struct tag<boost::reversed_range<Geometry> >
+#else
+struct tag<boost::range_detail::reverse_range<Geometry> >
+#endif
+{
+ typedef typename geometry::tag<Geometry>::type type;
+};
+
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_REVERSED_HPP
+
diff --git a/boost/geometry/geometries/adapted/boost_range/sliced.hpp b/boost/geometry/geometries/adapted/boost_range/sliced.hpp
new file mode 100644
index 000000000..70189819c
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_range/sliced.hpp
@@ -0,0 +1,36 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_SLICED_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_SLICED_HPP
+
+
+#include <boost/range/adaptor/sliced.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+template<typename Geometry>
+struct tag<boost::adaptors::sliced_range<Geometry> >
+{
+ typedef typename geometry::tag<Geometry>::type type;
+};
+
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_SLICED_HPP
+
diff --git a/boost/geometry/geometries/adapted/boost_range/strided.hpp b/boost/geometry/geometries/adapted/boost_range/strided.hpp
new file mode 100644
index 000000000..5c9cdd6a8
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_range/strided.hpp
@@ -0,0 +1,36 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_STRIDED_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_STRIDED_HPP
+
+
+#include <boost/range/adaptor/strided.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+template<typename Geometry>
+struct tag<boost::strided_range<Geometry> >
+{
+ typedef typename geometry::tag<Geometry>::type type;
+};
+
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_STRIDED_HPP
+
diff --git a/boost/geometry/geometries/adapted/boost_range/uniqued.hpp b/boost/geometry/geometries/adapted/boost_range/uniqued.hpp
new file mode 100644
index 000000000..beb51fe0b
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_range/uniqued.hpp
@@ -0,0 +1,40 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2010-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_UNIQUED_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_UNIQUED_HPP
+
+
+#include <boost/range/adaptor/uniqued.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+template<typename Geometry>
+#if BOOST_VERSION > 104500
+struct tag<boost::uniqued_range<Geometry> >
+#else
+struct tag<boost::range_detail::unique_range<Geometry> >
+#endif
+{
+ typedef typename geometry::tag<Geometry>::type type;
+};
+
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_RANGE_UNIQUED_HPP
+
diff --git a/boost/geometry/geometries/adapted/boost_tuple.hpp b/boost/geometry/geometries/adapted/boost_tuple.hpp
new file mode 100644
index 000000000..58065fe9a
--- /dev/null
+++ b/boost/geometry/geometries/adapted/boost_tuple.hpp
@@ -0,0 +1,109 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_TUPLE_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_BOOST_TUPLE_HPP
+
+
+#include <cstddef>
+
+#include <boost/tuple/tuple.hpp>
+
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+struct tag<boost::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> >
+{
+ typedef point_tag type;
+};
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+struct coordinate_type<boost::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> >
+{
+ typedef T1 type;
+};
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+struct dimension<boost::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> >
+ : boost::mpl::int_
+ <
+ boost::tuples::length
+ <
+ boost::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>
+ >::value
+ >
+{};
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10,
+ std::size_t Dimension>
+struct access
+ <
+ boost::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>,
+ Dimension
+ >
+{
+ static inline T1 get(
+ boost::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> const& point)
+ {
+ return point.template get<Dimension>();
+ }
+
+ static inline void set(
+ boost::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& point,
+ T1 const& value)
+ {
+ point.template get<Dimension>() = value;
+ }
+};
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+
+// Convenience registration macro to bind boost::tuple to a CS
+#define BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(CoordinateSystem) \
+ namespace boost { namespace geometry { namespace traits { \
+ template <typename T1, typename T2, typename T3, typename T4, typename T5, \
+ typename T6, typename T7, typename T8, typename T9, typename T10> \
+ struct coordinate_system<boost::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> > \
+ { \
+ typedef CoordinateSystem type; \
+ }; \
+ }}}
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_TUPLE_HPP
diff --git a/boost/geometry/geometries/adapted/c_array.hpp b/boost/geometry/geometries/adapted/c_array.hpp
new file mode 100644
index 000000000..1b4523d96
--- /dev/null
+++ b/boost/geometry/geometries/adapted/c_array.hpp
@@ -0,0 +1,111 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_HPP
+
+#include <cstddef>
+
+#include <boost/type_traits/is_arithmetic.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+// Create class and specialization to indicate the tag
+// for normal cases and the case that the type of the c-array is arithmetic
+template <bool>
+struct c_array_tag
+{
+ typedef geometry_not_recognized_tag type;
+};
+
+
+template <>
+struct c_array_tag<true>
+{
+ typedef point_tag type;
+};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+// Assign the point-tag, preventing arrays of points getting a point-tag
+template <typename CoordinateType, std::size_t DimensionCount>
+struct tag<CoordinateType[DimensionCount]>
+ : detail::c_array_tag<boost::is_arithmetic<CoordinateType>::value> {};
+
+
+template <typename CoordinateType, std::size_t DimensionCount>
+struct coordinate_type<CoordinateType[DimensionCount]>
+{
+ typedef CoordinateType type;
+};
+
+
+template <typename CoordinateType, std::size_t DimensionCount>
+struct dimension<CoordinateType[DimensionCount]>: boost::mpl::int_<DimensionCount> {};
+
+
+template <typename CoordinateType, std::size_t DimensionCount, std::size_t Dimension>
+struct access<CoordinateType[DimensionCount], Dimension>
+{
+ static inline CoordinateType get(CoordinateType const p[DimensionCount])
+ {
+ return p[Dimension];
+ }
+
+ static inline void set(CoordinateType p[DimensionCount],
+ CoordinateType const& value)
+ {
+ p[Dimension] = value;
+ }
+};
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+
+#define BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(CoordinateSystem) \
+ namespace boost { namespace geometry { namespace traits { \
+ template <typename T, std::size_t N> \
+ struct coordinate_system<T[N]> \
+ { \
+ typedef CoordinateSystem type; \
+ }; \
+ }}}
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_C_ARRAY_HPP
diff --git a/boost/geometry/geometries/adapted/std_pair_as_segment.hpp b/boost/geometry/geometries/adapted/std_pair_as_segment.hpp
new file mode 100644
index 000000000..e9200e0fd
--- /dev/null
+++ b/boost/geometry/geometries/adapted/std_pair_as_segment.hpp
@@ -0,0 +1,98 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_PAIR_AS_SEGMENT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_PAIR_AS_SEGMENT_HPP
+
+// Only possible if the std::pair is not used for iterator/pair
+// (maybe it is possible to avoid that by detecting in the other file
+// if an iterator was used in the pair)
+
+#ifdef BOOST_GEOMETRY_ADAPTED_STD_RANGE_TAG_DEFINED
+#error Include only one headerfile to register tag for adapted std:: containers or iterator pair
+#endif
+
+#define BOOST_GEOMETRY_ADAPTED_STD_RANGE_TAG_DEFINED
+
+
+#include <cstddef>
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+
+template <typename Point>
+struct tag<std::pair<Point, Point> >
+{
+ typedef segment_tag type;
+};
+
+template <typename Point>
+struct point_type<std::pair<Point, Point> >
+{
+ typedef Point type;
+};
+
+template <typename Point, std::size_t Dimension>
+struct indexed_access<std::pair<Point, Point>, 0, Dimension>
+{
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+
+ static inline coordinate_type get(std::pair<Point, Point> const& s)
+ {
+ return geometry::get<Dimension>(s.first);
+ }
+
+ static inline void set(std::pair<Point, Point>& s, coordinate_type const& value)
+ {
+ geometry::set<Dimension>(s.first, value);
+ }
+};
+
+
+template <typename Point, std::size_t Dimension>
+struct indexed_access<std::pair<Point, Point>, 1, Dimension>
+{
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+
+ static inline coordinate_type get(std::pair<Point, Point> const& s)
+ {
+ return geometry::get<Dimension>(s.second);
+ }
+
+ static inline void set(std::pair<Point, Point>& s, coordinate_type const& value)
+ {
+ geometry::set<Dimension>(s.second, value);
+ }
+};
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_PAIR_AS_SEGMENT_HPP
diff --git a/boost/geometry/geometries/box.hpp b/boost/geometry/geometries/box.hpp
new file mode 100644
index 000000000..a2e3d4fd7
--- /dev/null
+++ b/boost/geometry/geometries/box.hpp
@@ -0,0 +1,134 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_BOX_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_BOX_HPP
+
+#include <cstddef>
+
+#include <boost/concept/assert.hpp>
+
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+namespace model
+{
+
+
+/*!
+ \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)
+ {
+ geometry::convert(min_corner, m_min_corner);
+ geometry::convert(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;
+};
+
+
+} // namespace model
+
+
+// Traits specializations for box above
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename Point>
+struct tag<model::box<Point> >
+{
+ typedef box_tag type;
+};
+
+template <typename Point>
+struct point_type<model::box<Point> >
+{
+ typedef Point type;
+};
+
+template <typename Point, std::size_t Dimension>
+struct indexed_access<model::box<Point>, min_corner, Dimension>
+{
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+
+ static inline coordinate_type get(model::box<Point> const& b)
+ {
+ return geometry::get<Dimension>(b.min_corner());
+ }
+
+ static inline void set(model::box<Point>& b, coordinate_type const& value)
+ {
+ geometry::set<Dimension>(b.min_corner(), value);
+ }
+};
+
+template <typename Point, std::size_t Dimension>
+struct indexed_access<model::box<Point>, max_corner, Dimension>
+{
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+
+ static inline coordinate_type get(model::box<Point> const& b)
+ {
+ return geometry::get<Dimension>(b.max_corner());
+ }
+
+ static inline void set(model::box<Point>& b, coordinate_type const& value)
+ {
+ geometry::set<Dimension>(b.max_corner(), value);
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_BOX_HPP
diff --git a/boost/geometry/geometries/concepts/box_concept.hpp b/boost/geometry/geometries/concepts/box_concept.hpp
new file mode 100644
index 000000000..ea0d84cf3
--- /dev/null
+++ b/boost/geometry/geometries/concepts/box_concept.hpp
@@ -0,0 +1,136 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_BOX_CONCEPT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_BOX_CONCEPT_HPP
+
+
+#include <cstddef>
+
+#include <boost/concept_check.hpp>
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+
+namespace boost { namespace geometry { namespace concept
+{
+
+
+/*!
+\brief Box concept
+\ingroup concepts
+\par Formal definition:
+The box concept is defined as following:
+- there must be a specialization of traits::tag defining box_tag as type
+- there must be a specialization of traits::point_type to define the
+ underlying point type (even if it does not consist of points, it should define
+ this type, to indicate the points it can work with)
+- there must be a specialization of traits::indexed_access, per index
+ (min_corner, max_corner) and per dimension, with two functions:
+ - get to get a coordinate value
+ - set to set a coordinate value (this one is not checked for ConstBox)
+*/
+template <typename Geometry>
+class Box
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+
+
+ template
+ <
+ std::size_t Index,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+ >
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ Geometry* b = 0;
+ geometry::set<Index, Dimension>(*b, geometry::get<Index, Dimension>(*b));
+ dimension_checker<Index, Dimension + 1, DimensionCount>::apply();
+ }
+ };
+
+ template <std::size_t Index, std::size_t DimensionCount>
+ struct dimension_checker<Index, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public :
+ BOOST_CONCEPT_USAGE(Box)
+ {
+ static const std::size_t n = dimension<Geometry>::type::value;
+ dimension_checker<min_corner, 0, n>::apply();
+ dimension_checker<max_corner, 0, n>::apply();
+ }
+#endif
+};
+
+
+/*!
+\brief Box concept (const version)
+\ingroup const_concepts
+\details The ConstBox concept apply the same as the Box concept,
+but does not apply write access.
+*/
+template <typename Geometry>
+class ConstBox
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename coordinate_type<Geometry>::type coordinate_type;
+
+ template
+ <
+ std::size_t Index,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+ >
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ const Geometry* b = 0;
+ coordinate_type coord(geometry::get<Index, Dimension>(*b));
+ boost::ignore_unused_variable_warning(coord);
+ dimension_checker<Index, Dimension + 1, DimensionCount>::apply();
+ }
+ };
+
+ template <std::size_t Index, std::size_t DimensionCount>
+ struct dimension_checker<Index, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public :
+ BOOST_CONCEPT_USAGE(ConstBox)
+ {
+ static const std::size_t n = dimension<Geometry>::type::value;
+ dimension_checker<min_corner, 0, n>::apply();
+ dimension_checker<max_corner, 0, n>::apply();
+ }
+#endif
+};
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_BOX_CONCEPT_HPP
diff --git a/boost/geometry/geometries/concepts/check.hpp b/boost/geometry/geometries/concepts/check.hpp
new file mode 100644
index 000000000..68cca9e98
--- /dev/null
+++ b/boost/geometry/geometries/concepts/check.hpp
@@ -0,0 +1,205 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_CHECK_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_CHECK_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/concept/requires.hpp>
+
+#include <boost/type_traits/is_const.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+
+#include <boost/geometry/geometries/concepts/box_concept.hpp>
+#include <boost/geometry/geometries/concepts/linestring_concept.hpp>
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/geometries/concepts/polygon_concept.hpp>
+#include <boost/geometry/geometries/concepts/ring_concept.hpp>
+#include <boost/geometry/geometries/concepts/segment_concept.hpp>
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+#include <boost/variant/variant_fwd.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace concept_check
+{
+
+template <typename Concept>
+class check
+{
+ BOOST_CONCEPT_ASSERT((Concept ));
+};
+
+}} // namespace detail::concept_check
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry,
+ typename GeometryTag = typename geometry::tag<Geometry>::type,
+ bool IsConst = boost::is_const<Geometry>::type::value
+>
+struct check : not_implemented<GeometryTag>
+{};
+
+
+template <typename Geometry>
+struct check<Geometry, point_tag, true>
+ : detail::concept_check::check<concept::ConstPoint<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<Geometry, point_tag, false>
+ : detail::concept_check::check<concept::Point<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<Geometry, linestring_tag, true>
+ : detail::concept_check::check<concept::ConstLinestring<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<Geometry, linestring_tag, false>
+ : detail::concept_check::check<concept::Linestring<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<Geometry, ring_tag, true>
+ : detail::concept_check::check<concept::ConstRing<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<Geometry, ring_tag, false>
+ : detail::concept_check::check<concept::Ring<Geometry> >
+{};
+
+template <typename Geometry>
+struct check<Geometry, polygon_tag, true>
+ : detail::concept_check::check<concept::ConstPolygon<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<Geometry, polygon_tag, false>
+ : detail::concept_check::check<concept::Polygon<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<Geometry, box_tag, true>
+ : detail::concept_check::check<concept::ConstBox<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<Geometry, box_tag, false>
+ : detail::concept_check::check<concept::Box<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<Geometry, segment_tag, true>
+ : detail::concept_check::check<concept::ConstSegment<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<Geometry, segment_tag, false>
+ : detail::concept_check::check<concept::Segment<Geometry> >
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+
+
+namespace concept
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template <typename Geometry>
+struct checker : dispatch::check<Geometry>
+{};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct checker<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct checker<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const>
+{};
+
+
+}
+#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> c;
+ boost::ignore_unused_variable_warning(c);
+}
+
+
+/*!
+ \brief Checks, in compile-time, the concept of two geometries, and if they
+ have equal dimensions
+ \ingroup concepts
+*/
+template <typename Geometry1, typename Geometry2>
+inline void check_concepts_and_equal_dimensions()
+{
+ check<Geometry1>();
+ check<Geometry2>();
+ assert_dimension_equal<Geometry1, Geometry2>();
+}
+
+
+} // namespace concept
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_CHECK_HPP
diff --git a/boost/geometry/geometries/concepts/linestring_concept.hpp b/boost/geometry/geometries/concepts/linestring_concept.hpp
new file mode 100644
index 000000000..091336fe3
--- /dev/null
+++ b/boost/geometry/geometries/concepts/linestring_concept.hpp
@@ -0,0 +1,125 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_LINESTRING_CONCEPT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_LINESTRING_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/mutable_range.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+
+
+namespace boost { namespace geometry { namespace concept
+{
+
+
+/*!
+\brief Linestring concept
+\ingroup concepts
+\par Formal definition:
+The linestring concept is defined as following:
+- there must be a specialization of traits::tag defining linestring_tag as type
+- it must behave like a Boost.Range
+- it must implement a std::back_insert_iterator
+ - either by implementing push_back
+ - or by specializing std::back_insert_iterator
+
+\note to fulfill the concepts, no traits class has to be specialized to
+define the point type.
+
+\par Example:
+
+A custom linestring, defining the necessary specializations to fulfill to the concept.
+
+Suppose that the following linestring is defined:
+\dontinclude doxygen_5.cpp
+\skip custom_linestring1
+\until };
+
+It can then be adapted to the concept as following:
+\dontinclude doxygen_5.cpp
+\skip adapt custom_linestring1
+\until }}
+
+\note
+- There is also the registration macro BOOST_GEOMETRY_REGISTER_LINESTRING
+- For registration of std::vector<P> (and deque, and list) it is enough to
+include the header-file geometries/adapted/std_as_linestring.hpp. That registers
+a vector as a linestring (so it cannot be registered as a linear ring then,
+in the same source code).
+
+
+*/
+
+template <typename Geometry>
+class Linestring
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Point<point_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+public :
+
+ BOOST_CONCEPT_USAGE(Linestring)
+ {
+ Geometry* ls = 0;
+ traits::clear<Geometry>::apply(*ls);
+ traits::resize<Geometry>::apply(*ls, 0);
+ point_type* point = 0;
+ traits::push_back<Geometry>::apply(*ls, *point);
+ }
+#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>) );
+ // Relaxed the concept.
+ BOOST_CONCEPT_ASSERT( (boost::ForwardRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstLinestring)
+ {
+ }
+#endif
+};
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_LINESTRING_CONCEPT_HPP
diff --git a/boost/geometry/geometries/concepts/point_concept.hpp b/boost/geometry/geometries/concepts/point_concept.hpp
new file mode 100644
index 000000000..1e1b31e61
--- /dev/null
+++ b/boost/geometry/geometries/concepts/point_concept.hpp
@@ -0,0 +1,176 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POINT_CONCEPT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POINT_CONCEPT_HPP
+
+#include <cstddef>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+
+
+
+
+namespace boost { namespace geometry { namespace concept
+{
+
+/*!
+\brief Point concept.
+\ingroup concepts
+
+\par Formal definition:
+The point concept is defined as following:
+- there must be a specialization of traits::tag defining point_tag as type
+- there must be a specialization of traits::coordinate_type defining the type
+ of its coordinates
+- there must be a specialization of traits::coordinate_system defining its
+ coordinate system (cartesian, spherical, etc)
+- there must be a specialization of traits::dimension defining its number
+ of dimensions (2, 3, ...) (derive it conveniently
+ from boost::mpl::int_&lt;X&gt; for X-D)
+- there must be a specialization of traits::access, per dimension,
+ with two functions:
+ - \b get to get a coordinate value
+ - \b set to set a coordinate value (this one is not checked for ConstPoint)
+
+\par Example:
+
+A legacy point, defining the necessary specializations to fulfil to the concept.
+
+Suppose that the following point is defined:
+\dontinclude doxygen_5.cpp
+\skip legacy_point1
+\until };
+
+It can then be adapted to the concept as following:
+\dontinclude doxygen_5.cpp
+\skip adapt legacy_point1
+\until }}
+
+Note that it is done like above to show the system. Users will normally use the registration macro.
+
+\par Example:
+
+A read-only legacy point, using a macro to fulfil to the ConstPoint concept.
+It cannot be modified by the library but can be used in all algorithms where
+points are not modified.
+
+The point looks like the following:
+
+\dontinclude doxygen_5.cpp
+\skip legacy_point2
+\until };
+
+It uses the macro as following:
+\dontinclude doxygen_5.cpp
+\skip adapt legacy_point2
+\until end adaptation
+
+*/
+
+template <typename Geometry>
+class Point
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ typedef typename coordinate_type<Geometry>::type ctype;
+ typedef typename coordinate_system<Geometry>::type csystem;
+
+ enum { ccount = dimension<Geometry>::value };
+
+
+ template <typename P, std::size_t Dimension, std::size_t DimensionCount>
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ P* p = 0;
+ geometry::set<Dimension>(*p, geometry::get<Dimension>(*p));
+ dimension_checker<P, Dimension+1, DimensionCount>::apply();
+ }
+ };
+
+
+ template <typename P, std::size_t DimensionCount>
+ struct dimension_checker<P, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public:
+
+ /// BCCL macro to apply the Point concept
+ BOOST_CONCEPT_USAGE(Point)
+ {
+ dimension_checker<Geometry, 0, ccount>::apply();
+ }
+#endif
+};
+
+
+/*!
+\brief point concept (const version).
+
+\ingroup const_concepts
+
+\details The ConstPoint concept apply the same as the Point concept,
+but does not apply write access.
+
+*/
+template <typename Geometry>
+class ConstPoint
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ typedef typename coordinate_type<Geometry>::type ctype;
+ typedef typename coordinate_system<Geometry>::type csystem;
+
+ enum { ccount = dimension<Geometry>::value };
+
+
+ template <typename P, std::size_t Dimension, std::size_t DimensionCount>
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ const P* p = 0;
+ ctype coord(geometry::get<Dimension>(*p));
+ boost::ignore_unused_variable_warning(coord);
+ dimension_checker<P, Dimension+1, DimensionCount>::apply();
+ }
+ };
+
+
+ template <typename P, std::size_t DimensionCount>
+ struct dimension_checker<P, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public:
+
+ /// BCCL macro to apply the ConstPoint concept
+ BOOST_CONCEPT_USAGE(ConstPoint)
+ {
+ dimension_checker<Geometry, 0, ccount>::apply();
+ }
+#endif
+};
+
+}}} // namespace boost::geometry::concept
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POINT_CONCEPT_HPP
diff --git a/boost/geometry/geometries/concepts/polygon_concept.hpp b/boost/geometry/geometries/concepts/polygon_concept.hpp
new file mode 100644
index 000000000..b478a2274
--- /dev/null
+++ b/boost/geometry/geometries/concepts/polygon_concept.hpp
@@ -0,0 +1,135 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POLYGON_CONCEPT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POLYGON_CONCEPT_HPP
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/geometries/concepts/ring_concept.hpp>
+
+
+namespace boost { namespace geometry { namespace concept
+{
+
+/*!
+\brief Checks polygon concept
+\ingroup concepts
+*/
+template <typename PolygonType>
+class Polygon
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::remove_const<PolygonType>::type polygon_type;
+
+ typedef typename traits::ring_const_type<polygon_type>::type ring_const_type;
+ typedef typename traits::ring_mutable_type<polygon_type>::type ring_mutable_type;
+ typedef typename traits::interior_const_type<polygon_type>::type interior_const_type;
+ typedef typename traits::interior_mutable_type<polygon_type>::type interior_mutable_type;
+
+ typedef typename point_type<PolygonType>::type point_type;
+ typedef typename ring_type<PolygonType>::type ring_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()
+ {
+ polygon_type* poly = 0;
+ polygon_type const* cpoly = poly;
+
+ ring_mutable_type e = traits::exterior_ring<PolygonType>::get(*poly);
+ interior_mutable_type i = traits::interior_rings<PolygonType>::get(*poly);
+ ring_const_type ce = traits::exterior_ring<PolygonType>::get(*cpoly);
+ interior_const_type ci = traits::interior_rings<PolygonType>::get(*cpoly);
+
+ boost::ignore_unused_variable_warning(e);
+ boost::ignore_unused_variable_warning(i);
+ boost::ignore_unused_variable_warning(ce);
+ boost::ignore_unused_variable_warning(ci);
+ boost::ignore_unused_variable_warning(poly);
+ boost::ignore_unused_variable_warning(cpoly);
+ }
+ };
+
+public:
+
+ BOOST_CONCEPT_USAGE(Polygon)
+ {
+ checker::apply();
+ }
+#endif
+};
+
+
+/*!
+\brief Checks polygon concept (const version)
+\ingroup const_concepts
+*/
+template <typename PolygonType>
+class ConstPolygon
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ typedef typename boost::remove_const<PolygonType>::type const_polygon_type;
+
+ typedef typename traits::ring_const_type<const_polygon_type>::type ring_const_type;
+ typedef typename traits::interior_const_type<const_polygon_type>::type interior_const_type;
+
+ typedef typename point_type<const_polygon_type>::type point_type;
+ typedef typename ring_type<const_polygon_type>::type ring_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()
+ {
+ const_polygon_type const* cpoly = 0;
+
+ ring_const_type ce = traits::exterior_ring<const_polygon_type>::get(*cpoly);
+ interior_const_type ci = traits::interior_rings<const_polygon_type>::get(*cpoly);
+
+ boost::ignore_unused_variable_warning(ce);
+ boost::ignore_unused_variable_warning(ci);
+ boost::ignore_unused_variable_warning(cpoly);
+ }
+ };
+
+public:
+
+ BOOST_CONCEPT_USAGE(ConstPolygon)
+ {
+ checker::apply();
+ }
+#endif
+};
+
+}}} // namespace boost::geometry::concept
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POLYGON_CONCEPT_HPP
diff --git a/boost/geometry/geometries/concepts/ring_concept.hpp b/boost/geometry/geometries/concepts/ring_concept.hpp
new file mode 100644
index 000000000..02a36c96f
--- /dev/null
+++ b/boost/geometry/geometries/concepts/ring_concept.hpp
@@ -0,0 +1,99 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_RING_CONCEPT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_RING_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/mutable_range.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+
+namespace boost { namespace geometry { namespace concept
+{
+
+
+/*!
+\brief ring concept
+\ingroup concepts
+\par Formal definition:
+The ring concept is defined as following:
+- there must be a specialization of traits::tag defining ring_tag as type
+- it must behave like a Boost.Range
+- there can optionally be a specialization of traits::point_order defining the
+ order or orientation of its points, clockwise or counterclockwise.
+- it must implement a std::back_insert_iterator
+ (This is the same as the for the concept Linestring, and described there)
+
+\note to fulfill the concepts, no traits class has to be specialized to
+define the point 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)
+ {
+ Geometry* ring = 0;
+ traits::clear<Geometry>::apply(*ring);
+ traits::resize<Geometry>::apply(*ring, 0);
+ point_type* point = 0;
+ traits::push_back<Geometry>::apply(*ring, *point);
+ }
+#endif
+};
+
+
+/*!
+\brief (linear) ring concept (const version)
+\ingroup const_concepts
+\details The ConstLinearRing concept check the same as the Geometry concept,
+but does not check write access.
+*/
+template <typename Geometry>
+class ConstRing
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstRing)
+ {
+ }
+#endif
+};
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_RING_CONCEPT_HPP
diff --git a/boost/geometry/geometries/concepts/segment_concept.hpp b/boost/geometry/geometries/concepts/segment_concept.hpp
new file mode 100644
index 000000000..8d2d30015
--- /dev/null
+++ b/boost/geometry/geometries/concepts/segment_concept.hpp
@@ -0,0 +1,135 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_SEGMENT_CONCEPT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_SEGMENT_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+
+namespace boost { namespace geometry { namespace concept
+{
+
+
+/*!
+\brief Segment concept.
+\ingroup concepts
+\details 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 = 0;
+ geometry::set<Index, Dimension>(*s, geometry::get<Index, Dimension>(*s));
+ dimension_checker<Index, Dimension + 1, DimensionCount>::apply();
+ }
+ };
+
+ template <size_t Index, size_t DimensionCount>
+ struct dimension_checker<Index, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public :
+
+ BOOST_CONCEPT_USAGE(Segment)
+ {
+ static const size_t n = dimension<point_type>::type::value;
+ dimension_checker<0, 0, n>::apply();
+ dimension_checker<1, 0, n>::apply();
+ }
+#endif
+};
+
+
+/*!
+\brief Segment concept (const version).
+\ingroup const_concepts
+\details The ConstSegment concept verifies the same as the Segment concept,
+but does not verify write access.
+*/
+template <typename Geometry>
+class ConstSegment
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename coordinate_type<Geometry>::type coordinate_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point_type>) );
+
+
+ template <size_t Index, size_t Dimension, size_t DimensionCount>
+ struct dimension_checker
+ {
+ static void apply()
+ {
+ const Geometry* s = 0;
+ coordinate_type coord(geometry::get<Index, Dimension>(*s));
+ boost::ignore_unused_variable_warning(coord);
+ dimension_checker<Index, Dimension + 1, DimensionCount>::apply();
+ }
+ };
+
+ template <size_t Index, size_t DimensionCount>
+ struct dimension_checker<Index, DimensionCount, DimensionCount>
+ {
+ static void apply() {}
+ };
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstSegment)
+ {
+ static const size_t n = dimension<point_type>::type::value;
+ dimension_checker<0, 0, n>::apply();
+ dimension_checker<1, 0, n>::apply();
+ }
+#endif
+};
+
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_SEGMENT_CONCEPT_HPP
diff --git a/boost/geometry/geometries/geometries.hpp b/boost/geometry/geometries/geometries.hpp
new file mode 100644
index 000000000..cda55c1d2
--- /dev/null
+++ b/boost/geometry/geometries/geometries.hpp
@@ -0,0 +1,25 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_HPP
+
+#include <boost/geometry/geometries/point.hpp>
+#include <boost/geometry/geometries/linestring.hpp>
+#include <boost/geometry/geometries/polygon.hpp>
+
+#include <boost/geometry/geometries/box.hpp>
+#include <boost/geometry/geometries/ring.hpp>
+#include <boost/geometry/geometries/segment.hpp>
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_HPP
diff --git a/boost/geometry/geometries/linestring.hpp b/boost/geometry/geometries/linestring.hpp
new file mode 100644
index 000000000..38bc3d4c4
--- /dev/null
+++ b/boost/geometry/geometries/linestring.hpp
@@ -0,0 +1,95 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_LINESTRING_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_LINESTRING_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/assert.hpp>
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace model
+{
+
+/*!
+\brief A linestring (named so by OGC) is a collection (default a vector) of points.
+\ingroup geometries
+\tparam Point \tparam_point
+\tparam Container \tparam_container
+\tparam Allocator \tparam_allocator
+
+\qbk{before.synopsis,
+[heading Model of]
+[link geometry.reference.concepts.concept_linestring Linestring Concept]
+}
+
+*/
+template
+<
+ typename Point,
+ template<typename,typename> class Container = std::vector,
+ template<typename> class Allocator = std::allocator
+>
+class linestring : public Container<Point, Allocator<Point> >
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+ typedef Container<Point, Allocator<Point> > base_type;
+
+public :
+ /// \constructor_default{linestring}
+ inline linestring()
+ : base_type()
+ {}
+
+ /// \constructor_begin_end{linestring}
+ template <typename Iterator>
+ inline linestring(Iterator begin, Iterator end)
+ : base_type(begin, end)
+ {}
+};
+
+} // namespace model
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename Point,
+ template<typename,typename> class Container,
+ template<typename> class Allocator
+>
+struct tag<model::linestring<Point, Container, Allocator> >
+{
+ typedef linestring_tag type;
+};
+} // namespace traits
+
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_LINESTRING_HPP
diff --git a/boost/geometry/geometries/point.hpp b/boost/geometry/geometries/point.hpp
new file mode 100644
index 000000000..b53114731
--- /dev/null
+++ b/boost/geometry/geometries/point.hpp
@@ -0,0 +1,188 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_POINT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_POINT_HPP
+
+#include <cstddef>
+
+#include <boost/mpl/int.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/util/math.hpp>
+
+namespace boost { namespace geometry
+{
+
+// Silence warning C4127: conditional expression is constant
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4127)
+#endif
+
+
+namespace model
+{
+
+/*!
+\brief Basic point class, having coordinates defined in a neutral way
+\details Defines a neutral point class, fulfilling the Point Concept.
+ Library users can use this point class, or use their own point classes.
+ This point class is used in most of the samples and tests of Boost.Geometry
+ This point class is used occasionally within the library, where a temporary
+ point class is necessary.
+\ingroup geometries
+\tparam CoordinateType \tparam_numeric
+\tparam DimensionCount number of coordinates, usually 2 or 3
+\tparam CoordinateSystem coordinate system, for example cs::cartesian
+
+\qbk{[include reference/geometries/point.qbk]}
+\qbk{before.synopsis, [heading Model of]}
+\qbk{before.synopsis, [link geometry.reference.concepts.concept_point Point Concept]}
+
+
+*/
+template
+<
+ typename CoordinateType,
+ std::size_t DimensionCount,
+ typename CoordinateSystem
+>
+class point
+{
+public:
+
+ /// @brief Default constructor, no initialization
+ inline point()
+ {}
+
+ /// @brief Constructor to set one, two or three values
+ inline point(CoordinateType const& v0, CoordinateType const& v1 = 0, CoordinateType const& v2 = 0)
+ {
+ if (DimensionCount >= 1) m_values[0] = v0;
+ if (DimensionCount >= 2) m_values[1] = v1;
+ if (DimensionCount >= 3) m_values[2] = v2;
+ }
+
+ /// @brief Get a coordinate
+ /// @tparam K coordinate to get
+ /// @return the coordinate
+ template <std::size_t K>
+ inline CoordinateType const& get() const
+ {
+ BOOST_STATIC_ASSERT(K < DimensionCount);
+ return m_values[K];
+ }
+
+ /// @brief Set a coordinate
+ /// @tparam K coordinate to set
+ /// @param value value to set
+ template <std::size_t K>
+ inline void set(CoordinateType const& value)
+ {
+ BOOST_STATIC_ASSERT(K < DimensionCount);
+ m_values[K] = value;
+ }
+
+private:
+
+ CoordinateType m_values[DimensionCount];
+};
+
+
+} // namespace model
+
+// Adapt the point to the concept
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+template
+<
+ typename CoordinateType,
+ std::size_t DimensionCount,
+ typename CoordinateSystem
+>
+struct tag<model::point<CoordinateType, DimensionCount, CoordinateSystem> >
+{
+ typedef point_tag type;
+};
+
+template
+<
+ typename CoordinateType,
+ std::size_t DimensionCount,
+ typename CoordinateSystem
+>
+struct coordinate_type<model::point<CoordinateType, DimensionCount, CoordinateSystem> >
+{
+ typedef CoordinateType type;
+};
+
+template
+<
+ typename CoordinateType,
+ std::size_t DimensionCount,
+ typename CoordinateSystem
+>
+struct coordinate_system<model::point<CoordinateType, DimensionCount, CoordinateSystem> >
+{
+ typedef CoordinateSystem type;
+};
+
+template
+<
+ typename CoordinateType,
+ std::size_t DimensionCount,
+ typename CoordinateSystem
+>
+struct dimension<model::point<CoordinateType, DimensionCount, CoordinateSystem> >
+ : boost::mpl::int_<DimensionCount>
+{};
+
+template
+<
+ typename CoordinateType,
+ std::size_t DimensionCount,
+ typename CoordinateSystem,
+ std::size_t Dimension
+>
+struct access<model::point<CoordinateType, DimensionCount, CoordinateSystem>, Dimension>
+{
+ static inline CoordinateType get(
+ model::point<CoordinateType, DimensionCount, CoordinateSystem> const& p)
+ {
+ return p.template get<Dimension>();
+ }
+
+ static inline void set(
+ model::point<CoordinateType, DimensionCount, CoordinateSystem>& p,
+ CoordinateType const& value)
+ {
+ p.template set<Dimension>(value);
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_POINT_HPP
diff --git a/boost/geometry/geometries/point_xy.hpp b/boost/geometry/geometries/point_xy.hpp
new file mode 100644
index 000000000..652930666
--- /dev/null
+++ b/boost/geometry/geometries/point_xy.hpp
@@ -0,0 +1,128 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_POINT_XY_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_POINT_XY_HPP
+
+#include <cstddef>
+
+#include <boost/mpl/int.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/geometries/point.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace model { namespace d2
+{
+
+/*!
+\brief 2D point in Cartesian coordinate system
+\tparam CoordinateType numeric type, for example, double, float, int
+\tparam CoordinateSystem coordinate system, defaults to cs::cartesian
+
+\qbk{before.synopsis,
+[heading Model of]
+[link geometry.reference.concepts.concept_point Point Concept]
+}
+
+\qbk{[include reference/geometries/point_assign_warning.qbk]}
+
+*/
+template<typename CoordinateType, typename CoordinateSystem = cs::cartesian>
+class point_xy : public model::point<CoordinateType, 2, CoordinateSystem>
+{
+public:
+
+ /// Default constructor, does not initialize anything
+ inline point_xy()
+ : model::point<CoordinateType, 2, CoordinateSystem>()
+ {}
+
+ /// Constructor with x/y values
+ inline point_xy(CoordinateType const& x, CoordinateType const& y)
+ : model::point<CoordinateType, 2, CoordinateSystem>(x, y)
+ {}
+
+ /// Get x-value
+ inline CoordinateType const& x() const
+ { return this->template get<0>(); }
+
+ /// Get y-value
+ inline CoordinateType const& y() const
+ { return this->template get<1>(); }
+
+ /// Set x-value
+ inline void x(CoordinateType const& v)
+ { this->template set<0>(v); }
+
+ /// Set y-value
+ inline void y(CoordinateType const& v)
+ { this->template set<1>(v); }
+};
+
+
+}} // namespace model::d2
+
+
+// Adapt the point_xy to the concept
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename CoordinateType, typename CoordinateSystem>
+struct tag<model::d2::point_xy<CoordinateType, CoordinateSystem> >
+{
+ typedef point_tag type;
+};
+
+template<typename CoordinateType, typename CoordinateSystem>
+struct coordinate_type<model::d2::point_xy<CoordinateType, CoordinateSystem> >
+{
+ typedef CoordinateType type;
+};
+
+template<typename CoordinateType, typename CoordinateSystem>
+struct coordinate_system<model::d2::point_xy<CoordinateType, CoordinateSystem> >
+{
+ typedef CoordinateSystem type;
+};
+
+template<typename CoordinateType, typename CoordinateSystem>
+struct dimension<model::d2::point_xy<CoordinateType, CoordinateSystem> >
+ : boost::mpl::int_<2>
+{};
+
+template<typename CoordinateType, typename CoordinateSystem, std::size_t Dimension>
+struct access<model::d2::point_xy<CoordinateType, CoordinateSystem>, Dimension >
+{
+ static inline CoordinateType get(
+ model::d2::point_xy<CoordinateType, CoordinateSystem> const& p)
+ {
+ return p.template get<Dimension>();
+ }
+
+ static inline void set(model::d2::point_xy<CoordinateType, CoordinateSystem>& p,
+ CoordinateType const& value)
+ {
+ p.template set<Dimension>(value);
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_POINT_XY_HPP
diff --git a/boost/geometry/geometries/polygon.hpp b/boost/geometry/geometries/polygon.hpp
new file mode 100644
index 000000000..ec8d1ec38
--- /dev/null
+++ b/boost/geometry/geometries/polygon.hpp
@@ -0,0 +1,319 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_POLYGON_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_POLYGON_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/assert.hpp>
+
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/geometries/ring.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace model
+{
+
+/*!
+\brief The polygon contains an outer ring and zero or more inner rings.
+\ingroup geometries
+\tparam Point point type
+\tparam ClockWise true for clockwise direction,
+ false for CounterClockWise direction
+\tparam Closed true for closed polygons (last point == first point),
+ false open points
+\tparam PointList container type for points,
+ for example std::vector, std::list, std::deque
+\tparam RingList container type for inner rings,
+ for example std::vector, std::list, std::deque
+\tparam PointAlloc container-allocator-type, for the points
+\tparam RingAlloc container-allocator-type, for the rings
+\note The container collecting the points in the rings can be different
+ from the container collecting the inner rings. They all default to vector.
+
+\qbk{before.synopsis,
+[heading Model of]
+[link geometry.reference.concepts.concept_polygon Polygon Concept]
+}
+
+
+*/
+template
+<
+ typename Point,
+ bool ClockWise = true,
+ bool Closed = true,
+ template<typename, typename> class PointList = std::vector,
+ template<typename, typename> class RingList = std::vector,
+ template<typename> class PointAlloc = std::allocator,
+ template<typename> class RingAlloc = std::allocator
+>
+class polygon
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+public:
+
+ // Member types
+ typedef Point point_type;
+ typedef ring<Point, ClockWise, Closed, PointList, PointAlloc> ring_type;
+ typedef RingList<ring_type , RingAlloc<ring_type > > inner_container_type;
+
+ inline ring_type const& outer() const { return m_outer; }
+ inline inner_container_type const& inners() const { return m_inners; }
+
+ inline ring_type& outer() { return m_outer; }
+ inline inner_container_type & inners() { return m_inners; }
+
+ /// Utility method, clears outer and inner rings
+ inline void clear()
+ {
+ m_outer.clear();
+ m_inners.clear();
+ }
+
+private:
+
+ ring_type m_outer;
+ inner_container_type m_inners;
+};
+
+
+} // namespace model
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename Point,
+ bool ClockWise, bool Closed,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct tag
+<
+ model::polygon
+ <
+ Point, ClockWise, Closed,
+ PointList, RingList, PointAlloc, RingAlloc
+ >
+>
+{
+ typedef polygon_tag type;
+};
+
+template
+<
+ typename Point,
+ bool ClockWise, bool Closed,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct ring_const_type
+<
+ model::polygon
+ <
+ Point, ClockWise, Closed,
+ PointList, RingList, PointAlloc, RingAlloc
+ >
+>
+{
+ typedef typename model::polygon
+ <
+ Point, ClockWise, Closed,
+ PointList, RingList,
+ PointAlloc, RingAlloc
+ >::ring_type const& type;
+};
+
+
+template
+<
+ typename Point,
+ bool ClockWise, bool Closed,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct ring_mutable_type
+<
+ model::polygon
+ <
+ Point, ClockWise, Closed,
+ PointList, RingList, PointAlloc, RingAlloc
+ >
+>
+{
+ typedef typename model::polygon
+ <
+ Point, ClockWise, Closed,
+ PointList, RingList,
+ PointAlloc, RingAlloc
+ >::ring_type& type;
+};
+
+template
+<
+ typename Point,
+ bool ClockWise, bool Closed,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct interior_const_type
+<
+ model::polygon
+ <
+ Point, ClockWise, Closed,
+ PointList, RingList,
+ PointAlloc, RingAlloc
+ >
+>
+{
+ typedef typename model::polygon
+ <
+ Point, ClockWise, Closed,
+ PointList, RingList,
+ PointAlloc, RingAlloc
+ >::inner_container_type const& type;
+};
+
+
+template
+<
+ typename Point,
+ bool ClockWise, bool Closed,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct interior_mutable_type
+<
+ model::polygon
+ <
+ Point, ClockWise, Closed,
+ PointList, RingList,
+ PointAlloc, RingAlloc
+ >
+>
+{
+ typedef typename model::polygon
+ <
+ Point, ClockWise, Closed,
+ PointList, RingList,
+ PointAlloc, RingAlloc
+ >::inner_container_type& type;
+};
+
+
+template
+<
+ typename Point,
+ bool ClockWise, bool Closed,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct exterior_ring
+<
+ model::polygon
+ <
+ Point, ClockWise, Closed,
+ PointList, RingList, PointAlloc, RingAlloc
+ >
+>
+{
+ typedef model::polygon
+ <
+ Point, ClockWise, Closed,
+ PointList, RingList,
+ PointAlloc, RingAlloc
+ > polygon_type;
+
+ static inline typename polygon_type::ring_type& get(polygon_type& p)
+ {
+ return p.outer();
+ }
+
+ static inline typename polygon_type::ring_type const& get(
+ polygon_type const& p)
+ {
+ return p.outer();
+ }
+};
+
+template
+<
+ typename Point,
+ bool ClockWise, bool Closed,
+ template<typename, typename> class PointList,
+ template<typename, typename> class RingList,
+ template<typename> class PointAlloc,
+ template<typename> class RingAlloc
+>
+struct interior_rings
+<
+ model::polygon
+ <
+ Point, ClockWise, Closed,
+ PointList, RingList,
+ PointAlloc, RingAlloc
+ >
+>
+{
+ typedef model::polygon
+ <
+ Point, ClockWise, Closed, PointList, RingList,
+ PointAlloc, RingAlloc
+ > polygon_type;
+
+ static inline typename polygon_type::inner_container_type& get(
+ polygon_type& p)
+ {
+ return p.inners();
+ }
+
+ static inline typename polygon_type::inner_container_type const& get(
+ polygon_type const& p)
+ {
+ return p.inners();
+ }
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_POLYGON_HPP
diff --git a/boost/geometry/geometries/register/box.hpp b/boost/geometry/geometries/register/box.hpp
new file mode 100644
index 000000000..838c2bb5f
--- /dev/null
+++ b/boost/geometry/geometries/register/box.hpp
@@ -0,0 +1,179 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_BOX_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_BOX_HPP
+
+
+#ifndef DOXYGEN_NO_SPECIALIZATIONS
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS(Box, Point, MinCorner, MaxCorner) \
+template <size_t D> \
+struct indexed_access<Box, min_corner, D> \
+{ \
+ typedef typename coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) \
+ { return geometry::get<D>(b. MinCorner); } \
+ static inline void set(Box& b, ct const& value) \
+ { geometry::set<D>(b. MinCorner, value); } \
+}; \
+template <size_t D> \
+struct indexed_access<Box, max_corner, D> \
+{ \
+ typedef typename coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) \
+ { return geometry::get<D>(b. MaxCorner); } \
+ static inline void set(Box& b, ct const& value) \
+ { geometry::set<D>(b. MaxCorner, value); } \
+};
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_TEMPLATED(Box, MinCorner, MaxCorner) \
+template <typename P, size_t D> \
+struct indexed_access<Box<P>, min_corner, D> \
+{ \
+ typedef typename coordinate_type<P>::type ct; \
+ static inline ct get(Box<P> const& b) \
+ { return geometry::get<D>(b. MinCorner); } \
+ static inline void set(Box<P>& b, ct const& value) \
+ { geometry::set<D>(b. MinCorner, value); } \
+}; \
+template <typename P, size_t D> \
+struct indexed_access<Box<P>, max_corner, D> \
+{ \
+ typedef typename coordinate_type<P>::type ct; \
+ static inline ct get(Box<P> const& b) \
+ { return geometry::get<D>(b. MaxCorner); } \
+ static inline void set(Box<P>& b, ct const& value) \
+ { geometry::set<D>(b. MaxCorner, value); } \
+};
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_4VALUES(Box, Point, Left, Bottom, Right, Top) \
+template <> struct indexed_access<Box, min_corner, 0> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) { return b. Left; } \
+ static inline void set(Box& b, ct const& value) { b. Left = value; } \
+}; \
+template <> struct indexed_access<Box, min_corner, 1> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) { return b. Bottom; } \
+ static inline void set(Box& b, ct const& value) { b. Bottom = value; } \
+}; \
+template <> struct indexed_access<Box, max_corner, 0> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) { return b. Right; } \
+ static inline void set(Box& b, ct const& value) { b. Right = value; } \
+}; \
+template <> struct indexed_access<Box, max_corner, 1> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Box const& b) { return b. Top; } \
+ static inline void set(Box& b, ct const& value) { b. Top = value; } \
+};
+
+
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS(Box, PointType) \
+ template<> struct tag<Box > { typedef box_tag type; }; \
+ template<> struct point_type<Box > { typedef PointType type; };
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS_TEMPLATED(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
+
+
+
+/*!
+\brief \brief_macro{box}
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_BOX, box} The
+ box may contain template parameters, which must be specified then.
+\param Box \param_macro_type{Box}
+\param Point Point type on which box is based. Might be two or three-dimensional
+\param MinCorner minimum corner (should be public member or method)
+\param MaxCorner maximum corner (should be public member or method)
+
+\qbk{
+[heading Example]
+[register_box]
+[register_box_output]
+}
+*/
+#define BOOST_GEOMETRY_REGISTER_BOX(Box, Point, MinCorner, MaxCorner) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS(Box, Point) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS(Box, Point, MinCorner, MaxCorner) \
+}}}
+
+
+/*!
+\brief \brief_macro{box}
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_BOX_TEMPLATED, box}
+ \details_macro_templated{box, point}
+\param Box \param_macro_type{Box}
+\param MinCorner minimum corner (should be public member or method)
+\param MaxCorner maximum corner (should be public member or method)
+
+\qbk{
+[heading Example]
+[register_box_templated]
+[register_box_templated_output]
+}
+*/
+#define BOOST_GEOMETRY_REGISTER_BOX_TEMPLATED(Box, MinCorner, MaxCorner) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS_TEMPLATED(Box) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_TEMPLATED(Box, MinCorner, MaxCorner) \
+}}}
+
+/*!
+\brief \brief_macro{box}
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_BOX_2D_4VALUES, box}
+\param Box \param_macro_type{Box}
+\param Point Point type reported as point_type by box. Must be two dimensional.
+ Note that these box tyeps do not contain points, but they must have a
+ related point_type
+\param Left Left side (must be public member or method)
+\param Bottom Bottom side (must be public member or method)
+\param Right Right side (must be public member or method)
+\param Top Top side (must be public member or method)
+
+\qbk{
+[heading Example]
+[register_box_2d_4values]
+[register_box_2d_4values_output]
+}
+*/
+#define BOOST_GEOMETRY_REGISTER_BOX_2D_4VALUES(Box, Point, Left, Bottom, Right, Top) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_TRAITS(Box, Point) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_BOX_ACCESS_4VALUES(Box, Point, Left, Bottom, Right, Top) \
+}}}
+
+
+
+// CONST versions are for boxes probably not that common. Postponed.
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_BOX_HPP
diff --git a/boost/geometry/geometries/register/linestring.hpp b/boost/geometry/geometries/register/linestring.hpp
new file mode 100644
index 000000000..b06439874
--- /dev/null
+++ b/boost/geometry/geometries/register/linestring.hpp
@@ -0,0 +1,60 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_LINESTRING_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_LINESTRING_HPP
+
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+/*!
+\brief \brief_macro{linestring}
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_LINESTRING, linestring} The
+ linestring may contain template parameters, which must be specified then.
+\param Linestring \param_macro_type{linestring}
+
+\qbk{
+[heading Example]
+[register_linestring]
+[register_linestring_output]
+}
+*/
+#define BOOST_GEOMETRY_REGISTER_LINESTRING(Linestring) \
+namespace boost { namespace geometry { namespace traits { \
+ template<> struct tag<Linestring> { typedef linestring_tag type; }; \
+}}}
+
+
+/*!
+\brief \brief_macro{templated linestring}
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED, templated linestring}
+ \details_macro_templated{linestring, point}
+\param Linestring \param_macro_type{linestring (without template parameters)}
+
+\qbk{
+[heading Example]
+[register_linestring_templated]
+[register_linestring_templated_output]
+}
+*/
+#define BOOST_GEOMETRY_REGISTER_LINESTRING_TEMPLATED(Linestring) \
+namespace boost { namespace geometry { namespace traits { \
+ template<typename P> struct tag< Linestring<P> > { typedef linestring_tag type; }; \
+}}}
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_LINESTRING_HPP
diff --git a/boost/geometry/geometries/register/point.hpp b/boost/geometry/geometries/register/point.hpp
new file mode 100644
index 000000000..676582576
--- /dev/null
+++ b/boost/geometry/geometries/register/point.hpp
@@ -0,0 +1,173 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_POINT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_POINT_HPP
+
+
+#include <cstddef>
+
+#ifndef DOXYGEN_NO_SPECIALIZATIONS
+
+// Starting point, specialize basic traits necessary to register a point
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, Dim, CoordinateType, CoordinateSystem) \
+ template<> struct tag<Point> { typedef point_tag type; }; \
+ template<> struct dimension<Point> : boost::mpl::int_<Dim> {}; \
+ template<> struct coordinate_type<Point> { typedef CoordinateType type; }; \
+ template<> struct coordinate_system<Point> { typedef CoordinateSystem type; };
+
+// Specialize access class per dimension
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, Dim, CoordinateType, Get, Set) \
+ template<> struct access<Point, Dim> \
+ { \
+ static inline CoordinateType get(Point const& p) { return p. Get; } \
+ static inline void set(Point& p, CoordinateType const& value) { p. Set = value; } \
+ };
+
+// Const version
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, Dim, CoordinateType, Get) \
+ template<> struct access<Point, Dim> \
+ { \
+ static inline CoordinateType get(Point const& p) { return p. Get; } \
+ };
+
+
+// Getter/setter version
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_GET_SET(Point, Dim, CoordinateType, Get, Set) \
+ template<> struct access<Point, Dim> \
+ { \
+ static inline CoordinateType get(Point const& p) \
+ { return p. Get (); } \
+ static inline void set(Point& p, CoordinateType const& value) \
+ { p. Set ( value ); } \
+ };
+
+#endif // DOXYGEN_NO_SPECIALIZATIONS
+
+
+/*!
+\brief \brief_macro{2D point type}
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_POINT_2D, two-dimensional point type}
+\param Point \param_macro_type{Point}
+\param CoordinateType \param_macro_coortype{point}
+\param CoordinateSystem \param_macro_coorsystem
+\param Field0 \param_macro_member{\macro_x}
+\param Field1 \param_macro_member{\macro_y}
+
+\qbk{[include reference/geometries/register/point.qbk]}
+*/
+#define BOOST_GEOMETRY_REGISTER_POINT_2D(Point, CoordinateType, CoordinateSystem, Field0, Field1) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 2, CoordinateType, CoordinateSystem) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, 0, CoordinateType, Field0, Field0) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, 1, CoordinateType, Field1, Field1) \
+}}}
+
+/*!
+\brief \brief_macro{3D point type}
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_POINT_3D, three-dimensional point type}
+\param Point \param_macro_type{Point}
+\param CoordinateType \param_macro_coortype{point}
+\param CoordinateSystem \param_macro_coorsystem
+\param Field0 \param_macro_member{\macro_x}
+\param Field1 \param_macro_member{\macro_y}
+\param Field2 \param_macro_member{\macro_z}
+*/
+#define BOOST_GEOMETRY_REGISTER_POINT_3D(Point, CoordinateType, CoordinateSystem, Field0, Field1, Field2) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 3, CoordinateType, CoordinateSystem) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, 0, CoordinateType, Field0, Field0) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, 1, CoordinateType, Field1, Field1) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS(Point, 2, CoordinateType, Field2, Field2) \
+}}}
+
+/*!
+\brief \brief_macro{2D point type} \brief_macro_const
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_POINT_2D_CONST, two-dimensional point type}. \details_macro_const
+\param Point \param_macro_type{Point}
+\param CoordinateType \param_macro_coortype{point}
+\param CoordinateSystem \param_macro_coorsystem
+\param Field0 \param_macro_member{\macro_x}
+\param Field1 \param_macro_member{\macro_y}
+*/
+#define BOOST_GEOMETRY_REGISTER_POINT_2D_CONST(Point, CoordinateType, CoordinateSystem, Field0, Field1) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 2, CoordinateType, CoordinateSystem) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, 0, CoordinateType, Field0) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, 1, CoordinateType, Field1) \
+}}}
+
+/*!
+\brief \brief_macro{3D point type} \brief_macro_const
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_POINT_3D_CONST, three-dimensional point type}. \details_macro_const
+\param Point \param_macro_type{Point}
+\param CoordinateType \param_macro_coortype{point}
+\param CoordinateSystem \param_macro_coorsystem
+\param Field0 \param_macro_member{\macro_x}
+\param Field1 \param_macro_member{\macro_y}
+\param Field2 \param_macro_member{\macro_z}
+*/
+#define BOOST_GEOMETRY_REGISTER_POINT_3D_CONST(Point, CoordinateType, CoordinateSystem, Field0, Field1, Field2) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 3, CoordinateType, CoordinateSystem) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, 0, CoordinateType, Field0) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, 1, CoordinateType, Field1) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_CONST(Point, 2, CoordinateType, Field2) \
+}}}
+
+/*!
+\brief \brief_macro{2D point type} \brief_macro_getset
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET, two-dimensional point type}. \details_macro_getset
+\param Point \param_macro_type{Point}
+\param CoordinateType \param_macro_coortype{point}
+\param CoordinateSystem \param_macro_coorsystem
+\param Get0 \param_macro_getset{get, \macro_x}
+\param Get1 \param_macro_getset{get, \macro_y}
+\param Set0 \param_macro_getset{set, \macro_x}
+\param Set1 \param_macro_getset{set, \macro_y}
+*/
+#define BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET(Point, CoordinateType, CoordinateSystem, Get0, Get1, Set0, Set1) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 2, CoordinateType, CoordinateSystem) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_GET_SET(Point, 0, CoordinateType, Get0, Set0) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_GET_SET(Point, 1, CoordinateType, Get1, Set1) \
+}}}
+
+/*!
+\brief \brief_macro{3D point type} \brief_macro_getset
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_POINT_3D_GET_SET, three-dimensional point type}. \details_macro_getset
+\param Point \param_macro_type{Point}
+\param CoordinateType \param_macro_coortype{point}
+\param CoordinateSystem \param_macro_coorsystem
+\param Get0 \param_macro_getset{get, \macro_x}
+\param Get1 \param_macro_getset{get, \macro_y}
+\param Get2 \param_macro_getset{get, \macro_z}
+\param Set0 \param_macro_getset{set, \macro_x}
+\param Set1 \param_macro_getset{set, \macro_y}
+\param Set2 \param_macro_getset{set, \macro_z}
+*/
+#define BOOST_GEOMETRY_REGISTER_POINT_3D_GET_SET(Point, CoordinateType, CoordinateSystem, Get0, Get1, Get2, Set0, Set1, Set2) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_TRAITS(Point, 3, CoordinateType, CoordinateSystem) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_GET_SET(Point, 0, CoordinateType, Get0, Set0) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_GET_SET(Point, 1, CoordinateType, Get1, Set1) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_POINT_ACCESS_GET_SET(Point, 2, CoordinateType, Get2, Set2) \
+}}}
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_POINT_HPP
diff --git a/boost/geometry/geometries/register/ring.hpp b/boost/geometry/geometries/register/ring.hpp
new file mode 100644
index 000000000..fb6cb6720
--- /dev/null
+++ b/boost/geometry/geometries/register/ring.hpp
@@ -0,0 +1,60 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_RING_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_RING_HPP
+
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+/*!
+\brief \brief_macro{ring}
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_RING, ring} The
+ ring may contain template parameters, which must be specified then.
+\param Ring \param_macro_type{ring}
+
+\qbk{
+[heading Example]
+[register_ring]
+[register_ring_output]
+}
+*/
+#define BOOST_GEOMETRY_REGISTER_RING(Ring) \
+namespace boost { namespace geometry { namespace traits { \
+ template<> struct tag<Ring> { typedef ring_tag type; }; \
+}}}
+
+
+/*!
+\brief \brief_macro{templated ring}
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_RING_TEMPLATED, templated ring}
+ \details_macro_templated{ring, point}
+\param Ring \param_macro_type{ring (without template parameters)}
+
+\qbk{
+[heading Example]
+[register_ring_templated]
+[register_ring_templated_output]
+}
+*/
+#define BOOST_GEOMETRY_REGISTER_RING_TEMPLATED(Ring) \
+namespace boost { namespace geometry { namespace traits { \
+ template<typename P> struct tag< Ring<P> > { typedef ring_tag type; }; \
+}}}
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_RING_HPP
diff --git a/boost/geometry/geometries/register/segment.hpp b/boost/geometry/geometries/register/segment.hpp
new file mode 100644
index 000000000..6ea88c091
--- /dev/null
+++ b/boost/geometry/geometries/register/segment.hpp
@@ -0,0 +1,129 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_SEGMENT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_SEGMENT_HPP
+
+
+#ifndef DOXYGEN_NO_SPECIALIZATIONS
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS(Segment, Point, Index0, Index1) \
+template <size_t D> \
+struct indexed_access<Segment, min_corner, D> \
+{ \
+ typedef typename coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) \
+ { return geometry::get<D>(b. Index0); } \
+ static inline void set(Segment& b, ct const& value) \
+ { geometry::set<D>(b. Index0, value); } \
+}; \
+template <size_t D> \
+struct indexed_access<Segment, max_corner, D> \
+{ \
+ typedef typename coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) \
+ { return geometry::get<D>(b. Index1); } \
+ static inline void set(Segment& b, ct const& value) \
+ { geometry::set<D>(b. Index1, value); } \
+};
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS_TEMPLATIZED(Segment, Index0, Index1) \
+template <typename P, size_t D> \
+struct indexed_access<Segment<P>, min_corner, D> \
+{ \
+ typedef typename coordinate_type<P>::type ct; \
+ static inline ct get(Segment<P> const& b) \
+ { return geometry::get<D>(b. Index0); } \
+ static inline void set(Segment<P>& b, ct const& value) \
+ { geometry::set<D>(b. Index0, value); } \
+}; \
+template <typename P, size_t D> \
+struct indexed_access<Segment<P>, max_corner, D> \
+{ \
+ typedef typename coordinate_type<P>::type ct; \
+ static inline ct get(Segment<P> const& b) \
+ { return geometry::get<D>(b. Index1); } \
+ static inline void set(Segment<P>& b, ct const& value) \
+ { geometry::set<D>(b. Index1, value); } \
+};
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS_4VALUES(Segment, Point, Left, Bottom, Right, Top) \
+template <> struct indexed_access<Segment, min_corner, 0> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) { return b. Left; } \
+ static inline void set(Segment& b, ct const& value) { b. Left = value; } \
+}; \
+template <> struct indexed_access<Segment, min_corner, 1> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) { return b. Bottom; } \
+ static inline void set(Segment& b, ct const& value) { b. Bottom = value; } \
+}; \
+template <> struct indexed_access<Segment, max_corner, 0> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) { return b. Right; } \
+ static inline void set(Segment& b, ct const& value) { b. Right = value; } \
+}; \
+template <> struct indexed_access<Segment, max_corner, 1> \
+{ \
+ typedef coordinate_type<Point>::type ct; \
+ static inline ct get(Segment const& b) { return b. Top; } \
+ static inline void set(Segment& b, ct const& value) { b. Top = value; } \
+};
+
+
+
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS(Segment, PointType) \
+ template<> struct tag<Segment > { typedef segment_tag type; }; \
+ template<> struct point_type<Segment > { typedef PointType type; };
+
+#define BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS_TEMPLATIZED(Segment) \
+ template<typename P> struct tag<Segment<P> > { typedef segment_tag type; }; \
+ template<typename P> struct point_type<Segment<P> > { typedef P type; };
+
+#endif // DOXYGEN_NO_SPECIALIZATIONS
+
+
+
+#define BOOST_GEOMETRY_REGISTER_SEGMENT(Segment, PointType, Index0, Index1) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS(Segment, PointType) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS(Segment, PointType, Index0, Index1) \
+}}}
+
+
+#define BOOST_GEOMETRY_REGISTER_SEGMENT_TEMPLATIZED(Segment, Index0, Index1) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS_TEMPLATIZED(Segment) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS_TEMPLATIZED(Segment, Index0, Index1) \
+}}}
+
+#define BOOST_GEOMETRY_REGISTER_SEGMENT_2D_4VALUES(Segment, PointType, Left, Bottom, Right, Top) \
+namespace boost { namespace geometry { namespace traits { \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_TRAITS(Segment, PointType) \
+ BOOST_GEOMETRY_DETAIL_SPECIALIZE_SEGMENT_ACCESS_4VALUES(Segment, PointType, Left, Bottom, Right, Top) \
+}}}
+
+
+
+// CONST versions are for segments probably not that common. Postponed.
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_REGISTER_SEGMENT_HPP
diff --git a/boost/geometry/geometries/ring.hpp b/boost/geometry/geometries/ring.hpp
new file mode 100644
index 000000000..998619785
--- /dev/null
+++ b/boost/geometry/geometries/ring.hpp
@@ -0,0 +1,153 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_RING_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_RING_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/assert.hpp>
+
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/point_order.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace model
+{
+/*!
+\brief A ring (aka linear ring) is a closed line which should not be selfintersecting
+\ingroup geometries
+\tparam Point point type
+\tparam ClockWise true for clockwise direction,
+ false for CounterClockWise direction
+\tparam Closed true for closed polygons (last point == first point),
+ false open points
+\tparam Container container type, for example std::vector, std::deque
+\tparam Allocator container-allocator-type
+
+\qbk{before.synopsis,
+[heading Model of]
+[link geometry.reference.concepts.concept_ring Ring Concept]
+}
+*/
+template
+<
+ typename Point,
+ bool ClockWise = true, bool Closed = true,
+ template<typename, typename> class Container = std::vector,
+ template<typename> class Allocator = std::allocator
+>
+class ring : public Container<Point, Allocator<Point> >
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+ typedef Container<Point, Allocator<Point> > base_type;
+
+public :
+ /// \constructor_default{ring}
+ inline ring()
+ : base_type()
+ {}
+
+ /// \constructor_begin_end{ring}
+ template <typename Iterator>
+ inline ring(Iterator begin, Iterator end)
+ : base_type(begin, end)
+ {}
+};
+
+} // namespace model
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename Point,
+ bool ClockWise, bool Closed,
+ template<typename, typename> class Container,
+ template<typename> class Allocator
+>
+struct tag<model::ring<Point, ClockWise, Closed, Container, Allocator> >
+{
+ typedef ring_tag type;
+};
+
+
+template
+<
+ typename Point,
+ bool Closed,
+ template<typename, typename> class Container,
+ template<typename> class Allocator
+>
+struct point_order<model::ring<Point, false, Closed, Container, Allocator> >
+{
+ static const order_selector value = counterclockwise;
+};
+
+
+template
+<
+ typename Point,
+ bool Closed,
+ template<typename, typename> class Container,
+ template<typename> class Allocator
+>
+struct point_order<model::ring<Point, true, Closed, Container, Allocator> >
+{
+ static const order_selector value = clockwise;
+};
+
+template
+<
+ typename Point,
+ bool PointOrder,
+ template<typename, typename> class Container,
+ template<typename> class Allocator
+>
+struct closure<model::ring<Point, PointOrder, true, Container, Allocator> >
+{
+ static const closure_selector value = closed;
+};
+
+template
+<
+ typename Point,
+ bool PointOrder,
+ template<typename, typename> class Container,
+ template<typename> class Allocator
+>
+struct closure<model::ring<Point, PointOrder, false, Container, Allocator> >
+{
+ static const closure_selector value = open;
+};
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_RING_HPP
diff --git a/boost/geometry/geometries/segment.hpp b/boost/geometry/geometries/segment.hpp
new file mode 100644
index 000000000..3f47f79ec
--- /dev/null
+++ b/boost/geometry/geometries/segment.hpp
@@ -0,0 +1,203 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_SEGMENT_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_SEGMENT_HPP
+
+#include <cstddef>
+
+#include <boost/concept/assert.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_const.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace model
+{
+
+/*!
+\brief Class segment: small class containing two points
+\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 There is also a point-referring-segment, class referring_segment,
+ containing point references, where points are NOT copied
+*/
+template<typename Point>
+class segment : public std::pair<Point, Point>
+{
+public :
+ inline segment()
+ {}
+
+ inline segment(Point const& p1, Point const& p2)
+ {
+ this->first = p1;
+ this->second = p2;
+ }
+};
+
+
+/*!
+\brief Class segment: small class containing two (templatized) point references
+\ingroup geometries
+\details From Wikipedia: In geometry, a line segment is a part of a line that is bounded
+ by two distinct end points, and contains every point on the line between its end points.
+\note The structure is like std::pair, and can often be used interchangeable.
+Difference is that it refers to points, does not have points.
+\note Like std::pair, points are public available.
+\note type is const or non const, so geometry::segment<P> or geometry::segment<P const>
+\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 referring_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 referring_segment(point_type& p1, point_type& p2)
+ : first(p1)
+ , second(p2)
+ {}
+};
+
+
+} // namespace model
+
+
+// Traits specializations for segment above
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename Point>
+struct tag<model::segment<Point> >
+{
+ typedef segment_tag type;
+};
+
+template <typename Point>
+struct point_type<model::segment<Point> >
+{
+ typedef Point type;
+};
+
+template <typename Point, std::size_t Dimension>
+struct indexed_access<model::segment<Point>, 0, Dimension>
+{
+ typedef model::segment<Point> segment_type;
+ typedef typename geometry::coordinate_type<segment_type>::type coordinate_type;
+
+ static inline coordinate_type get(segment_type const& s)
+ {
+ return geometry::get<Dimension>(s.first);
+ }
+
+ static inline void set(segment_type& s, coordinate_type const& value)
+ {
+ geometry::set<Dimension>(s.first, value);
+ }
+};
+
+
+template <typename Point, std::size_t Dimension>
+struct indexed_access<model::segment<Point>, 1, Dimension>
+{
+ typedef model::segment<Point> segment_type;
+ typedef typename geometry::coordinate_type<segment_type>::type coordinate_type;
+
+ static inline coordinate_type get(segment_type const& s)
+ {
+ return geometry::get<Dimension>(s.second);
+ }
+
+ static inline void set(segment_type& s, coordinate_type const& value)
+ {
+ geometry::set<Dimension>(s.second, value);
+ }
+};
+
+
+template <typename ConstOrNonConstPoint>
+struct tag<model::referring_segment<ConstOrNonConstPoint> >
+{
+ typedef segment_tag type;
+};
+
+template <typename ConstOrNonConstPoint>
+struct point_type<model::referring_segment<ConstOrNonConstPoint> >
+{
+ typedef ConstOrNonConstPoint type;
+};
+
+template <typename ConstOrNonConstPoint, std::size_t Dimension>
+struct indexed_access<model::referring_segment<ConstOrNonConstPoint>, 0, Dimension>
+{
+ typedef model::referring_segment<ConstOrNonConstPoint> segment_type;
+ typedef typename geometry::coordinate_type<segment_type>::type coordinate_type;
+
+ static inline coordinate_type get(segment_type const& s)
+ {
+ return geometry::get<Dimension>(s.first);
+ }
+
+ static inline void set(segment_type& s, coordinate_type const& value)
+ {
+ geometry::set<Dimension>(s.first, value);
+ }
+};
+
+
+template <typename ConstOrNonConstPoint, std::size_t Dimension>
+struct indexed_access<model::referring_segment<ConstOrNonConstPoint>, 1, Dimension>
+{
+ typedef model::referring_segment<ConstOrNonConstPoint> segment_type;
+ typedef typename geometry::coordinate_type<segment_type>::type coordinate_type;
+
+ static inline coordinate_type get(segment_type const& s)
+ {
+ return geometry::get<Dimension>(s.second);
+ }
+
+ static inline void set(segment_type& s, coordinate_type const& value)
+ {
+ geometry::set<Dimension>(s.second, value);
+ }
+};
+
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_SEGMENT_HPP
diff --git a/boost/geometry/geometries/variant.hpp b/boost/geometry/geometries/variant.hpp
new file mode 100644
index 000000000..9db11d5a8
--- /dev/null
+++ b/boost/geometry/geometries/variant.hpp
@@ -0,0 +1,34 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRIES_VARIANT_GEOMETRY_HPP
+#define BOOST_GEOMETRY_GEOMETRIES_VARIANT_GEOMETRY_HPP
+
+
+#include <boost/variant/variant_fwd.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct point_type<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+ : point_type<T0>
+{};
+
+
+} // namespace geometry
+} // namespace boost
+
+
+#endif // BOOST_GEOMETRY_GEOMETRIES_VARIANT_GEOMETRY_HPP
diff --git a/boost/geometry/geometry.hpp b/boost/geometry/geometry.hpp
new file mode 100644
index 000000000..dce17e260
--- /dev/null
+++ b/boost/geometry/geometry.hpp
@@ -0,0 +1,92 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRY_HPP
+#define BOOST_GEOMETRY_GEOMETRY_HPP
+
+// Shortcut to include all header files
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+// Core algorithms
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/topological_dimension.hpp>
+
+
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/arithmetic/dot_product.hpp>
+
+#include <boost/geometry/strategies/strategies.hpp>
+
+#include <boost/geometry/algorithms/append.hpp>
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/buffer.hpp>
+#include <boost/geometry/algorithms/centroid.hpp>
+#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/comparable_distance.hpp>
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/algorithms/convex_hull.hpp>
+#include <boost/geometry/algorithms/correct.hpp>
+#include <boost/geometry/algorithms/covered_by.hpp>
+#include <boost/geometry/algorithms/difference.hpp>
+#include <boost/geometry/algorithms/disjoint.hpp>
+#include <boost/geometry/algorithms/distance.hpp>
+#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/algorithms/equals.hpp>
+#include <boost/geometry/algorithms/expand.hpp>
+#include <boost/geometry/algorithms/for_each.hpp>
+#include <boost/geometry/algorithms/intersection.hpp>
+#include <boost/geometry/algorithms/intersects.hpp>
+#include <boost/geometry/algorithms/length.hpp>
+#include <boost/geometry/algorithms/make.hpp>
+#include <boost/geometry/algorithms/num_geometries.hpp>
+#include <boost/geometry/algorithms/num_interior_rings.hpp>
+#include <boost/geometry/algorithms/num_points.hpp>
+#include <boost/geometry/algorithms/overlaps.hpp>
+#include <boost/geometry/algorithms/perimeter.hpp>
+#include <boost/geometry/algorithms/reverse.hpp>
+#include <boost/geometry/algorithms/simplify.hpp>
+#include <boost/geometry/algorithms/sym_difference.hpp>
+#include <boost/geometry/algorithms/touches.hpp>
+#include <boost/geometry/algorithms/transform.hpp>
+#include <boost/geometry/algorithms/union.hpp>
+#include <boost/geometry/algorithms/unique.hpp>
+#include <boost/geometry/algorithms/within.hpp>
+
+// Include multi a.o. because it can give weird effects
+// if you don't (e.g. area=0 of a multipolygon)
+#include <boost/geometry/multi/multi.hpp>
+
+// check includes all concepts
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/util/for_each_coordinate.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+#include <boost/geometry/io/dsv/write.hpp>
+
+#include <boost/geometry/views/box_view.hpp>
+#include <boost/geometry/views/segment_view.hpp>
+
+#include <boost/geometry/io/io.hpp>
+#include <boost/geometry/io/svg/svg_mapper.hpp>
+
+#endif // BOOST_GEOMETRY_GEOMETRY_HPP
diff --git a/boost/geometry/index/adaptors/query.hpp b/boost/geometry/index/adaptors/query.hpp
new file mode 100644
index 000000000..472b3693b
--- /dev/null
+++ b/boost/geometry/index/adaptors/query.hpp
@@ -0,0 +1,88 @@
+// Boost.Geometry Index
+//
+// Query range adaptor
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_ADAPTORS_QUERY_HPP
+#define BOOST_GEOMETRY_INDEX_ADAPTORS_QUERY_HPP
+
+/*!
+\defgroup adaptors Adaptors (boost::geometry::index::adaptors::)
+*/
+
+namespace boost { namespace geometry { namespace index {
+
+namespace adaptors {
+
+namespace detail {
+
+template <typename Index>
+class query_range
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ NOT_IMPLEMENTED_FOR_THIS_INDEX,
+ (query_range));
+
+ typedef int* iterator;
+ typedef const int* const_iterator;
+
+ template <typename Predicates>
+ inline query_range(
+ Index const&,
+ Predicates const&)
+ {}
+
+ inline iterator begin() { return 0; }
+ inline iterator end() { return 0; }
+ inline const_iterator begin() const { return 0; }
+ inline const_iterator end() const { return 0; }
+};
+
+// TODO: awulkiew - consider removing reference from predicates
+
+template<typename Predicates>
+struct query
+{
+ inline explicit query(Predicates const& pred)
+ : predicates(pred)
+ {}
+
+ Predicates const& predicates;
+};
+
+template<typename Index, typename Predicates>
+index::adaptors::detail::query_range<Index>
+operator|(
+ Index const& si,
+ index::adaptors::detail::query<Predicates> const& f)
+{
+ return index::adaptors::detail::query_range<Index>(si, f.predicates);
+}
+
+} // namespace detail
+
+/*!
+\brief The query index adaptor generator.
+
+\ingroup adaptors
+
+\param pred Predicates.
+*/
+template <typename Predicates>
+detail::query<Predicates>
+queried(Predicates const& pred)
+{
+ return detail::query<Predicates>(pred);
+}
+
+} // namespace adaptors
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_ADAPTORS_QUERY_HPP
diff --git a/boost/geometry/index/detail/algorithms/bounds.hpp b/boost/geometry/index/detail/algorithms/bounds.hpp
new file mode 100644
index 000000000..58c575d26
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/bounds.hpp
@@ -0,0 +1,41 @@
+// Boost.Geometry Index
+//
+// n-dimensional bounds
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_BOUNDS_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_BOUNDS_HPP
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+namespace dispatch {
+
+template <typename Geometry,
+ typename Bounds,
+ typename TagGeometry = typename geometry::tag<Geometry>::type,
+ typename TagBounds = typename geometry::tag<Bounds>::type>
+struct bounds
+{
+ static inline void apply(Geometry const& g, Bounds & b)
+ {
+ geometry::convert(g, b);
+ }
+};
+
+} // namespace dispatch
+
+template <typename Geometry, typename Bounds>
+inline void bounds(Geometry const& g, Bounds & b)
+{
+ concept::check_concepts_and_equal_dimensions<Geometry const, Bounds>();
+ dispatch::bounds<Geometry, Bounds>::apply(g, b);
+}
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_BOUNDS_HPP
diff --git a/boost/geometry/index/detail/algorithms/comparable_distance_centroid.hpp b/boost/geometry/index/detail/algorithms/comparable_distance_centroid.hpp
new file mode 100644
index 000000000..841876eb3
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/comparable_distance_centroid.hpp
@@ -0,0 +1,77 @@
+// Boost.Geometry Index
+//
+// squared distance between point and centroid of the box or point
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_CENTROID_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_CENTROID_HPP
+
+#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>
+#include <boost/geometry/index/detail/algorithms/diff_abs.hpp>
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+struct comparable_distance_centroid_tag {};
+
+template <
+ typename Point,
+ typename PointIndexable,
+ size_t N>
+struct sum_for_indexable<Point, PointIndexable, point_tag, comparable_distance_centroid_tag, N>
+{
+ typedef typename geometry::default_distance_result<Point, PointIndexable>::type result_type;
+
+ inline static result_type apply(Point const& pt, PointIndexable const& i)
+ {
+ return geometry::comparable_distance(pt, i);
+ }
+};
+
+template <
+ typename Point,
+ typename BoxIndexable,
+ size_t DimensionIndex>
+struct sum_for_indexable_dimension<Point, BoxIndexable, box_tag, comparable_distance_centroid_tag, DimensionIndex>
+{
+ typedef typename geometry::default_distance_result<Point, BoxIndexable>::type result_type;
+
+ inline static result_type apply(Point const& pt, BoxIndexable const& i)
+ {
+ typedef typename coordinate_type<Point>::type point_coord_t;
+ typedef typename coordinate_type<BoxIndexable>::type indexable_coord_t;
+
+ point_coord_t pt_c = geometry::get<DimensionIndex>(pt);
+ indexable_coord_t ind_c_min = geometry::get<geometry::min_corner, DimensionIndex>(i);
+ indexable_coord_t ind_c_max = geometry::get<geometry::max_corner, DimensionIndex>(i);
+
+ indexable_coord_t ind_c_avg = ind_c_min + (ind_c_max - ind_c_min) / 2;
+ // TODO: awulkiew - is (ind_c_min + ind_c_max) / 2 safe?
+
+ result_type diff = detail::diff_abs(ind_c_avg, pt_c);
+
+ return diff * diff;
+ }
+};
+
+template <typename Point, typename Indexable>
+typename geometry::default_distance_result<Point, Indexable>::type
+comparable_distance_centroid(Point const& pt, Indexable const& i)
+{
+ return detail::sum_for_indexable<
+ Point,
+ Indexable,
+ typename tag<Indexable>::type,
+ detail::comparable_distance_centroid_tag,
+ dimension<Indexable>::value
+ >::apply(pt, i);
+}
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // #define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_CENTROID_HPP
+
diff --git a/boost/geometry/index/detail/algorithms/comparable_distance_far.hpp b/boost/geometry/index/detail/algorithms/comparable_distance_far.hpp
new file mode 100644
index 000000000..07dfcfc0f
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/comparable_distance_far.hpp
@@ -0,0 +1,66 @@
+// Boost.Geometry Index
+//
+// squared distance between point and furthest point of the box or point
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_FAR_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_FAR_HPP
+
+#include <boost/geometry/index/detail/algorithms/diff_abs.hpp>
+#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+// minmaxdist component
+
+struct comparable_distance_far_tag {};
+
+template <
+ typename Point,
+ typename BoxIndexable,
+ size_t DimensionIndex>
+struct sum_for_indexable_dimension<Point, BoxIndexable, box_tag, comparable_distance_far_tag, DimensionIndex>
+{
+ typedef typename geometry::default_distance_result<Point, BoxIndexable>::type result_type;
+
+ inline static result_type apply(Point const& pt, BoxIndexable const& i)
+ {
+ typedef typename coordinate_type<Point>::type point_coord_t;
+ typedef typename coordinate_type<BoxIndexable>::type indexable_coord_t;
+
+ point_coord_t pt_c = geometry::get<DimensionIndex>(pt);
+ indexable_coord_t ind_c_min = geometry::get<geometry::min_corner, DimensionIndex>(i);
+ indexable_coord_t ind_c_max = geometry::get<geometry::max_corner, DimensionIndex>(i);
+
+ result_type further_diff = 0;
+
+ if ( (ind_c_min + ind_c_max) / 2 <= pt_c )
+ further_diff = pt_c - ind_c_min;
+ else
+ further_diff = detail::diff_abs(pt_c, ind_c_max); // unsigned values protection
+
+ return further_diff * further_diff;
+ }
+};
+
+template <typename Point, typename Indexable>
+typename geometry::default_distance_result<Point, Indexable>::type
+comparable_distance_far(Point const& pt, Indexable const& i)
+{
+ return detail::sum_for_indexable<
+ Point,
+ Indexable,
+ typename tag<Indexable>::type,
+ detail::comparable_distance_far_tag,
+ dimension<Indexable>::value
+ >::apply(pt, i);
+}
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_FAR_HPP
diff --git a/boost/geometry/index/detail/algorithms/comparable_distance_near.hpp b/boost/geometry/index/detail/algorithms/comparable_distance_near.hpp
new file mode 100644
index 000000000..5584bf85e
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/comparable_distance_near.hpp
@@ -0,0 +1,77 @@
+// Boost.Geometry Index
+//
+// squared distance between point and nearest point of the box or point
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_NEAR_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_NEAR_HPP
+
+#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+struct comparable_distance_near_tag {};
+
+template <
+ typename Point,
+ typename PointIndexable,
+ size_t N>
+struct sum_for_indexable<Point, PointIndexable, point_tag, comparable_distance_near_tag, N>
+{
+ typedef typename geometry::default_distance_result<Point, PointIndexable>::type result_type;
+
+ inline static result_type apply(Point const& pt, PointIndexable const& i)
+ {
+ return geometry::comparable_distance(pt, i);
+ }
+};
+
+template <
+ typename Point,
+ typename BoxIndexable,
+ size_t DimensionIndex>
+struct sum_for_indexable_dimension<Point, BoxIndexable, box_tag, comparable_distance_near_tag, DimensionIndex>
+{
+ typedef typename geometry::default_distance_result<Point, BoxIndexable>::type result_type;
+
+ inline static result_type apply(Point const& pt, BoxIndexable const& i)
+ {
+ typedef typename coordinate_type<Point>::type point_coord_t;
+ typedef typename coordinate_type<BoxIndexable>::type indexable_coord_t;
+
+ point_coord_t pt_c = geometry::get<DimensionIndex>(pt);
+ indexable_coord_t ind_c_min = geometry::get<geometry::min_corner, DimensionIndex>(i);
+ indexable_coord_t ind_c_max = geometry::get<geometry::max_corner, DimensionIndex>(i);
+
+ result_type diff = 0;
+
+ if ( pt_c < ind_c_min )
+ diff = ind_c_min - pt_c;
+ else if ( ind_c_max < pt_c )
+ diff = pt_c - ind_c_max;
+
+ return diff * diff;
+ }
+};
+
+template <typename Point, typename Indexable>
+typename geometry::default_distance_result<Point, Indexable>::type
+comparable_distance_near(Point const& pt, Indexable const& i)
+{
+ return detail::sum_for_indexable<
+ Point,
+ Indexable,
+ typename tag<Indexable>::type,
+ detail::comparable_distance_near_tag,
+ dimension<Indexable>::value
+ >::apply(pt, i);
+}
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_NEAR_HPP
diff --git a/boost/geometry/index/detail/algorithms/content.hpp b/boost/geometry/index/detail/algorithms/content.hpp
new file mode 100644
index 000000000..1c4739d8e
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/content.hpp
@@ -0,0 +1,85 @@
+// Boost.Geometry Index
+//
+// n-dimensional content (hypervolume) - 2d area, 3d volume, ...
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_CONTENT_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_CONTENT_HPP
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+template <typename Indexable>
+struct default_content_result
+{
+ typedef typename select_most_precise<
+ typename coordinate_type<Indexable>::type,
+ long double
+ >::type type;
+};
+
+namespace dispatch {
+
+template <typename Box, size_t CurrentDimension>
+struct content_box
+{
+ BOOST_STATIC_ASSERT(0 < CurrentDimension);
+ //BOOST_STATIC_ASSERT(CurrentDimension <= traits::dimension<Box>::value);
+
+ static inline typename detail::default_content_result<Box>::type apply(Box const& b)
+ {
+ return content_box<Box, CurrentDimension - 1>::apply(b) *
+ ( get<max_corner, CurrentDimension - 1>(b) - get<min_corner, CurrentDimension - 1>(b) );
+ }
+};
+
+template <typename Box>
+struct content_box<Box, 1>
+{
+ static inline typename detail::default_content_result<Box>::type apply(Box const& b)
+ {
+ return get<max_corner, 0>(b) - get<min_corner, 0>(b);
+ }
+};
+
+template <typename Indexable, typename Tag>
+struct content
+{
+ BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_INDEXABLE_AND_TAG, (Indexable, Tag));
+};
+
+template <typename Indexable>
+struct content<Indexable, point_tag>
+{
+ static typename detail::default_content_result<Indexable>::type apply(Indexable const&)
+ {
+ return 0;
+ }
+};
+
+template <typename Indexable>
+struct content<Indexable, box_tag>
+{
+ static typename default_content_result<Indexable>::type apply(Indexable const& b)
+ {
+ return dispatch::content_box<Indexable, dimension<Indexable>::value>::apply(b);
+ }
+};
+
+} // namespace dispatch
+
+template <typename Indexable>
+typename default_content_result<Indexable>::type content(Indexable const& b)
+{
+ return dispatch::content<Indexable,
+ typename tag<Indexable>::type
+ >::apply(b);
+}
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_CONTENT_HPP
diff --git a/boost/geometry/index/detail/algorithms/diff_abs.hpp b/boost/geometry/index/detail/algorithms/diff_abs.hpp
new file mode 100644
index 000000000..ec63bd9a5
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/diff_abs.hpp
@@ -0,0 +1,39 @@
+// Boost.Geometry Index
+//
+// Abs of difference
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_DIFF_ABS_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_DIFF_ABS_HPP
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+template <typename T>
+inline T diff_abs_dispatch(T const& v1, T const& v2, boost::mpl::bool_<true> const& /*is_integral*/)
+{
+ return v1 < v2 ? v2 - v1 : v1 - v2;
+}
+
+template <typename T>
+inline T diff_abs_dispatch(T const& v1, T const& v2, boost::mpl::bool_<false> const& /*is_integral*/)
+{
+ return ::fabs(v1 - v2);
+}
+
+template <typename T>
+inline T diff_abs(T const& v1, T const& v2)
+{
+ typedef boost::mpl::bool_<
+ boost::is_integral<T>::value
+ > is_integral;
+ return diff_abs_dispatch(v1, v2, is_integral());
+}
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_DIFF_ABS_HPP
diff --git a/boost/geometry/index/detail/algorithms/intersection_content.hpp b/boost/geometry/index/detail/algorithms/intersection_content.hpp
new file mode 100644
index 000000000..955d6eb65
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/intersection_content.hpp
@@ -0,0 +1,36 @@
+// Boost.Geometry Index
+//
+// boxes union/intersection area/volume
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_INTERSECTION_CONTENT_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_INTERSECTION_CONTENT_HPP
+
+#include <boost/geometry/algorithms/intersection.hpp>
+#include <boost/geometry/index/detail/algorithms/content.hpp>
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+/**
+ * \brief Compute the area of the intersection of b1 and b2
+ */
+template <typename Box>
+inline typename default_content_result<Box>::type intersection_content(Box const& box1, Box const& box2)
+{
+ if ( geometry::intersects(box1, box2) )
+ {
+ Box box_intersection;
+ geometry::intersection(box1, box2, box_intersection);
+ return detail::content(box_intersection);
+ }
+ return 0;
+}
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_INTERSECTION_CONTENT_HPP
diff --git a/boost/geometry/index/detail/algorithms/is_valid.hpp b/boost/geometry/index/detail/algorithms/is_valid.hpp
new file mode 100644
index 000000000..56c164dae
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/is_valid.hpp
@@ -0,0 +1,79 @@
+// Boost.Geometry Index
+//
+// n-dimensional box's / point validity check
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_IS_VALID_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_IS_VALID_HPP
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+namespace dispatch {
+
+template <typename Box, size_t Dimension>
+struct is_valid_box
+{
+ BOOST_MPL_ASSERT_MSG(
+ (0 < Dimension && Dimension <= dimension<Box>::value),
+ INVALID_DIMENSION_PARAMETER,
+ (is_valid_box));
+
+ static inline bool apply(Box const& b)
+ {
+ return is_valid_box<Box, Dimension - 1>::apply(b) &&
+ ( get<min_corner, Dimension - 1>(b) <= get<max_corner, Dimension - 1>(b) );
+ }
+};
+
+template <typename Box>
+struct is_valid_box<Box, 1>
+{
+ static inline bool apply(Box const& b)
+ {
+ return get<min_corner, 0>(b) <= get<max_corner, 0>(b);
+ }
+};
+
+template <typename Indexable, typename Tag>
+struct is_valid
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ NOT_IMPLEMENTED_FOR_THIS_INDEXABLE,
+ (is_valid));
+};
+
+template <typename Indexable>
+struct is_valid<Indexable, point_tag>
+{
+ static inline bool apply(Indexable const&)
+ {
+ return true;
+ }
+};
+
+template <typename Indexable>
+struct is_valid<Indexable, box_tag>
+{
+ static inline bool apply(Indexable const& b)
+ {
+ return dispatch::is_valid_box<Indexable, dimension<Indexable>::value>::apply(b);
+ }
+};
+
+} // namespace dispatch
+
+template <typename Indexable>
+inline bool is_valid(Indexable const& b)
+{
+ return dispatch::is_valid<Indexable, typename tag<Indexable>::type>::apply(b);
+}
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_DETAIL_INDEX_ALGORITHMS_IS_VALID_HPP
diff --git a/boost/geometry/index/detail/algorithms/margin.hpp b/boost/geometry/index/detail/algorithms/margin.hpp
new file mode 100644
index 000000000..8e2685ab3
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/margin.hpp
@@ -0,0 +1,167 @@
+// Boost.Geometry Index
+//
+// n-dimensional box's margin value (hypersurface), 2d perimeter, 3d surface, etc...
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MARGIN_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MARGIN_HPP
+
+// WARNING! comparable_margin() will work only if the same Geometries are compared
+// so it shouldn't be used in the case of Variants!
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+template <typename Box>
+struct default_margin_result
+{
+ typedef typename select_most_precise<
+ typename coordinate_type<Box>::type,
+ long double
+ >::type type;
+};
+
+//template <typename Box, size_t CurrentDimension, size_t EdgeDimension>
+//struct margin_for_each_edge
+//{
+// BOOST_STATIC_ASSERT(0 < CurrentDimension);
+// BOOST_STATIC_ASSERT(0 < EdgeDimension);
+//
+// static inline typename default_margin_result<Box>::type apply(Box const& b)
+// {
+// return margin_for_each_edge<Box, CurrentDimension, EdgeDimension - 1>::apply(b) *
+// ( geometry::get<max_corner, EdgeDimension - 1>(b) - geometry::get<min_corner, EdgeDimension - 1>(b) );
+// }
+//};
+//
+//template <typename Box, size_t CurrentDimension>
+//struct margin_for_each_edge<Box, CurrentDimension, CurrentDimension>
+//{
+// BOOST_STATIC_ASSERT(0 < CurrentDimension);
+//
+// static inline typename default_margin_result<Box>::type apply(Box const& b)
+// {
+// return margin_for_each_edge<Box, CurrentDimension, CurrentDimension - 1>::apply(b);
+// }
+//};
+//
+//template <typename Box, size_t CurrentDimension>
+//struct margin_for_each_edge<Box, CurrentDimension, 1>
+//{
+// BOOST_STATIC_ASSERT(0 < CurrentDimension);
+//
+// static inline typename default_margin_result<Box>::type apply(Box const& b)
+// {
+// return geometry::get<max_corner, 0>(b) - geometry::get<min_corner, 0>(b);
+// }
+//};
+//
+//template <typename Box>
+//struct margin_for_each_edge<Box, 1, 1>
+//{
+// static inline typename default_margin_result<Box>::type apply(Box const& /*b*/)
+// {
+// return 1;
+// }
+//};
+//
+//template <typename Box, size_t CurrentDimension>
+//struct margin_for_each_dimension
+//{
+// BOOST_STATIC_ASSERT(0 < CurrentDimension);
+// BOOST_STATIC_ASSERT(CurrentDimension <= detail::traits::dimension<Box>::value);
+//
+// static inline typename default_margin_result<Box>::type apply(Box const& b)
+// {
+// return margin_for_each_dimension<Box, CurrentDimension - 1>::apply(b) +
+// margin_for_each_edge<Box, CurrentDimension, detail::traits::dimension<Box>::value>::apply(b);
+// }
+//};
+//
+//template <typename Box>
+//struct margin_for_each_dimension<Box, 1>
+//{
+// static inline typename default_margin_result<Box>::type apply(Box const& b)
+// {
+// return margin_for_each_edge<Box, 1, detail::traits::dimension<Box>::value>::apply(b);
+// }
+//};
+
+// TODO - test if this definition of margin is ok for Dimension > 2
+// Now it's sum of edges lengths
+// maybe margin_for_each_dimension should be used to get more or less hypersurface?
+
+template <typename Box, size_t CurrentDimension>
+struct simple_margin_for_each_dimension
+{
+ BOOST_STATIC_ASSERT(0 < CurrentDimension);
+ //BOOST_STATIC_ASSERT(CurrentDimension <= dimension<Box>::value);
+
+ static inline typename default_margin_result<Box>::type apply(Box const& b)
+ {
+ return simple_margin_for_each_dimension<Box, CurrentDimension - 1>::apply(b) +
+ geometry::get<max_corner, CurrentDimension - 1>(b) - geometry::get<min_corner, CurrentDimension - 1>(b);
+ }
+};
+
+template <typename Box>
+struct simple_margin_for_each_dimension<Box, 1>
+{
+ static inline typename default_margin_result<Box>::type apply(Box const& b)
+ {
+ return geometry::get<max_corner, 0>(b) - geometry::get<min_corner, 0>(b);
+ }
+};
+
+namespace dispatch {
+
+template <typename Geometry, typename Tag>
+struct comparable_margin
+{
+ BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_GEOMETRY, (Geometry, Tag));
+};
+
+template <typename Geometry>
+struct comparable_margin<Geometry, point_tag>
+{
+ typedef typename default_margin_result<Geometry>::type result_type;
+
+ static inline result_type apply(Geometry const& ) { return 0; }
+};
+
+template <typename Box>
+struct comparable_margin<Box, box_tag>
+{
+ typedef typename default_margin_result<Box>::type result_type;
+
+ static inline result_type apply(Box const& g)
+ {
+ //return detail::margin_for_each_dimension<Box, dimension<Box>::value>::apply(g);
+ return detail::simple_margin_for_each_dimension<Box, dimension<Box>::value>::apply(g);
+ }
+};
+
+} // namespace dispatch
+
+template <typename Geometry>
+typename default_margin_result<Geometry>::type comparable_margin(Geometry const& g)
+{
+ return dispatch::comparable_margin<
+ Geometry,
+ typename tag<Geometry>::type
+ >::apply(g);
+}
+
+//template <typename Box>
+//typename default_margin_result<Box>::type margin(Box const& b)
+//{
+// return 2 * detail::margin_for_each_dimension<Box, dimension<Box>::value>::apply(b);
+//}
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MARGIN_HPP
diff --git a/boost/geometry/index/detail/algorithms/minmaxdist.hpp b/boost/geometry/index/detail/algorithms/minmaxdist.hpp
new file mode 100644
index 000000000..680fb202b
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/minmaxdist.hpp
@@ -0,0 +1,119 @@
+// Boost.Geometry Index
+//
+// minmaxdist used in R-tree k nearest neighbors query
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MINMAXDIST_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MINMAXDIST_HPP
+
+#include <boost/geometry/algorithms/distance.hpp>
+#include <boost/geometry/algorithms/comparable_distance.hpp>
+
+#include <boost/geometry/index/detail/algorithms/diff_abs.hpp>
+#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>
+#include <boost/geometry/index/detail/algorithms/smallest_for_indexable.hpp>
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+struct minmaxdist_tag {};
+
+template <
+ typename Point,
+ typename BoxIndexable,
+ size_t DimensionIndex>
+struct smallest_for_indexable_dimension<Point, BoxIndexable, box_tag, minmaxdist_tag, DimensionIndex>
+{
+ typedef typename geometry::default_distance_result<Point, BoxIndexable>::type result_type;
+
+ inline static result_type apply(Point const& pt, BoxIndexable const& i, result_type const& maxd)
+ {
+ typedef typename coordinate_type<Point>::type point_coord_t;
+ typedef typename coordinate_type<BoxIndexable>::type indexable_coord_t;
+
+ point_coord_t pt_c = geometry::get<DimensionIndex>(pt);
+ indexable_coord_t ind_c_min = geometry::get<geometry::min_corner, DimensionIndex>(i);
+ indexable_coord_t ind_c_max = geometry::get<geometry::max_corner, DimensionIndex>(i);
+
+ indexable_coord_t ind_c_avg = ind_c_min + (ind_c_max - ind_c_min) / 2;
+ // TODO: awulkiew - is (ind_c_min + ind_c_max) / 2 safe?
+
+ // TODO: awulkiew - optimize! don't calculate 2x pt_c <= ind_c_avg
+ // take particular case pt_c == ind_c_avg into account
+
+ result_type closer_comp = 0;
+ if ( pt_c <= ind_c_avg )
+ closer_comp = detail::diff_abs(pt_c, ind_c_min); // unsigned values protection
+ else
+ closer_comp = ind_c_max - pt_c;
+
+ result_type further_comp = 0;
+ if ( ind_c_avg <= pt_c )
+ further_comp = pt_c - ind_c_min;
+ else
+ further_comp = detail::diff_abs(pt_c, ind_c_max); // unsigned values protection
+
+ return (maxd + closer_comp * closer_comp) - further_comp * further_comp;
+ }
+};
+
+template <typename Point, typename Indexable, typename IndexableTag>
+struct minmaxdist_impl
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ NOT_IMPLEMENTED_FOR_THIS_INDEXABLE_TAG_TYPE,
+ (minmaxdist_impl));
+};
+
+template <typename Point, typename Indexable>
+struct minmaxdist_impl<Point, Indexable, point_tag>
+{
+ typedef typename geometry::default_distance_result<Point, Indexable>::type result_type;
+
+ inline static result_type apply(Point const& pt, Indexable const& i)
+ {
+ return geometry::comparable_distance(pt, i);
+ }
+};
+
+template <typename Point, typename Indexable>
+struct minmaxdist_impl<Point, Indexable, box_tag>
+{
+ typedef typename geometry::default_distance_result<Point, Indexable>::type result_type;
+
+ inline static result_type apply(Point const& pt, Indexable const& i)
+ {
+ result_type maxd = geometry::comparable_distance(pt, i);
+
+ return smallest_for_indexable<
+ Point,
+ Indexable,
+ box_tag,
+ minmaxdist_tag,
+ dimension<Indexable>::value
+ >::apply(pt, i, maxd);
+ }
+};
+
+/**
+ * This is comparable distace.
+ */
+template <typename Point, typename Indexable>
+typename geometry::default_distance_result<Point, Indexable>::type
+minmaxdist(Point const& pt, Indexable const& i)
+{
+ return detail::minmaxdist_impl<
+ Point,
+ Indexable,
+ typename tag<Indexable>::type
+ >::apply(pt, i);
+}
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MINMAXDIST_HPP
diff --git a/boost/geometry/index/detail/algorithms/path_intersection.hpp b/boost/geometry/index/detail/algorithms/path_intersection.hpp
new file mode 100644
index 000000000..a9e0f3dcb
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/path_intersection.hpp
@@ -0,0 +1,114 @@
+// Boost.Geometry Index
+//
+// n-dimensional box-linestring intersection
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_PATH_INTERSECTION_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_PATH_INTERSECTION_HPP
+
+#include <boost/geometry/index/detail/algorithms/segment_intersection.hpp>
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+namespace dispatch {
+
+template <typename Indexable, typename Geometry, typename IndexableTag, typename GeometryTag>
+struct path_intersection
+{
+ BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_GEOMETRY_OR_INDEXABLE, (path_intersection));
+};
+
+template <typename Indexable, typename Segment>
+struct path_intersection<Indexable, Segment, box_tag, segment_tag>
+{
+ typedef typename default_distance_result<typename point_type<Segment>::type>::type comparable_distance_type;
+
+ static inline bool apply(Indexable const& b, Segment const& segment, comparable_distance_type & comparable_distance)
+ {
+ typedef typename point_type<Segment>::type point_type;
+ point_type p1, p2;
+ geometry::detail::assign_point_from_index<0>(segment, p1);
+ geometry::detail::assign_point_from_index<1>(segment, p2);
+ return index::detail::segment_intersection(b, p1, p2, comparable_distance);
+ }
+};
+
+template <typename Indexable, typename Linestring>
+struct path_intersection<Indexable, Linestring, box_tag, linestring_tag>
+{
+ typedef typename default_length_result<Linestring>::type comparable_distance_type;
+
+ static inline bool apply(Indexable const& b, Linestring const& path, comparable_distance_type & comparable_distance)
+ {
+ typedef typename ::boost::range_value<Linestring>::type point_type;
+ typedef typename ::boost::range_const_iterator<Linestring>::type const_iterator;
+ typedef typename ::boost::range_size<Linestring>::type size_type;
+
+ const size_type count = ::boost::size(path);
+
+ if ( count == 2 )
+ {
+ return index::detail::segment_intersection(b, *::boost::begin(path), *(::boost::begin(path)+1), comparable_distance);
+ }
+ else if ( 2 < count )
+ {
+ const_iterator it0 = ::boost::begin(path);
+ const_iterator it1 = ::boost::begin(path) + 1;
+ const_iterator last = ::boost::end(path);
+
+ comparable_distance = 0;
+
+ for ( ; it1 != last ; ++it0, ++it1 )
+ {
+ typename default_distance_result<point_type, point_type>::type
+ dist = geometry::distance(*it0, *it1);
+
+ comparable_distance_type rel_dist;
+ if ( index::detail::segment_intersection(b, *it0, *it1, rel_dist) )
+ {
+ comparable_distance += dist * rel_dist;
+ return true;
+ }
+ else
+ comparable_distance += dist;
+ }
+ }
+
+ return false;
+ }
+};
+
+} // namespace dispatch
+
+template <typename Indexable, typename SegmentOrLinestring>
+struct default_path_intersection_distance_type
+{
+ typedef typename dispatch::path_intersection<
+ Indexable, SegmentOrLinestring,
+ typename tag<Indexable>::type,
+ typename tag<SegmentOrLinestring>::type
+ >::comparable_distance_type type;
+};
+
+template <typename Indexable, typename SegmentOrLinestring> inline
+bool path_intersection(Indexable const& b,
+ SegmentOrLinestring const& path,
+ typename default_path_intersection_distance_type<Indexable, SegmentOrLinestring>::type & comparable_distance)
+{
+ // TODO check Indexable and Linestring concepts
+
+ return dispatch::path_intersection<
+ Indexable, SegmentOrLinestring,
+ typename tag<Indexable>::type,
+ typename tag<SegmentOrLinestring>::type
+ >::apply(b, path, comparable_distance);
+}
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_PATH_INTERSECTION_HPP
diff --git a/boost/geometry/index/detail/algorithms/segment_intersection.hpp b/boost/geometry/index/detail/algorithms/segment_intersection.hpp
new file mode 100644
index 000000000..4ae82c6ba
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/segment_intersection.hpp
@@ -0,0 +1,141 @@
+// Boost.Geometry Index
+//
+// n-dimensional box-segment intersection
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SEGMENT_INTERSECTION_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SEGMENT_INTERSECTION_HPP
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+//template <typename Indexable, typename Point>
+//struct default_relative_distance_type
+//{
+// typedef typename select_most_precise<
+// typename select_most_precise<
+// typename coordinate_type<Indexable>::type,
+// typename coordinate_type<Point>::type
+// >::type,
+// float // TODO - use bigger type, calculated from the size of coordinate types
+// >::type type;
+//
+//
+// BOOST_MPL_ASSERT_MSG((!::boost::is_unsigned<type>::value),
+// THIS_TYPE_SHOULDNT_BE_UNSIGNED, (type));
+//};
+
+namespace dispatch {
+
+template <typename Box, typename Point, size_t I>
+struct box_segment_intersection_dim
+{
+ BOOST_STATIC_ASSERT(I < dimension<Box>::value);
+ BOOST_STATIC_ASSERT(I < dimension<Point>::value);
+ BOOST_STATIC_ASSERT(dimension<Point>::value == dimension<Box>::value);
+
+ // WARNING! - RelativeDistance must be IEEE float for this to work
+
+ template <typename RelativeDistance>
+ static inline bool apply(Box const& b, Point const& p0, Point const& p1,
+ RelativeDistance & t_near, RelativeDistance & t_far)
+ {
+ RelativeDistance ray_d = geometry::get<I>(p1) - geometry::get<I>(p0);
+ RelativeDistance tn = ( geometry::get<min_corner, I>(b) - geometry::get<I>(p0) ) / ray_d;
+ RelativeDistance tf = ( geometry::get<max_corner, I>(b) - geometry::get<I>(p0) ) / ray_d;
+ if ( tf < tn )
+ ::std::swap(tn, tf);
+
+ if ( t_near < tn )
+ t_near = tn;
+ if ( tf < t_far )
+ t_far = tf;
+
+ return 0 <= t_far && t_near <= t_far;
+ }
+};
+
+template <typename Box, typename Point, size_t CurrentDimension>
+struct box_segment_intersection
+{
+ BOOST_STATIC_ASSERT(0 < CurrentDimension);
+
+ typedef box_segment_intersection_dim<Box, Point, CurrentDimension - 1> for_dim;
+
+ template <typename RelativeDistance>
+ static inline bool apply(Box const& b, Point const& p0, Point const& p1,
+ RelativeDistance & t_near, RelativeDistance & t_far)
+ {
+ return box_segment_intersection<Box, Point, CurrentDimension - 1>::apply(b, p0, p1, t_near, t_far)
+ && for_dim::apply(b, p0, p1, t_near, t_far);
+ }
+};
+
+template <typename Box, typename Point>
+struct box_segment_intersection<Box, Point, 1>
+{
+ typedef box_segment_intersection_dim<Box, Point, 0> for_dim;
+
+ template <typename RelativeDistance>
+ static inline bool apply(Box const& b, Point const& p0, Point const& p1,
+ RelativeDistance & t_near, RelativeDistance & t_far)
+ {
+ return for_dim::apply(b, p0, p1, t_near, t_far);
+ }
+};
+
+template <typename Indexable, typename Point, typename Tag>
+struct segment_intersection
+{
+ BOOST_MPL_ASSERT_MSG((false), NOT_IMPLEMENTED_FOR_THIS_GEOMETRY, (segment_intersection));
+};
+
+template <typename Indexable, typename Point>
+struct segment_intersection<Indexable, Point, point_tag>
+{
+ BOOST_MPL_ASSERT_MSG((false), SEGMENT_POINT_INTERSECTION_UNAVAILABLE, (segment_intersection));
+};
+
+template <typename Indexable, typename Point>
+struct segment_intersection<Indexable, Point, box_tag>
+{
+ typedef dispatch::box_segment_intersection<Indexable, Point, dimension<Indexable>::value> impl;
+
+ template <typename RelativeDistance>
+ static inline bool apply(Indexable const& b, Point const& p0, Point const& p1, RelativeDistance & relative_distance)
+ {
+ static const bool check = !::boost::is_integral<RelativeDistance>::value;
+ BOOST_MPL_ASSERT_MSG(check, RELATIVE_DISTANCE_MUST_BE_FLOATING_POINT_TYPE, (RelativeDistance));
+
+ RelativeDistance t_near = -(::std::numeric_limits<RelativeDistance>::max)();
+ RelativeDistance t_far = (::std::numeric_limits<RelativeDistance>::max)();
+
+ return impl::apply(b, p0, p1, t_near, t_far) &&
+ (t_near <= 1) &&
+ ( relative_distance = 0 < t_near ? t_near : 0, true );
+ }
+};
+
+} // namespace dispatch
+
+template <typename Indexable, typename Point, typename RelativeDistance> inline
+bool segment_intersection(Indexable const& b,
+ Point const& p0,
+ Point const& p1,
+ RelativeDistance & relative_distance)
+{
+ // TODO check Indexable and Point concepts
+
+ return dispatch::segment_intersection<
+ Indexable, Point,
+ typename tag<Indexable>::type
+ >::apply(b, p0, p1, relative_distance);
+}
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SEGMENT_INTERSECTION_HPP
diff --git a/boost/geometry/index/detail/algorithms/smallest_for_indexable.hpp b/boost/geometry/index/detail/algorithms/smallest_for_indexable.hpp
new file mode 100644
index 000000000..3ca335d5a
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/smallest_for_indexable.hpp
@@ -0,0 +1,80 @@
+// Boost.Geometry Index
+//
+// Get smallest value calculated for indexable's dimensions, used in R-tree k nearest neighbors query
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SMALLEST_FOR_INDEXABLE_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SMALLEST_FOR_INDEXABLE_HPP
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+template <
+ typename Geometry,
+ typename Indexable,
+ typename IndexableTag,
+ typename AlgoTag,
+ size_t DimensionIndex>
+struct smallest_for_indexable_dimension
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ NOT_IMPLEMENTED_FOR_THIS_INDEXABLE_TAG_TYPE,
+ (smallest_for_indexable_dimension));
+};
+
+template <
+ typename Geometry,
+ typename Indexable,
+ typename IndexableTag,
+ typename AlgoTag,
+ size_t N>
+struct smallest_for_indexable
+{
+ typedef typename smallest_for_indexable_dimension<
+ Geometry, Indexable, IndexableTag, AlgoTag, N - 1
+ >::result_type result_type;
+
+ template <typename Data>
+ inline static result_type apply(Geometry const& g, Indexable const& i, Data const& data)
+ {
+ result_type r1 = smallest_for_indexable<
+ Geometry, Indexable, IndexableTag, AlgoTag, N - 1
+ >::apply(g, i, data);
+
+ result_type r2 = smallest_for_indexable_dimension<
+ Geometry, Indexable, IndexableTag, AlgoTag, N - 1
+ >::apply(g, i, data);
+
+ return r1 < r2 ? r1 : r2;
+ }
+};
+
+template <
+ typename Geometry,
+ typename Indexable,
+ typename IndexableTag,
+ typename AlgoTag>
+struct smallest_for_indexable<Geometry, Indexable, IndexableTag, AlgoTag, 1>
+{
+ typedef typename smallest_for_indexable_dimension<
+ Geometry, Indexable, IndexableTag, AlgoTag, 0
+ >::result_type result_type;
+
+ template <typename Data>
+ inline static result_type apply(Geometry const& g, Indexable const& i, Data const& data)
+ {
+ return
+ smallest_for_indexable_dimension<
+ Geometry, Indexable, IndexableTag, AlgoTag, 0
+ >::apply(g, i, data);
+ }
+};
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SMALLEST_FOR_INDEXABLE_HPP
diff --git a/boost/geometry/index/detail/algorithms/sum_for_indexable.hpp b/boost/geometry/index/detail/algorithms/sum_for_indexable.hpp
new file mode 100644
index 000000000..4aef36352
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/sum_for_indexable.hpp
@@ -0,0 +1,76 @@
+// Boost.Geometry Index
+//
+// Sum values calculated for indexable's dimensions, used e.g. in R-tree k nearest neighbors query
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SUM_FOR_INDEXABLE_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SUM_FOR_INDEXABLE_HPP
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+template <
+ typename Geometry,
+ typename Indexable,
+ typename IndexableTag,
+ typename AlgoTag,
+ size_t DimensionIndex>
+struct sum_for_indexable_dimension
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ NOT_IMPLEMENTED_FOR_THIS_INDEXABLE_TAG_TYPE,
+ (sum_for_indexable_dimension));
+};
+
+template <
+ typename Geometry,
+ typename Indexable,
+ typename IndexableTag,
+ typename AlgoTag,
+ size_t N>
+struct sum_for_indexable
+{
+ typedef typename sum_for_indexable_dimension<
+ Geometry, Indexable, IndexableTag, AlgoTag, N - 1
+ >::result_type result_type;
+
+ inline static result_type apply(Geometry const& g, Indexable const& i)
+ {
+ return
+ sum_for_indexable<
+ Geometry, Indexable, IndexableTag, AlgoTag, N - 1
+ >::apply(g, i) +
+ sum_for_indexable_dimension<
+ Geometry, Indexable, IndexableTag, AlgoTag, N - 1
+ >::apply(g, i);
+ }
+};
+
+template <
+ typename Geometry,
+ typename Indexable,
+ typename IndexableTag,
+ typename AlgoTag>
+struct sum_for_indexable<Geometry, Indexable, IndexableTag, AlgoTag, 1>
+{
+ typedef typename sum_for_indexable_dimension<
+ Geometry, Indexable, IndexableTag, AlgoTag, 0
+ >::result_type result_type;
+
+ inline static result_type apply(Geometry const& g, Indexable const& i)
+ {
+ return
+ sum_for_indexable_dimension<
+ Geometry, Indexable, IndexableTag, AlgoTag, 0
+ >::apply(g, i);
+ }
+};
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SUM_FOR_INDEXABLE_HPP
diff --git a/boost/geometry/index/detail/algorithms/union_content.hpp b/boost/geometry/index/detail/algorithms/union_content.hpp
new file mode 100644
index 000000000..3acdc3d19
--- /dev/null
+++ b/boost/geometry/index/detail/algorithms/union_content.hpp
@@ -0,0 +1,33 @@
+// Boost.Geometry Index
+//
+// boxes union/sum area/volume
+//
+// Copyright (c) 2008 Federico J. Fernandez.
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_UNION_CONTENT_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_UNION_CONTENT_HPP
+
+#include <boost/geometry/algorithms/expand.hpp>
+#include <boost/geometry/index/detail/algorithms/content.hpp>
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+/**
+ * \brief Compute the area of the union of b1 and b2
+ */
+template <typename Box, typename Geometry>
+inline typename default_content_result<Box>::type union_content(Box const& b, Geometry const& g)
+{
+ Box expanded_box(b);
+ geometry::expand(expanded_box, g);
+ return detail::content(expanded_box);
+}
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_UNION_CONTENT_HPP
diff --git a/boost/geometry/index/detail/assert.hpp b/boost/geometry/index/detail/assert.hpp
new file mode 100644
index 000000000..22af315bc
--- /dev/null
+++ b/boost/geometry/index/detail/assert.hpp
@@ -0,0 +1,30 @@
+// Boost.Geometry Index
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ASSERT_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_ASSERT_HPP
+
+#include <boost/assert.hpp>
+
+#define BOOST_GEOMETRY_INDEX_ASSERT(CONDITION, TEXT_MSG) \
+ BOOST_ASSERT_MSG(CONDITION, TEXT_MSG)
+
+// TODO - change it to something like:
+// BOOST_ASSERT((CONDITION) && (TEXT_MSG))
+
+#if defined(BOOST_DISABLE_ASSERTS) || defined(NDEBUG)
+
+#define BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(PARAM)
+
+#else
+
+#define BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(PARAM) PARAM
+
+#endif
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ASSERT_HPP
diff --git a/boost/geometry/index/detail/config_begin.hpp b/boost/geometry/index/detail/config_begin.hpp
new file mode 100644
index 000000000..21c346012
--- /dev/null
+++ b/boost/geometry/index/detail/config_begin.hpp
@@ -0,0 +1,21 @@
+// Boost.Geometry Index
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_MSVC
+
+ #pragma warning (push)
+ #pragma warning (disable : 4512) // assignment operator could not be generated
+ #pragma warning (disable : 4127) // conditional expression is constant
+
+ // temporary?
+ #pragma warning (disable : 4180) // qualifier applied to function type has no meaning
+
+#endif //BOOST_MSVC
+
diff --git a/boost/geometry/index/detail/config_end.hpp b/boost/geometry/index/detail/config_end.hpp
new file mode 100644
index 000000000..d144c3369
--- /dev/null
+++ b/boost/geometry/index/detail/config_end.hpp
@@ -0,0 +1,12 @@
+// Boost.Geometry Index
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#if defined BOOST_MSVC
+ #pragma warning (pop)
+#endif
+
diff --git a/boost/geometry/index/detail/distance_predicates.hpp b/boost/geometry/index/detail/distance_predicates.hpp
new file mode 100644
index 000000000..c5c2c4c51
--- /dev/null
+++ b/boost/geometry/index/detail/distance_predicates.hpp
@@ -0,0 +1,161 @@
+// Boost.Geometry Index
+//
+// Spatial index distance predicates, calculators and checkers
+// used in nearest query - specialized for envelopes
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_DISTANCE_PREDICATES_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_DISTANCE_PREDICATES_HPP
+
+#include <boost/geometry/index/detail/algorithms/comparable_distance_near.hpp>
+#include <boost/geometry/index/detail/algorithms/comparable_distance_far.hpp>
+#include <boost/geometry/index/detail/algorithms/comparable_distance_centroid.hpp>
+#include <boost/geometry/index/detail/algorithms/path_intersection.hpp>
+
+#include <boost/geometry/index/detail/tags.hpp>
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+// ------------------------------------------------------------------ //
+// relations
+// ------------------------------------------------------------------ //
+
+template <typename T>
+struct to_nearest
+{
+ to_nearest(T const& v) : value(v) {}
+ T value;
+};
+
+template <typename T>
+struct to_centroid
+{
+ to_centroid(T const& v) : value(v) {}
+ T value;
+};
+
+template <typename T>
+struct to_furthest
+{
+ to_furthest(T const& v) : value(v) {}
+ T value;
+};
+
+// tags
+
+struct to_nearest_tag {};
+struct to_centroid_tag {};
+struct to_furthest_tag {};
+
+// ------------------------------------------------------------------ //
+// relation traits and access
+// ------------------------------------------------------------------ //
+
+template <typename T>
+struct relation
+{
+ typedef T value_type;
+ typedef to_nearest_tag tag;
+ static inline T const& value(T const& v) { return v; }
+ static inline T & value(T & v) { return v; }
+};
+
+template <typename T>
+struct relation< to_nearest<T> >
+{
+ typedef T value_type;
+ typedef to_nearest_tag tag;
+ static inline T const& value(to_nearest<T> const& r) { return r.value; }
+ static inline T & value(to_nearest<T> & r) { return r.value; }
+};
+
+template <typename T>
+struct relation< to_centroid<T> >
+{
+ typedef T value_type;
+ typedef to_centroid_tag tag;
+ static inline T const& value(to_centroid<T> const& r) { return r.value; }
+ static inline T & value(to_centroid<T> & r) { return r.value; }
+};
+
+template <typename T>
+struct relation< to_furthest<T> >
+{
+ typedef T value_type;
+ typedef to_furthest_tag tag;
+ static inline T const& value(to_furthest<T> const& r) { return r.value; }
+ static inline T & value(to_furthest<T> & r) { return r.value; }
+};
+
+// ------------------------------------------------------------------ //
+// calculate_distance
+// ------------------------------------------------------------------ //
+
+template <typename Predicate, typename Indexable, typename Tag>
+struct calculate_distance
+{
+ BOOST_MPL_ASSERT_MSG((false), INVALID_PREDICATE_OR_TAG, (calculate_distance));
+};
+
+// this handles nearest() with default Point parameter, to_nearest() and bounds
+template <typename PointRelation, typename Indexable, typename Tag>
+struct calculate_distance< nearest<PointRelation>, Indexable, Tag >
+{
+ typedef detail::relation<PointRelation> relation;
+ typedef typename relation::value_type point_type;
+ typedef typename geometry::default_distance_result<point_type, Indexable>::type result_type;
+
+ static inline bool apply(nearest<PointRelation> const& p, Indexable const& i, result_type & result)
+ {
+ result = index::detail::comparable_distance_near(relation::value(p.point_or_relation), i);
+ return true;
+ }
+};
+
+template <typename Point, typename Indexable>
+struct calculate_distance< nearest< to_centroid<Point> >, Indexable, value_tag>
+{
+ typedef Point point_type;
+ typedef typename geometry::default_distance_result<point_type, Indexable>::type result_type;
+
+ static inline bool apply(nearest< to_centroid<Point> > const& p, Indexable const& i, result_type & result)
+ {
+ result = index::detail::comparable_distance_centroid(p.point_or_relation.value, i);
+ return true;
+ }
+};
+
+template <typename Point, typename Indexable>
+struct calculate_distance< nearest< to_furthest<Point> >, Indexable, value_tag>
+{
+ typedef Point point_type;
+ typedef typename geometry::default_distance_result<point_type, Indexable>::type result_type;
+
+ static inline bool apply(nearest< to_furthest<Point> > const& p, Indexable const& i, result_type & result)
+ {
+ result = index::detail::comparable_distance_far(p.point_or_relation.value, i);
+ return true;
+ }
+};
+
+template <typename SegmentOrLinestring, typename Indexable, typename Tag>
+struct calculate_distance< path<SegmentOrLinestring>, Indexable, Tag>
+{
+ typedef typename index::detail::default_path_intersection_distance_type<
+ Indexable, SegmentOrLinestring
+ >::type result_type;
+
+ static inline bool apply(path<SegmentOrLinestring> const& p, Indexable const& i, result_type & result)
+ {
+ return index::detail::path_intersection(i, p.geometry, result);
+ }
+};
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_RTREE_DISTANCE_PREDICATES_HPP
diff --git a/boost/geometry/index/detail/exception.hpp b/boost/geometry/index/detail/exception.hpp
new file mode 100644
index 000000000..c3ea0e192
--- /dev/null
+++ b/boost/geometry/index/detail/exception.hpp
@@ -0,0 +1,72 @@
+// Boost.Geometry Index
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_EXCEPTION_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_EXCEPTION_HPP
+
+#ifndef BOOST_NO_EXCEPTIONS
+#include <stdexcept>
+#else
+#include <cstdlib>
+#endif
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+#ifndef BOOST_NO_EXCEPTIONS
+
+inline void throw_runtime_error(const char * str)
+{
+ throw std::runtime_error(str);
+}
+
+inline void throw_logic_error(const char * str)
+{
+ throw std::logic_error(str);
+}
+
+inline void throw_invalid_argument(const char * str)
+{
+ throw std::invalid_argument(str);
+}
+
+inline void throw_length_error(const char * str)
+{
+ throw std::length_error(str);
+}
+
+#else
+
+inline void throw_runtime_error(const char * str)
+{
+ BOOST_ASSERT_MSG(!"runtime_error thrown", str);
+ std::abort();
+}
+
+inline void throw_logic_error(const char * str)
+{
+ BOOST_ASSERT_MSG(!"logic_error thrown", str);
+ std::abort();
+}
+
+inline void throw_invalid_argument(const char * str)
+{
+ BOOST_ASSERT_MSG(!"invalid_argument thrown", str);
+ std::abort();
+}
+
+inline void throw_length_error(const char * str)
+{
+ BOOST_ASSERT_MSG(!"length_error thrown", str);
+ std::abort();
+}
+
+#endif
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXCEPTION_HPP
diff --git a/boost/geometry/index/detail/meta.hpp b/boost/geometry/index/detail/meta.hpp
new file mode 100644
index 000000000..bec1380b0
--- /dev/null
+++ b/boost/geometry/index/detail/meta.hpp
@@ -0,0 +1,42 @@
+// Boost.Geometry Index
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/range.hpp>
+#include <boost/mpl/aux_/has_type.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/and.hpp>
+//#include <boost/type_traits/is_convertible.hpp>
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_META_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_META_HPP
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+template <typename T>
+struct is_range
+ : ::boost::mpl::aux::has_type< ::boost::range_iterator<T> >
+{};
+
+//template <typename T, typename V, bool IsRange>
+//struct is_range_of_convertible_values_impl
+// : ::boost::is_convertible<typename ::boost::range_value<T>::type, V>
+//{};
+//
+//template <typename T, typename V>
+//struct is_range_of_convertible_values_impl<T, V, false>
+// : ::boost::mpl::bool_<false>
+//{};
+//
+//template <typename T, typename V>
+//struct is_range_of_convertible_values
+// : is_range_of_convertible_values_impl<T, V, is_range<T>::value>
+//{};
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_META_HPP
diff --git a/boost/geometry/index/detail/predicates.hpp b/boost/geometry/index/detail/predicates.hpp
new file mode 100644
index 000000000..fd5a92796
--- /dev/null
+++ b/boost/geometry/index/detail/predicates.hpp
@@ -0,0 +1,814 @@
+// Boost.Geometry Index
+//
+// Spatial query predicates definition and checks.
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP
+
+#include <boost/geometry/index/predicates.hpp>
+#include <boost/geometry/index/detail/tags.hpp>
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+// ------------------------------------------------------------------ //
+// predicates
+// ------------------------------------------------------------------ //
+
+template <typename Fun, bool IsFunction>
+struct satisfies_impl
+{
+ satisfies_impl(Fun f) : fun(f) {}
+ Fun * fun;
+};
+
+template <typename Fun>
+struct satisfies_impl<Fun, false>
+{
+ satisfies_impl(Fun const& f) : fun(f) {}
+ Fun fun;
+};
+
+template <typename Fun, bool Negated>
+struct satisfies
+ : satisfies_impl<Fun, ::boost::is_function<Fun>::value>
+{
+ typedef satisfies_impl<Fun, ::boost::is_function<Fun>::value> base;
+
+ satisfies(Fun const& f) : base(f) {}
+ satisfies(base const& b) : base(b) {}
+};
+
+// ------------------------------------------------------------------ //
+
+struct contains_tag {};
+struct covered_by_tag {};
+struct covers_tag {};
+struct disjoint_tag {};
+struct intersects_tag {};
+struct overlaps_tag {};
+struct touches_tag {};
+struct within_tag {};
+
+template <typename Geometry, typename Tag, bool Negated>
+struct spatial_predicate
+{
+ spatial_predicate(Geometry const& g) : geometry(g) {}
+ Geometry geometry;
+};
+
+// ------------------------------------------------------------------ //
+
+// TODO
+// may be replaced by
+// nearest_predicate<Geometry>
+// Geometry geometry
+// unsigned count
+// + point_tag, path_tag
+
+template <typename PointOrRelation>
+struct nearest
+{
+ nearest(PointOrRelation const& por, unsigned k)
+ : point_or_relation(por)
+ , count(k)
+ {}
+ PointOrRelation point_or_relation;
+ unsigned count;
+};
+
+template <typename SegmentOrLinestring>
+struct path
+{
+ path(SegmentOrLinestring const& g, unsigned k)
+ : geometry(g)
+ , count(k)
+ {}
+ SegmentOrLinestring geometry;
+ unsigned count;
+};
+
+// ------------------------------------------------------------------ //
+// predicate_check
+// ------------------------------------------------------------------ //
+
+template <typename Predicate, typename Tag>
+struct predicate_check
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ NOT_IMPLEMENTED_FOR_THIS_PREDICATE_OR_TAG,
+ (predicate_check));
+};
+
+// ------------------------------------------------------------------ //
+
+template <typename Fun>
+struct predicate_check<satisfies<Fun, false>, value_tag>
+{
+ template <typename Value, typename Indexable>
+ static inline bool apply(satisfies<Fun, false> const& p, Value const& v, Indexable const&)
+ {
+ return p.fun(v);
+ }
+};
+
+template <typename Fun>
+struct predicate_check<satisfies<Fun, true>, value_tag>
+{
+ template <typename Value, typename Indexable>
+ static inline bool apply(satisfies<Fun, true> const& p, Value const& v, Indexable const&)
+ {
+ return !p.fun(v);
+ }
+};
+
+// ------------------------------------------------------------------ //
+
+template <typename Tag>
+struct spatial_predicate_call
+{
+ BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_TAG, (Tag));
+};
+
+template <>
+struct spatial_predicate_call<contains_tag>
+{
+ template <typename G1, typename G2>
+ static inline bool apply(G1 const& g1, G2 const& g2)
+ {
+ return geometry::within(g2, g1);
+ }
+};
+
+template <>
+struct spatial_predicate_call<covered_by_tag>
+{
+ template <typename G1, typename G2>
+ static inline bool apply(G1 const& g1, G2 const& g2)
+ {
+ return geometry::covered_by(g1, g2);
+ }
+};
+
+template <>
+struct spatial_predicate_call<covers_tag>
+{
+ template <typename G1, typename G2>
+ static inline bool apply(G1 const& g1, G2 const& g2)
+ {
+ return geometry::covered_by(g2, g1);
+ }
+};
+
+template <>
+struct spatial_predicate_call<disjoint_tag>
+{
+ template <typename G1, typename G2>
+ static inline bool apply(G1 const& g1, G2 const& g2)
+ {
+ return geometry::disjoint(g1, g2);
+ }
+};
+
+template <>
+struct spatial_predicate_call<intersects_tag>
+{
+ template <typename G1, typename G2>
+ static inline bool apply(G1 const& g1, G2 const& g2)
+ {
+ return geometry::intersects(g1, g2);
+ }
+};
+
+template <>
+struct spatial_predicate_call<overlaps_tag>
+{
+ template <typename G1, typename G2>
+ static inline bool apply(G1 const& g1, G2 const& g2)
+ {
+ return geometry::overlaps(g1, g2);
+ }
+};
+
+template <>
+struct spatial_predicate_call<touches_tag>
+{
+ template <typename G1, typename G2>
+ static inline bool apply(G1 const& g1, G2 const& g2)
+ {
+ return geometry::touches(g1, g2);
+ }
+};
+
+template <>
+struct spatial_predicate_call<within_tag>
+{
+ template <typename G1, typename G2>
+ static inline bool apply(G1 const& g1, G2 const& g2)
+ {
+ return geometry::within(g1, g2);
+ }
+};
+
+// ------------------------------------------------------------------ //
+
+// spatial predicate
+template <typename Geometry, typename Tag>
+struct predicate_check<spatial_predicate<Geometry, Tag, false>, value_tag>
+{
+ typedef spatial_predicate<Geometry, Tag, false> Pred;
+
+ template <typename Value, typename Indexable>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ {
+ return spatial_predicate_call<Tag>::apply(i, p.geometry);
+ }
+};
+
+// negated spatial predicate
+template <typename Geometry, typename Tag>
+struct predicate_check<spatial_predicate<Geometry, Tag, true>, value_tag>
+{
+ typedef spatial_predicate<Geometry, Tag, true> Pred;
+
+ template <typename Value, typename Indexable>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ {
+ return !spatial_predicate_call<Tag>::apply(i, p.geometry);
+ }
+};
+
+// ------------------------------------------------------------------ //
+
+template <typename DistancePredicates>
+struct predicate_check<nearest<DistancePredicates>, value_tag>
+{
+ template <typename Value, typename Box>
+ static inline bool apply(nearest<DistancePredicates> const&, Value const&, Box const&)
+ {
+ return true;
+ }
+};
+
+template <typename Linestring>
+struct predicate_check<path<Linestring>, value_tag>
+{
+ template <typename Value, typename Box>
+ static inline bool apply(path<Linestring> const&, Value const&, Box const&)
+ {
+ return true;
+ }
+};
+
+// ------------------------------------------------------------------ //
+// predicates_check for bounds
+// ------------------------------------------------------------------ //
+
+template <typename Fun, bool Negated>
+struct predicate_check<satisfies<Fun, Negated>, bounds_tag>
+{
+ template <typename Value, typename Box>
+ static bool apply(satisfies<Fun, Negated> const&, Value const&, Box const&)
+ {
+ return true;
+ }
+};
+
+// ------------------------------------------------------------------ //
+
+// NOT NEGATED
+// value_tag bounds_tag
+// ---------------------------
+// contains(I,G) contains(I,G)
+// covered_by(I,G) intersects(I,G)
+// covers(I,G) covers(I,G)
+// disjoint(I,G) !covered_by(I,G)
+// intersects(I,G) intersects(I,G)
+// overlaps(I,G) intersects(I,G) - possibly change to the version without border case, e.g. intersects_without_border(0,0x1,1, 1,1x2,2) should give false
+// touches(I,G) intersects(I,G)
+// within(I,G) intersects(I,G) - possibly change to the version without border case, e.g. intersects_without_border(0,0x1,1, 1,1x2,2) should give false
+
+// spatial predicate - default
+template <typename Geometry, typename Tag>
+struct predicate_check<spatial_predicate<Geometry, Tag, false>, bounds_tag>
+{
+ typedef spatial_predicate<Geometry, Tag, false> Pred;
+
+ template <typename Value, typename Indexable>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ {
+ return spatial_predicate_call<intersects_tag>::apply(i, p.geometry);
+ }
+};
+
+// spatial predicate - contains
+template <typename Geometry>
+struct predicate_check<spatial_predicate<Geometry, contains_tag, false>, bounds_tag>
+{
+ typedef spatial_predicate<Geometry, contains_tag, false> Pred;
+
+ template <typename Value, typename Indexable>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ {
+ return spatial_predicate_call<contains_tag>::apply(i, p.geometry);
+ }
+};
+
+// spatial predicate - covers
+template <typename Geometry>
+struct predicate_check<spatial_predicate<Geometry, covers_tag, false>, bounds_tag>
+{
+ typedef spatial_predicate<Geometry, covers_tag, false> Pred;
+
+ template <typename Value, typename Indexable>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ {
+ return spatial_predicate_call<covers_tag>::apply(i, p.geometry);
+ }
+};
+
+// spatial predicate - disjoint
+template <typename Geometry>
+struct predicate_check<spatial_predicate<Geometry, disjoint_tag, false>, bounds_tag>
+{
+ typedef spatial_predicate<Geometry, disjoint_tag, false> Pred;
+
+ template <typename Value, typename Indexable>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ {
+ return !spatial_predicate_call<covered_by_tag>::apply(i, p.geometry);
+ }
+};
+
+// NEGATED
+// value_tag bounds_tag
+// ---------------------------
+// !contains(I,G) TRUE
+// !covered_by(I,G) !covered_by(I,G)
+// !covers(I,G) TRUE
+// !disjoint(I,G) !disjoint(I,G)
+// !intersects(I,G) !covered_by(I,G)
+// !overlaps(I,G) TRUE
+// !touches(I,G) !intersects(I,G)
+// !within(I,G) !within(I,G)
+
+// negated spatial predicate - default
+template <typename Geometry, typename Tag>
+struct predicate_check<spatial_predicate<Geometry, Tag, true>, bounds_tag>
+{
+ typedef spatial_predicate<Geometry, Tag, true> Pred;
+
+ template <typename Value, typename Indexable>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ {
+ return !spatial_predicate_call<Tag>::apply(i, p.geometry);
+ }
+};
+
+// negated spatial predicate - contains
+template <typename Geometry>
+struct predicate_check<spatial_predicate<Geometry, contains_tag, true>, bounds_tag>
+{
+ typedef spatial_predicate<Geometry, contains_tag, true> Pred;
+
+ template <typename Value, typename Indexable>
+ static inline bool apply(Pred const& , Value const&, Indexable const& )
+ {
+ return true;
+ }
+};
+
+// negated spatial predicate - covers
+template <typename Geometry>
+struct predicate_check<spatial_predicate<Geometry, covers_tag, true>, bounds_tag>
+{
+ typedef spatial_predicate<Geometry, covers_tag, true> Pred;
+
+ template <typename Value, typename Indexable>
+ static inline bool apply(Pred const& , Value const&, Indexable const& )
+ {
+ return true;
+ }
+};
+
+// negated spatial predicate - intersects
+template <typename Geometry>
+struct predicate_check<spatial_predicate<Geometry, intersects_tag, true>, bounds_tag>
+{
+ typedef spatial_predicate<Geometry, intersects_tag, true> Pred;
+
+ template <typename Value, typename Indexable>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ {
+ return !spatial_predicate_call<covered_by_tag>::apply(i, p.geometry);
+ }
+};
+
+// negated spatial predicate - overlaps
+template <typename Geometry>
+struct predicate_check<spatial_predicate<Geometry, overlaps_tag, true>, bounds_tag>
+{
+ typedef spatial_predicate<Geometry, overlaps_tag, true> Pred;
+
+ template <typename Value, typename Indexable>
+ static inline bool apply(Pred const& , Value const&, Indexable const& )
+ {
+ return true;
+ }
+};
+
+// negated spatial predicate - touches
+template <typename Geometry>
+struct predicate_check<spatial_predicate<Geometry, touches_tag, true>, bounds_tag>
+{
+ typedef spatial_predicate<Geometry, touches_tag, true> Pred;
+
+ template <typename Value, typename Indexable>
+ static inline bool apply(Pred const& p, Value const&, Indexable const& i)
+ {
+ return !spatial_predicate_call<intersects_tag>::apply(i, p.geometry);
+ }
+};
+
+// ------------------------------------------------------------------ //
+
+template <typename DistancePredicates>
+struct predicate_check<nearest<DistancePredicates>, bounds_tag>
+{
+ template <typename Value, typename Box>
+ static inline bool apply(nearest<DistancePredicates> const&, Value const&, Box const&)
+ {
+ return true;
+ }
+};
+
+template <typename Linestring>
+struct predicate_check<path<Linestring>, bounds_tag>
+{
+ template <typename Value, typename Box>
+ static inline bool apply(path<Linestring> const&, Value const&, Box const&)
+ {
+ return true;
+ }
+};
+
+// ------------------------------------------------------------------ //
+// predicates_length
+// ------------------------------------------------------------------ //
+
+template <typename T>
+struct predicates_length
+{
+ static const unsigned value = 1;
+};
+
+//template <typename F, typename S>
+//struct predicates_length< std::pair<F, S> >
+//{
+// static const unsigned value = 2;
+//};
+
+//template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
+//struct predicates_length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
+//{
+// static const unsigned value = boost::tuples::length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::value;
+//};
+
+template <typename Head, typename Tail>
+struct predicates_length< boost::tuples::cons<Head, Tail> >
+{
+ static const unsigned value = boost::tuples::length< boost::tuples::cons<Head, Tail> >::value;
+};
+
+// ------------------------------------------------------------------ //
+// predicates_element
+// ------------------------------------------------------------------ //
+
+template <unsigned I, typename T>
+struct predicates_element
+{
+ BOOST_MPL_ASSERT_MSG((I < 1), INVALID_INDEX, (predicates_element));
+ typedef T type;
+ static type const& get(T const& p) { return p; }
+};
+
+//template <unsigned I, typename F, typename S>
+//struct predicates_element< I, std::pair<F, S> >
+//{
+// BOOST_MPL_ASSERT_MSG((I < 2), INVALID_INDEX, (predicates_element));
+//
+// typedef F type;
+// static type const& get(std::pair<F, S> const& p) { return p.first; }
+//};
+//
+//template <typename F, typename S>
+//struct predicates_element< 1, std::pair<F, S> >
+//{
+// typedef S type;
+// static type const& get(std::pair<F, S> const& p) { return p.second; }
+//};
+//
+//template <unsigned I, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
+//struct predicates_element< I, boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
+//{
+// typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> predicate_type;
+//
+// typedef typename boost::tuples::element<I, predicate_type>::type type;
+// static type const& get(predicate_type const& p) { return boost::get<I>(p); }
+//};
+
+template <unsigned I, typename Head, typename Tail>
+struct predicates_element< I, boost::tuples::cons<Head, Tail> >
+{
+ typedef boost::tuples::cons<Head, Tail> predicate_type;
+
+ typedef typename boost::tuples::element<I, predicate_type>::type type;
+ static type const& get(predicate_type const& p) { return boost::get<I>(p); }
+};
+
+// ------------------------------------------------------------------ //
+// predicates_check
+// ------------------------------------------------------------------ //
+
+//template <typename PairPredicates, typename Tag, unsigned First, unsigned Last>
+//struct predicates_check_pair {};
+//
+//template <typename PairPredicates, typename Tag, unsigned I>
+//struct predicates_check_pair<PairPredicates, Tag, I, I>
+//{
+// template <typename Value, typename Indexable>
+// static inline bool apply(PairPredicates const& , Value const& , Indexable const& )
+// {
+// return true;
+// }
+//};
+//
+//template <typename PairPredicates, typename Tag>
+//struct predicates_check_pair<PairPredicates, Tag, 0, 1>
+//{
+// template <typename Value, typename Indexable>
+// static inline bool apply(PairPredicates const& p, Value const& v, Indexable const& i)
+// {
+// return predicate_check<typename PairPredicates::first_type, Tag>::apply(p.first, v, i);
+// }
+//};
+//
+//template <typename PairPredicates, typename Tag>
+//struct predicates_check_pair<PairPredicates, Tag, 1, 2>
+//{
+// template <typename Value, typename Indexable>
+// static inline bool apply(PairPredicates const& p, Value const& v, Indexable const& i)
+// {
+// return predicate_check<typename PairPredicates::second_type, Tag>::apply(p.second, v, i);
+// }
+//};
+//
+//template <typename PairPredicates, typename Tag>
+//struct predicates_check_pair<PairPredicates, Tag, 0, 2>
+//{
+// template <typename Value, typename Indexable>
+// static inline bool apply(PairPredicates const& p, Value const& v, Indexable const& i)
+// {
+// return predicate_check<typename PairPredicates::first_type, Tag>::apply(p.first, v, i)
+// && predicate_check<typename PairPredicates::second_type, Tag>::apply(p.second, v, i);
+// }
+//};
+
+template <typename TuplePredicates, typename Tag, unsigned First, unsigned Last>
+struct predicates_check_tuple
+{
+ template <typename Value, typename Indexable>
+ static inline bool apply(TuplePredicates const& p, Value const& v, Indexable const& i)
+ {
+ return
+ predicate_check<
+ typename boost::tuples::element<First, TuplePredicates>::type,
+ Tag
+ >::apply(boost::get<First>(p), v, i) &&
+ predicates_check_tuple<TuplePredicates, Tag, First+1, Last>::apply(p, v, i);
+ }
+};
+
+template <typename TuplePredicates, typename Tag, unsigned First>
+struct predicates_check_tuple<TuplePredicates, Tag, First, First>
+{
+ template <typename Value, typename Indexable>
+ static inline bool apply(TuplePredicates const& , Value const& , Indexable const& )
+ {
+ return true;
+ }
+};
+
+template <typename Predicate, typename Tag, unsigned First, unsigned Last>
+struct predicates_check_impl
+{
+ static const bool check = First < 1 && Last <= 1 && First <= Last;
+ BOOST_MPL_ASSERT_MSG((check), INVALID_INDEXES, (predicates_check_impl));
+
+ template <typename Value, typename Indexable>
+ static inline bool apply(Predicate const& p, Value const& v, Indexable const& i)
+ {
+ return predicate_check<Predicate, Tag>::apply(p, v, i);
+ }
+};
+
+//template <typename Predicate1, typename Predicate2, typename Tag, size_t First, size_t Last>
+//struct predicates_check_impl<std::pair<Predicate1, Predicate2>, Tag, First, Last>
+//{
+// BOOST_MPL_ASSERT_MSG((First < 2 && Last <= 2 && First <= Last), INVALID_INDEXES, (predicates_check_impl));
+//
+// template <typename Value, typename Indexable>
+// static inline bool apply(std::pair<Predicate1, Predicate2> const& p, Value const& v, Indexable const& i)
+// {
+// return predicate_check<Predicate1, Tag>::apply(p.first, v, i)
+// && predicate_check<Predicate2, Tag>::apply(p.second, v, i);
+// }
+//};
+//
+//template <
+// typename T0, typename T1, typename T2, typename T3, typename T4,
+// typename T5, typename T6, typename T7, typename T8, typename T9,
+// typename Tag, unsigned First, unsigned Last
+//>
+//struct predicates_check_impl<
+// boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>,
+// Tag, First, Last
+//>
+//{
+// typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> predicates_type;
+//
+// static const unsigned pred_len = boost::tuples::length<predicates_type>::value;
+// BOOST_MPL_ASSERT_MSG((First < pred_len && Last <= pred_len && First <= Last), INVALID_INDEXES, (predicates_check_impl));
+//
+// template <typename Value, typename Indexable>
+// static inline bool apply(predicates_type const& p, Value const& v, Indexable const& i)
+// {
+// return predicates_check_tuple<
+// predicates_type,
+// Tag, First, Last
+// >::apply(p, v, i);
+// }
+//};
+
+template <typename Head, typename Tail, typename Tag, unsigned First, unsigned Last>
+struct predicates_check_impl<
+ boost::tuples::cons<Head, Tail>,
+ Tag, First, Last
+>
+{
+ typedef boost::tuples::cons<Head, Tail> predicates_type;
+
+ static const unsigned pred_len = boost::tuples::length<predicates_type>::value;
+ static const bool check = First < pred_len && Last <= pred_len && First <= Last;
+ BOOST_MPL_ASSERT_MSG((check), INVALID_INDEXES, (predicates_check_impl));
+
+ template <typename Value, typename Indexable>
+ static inline bool apply(predicates_type const& p, Value const& v, Indexable const& i)
+ {
+ return predicates_check_tuple<
+ predicates_type,
+ Tag, First, Last
+ >::apply(p, v, i);
+ }
+};
+
+template <typename Tag, unsigned First, unsigned Last, typename Predicates, typename Value, typename Indexable>
+inline bool predicates_check(Predicates const& p, Value const& v, Indexable const& i)
+{
+ return detail::predicates_check_impl<Predicates, Tag, First, Last>
+ ::apply(p, v, i);
+}
+
+// ------------------------------------------------------------------ //
+// nearest predicate helpers
+// ------------------------------------------------------------------ //
+
+// predicates_is_nearest
+
+template <typename P>
+struct predicates_is_distance
+{
+ static const unsigned value = 0;
+};
+
+template <typename DistancePredicates>
+struct predicates_is_distance< nearest<DistancePredicates> >
+{
+ static const unsigned value = 1;
+};
+
+template <typename Linestring>
+struct predicates_is_distance< path<Linestring> >
+{
+ static const unsigned value = 1;
+};
+
+// predicates_count_nearest
+
+template <typename T>
+struct predicates_count_distance
+{
+ static const unsigned value = predicates_is_distance<T>::value;
+};
+
+//template <typename F, typename S>
+//struct predicates_count_distance< std::pair<F, S> >
+//{
+// static const unsigned value = predicates_is_distance<F>::value
+// + predicates_is_distance<S>::value;
+//};
+
+template <typename Tuple, unsigned N>
+struct predicates_count_distance_tuple
+{
+ static const unsigned value =
+ predicates_is_distance<typename boost::tuples::element<N-1, Tuple>::type>::value
+ + predicates_count_distance_tuple<Tuple, N-1>::value;
+};
+
+template <typename Tuple>
+struct predicates_count_distance_tuple<Tuple, 1>
+{
+ static const unsigned value =
+ predicates_is_distance<typename boost::tuples::element<0, Tuple>::type>::value;
+};
+
+//template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
+//struct predicates_count_distance< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
+//{
+// static const unsigned value = predicates_count_distance_tuple<
+// boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>,
+// boost::tuples::length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::value
+// >::value;
+//};
+
+template <typename Head, typename Tail>
+struct predicates_count_distance< boost::tuples::cons<Head, Tail> >
+{
+ static const unsigned value = predicates_count_distance_tuple<
+ boost::tuples::cons<Head, Tail>,
+ boost::tuples::length< boost::tuples::cons<Head, Tail> >::value
+ >::value;
+};
+
+// predicates_find_nearest
+
+template <typename T>
+struct predicates_find_distance
+{
+ static const unsigned value = predicates_is_distance<T>::value ? 0 : 1;
+};
+
+//template <typename F, typename S>
+//struct predicates_find_distance< std::pair<F, S> >
+//{
+// static const unsigned value = predicates_is_distance<F>::value ? 0 :
+// (predicates_is_distance<S>::value ? 1 : 2);
+//};
+
+template <typename Tuple, unsigned N>
+struct predicates_find_distance_tuple
+{
+ static const bool is_found = predicates_find_distance_tuple<Tuple, N-1>::is_found
+ || predicates_is_distance<typename boost::tuples::element<N-1, Tuple>::type>::value;
+
+ static const unsigned value = predicates_find_distance_tuple<Tuple, N-1>::is_found ?
+ predicates_find_distance_tuple<Tuple, N-1>::value :
+ (predicates_is_distance<typename boost::tuples::element<N-1, Tuple>::type>::value ?
+ N-1 : boost::tuples::length<Tuple>::value);
+};
+
+template <typename Tuple>
+struct predicates_find_distance_tuple<Tuple, 1>
+{
+ static const bool is_found = predicates_is_distance<typename boost::tuples::element<0, Tuple>::type>::value;
+ static const unsigned value = is_found ? 0 : boost::tuples::length<Tuple>::value;
+};
+
+//template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
+//struct predicates_find_distance< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
+//{
+// static const unsigned value = predicates_find_distance_tuple<
+// boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>,
+// boost::tuples::length< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >::value
+// >::value;
+//};
+
+template <typename Head, typename Tail>
+struct predicates_find_distance< boost::tuples::cons<Head, Tail> >
+{
+ static const unsigned value = predicates_find_distance_tuple<
+ boost::tuples::cons<Head, Tail>,
+ boost::tuples::length< boost::tuples::cons<Head, Tail> >::value
+ >::value;
+};
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_PREDICATES_HPP
diff --git a/boost/geometry/index/detail/pushable_array.hpp b/boost/geometry/index/detail/pushable_array.hpp
new file mode 100644
index 000000000..180d46580
--- /dev/null
+++ b/boost/geometry/index/detail/pushable_array.hpp
@@ -0,0 +1,171 @@
+// Boost.Geometry Index
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_PUSHABLE_ARRAY_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_PUSHABLE_ARRAY_HPP
+
+#include <boost/array.hpp>
+
+#include <boost/geometry/index/detail/assert.hpp>
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+template <typename Element, size_t Capacity>
+class pushable_array
+{
+ typedef typename boost::array<Element, Capacity> array_type;
+
+public:
+ typedef typename array_type::value_type value_type;
+ typedef typename array_type::size_type size_type;
+ typedef typename array_type::iterator iterator;
+ typedef typename array_type::const_iterator const_iterator;
+ typedef typename array_type::reverse_iterator reverse_iterator;
+ typedef typename array_type::const_reverse_iterator const_reverse_iterator;
+ typedef typename array_type::reference reference;
+ typedef typename array_type::const_reference const_reference;
+
+ inline pushable_array()
+ : m_size(0)
+ {}
+
+ inline explicit pushable_array(size_type s)
+ : m_size(s)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(s <= Capacity, "size too big");
+ }
+
+ inline void resize(size_type s)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(s <= Capacity, "size too big");
+ m_size = s;
+ }
+
+ inline void reserve(size_type /*s*/)
+ {
+ //BOOST_GEOMETRY_INDEX_ASSERT(s <= Capacity, "size too big");
+ // do nothing
+ }
+
+ inline Element & operator[](size_type i)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(i < m_size, "index of the element outside the container");
+ return m_array[i];
+ }
+
+ inline Element const& operator[](size_type i) const
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(i < m_size, "index of the element outside the container");
+ return m_array[i];
+ }
+
+ inline Element const& front() const
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < m_size, "there are no elements in the container");
+ return m_array.front();
+ }
+
+ inline Element & front()
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < m_size, "there are no elements in the container");
+ return m_array.front();
+ }
+
+ inline Element const& back() const
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < m_size, "there are no elements in the container");
+ return *(begin() + (m_size - 1));
+ }
+
+ inline Element & back()
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < m_size, "there are no elements in the container");
+ return *(begin() + (m_size - 1));
+ }
+
+ inline iterator begin()
+ {
+ return m_array.begin();
+ }
+
+ inline iterator end()
+ {
+ return m_array.begin() + m_size;
+ }
+
+ inline const_iterator begin() const
+ {
+ return m_array.begin();
+ }
+
+ inline const_iterator end() const
+ {
+ return m_array.begin() + m_size;
+ }
+
+ inline reverse_iterator rbegin()
+ {
+ return reverse_iterator(end());
+ }
+
+ inline reverse_iterator rend()
+ {
+ return reverse_iterator(begin());
+ }
+
+ inline const_reverse_iterator rbegin() const
+ {
+ return const_reverse_iterator(end());
+ }
+
+ inline const_reverse_iterator rend() const
+ {
+ return const_reverse_iterator(begin());
+ }
+
+ inline void clear()
+ {
+ m_size = 0;
+ }
+
+ inline void push_back(Element const& v)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(m_size < Capacity, "can't further increase the size of the container");
+ m_array[m_size] = v;
+ ++m_size;
+ }
+
+ inline void pop_back()
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < m_size, "there are no elements in the container");
+ --m_size;
+ }
+
+ inline bool empty() const
+ {
+ return m_size == 0;
+ }
+
+ inline size_t size() const
+ {
+ return m_size;
+ }
+
+ inline size_t capacity() const
+ {
+ return Capacity;
+ }
+
+private:
+ boost::array<Element, Capacity> m_array;
+ size_type m_size;
+};
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_PUSHABLE_ARRAY_HPP
diff --git a/boost/geometry/index/detail/rtree/adaptors.hpp b/boost/geometry/index/detail/rtree/adaptors.hpp
new file mode 100644
index 000000000..4e0eb9ba0
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/adaptors.hpp
@@ -0,0 +1,54 @@
+// Boost.Geometry Index
+//
+// R-tree queries range adaptors
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ADAPTORS_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ADAPTORS_HPP
+
+#include <deque>
+#include <boost/static_assert.hpp>
+
+#include <boost/geometry/index/adaptors/query.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+template <typename Value, typename Options, typename IndexableGetter, typename EqualTo, typename Allocator>
+class rtree;
+
+namespace adaptors { namespace detail {
+
+template <typename Value, typename Options, typename IndexableGetter, typename EqualTo, typename Allocator>
+class query_range< index::rtree<Value, Options, IndexableGetter, EqualTo, Allocator> >
+{
+public:
+ typedef std::vector<Value> result_type;
+ typedef typename result_type::iterator iterator;
+ typedef typename result_type::const_iterator const_iterator;
+
+ template <typename Predicates> inline
+ query_range(index::rtree<Value, Options, IndexableGetter, EqualTo, Allocator> const& rtree,
+ Predicates const& pred)
+ {
+ rtree.query(pred, std::back_inserter(m_result));
+ }
+
+ inline iterator begin() { return m_result.begin(); }
+ inline iterator end() { return m_result.end(); }
+ inline const_iterator begin() const { return m_result.begin(); }
+ inline const_iterator end() const { return m_result.end(); }
+
+private:
+ result_type m_result;
+};
+
+}} // namespace adaptors::detail
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ADAPTORS_HPP
diff --git a/boost/geometry/index/detail/rtree/kmeans/kmeans.hpp b/boost/geometry/index/detail/rtree/kmeans/kmeans.hpp
new file mode 100644
index 000000000..3f61482b2
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/kmeans/kmeans.hpp
@@ -0,0 +1,16 @@
+// Boost.Geometry Index
+//
+// R-tree kmeans algorithm implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_KMEANS_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_KMEANS_HPP
+
+#include <boost/geometry/index/rtree/kmeans/split.hpp>
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_KMEANS_HPP
diff --git a/boost/geometry/index/detail/rtree/kmeans/split.hpp b/boost/geometry/index/detail/rtree/kmeans/split.hpp
new file mode 100644
index 000000000..f19654972
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/kmeans/split.hpp
@@ -0,0 +1,87 @@
+// Boost.Geometry Index
+//
+// R-tree kmeans split algorithm implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_SPLIT_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_SPLIT_HPP
+
+#include <boost/geometry/index/rtree/node/node.hpp>
+#include <boost/geometry/index/rtree/visitors/insert.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+namespace kmeans {
+
+// some details
+
+} // namespace kmeans
+
+// split_kmeans_tag
+// OR
+// split_clusters_tag and redistribute_kmeans_tag - then redistribute will probably slightly different interface
+// or some other than "redistribute"
+
+// 1. for this algorithm one probably MUST USE NON-STATIC NODES with node_default_tag
+// or the algorithm must be changed somehow - to not store additional nodes in the current node
+// but return excessive element/elements container instead (possibly pushable_array<1> or std::vector)
+// this would also cause building of smaller trees since +1 element in nodes wouldn't be needed in different redistributing algorithms
+// 2. it is probably possible to add e.g. 2 levels of tree in one insert
+
+// Edge case is that every node split generates M + 1 children, in parent containing M nodes
+// result is 2M + 1 nodes in parent on this level
+// On next level the same, next the same and so on.
+// We have Depth*M+1 nodes in the root
+// The tree may then gain some > 1 levels in one insert
+// split::apply() manages this but special attention is required
+
+// which algorithm should be used to choose current node in traversing while inserting?
+// some of the currently used ones or some using mean values as well?
+
+// TODO
+// 1. Zmienic troche algorytm zeby przekazywal nadmiarowe elementy do split
+// i pobieral ze split nadmiarowe elementy rodzica
+// W zaleznosci od algorytmu w rozny sposob - l/q/r* powinny zwracac np pushable_array<1>
+// wtedy tez is_overerflow (z R* insert?) bedzie nieportrzebne
+// Dla kmeans zapewne std::vector, jednak w wezlach nadal moglaby byc pushable_array
+// 2. Fajnie byloby tez uproscic te wszystkie parametry root,parent,index itd. Mozliwe ze okazalyby sie zbedne
+// 3. Sprawdzyc czasy wykonywania i zajetosc pamieci
+// 4. Pamietac o parametryzacji kontenera z nadmiarowymi elementami
+// PS. Z R* reinsertami moze byc masakra
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class split<Value, Options, Translator, Box, Allocators, split_kmeans_tag>
+{
+protected:
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef typename Options::parameters_type parameters_type;
+
+public:
+ template <typename Node>
+ static inline void apply(node* & root_node,
+ size_t & leafs_level,
+ Node & n,
+ internal_node *parent_node,
+ size_t current_child_index,
+ Translator const& tr,
+ Allocators & allocators)
+ {
+
+ }
+};
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_KMEANS_SPLIT_HPP
diff --git a/boost/geometry/index/detail/rtree/linear/linear.hpp b/boost/geometry/index/detail/rtree/linear/linear.hpp
new file mode 100644
index 000000000..1461692a1
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/linear/linear.hpp
@@ -0,0 +1,16 @@
+// Boost.Geometry Index
+//
+// R-tree linear algorithm implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_LINEAR_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_LINEAR_HPP
+
+#include <boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp>
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_LINEAR_HPP
diff --git a/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp b/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp
new file mode 100644
index 000000000..45bd18a79
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp
@@ -0,0 +1,447 @@
+// Boost.Geometry Index
+//
+// R-tree linear split algorithm implementation
+//
+// Copyright (c) 2008 Federico J. Fernandez.
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_REDISTRIBUTE_ELEMENTS_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_REDISTRIBUTE_ELEMENTS_HPP
+
+#include <boost/type_traits/is_unsigned.hpp>
+
+#include <boost/geometry/index/detail/algorithms/content.hpp>
+
+#include <boost/geometry/index/detail/rtree/node/node.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+namespace linear {
+
+template <typename R, typename T>
+inline R difference_dispatch(T const& from, T const& to, ::boost::mpl::bool_<false> const& /*is_unsigned*/)
+{
+ return to - from;
+}
+
+template <typename R, typename T>
+inline R difference_dispatch(T const& from, T const& to, ::boost::mpl::bool_<true> const& /*is_unsigned*/)
+{
+ return from <= to ? R(to - from) : -R(from - to);
+}
+
+template <typename R, typename T>
+inline R difference(T const& from, T const& to)
+{
+ BOOST_MPL_ASSERT_MSG(!boost::is_unsigned<R>::value, RESULT_CANT_BE_UNSIGNED, (R));
+
+ typedef ::boost::mpl::bool_<
+ boost::is_unsigned<T>::value
+ > is_unsigned;
+
+ return difference_dispatch<R>(from, to, is_unsigned());
+}
+
+// TODO: awulkiew
+// In general, all aerial Indexables in the tree with box-like nodes will be analyzed as boxes
+// because they must fit into larger box. Therefore the algorithm could be the same for Bounds type.
+// E.g. if Bounds type is sphere, Indexables probably should be analyzed as spheres.
+// 1. View could be provided to 'see' all Indexables as Bounds type.
+// Not ok in the case of big types like Ring, however it's possible that Rings won't be supported,
+// only simple types. Even then if we consider storing Box inside the Sphere we must calculate
+// the bounding sphere 2x for each box because there are 2 loops. For each calculation this means
+// 4-2d or 8-3d expansions or -, / and sqrt().
+// 2. Additional container could be used and reused if the Indexable type is other than the Bounds type.
+
+// IMPORTANT!
+// Still probably the best way would be providing specialized algorithms for each Indexable-Bounds pair!
+// Probably on pick_seeds algorithm level - For Bounds=Sphere seeds would be choosen differently
+
+// TODO: awulkiew
+// there are loops inside find_greatest_normalized_separation::apply()
+// iteration is done for each DimensionIndex.
+// Separations and seeds for all DimensionIndex(es) could be calculated at once, stored, then the greatest would be choosen.
+
+// The following struct/method was adapted for the preliminary version of the R-tree. Then it was called:
+// void find_normalized_separations(std::vector<Box> const& boxes, T& separation, unsigned int& first, unsigned int& second) const
+
+template <typename Elements, typename Parameters, typename Translator, typename Tag, size_t DimensionIndex>
+struct find_greatest_normalized_separation
+{
+ BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_TAG, (Tag));
+};
+
+template <typename Elements, typename Parameters, typename Translator, size_t DimensionIndex>
+struct find_greatest_normalized_separation<Elements, Parameters, Translator, box_tag, DimensionIndex>
+{
+ typedef typename Elements::value_type element_type;
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
+ typedef typename coordinate_type<indexable_type>::type coordinate_type;
+
+ typedef typename boost::mpl::if_c<
+ boost::is_integral<coordinate_type>::value,
+ double,
+ coordinate_type
+ >::type separation_type;
+
+ static inline void apply(Elements const& elements,
+ Parameters const& parameters,
+ Translator const& translator,
+ separation_type & separation,
+ size_t & seed1,
+ size_t & seed2)
+ {
+ const size_t elements_count = parameters.get_max_elements() + 1;
+ BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "unexpected number of elements");
+ BOOST_GEOMETRY_INDEX_ASSERT(2 <= elements_count, "unexpected number of elements");
+
+ // find the lowest low, highest high
+ coordinate_type lowest_low = geometry::get<min_corner, DimensionIndex>(rtree::element_indexable(elements[0], translator));
+ coordinate_type highest_high = geometry::get<max_corner, DimensionIndex>(rtree::element_indexable(elements[0], translator));
+ // and the lowest high
+ coordinate_type lowest_high = highest_high;
+ size_t lowest_high_index = 0;
+ for ( size_t i = 1 ; i < elements_count ; ++i )
+ {
+ coordinate_type min_coord = geometry::get<min_corner, DimensionIndex>(rtree::element_indexable(elements[i], translator));
+ coordinate_type max_coord = geometry::get<max_corner, DimensionIndex>(rtree::element_indexable(elements[i], translator));
+
+ if ( max_coord < lowest_high )
+ {
+ lowest_high = max_coord;
+ lowest_high_index = i;
+ }
+
+ if ( min_coord < lowest_low )
+ lowest_low = min_coord;
+
+ if ( highest_high < max_coord )
+ highest_high = max_coord;
+ }
+
+ // find the highest low
+ size_t highest_low_index = lowest_high_index == 0 ? 1 : 0;
+ coordinate_type highest_low = geometry::get<min_corner, DimensionIndex>(rtree::element_indexable(elements[highest_low_index], translator));
+ for ( size_t i = highest_low_index ; i < elements_count ; ++i )
+ {
+ coordinate_type min_coord = geometry::get<min_corner, DimensionIndex>(rtree::element_indexable(elements[i], translator));
+ if ( highest_low < min_coord &&
+ i != lowest_high_index )
+ {
+ highest_low = min_coord;
+ highest_low_index = i;
+ }
+ }
+
+ coordinate_type const width = highest_high - lowest_low;
+
+ // highest_low - lowest_high
+ separation = difference<separation_type>(lowest_high, highest_low);
+ // BOOST_ASSERT(0 <= width);
+ if ( std::numeric_limits<coordinate_type>::epsilon() < width )
+ separation /= width;
+
+ seed1 = highest_low_index;
+ seed2 = lowest_high_index;
+
+ ::boost::ignore_unused_variable_warning(parameters);
+ }
+};
+
+// Version for points doesn't calculate normalized separation since it would always be equal to 1
+// It returns two seeds most distant to each other, separation is equal to distance
+template <typename Elements, typename Parameters, typename Translator, size_t DimensionIndex>
+struct find_greatest_normalized_separation<Elements, Parameters, Translator, point_tag, DimensionIndex>
+{
+ typedef typename Elements::value_type element_type;
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
+ typedef typename coordinate_type<indexable_type>::type coordinate_type;
+
+ typedef coordinate_type separation_type;
+
+ static inline void apply(Elements const& elements,
+ Parameters const& parameters,
+ Translator const& translator,
+ separation_type & separation,
+ size_t & seed1,
+ size_t & seed2)
+ {
+ const size_t elements_count = parameters.get_max_elements() + 1;
+ BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "unexpected number of elements");
+ BOOST_GEOMETRY_INDEX_ASSERT(2 <= elements_count, "unexpected number of elements");
+
+ // find the lowest low, highest high
+ coordinate_type lowest = geometry::get<DimensionIndex>(rtree::element_indexable(elements[0], translator));
+ coordinate_type highest = geometry::get<DimensionIndex>(rtree::element_indexable(elements[0], translator));
+ size_t lowest_index = 0;
+ size_t highest_index = 0;
+ for ( size_t i = 1 ; i < elements_count ; ++i )
+ {
+ coordinate_type coord = geometry::get<DimensionIndex>(rtree::element_indexable(elements[i], translator));
+
+ if ( coord < lowest )
+ {
+ lowest = coord;
+ lowest_index = i;
+ }
+
+ if ( highest < coord )
+ {
+ highest = coord;
+ highest_index = i;
+ }
+ }
+
+ separation = highest - lowest;
+ seed1 = lowest_index;
+ seed2 = highest_index;
+
+ if ( lowest_index == highest_index )
+ seed2 = (lowest_index + 1) % elements_count; // % is just in case since if this is true lowest_index is 0
+
+ ::boost::ignore_unused_variable_warning(parameters);
+ }
+};
+
+template <typename Elements, typename Parameters, typename Translator, size_t Dimension>
+struct pick_seeds_impl
+{
+ BOOST_STATIC_ASSERT(0 < Dimension);
+
+ typedef typename Elements::value_type element_type;
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
+ typedef typename coordinate_type<indexable_type>::type coordinate_type;
+
+ typedef find_greatest_normalized_separation<
+ Elements, Parameters, Translator,
+ typename tag<indexable_type>::type, Dimension - 1
+ > find_norm_sep;
+
+ typedef typename find_norm_sep::separation_type separation_type;
+
+ static inline void apply(Elements const& elements,
+ Parameters const& parameters,
+ Translator const& tr,
+ separation_type & separation,
+ size_t & seed1,
+ size_t & seed2)
+ {
+ pick_seeds_impl<Elements, Parameters, Translator, Dimension - 1>::apply(elements, parameters, tr, separation, seed1, seed2);
+
+ separation_type current_separation;
+ size_t s1, s2;
+ find_norm_sep::apply(elements, parameters, tr, current_separation, s1, s2);
+
+ // in the old implementation different operator was used: <= (y axis prefered)
+ if ( separation < current_separation )
+ {
+ separation = current_separation;
+ seed1 = s1;
+ seed2 = s2;
+ }
+ }
+};
+
+template <typename Elements, typename Parameters, typename Translator>
+struct pick_seeds_impl<Elements, Parameters, Translator, 1>
+{
+ typedef typename Elements::value_type element_type;
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
+ typedef typename coordinate_type<indexable_type>::type coordinate_type;
+
+ typedef find_greatest_normalized_separation<
+ Elements, Parameters, Translator,
+ typename tag<indexable_type>::type, 0
+ > find_norm_sep;
+
+ typedef typename find_norm_sep::separation_type separation_type;
+
+ static inline void apply(Elements const& elements,
+ Parameters const& parameters,
+ Translator const& tr,
+ separation_type & separation,
+ size_t & seed1,
+ size_t & seed2)
+ {
+ find_norm_sep::apply(elements, parameters, tr, separation, seed1, seed2);
+ }
+};
+
+// from void linear_pick_seeds(node_pointer const& n, unsigned int &seed1, unsigned int &seed2) const
+
+template <typename Elements, typename Parameters, typename Translator>
+struct pick_seeds
+{
+ typedef typename Elements::value_type element_type;
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
+ typedef typename coordinate_type<indexable_type>::type coordinate_type;
+
+ static const size_t dimension = geometry::dimension<indexable_type>::value;
+
+ typedef pick_seeds_impl<Elements, Parameters, Translator, dimension> impl;
+ typedef typename impl::separation_type separation_type;
+
+ static inline void apply(Elements const& elements,
+ Parameters const& parameters,
+ Translator const& tr,
+ size_t & seed1,
+ size_t & seed2)
+ {
+ separation_type separation = 0;
+ pick_seeds_impl<Elements, Parameters, Translator, dimension>::apply(elements, parameters, tr, separation, seed1, seed2);
+ }
+};
+
+} // namespace linear
+
+// from void split_node(node_pointer const& n, node_pointer& n1, node_pointer& n2) const
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+struct redistribute_elements<Value, Options, Translator, Box, Allocators, linear_tag>
+{
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ template <typename Node>
+ static inline void apply(Node & n,
+ Node & second_node,
+ Box & box1,
+ Box & box2,
+ parameters_type const& parameters,
+ Translator const& translator,
+ Allocators & allocators)
+ {
+ typedef typename rtree::elements_type<Node>::type elements_type;
+ typedef typename elements_type::value_type element_type;
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
+ typedef typename coordinate_type<indexable_type>::type coordinate_type;
+ typedef typename index::detail::default_content_result<Box>::type content_type;
+
+ elements_type & elements1 = rtree::elements(n);
+ elements_type & elements2 = rtree::elements(second_node);
+ const size_t elements1_count = parameters.get_max_elements() + 1;
+
+ BOOST_GEOMETRY_INDEX_ASSERT(elements1.size() == elements1_count, "unexpected number of elements");
+
+ // copy original elements
+ elements_type elements_copy(elements1); // MAY THROW, STRONG (alloc, copy)
+
+ // calculate initial seeds
+ size_t seed1 = 0;
+ size_t seed2 = 0;
+ linear::pick_seeds<
+ elements_type,
+ parameters_type,
+ Translator
+ >::apply(elements_copy, parameters, translator, seed1, seed2);
+
+ // prepare nodes' elements containers
+ elements1.clear();
+ BOOST_GEOMETRY_INDEX_ASSERT(elements2.empty(), "unexpected container state");
+
+ BOOST_TRY
+ {
+ // add seeds
+ elements1.push_back(elements_copy[seed1]); // MAY THROW, STRONG (copy)
+ elements2.push_back(elements_copy[seed2]); // MAY THROW, STRONG (alloc, copy)
+
+ // calculate boxes
+ detail::bounds(rtree::element_indexable(elements_copy[seed1], translator), box1);
+ detail::bounds(rtree::element_indexable(elements_copy[seed2], translator), box2);
+
+ // initialize areas
+ content_type content1 = index::detail::content(box1);
+ content_type content2 = index::detail::content(box2);
+
+ BOOST_GEOMETRY_INDEX_ASSERT(2 <= elements1_count, "unexpected elements number");
+ size_t remaining = elements1_count - 2;
+
+ // redistribute the rest of the elements
+ for ( size_t i = 0 ; i < elements1_count ; ++i )
+ {
+ if (i != seed1 && i != seed2)
+ {
+ element_type const& elem = elements_copy[i];
+ indexable_type const& indexable = rtree::element_indexable(elem, translator);
+
+ // if there is small number of elements left and the number of elements in node is lesser than min_elems
+ // just insert them to this node
+ if ( elements1.size() + remaining <= parameters.get_min_elements() )
+ {
+ elements1.push_back(elem); // MAY THROW, STRONG (copy)
+ geometry::expand(box1, indexable);
+ content1 = index::detail::content(box1);
+ }
+ else if ( elements2.size() + remaining <= parameters.get_min_elements() )
+ {
+ elements2.push_back(elem); // MAY THROW, STRONG (alloc, copy)
+ geometry::expand(box2, indexable);
+ content2 = index::detail::content(box2);
+ }
+ // choose better node and insert element
+ else
+ {
+ // calculate enlarged boxes and areas
+ Box enlarged_box1(box1);
+ Box enlarged_box2(box2);
+ geometry::expand(enlarged_box1, indexable);
+ geometry::expand(enlarged_box2, indexable);
+ content_type enlarged_content1 = index::detail::content(enlarged_box1);
+ content_type enlarged_content2 = index::detail::content(enlarged_box2);
+
+ content_type content_increase1 = enlarged_content1 - content1;
+ content_type content_increase2 = enlarged_content2 - content2;
+
+ // choose group which box content have to be enlarged least or has smaller content or has fewer elements
+ if ( content_increase1 < content_increase2 ||
+ ( content_increase1 == content_increase2 &&
+ ( content1 < content2 ||
+ ( content1 == content2 && elements1.size() <= elements2.size() ) ) ) )
+ {
+ elements1.push_back(elem); // MAY THROW, STRONG (copy)
+ box1 = enlarged_box1;
+ content1 = enlarged_content1;
+ }
+ else
+ {
+ elements2.push_back(elem); // MAY THROW, STRONG (alloc, copy)
+ box2 = enlarged_box2;
+ content2 = enlarged_content2;
+ }
+ }
+
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < remaining, "unexpected value");
+ --remaining;
+ }
+ }
+ }
+ BOOST_CATCH(...)
+ {
+ elements1.clear();
+ elements2.clear();
+
+ rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_copy, allocators);
+ //elements_copy.clear();
+
+ BOOST_RETHROW // RETHROW, BASIC
+ }
+ BOOST_CATCH_END
+ }
+};
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_LINEAR_REDISTRIBUTE_ELEMENTS_HPP
diff --git a/boost/geometry/index/detail/rtree/node/auto_deallocator.hpp b/boost/geometry/index/detail/rtree/node/auto_deallocator.hpp
new file mode 100644
index 000000000..dd55c6d76
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/node/auto_deallocator.hpp
@@ -0,0 +1,38 @@
+// Boost.Geometry Index
+//
+// R-tree auto deallocator
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_AUTO_DEALLOCATOR_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_AUTO_DEALLOCATOR_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+template <typename Alloc>
+class auto_deallocator
+{
+ auto_deallocator(auto_deallocator const&);
+ auto_deallocator & operator=(auto_deallocator const&);
+public:
+ typedef typename Alloc::pointer pointer;
+ inline auto_deallocator(Alloc & a, pointer p) : m_alloc(a), m_ptr(p) {}
+ inline ~auto_deallocator() { if ( m_ptr ) boost::container::allocator_traits<Alloc>::deallocate(m_alloc, m_ptr, 1); }
+ inline void release() { m_ptr = 0; }
+ inline pointer ptr() { return m_ptr; }
+private:
+ Alloc & m_alloc;
+ pointer m_ptr;
+};
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_AUTO_DEALLOCATOR_HPP
diff --git a/boost/geometry/index/detail/rtree/node/concept.hpp b/boost/geometry/index/detail/rtree/node/concept.hpp
new file mode 100644
index 000000000..30fa44d26
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/node/concept.hpp
@@ -0,0 +1,85 @@
+// Boost.Geometry Index
+//
+// R-tree node concept
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_CONCEPT_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_CONCEPT_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
+struct node
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ NOT_IMPLEMENTED_FOR_THIS_TAG_TYPE,
+ (node));
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
+struct internal_node
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ NOT_IMPLEMENTED_FOR_THIS_TAG_TYPE,
+ (internal_node));
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
+struct leaf
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ NOT_IMPLEMENTED_FOR_THIS_TAG_TYPE,
+ (leaf));
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag, bool IsVisitableConst>
+struct visitor
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ NOT_IMPLEMENTED_FOR_THIS_TAG_TYPE,
+ (visitor));
+};
+
+template <typename Allocator, typename Value, typename Parameters, typename Box, typename Tag>
+class allocators
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ NOT_IMPLEMENTED_FOR_THIS_TAG_TYPE,
+ (allocators));
+};
+
+template <typename Allocators, typename Node>
+struct create_node
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ NOT_IMPLEMENTED_FOR_THIS_NODE_TYPE,
+ (create_node));
+};
+
+template <typename Allocators, typename Node>
+struct destroy_node
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ NOT_IMPLEMENTED_FOR_THIS_NODE_TYPE,
+ (destroy_node));
+};
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_CONCEPT_HPP
diff --git a/boost/geometry/index/detail/rtree/node/dynamic_visitor.hpp b/boost/geometry/index/detail/rtree/node/dynamic_visitor.hpp
new file mode 100644
index 000000000..477d937db
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/node/dynamic_visitor.hpp
@@ -0,0 +1,88 @@
+// Boost.Geometry Index
+//
+// R-tree nodes dynamic visitor and nodes base type
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_DYNAMIC_VISITOR_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_DYNAMIC_VISITOR_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+// visitor forward declaration
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag, bool IsVisitableConst>
+struct dynamic_visitor;
+
+// node
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
+struct dynamic_node
+{
+ virtual ~dynamic_node() {}
+ virtual void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, Tag, false> &) = 0;
+ virtual void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, Tag, true> &) const = 0;
+};
+
+// nodes variants forward declarations
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
+struct dynamic_internal_node;
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
+struct dynamic_leaf;
+
+// visitor
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
+struct dynamic_visitor<Value, Parameters, Box, Allocators, Tag, true>
+{
+ typedef dynamic_internal_node<Value, Parameters, Box, Allocators, Tag> internal_node;
+ typedef dynamic_leaf<Value, Parameters, Box, Allocators, Tag> leaf;
+
+ virtual ~dynamic_visitor() {}
+
+ virtual void operator()(internal_node const&) = 0;
+ virtual void operator()(leaf const&) = 0;
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
+struct dynamic_visitor<Value, Parameters, Box, Allocators, Tag, false>
+{
+ typedef dynamic_internal_node<Value, Parameters, Box, Allocators, Tag> internal_node;
+ typedef dynamic_leaf<Value, Parameters, Box, Allocators, Tag> leaf;
+
+ virtual ~dynamic_visitor() {}
+
+ virtual void operator()(internal_node &) = 0;
+ virtual void operator()(leaf &) = 0;
+};
+
+// nodes conversion
+
+template <typename Derived, typename Parameters, typename Value, typename Box, typename Allocators, typename Tag>
+inline Derived & get(dynamic_node<Value, Parameters, Box, Allocators, Tag> & n)
+{
+ BOOST_GEOMETRY_INDEX_ASSERT(dynamic_cast<Derived*>(&n), "can't cast to a Derived type");
+ return static_cast<Derived&>(n);
+}
+
+// apply visitor
+
+template <typename Visitor, typename Visitable>
+inline void apply_visitor(Visitor & v, Visitable & n)
+{
+ BOOST_GEOMETRY_INDEX_ASSERT(&n, "null ptr");
+ n.apply_visitor(v);
+}
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_DYNAMIC_VISITOR_HPP
diff --git a/boost/geometry/index/detail/rtree/node/node.hpp b/boost/geometry/index/detail/rtree/node/node.hpp
new file mode 100644
index 000000000..d788cdc0d
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/node/node.hpp
@@ -0,0 +1,175 @@
+// Boost.Geometry Index
+//
+// R-tree nodes
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_HPP
+
+#include <boost/container/vector.hpp>
+#include <boost/geometry/index/detail/varray.hpp>
+
+#include <boost/geometry/index/detail/rtree/node/concept.hpp>
+#include <boost/geometry/index/detail/rtree/node/pairs.hpp>
+#include <boost/geometry/index/detail/rtree/node/auto_deallocator.hpp>
+
+#include <boost/geometry/index/detail/rtree/node/dynamic_visitor.hpp>
+#include <boost/geometry/index/detail/rtree/node/node_d_mem_dynamic.hpp>
+#include <boost/geometry/index/detail/rtree/node/node_d_mem_static.hpp>
+
+#include <boost/geometry/index/detail/rtree/node/static_visitor.hpp>
+#include <boost/geometry/index/detail/rtree/node/node_s_mem_dynamic.hpp>
+#include <boost/geometry/index/detail/rtree/node/node_s_mem_static.hpp>
+
+#include <boost/geometry/index/detail/rtree/node/node_auto_ptr.hpp>
+
+#include <boost/geometry/algorithms/expand.hpp>
+
+#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
+
+#include <boost/geometry/index/detail/algorithms/bounds.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+// elements box
+
+template <typename Box, typename FwdIter, typename Translator>
+inline Box elements_box(FwdIter first, FwdIter last, Translator const& tr)
+{
+ Box result;
+
+ if ( first == last )
+ {
+ geometry::assign_inverse(result);
+ return result;
+ }
+
+ detail::bounds(element_indexable(*first, tr), result);
+ ++first;
+
+ for ( ; first != last ; ++first )
+ geometry::expand(result, element_indexable(*first, tr));
+
+ return result;
+}
+
+// destroys subtree if the element is internal node's element
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+struct destroy_element
+{
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
+
+ inline static void apply(typename internal_node::elements_type::value_type & element, Allocators & allocators)
+ {
+ node_auto_ptr dummy(element.second, allocators);
+ element.second = 0;
+ }
+
+ inline static void apply(typename leaf::elements_type::value_type &, Allocators &) {}
+};
+
+// destroys stored subtrees if internal node's elements are passed
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+struct destroy_elements
+{
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
+
+ inline static void apply(typename internal_node::elements_type & elements, Allocators & allocators)
+ {
+ for ( size_t i = 0 ; i < elements.size() ; ++i )
+ {
+ node_auto_ptr dummy(elements[i].second, allocators);
+ elements[i].second = 0;
+ }
+ }
+
+ inline static void apply(typename leaf::elements_type &, Allocators &)
+ {}
+
+ inline static void apply(typename internal_node::elements_type::iterator first,
+ typename internal_node::elements_type::iterator last,
+ Allocators & allocators)
+ {
+ for ( ; first != last ; ++first )
+ {
+ node_auto_ptr dummy(first->second, allocators);
+ first->second = 0;
+ }
+ }
+
+ inline static void apply(typename leaf::elements_type::iterator /*first*/,
+ typename leaf::elements_type::iterator /*last*/,
+ Allocators & /*allocators*/)
+ {}
+};
+
+// clears node, deletes all subtrees stored in node
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+struct clear_node
+{
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ inline static void apply(node & node, Allocators & allocators)
+ {
+ rtree::visitors::is_leaf<Value, Options, Box, Allocators> ilv;
+ rtree::apply_visitor(ilv, node);
+ if ( ilv.result )
+ {
+ apply(rtree::get<leaf>(node), allocators);
+ }
+ else
+ {
+ apply(rtree::get<internal_node>(node), allocators);
+ }
+ }
+
+ inline static void apply(internal_node & internal_node, Allocators & allocators)
+ {
+ destroy_elements<Value, Options, Translator, Box, Allocators>::apply(rtree::elements(internal_node), allocators);
+ rtree::elements(internal_node).clear();
+ }
+
+ inline static void apply(leaf & leaf, Allocators &)
+ {
+ rtree::elements(leaf).clear();
+ }
+};
+
+template <typename Container, typename Iterator>
+void move_from_back(Container & container, Iterator it)
+{
+ BOOST_GEOMETRY_INDEX_ASSERT(!container.empty(), "cannot copy from empty container");
+ Iterator back_it = container.end();
+ --back_it;
+ if ( it != back_it )
+ {
+ *it = boost::move(*back_it); // MAY THROW (copy)
+ }
+}
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_HPP
diff --git a/boost/geometry/index/detail/rtree/node/node_auto_ptr.hpp b/boost/geometry/index/detail/rtree/node/node_auto_ptr.hpp
new file mode 100644
index 000000000..359d4380d
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/node/node_auto_ptr.hpp
@@ -0,0 +1,79 @@
+// Boost.Geometry Index
+//
+// R-tree node auto ptr
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_AUTO_PTR_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_AUTO_PTR_HPP
+
+#include <boost/geometry/index/detail/rtree/visitors/destroy.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class node_auto_ptr
+{
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename Allocators::node_pointer pointer;
+
+ node_auto_ptr(node_auto_ptr const&);
+ node_auto_ptr & operator=(node_auto_ptr const&);
+
+public:
+ node_auto_ptr(pointer ptr, Allocators & allocators)
+ : m_ptr(ptr)
+ , m_allocators(allocators)
+ {}
+
+ ~node_auto_ptr()
+ {
+ reset();
+ }
+
+ void reset(pointer ptr = 0)
+ {
+ if ( m_ptr )
+ {
+ detail::rtree::visitors::destroy<Value, Options, Translator, Box, Allocators> del_v(m_ptr, m_allocators);
+ detail::rtree::apply_visitor(del_v, *m_ptr);
+ }
+ m_ptr = ptr;
+ }
+
+ void release()
+ {
+ m_ptr = 0;
+ }
+
+ pointer get() const
+ {
+ return m_ptr;
+ }
+
+ node & operator*() const
+ {
+ return *m_ptr;
+ }
+
+ pointer operator->() const
+ {
+ return m_ptr;
+ }
+
+private:
+ pointer m_ptr;
+ Allocators & m_allocators;
+};
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_AUTO_PTR_HPP
diff --git a/boost/geometry/index/detail/rtree/node/node_d_mem_dynamic.hpp b/boost/geometry/index/detail/rtree/node/node_d_mem_dynamic.hpp
new file mode 100644
index 000000000..832335f24
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/node/node_d_mem_dynamic.hpp
@@ -0,0 +1,358 @@
+// Boost.Geometry Index
+//
+// R-tree nodes based on run-time polymorphism, storing std::vectors
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct dynamic_internal_node<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag>
+ : public dynamic_node<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag>
+{
+ typedef typename Allocators::leaf_allocator_type::template rebind<
+ rtree::ptr_pair<Box, typename Allocators::node_pointer>
+ >::other elements_allocator_type;
+
+ typedef boost::container::vector<
+ rtree::ptr_pair<Box, typename Allocators::node_pointer>,
+ elements_allocator_type
+ > elements_type;
+
+ template <typename Al>
+ inline dynamic_internal_node(Al const& al)
+ : elements(al)
+ {}
+
+ void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag, false> & v) { v(*this); }
+ void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag, true> & v) const { v(*this); }
+
+ elements_type elements;
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct dynamic_leaf<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag>
+ : public dynamic_node<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag>
+{
+ typedef typename Allocators::leaf_allocator_type::template rebind<
+ Value
+ >::other elements_allocator_type;
+
+ typedef boost::container::vector<
+ Value,
+ elements_allocator_type
+ > elements_type;
+
+ template <typename Al>
+ inline dynamic_leaf(Al const& al)
+ : elements(al)
+ {}
+
+ void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag, false> & v) { v(*this); }
+ void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag, true> & v) const { v(*this); }
+
+ elements_type elements;
+};
+
+// nodes traits
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct node<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag>
+{
+ typedef dynamic_node<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag> type;
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct internal_node<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag>
+{
+ typedef dynamic_internal_node<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag> type;
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct leaf<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag>
+{
+ typedef dynamic_leaf<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag> type;
+};
+
+// visitor traits
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>
+struct visitor<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag, IsVisitableConst>
+{
+ typedef dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_dynamic_tag, IsVisitableConst> type;
+};
+
+// element's indexable type
+
+template <typename Element, typename Translator>
+struct element_indexable_type
+{
+ typedef typename indexable_type<Translator>::type type;
+};
+
+template <typename First, typename Pointer, typename Translator>
+struct element_indexable_type<
+ rtree::ptr_pair<First, Pointer>,
+ Translator
+>
+{
+ typedef First type;
+};
+
+// element's indexable getter
+
+template <typename Element, typename Translator>
+typename result_type<Translator>::type
+element_indexable(Element const& el, Translator const& tr)
+{
+ return tr(el);
+}
+
+template <typename First, typename Pointer, typename Translator>
+First const&
+element_indexable(rtree::ptr_pair<First, Pointer> const& el, Translator const& /*tr*/)
+{
+ return el.first;
+}
+
+// nodes elements
+
+template <typename Node>
+struct elements_type
+{
+ typedef typename Node::elements_type type;
+};
+
+template <typename Node>
+inline typename elements_type<Node>::type &
+elements(Node & n)
+{
+ return n.elements;
+}
+
+template <typename Node>
+inline typename elements_type<Node>::type const&
+elements(Node const& n)
+{
+ return n.elements;
+}
+
+// elements derived type
+template <typename Elements, typename NewValue>
+struct container_from_elements_type
+{
+ typedef boost::container::vector<NewValue> type;
+};
+
+// allocators
+
+template <typename Allocator, typename Value, typename Parameters, typename Box>
+class allocators<Allocator, Value, Parameters, Box, node_d_mem_dynamic_tag>
+ : public Allocator::template rebind<
+ typename internal_node<Value, Parameters, Box, allocators<Allocator, Value, Parameters, Box, node_d_mem_dynamic_tag>, node_d_mem_dynamic_tag>::type
+ >::other
+ , public Allocator::template rebind<
+ typename leaf<Value, Parameters, Box, allocators<Allocator, Value, Parameters, Box, node_d_mem_dynamic_tag>, node_d_mem_dynamic_tag>::type
+ >::other
+{
+ typedef typename Allocator::template rebind<
+ Value
+ >::other value_allocator_type;
+
+public:
+ typedef Allocator allocator_type;
+
+ typedef Value value_type;
+ typedef typename value_allocator_type::reference reference;
+ typedef typename value_allocator_type::const_reference const_reference;
+ typedef typename value_allocator_type::size_type size_type;
+ typedef typename value_allocator_type::difference_type difference_type;
+ typedef typename value_allocator_type::pointer pointer;
+ typedef typename value_allocator_type::const_pointer const_pointer;
+
+ typedef typename Allocator::template rebind<
+ typename node<Value, Parameters, Box, allocators, node_d_mem_dynamic_tag>::type
+ >::other::pointer node_pointer;
+
+ typedef typename Allocator::template rebind<
+ typename internal_node<Value, Parameters, Box, allocators, node_d_mem_dynamic_tag>::type
+ >::other::pointer internal_node_pointer;
+
+ typedef typename Allocator::template rebind<
+ typename internal_node<Value, Parameters, Box, allocators, node_d_mem_dynamic_tag>::type
+ >::other internal_node_allocator_type;
+
+ typedef typename Allocator::template rebind<
+ typename leaf<Value, Parameters, Box, allocators, node_d_mem_dynamic_tag>::type
+ >::other leaf_allocator_type;
+
+ inline allocators()
+ : internal_node_allocator_type()
+ , leaf_allocator_type()
+ {}
+
+ template <typename Alloc>
+ inline explicit allocators(Alloc const& alloc)
+ : internal_node_allocator_type(alloc)
+ , leaf_allocator_type(alloc)
+ {}
+
+ inline allocators(BOOST_FWD_REF(allocators) a)
+ : internal_node_allocator_type(boost::move(a.internal_node_allocator()))
+ , leaf_allocator_type(boost::move(a.leaf_allocator()))
+ {}
+
+ inline allocators & operator=(BOOST_FWD_REF(allocators) a)
+ {
+ internal_node_allocator() = ::boost::move(a.internal_node_allocator());
+ leaf_allocator() = ::boost::move(a.leaf_allocator());
+ return *this;
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ inline allocators & operator=(allocators const& a)
+ {
+ internal_node_allocator() = a.internal_node_allocator();
+ leaf_allocator() = a.leaf_allocator();
+ return *this;
+ }
+#endif
+
+ void swap(allocators & a)
+ {
+ boost::swap(internal_node_allocator(), a.internal_node_allocator());
+ boost::swap(leaf_allocator(), a.leaf_allocator());
+ }
+
+ bool operator==(allocators const& a) const { return leaf_allocator() == a.leaf_allocator(); }
+ template <typename Alloc>
+ bool operator==(Alloc const& a) const { return leaf_allocator() == leaf_allocator_type(a); }
+
+ Allocator allocator() const { return Allocator(leaf_allocator()); }
+
+ internal_node_allocator_type & internal_node_allocator() { return *this; }
+ internal_node_allocator_type const& internal_node_allocator() const { return *this; }
+ leaf_allocator_type & leaf_allocator() { return *this; }
+ leaf_allocator_type const& leaf_allocator() const { return *this; }
+};
+
+// create_node_impl
+
+template <typename BaseNodePtr, typename Node>
+struct create_dynamic_node
+{
+ template <typename AllocNode>
+ static inline BaseNodePtr apply(AllocNode & alloc_node)
+ {
+ typedef boost::container::allocator_traits<AllocNode> Al;
+ typedef typename Al::pointer P;
+
+ P p = Al::allocate(alloc_node, 1);
+
+ if ( 0 == p )
+ throw_runtime_error("boost::geometry::index::rtree node creation failed");
+
+ auto_deallocator<AllocNode> deallocator(alloc_node, p);
+
+ Al::construct(alloc_node, boost::addressof(*p), alloc_node);
+
+ deallocator.release();
+ return p;
+ }
+};
+
+// destroy_node_impl
+
+template <typename Node>
+struct destroy_dynamic_node
+{
+ template <typename AllocNode, typename BaseNodePtr>
+ static inline void apply(AllocNode & alloc_node, BaseNodePtr n)
+ {
+ typedef boost::container::allocator_traits<AllocNode> Al;
+ typedef typename Al::pointer P;
+
+ P p(&static_cast<Node&>(rtree::get<Node>(*n)));
+ Al::destroy(alloc_node, boost::addressof(*p));
+ Al::deallocate(alloc_node, p, 1);
+ }
+};
+
+// create_node
+
+template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
+struct create_node<
+ Allocators,
+ dynamic_internal_node<Value, Parameters, Box, Allocators, Tag>
+>
+{
+ static inline typename Allocators::node_pointer
+ apply(Allocators & allocators)
+ {
+ return create_dynamic_node<
+ typename Allocators::node_pointer,
+ dynamic_internal_node<Value, Parameters, Box, Allocators, Tag>
+ >::apply(allocators.internal_node_allocator());
+ }
+};
+
+template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
+struct create_node<
+ Allocators,
+ dynamic_leaf<Value, Parameters, Box, Allocators, Tag>
+>
+{
+ static inline typename Allocators::node_pointer
+ apply(Allocators & allocators)
+ {
+ return create_dynamic_node<
+ typename Allocators::node_pointer,
+ dynamic_leaf<Value, Parameters, Box, Allocators, Tag>
+ >::apply(allocators.leaf_allocator());
+ }
+};
+
+// destroy_node
+
+template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
+struct destroy_node<
+ Allocators,
+ dynamic_internal_node<Value, Parameters, Box, Allocators, Tag>
+>
+{
+ static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)
+ {
+ destroy_dynamic_node<
+ dynamic_internal_node<Value, Parameters, Box, Allocators, Tag>
+ >::apply(allocators.internal_node_allocator(), n);
+ }
+};
+
+template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
+struct destroy_node<
+ Allocators,
+ dynamic_leaf<Value, Parameters, Box, Allocators, Tag>
+>
+{
+ static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)
+ {
+ destroy_dynamic_node<
+ dynamic_leaf<Value, Parameters, Box, Allocators, Tag>
+ >::apply(allocators.leaf_allocator(), n);
+ }
+};
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_HPP
diff --git a/boost/geometry/index/detail/rtree/node/node_d_mem_static.hpp b/boost/geometry/index/detail/rtree/node/node_d_mem_static.hpp
new file mode 100644
index 000000000..bfbe0ae93
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/node/node_d_mem_static.hpp
@@ -0,0 +1,199 @@
+// Boost.Geometry Index
+//
+// R-tree nodes based on runtime-polymorphism, storing static-size containers
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_STATIC_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_STATIC_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct dynamic_internal_node<Value, Parameters, Box, Allocators, node_d_mem_static_tag>
+ : public dynamic_node<Value, Parameters, Box, Allocators, node_d_mem_static_tag>
+{
+ typedef typename Allocators::leaf_allocator_type::template rebind<
+ rtree::ptr_pair<Box, typename Allocators::node_pointer>
+ >::other elements_allocator_type;
+
+ typedef detail::varray<
+ rtree::ptr_pair<Box, typename Allocators::node_pointer>,
+ Parameters::max_elements + 1
+ > elements_type;
+
+ template <typename Alloc>
+ inline dynamic_internal_node(Alloc const&) {}
+
+ void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_static_tag, false> & v) { v(*this); }
+ void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_static_tag, true> & v) const { v(*this); }
+
+ elements_type elements;
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct dynamic_leaf<Value, Parameters, Box, Allocators, node_d_mem_static_tag>
+ : public dynamic_node<Value, Parameters, Box, Allocators, node_d_mem_static_tag>
+{
+ typedef typename Allocators::leaf_allocator_type::template rebind<
+ Value
+ >::other elements_allocator_type;
+
+ typedef detail::varray<
+ Value,
+ Parameters::max_elements + 1
+ > elements_type;
+
+ template <typename Alloc>
+ inline dynamic_leaf(Alloc const&) {}
+
+ void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_static_tag, false> & v) { v(*this); }
+ void apply_visitor(dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_static_tag, true> & v) const { v(*this); }
+
+ elements_type elements;
+};
+
+// nodes traits
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct node<Value, Parameters, Box, Allocators, node_d_mem_static_tag>
+{
+ typedef dynamic_node<Value, Parameters, Box, Allocators, node_d_mem_static_tag> type;
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct internal_node<Value, Parameters, Box, Allocators, node_d_mem_static_tag>
+{
+ typedef dynamic_internal_node<Value, Parameters, Box, Allocators, node_d_mem_static_tag> type;
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct leaf<Value, Parameters, Box, Allocators, node_d_mem_static_tag>
+{
+ typedef dynamic_leaf<Value, Parameters, Box, Allocators, node_d_mem_static_tag> type;
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>
+struct visitor<Value, Parameters, Box, Allocators, node_d_mem_static_tag, IsVisitableConst>
+{
+ typedef dynamic_visitor<Value, Parameters, Box, Allocators, node_d_mem_static_tag, IsVisitableConst> type;
+};
+
+// elements derived type
+template <typename OldValue, size_t N, typename NewValue>
+struct container_from_elements_type<detail::varray<OldValue, N>, NewValue>
+{
+ typedef detail::varray<NewValue, N> type;
+};
+
+// allocators
+
+template <typename Allocator, typename Value, typename Parameters, typename Box>
+class allocators<Allocator, Value, Parameters, Box, node_d_mem_static_tag>
+ : public Allocator::template rebind<
+ typename internal_node<
+ Value, Parameters, Box,
+ allocators<Allocator, Value, Parameters, Box, node_d_mem_static_tag>,
+ node_d_mem_static_tag
+ >::type
+ >::other
+ , public Allocator::template rebind<
+ typename leaf<
+ Value, Parameters, Box,
+ allocators<Allocator, Value, Parameters, Box, node_d_mem_static_tag>,
+ node_d_mem_static_tag
+ >::type
+ >::other
+{
+ typedef typename Allocator::template rebind<
+ Value
+ >::other value_allocator_type;
+
+public:
+ typedef Allocator allocator_type;
+
+ typedef Value value_type;
+ typedef value_type & reference;
+ typedef const value_type & const_reference;
+ typedef typename value_allocator_type::size_type size_type;
+ typedef typename value_allocator_type::difference_type difference_type;
+ typedef typename value_allocator_type::pointer pointer;
+ typedef typename value_allocator_type::const_pointer const_pointer;
+
+ typedef typename Allocator::template rebind<
+ typename node<Value, Parameters, Box, allocators, node_d_mem_static_tag>::type
+ >::other::pointer node_pointer;
+
+ typedef typename Allocator::template rebind<
+ typename internal_node<Value, Parameters, Box, allocators, node_d_mem_static_tag>::type
+ >::other::pointer internal_node_pointer;
+
+ typedef typename Allocator::template rebind<
+ typename internal_node<Value, Parameters, Box, allocators, node_d_mem_static_tag>::type
+ >::other internal_node_allocator_type;
+
+ typedef typename Allocator::template rebind<
+ typename leaf<Value, Parameters, Box, allocators, node_d_mem_static_tag>::type
+ >::other leaf_allocator_type;
+
+ inline allocators()
+ : internal_node_allocator_type()
+ , leaf_allocator_type()
+ {}
+
+ template <typename Alloc>
+ inline explicit allocators(Alloc const& alloc)
+ : internal_node_allocator_type(alloc)
+ , leaf_allocator_type(alloc)
+ {}
+
+ inline allocators(BOOST_FWD_REF(allocators) a)
+ : internal_node_allocator_type(boost::move(a.internal_node_allocator()))
+ , leaf_allocator_type(boost::move(a.leaf_allocator()))
+ {}
+
+ inline allocators & operator=(BOOST_FWD_REF(allocators) a)
+ {
+ internal_node_allocator() = ::boost::move(a.internal_node_allocator());
+ leaf_allocator() = ::boost::move(a.leaf_allocator());
+ return *this;
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ inline allocators & operator=(allocators const& a)
+ {
+ internal_node_allocator() = a.internal_node_allocator();
+ leaf_allocator() = a.leaf_allocator();
+ return *this;
+ }
+#endif
+
+ void swap(allocators & a)
+ {
+ boost::swap(internal_node_allocator(), a.internal_node_allocator());
+ boost::swap(leaf_allocator(), a.leaf_allocator());
+ }
+
+ bool operator==(allocators const& a) const { return leaf_allocator() == a.leaf_allocator(); }
+ template <typename Alloc>
+ bool operator==(Alloc const& a) const { return leaf_allocator() == leaf_allocator_type(a); }
+
+ Allocator allocator() const { return Allocator(leaf_allocator()); }
+
+ internal_node_allocator_type & internal_node_allocator() { return *this; }
+ internal_node_allocator_type const& internal_node_allocator() const { return *this; }
+ leaf_allocator_type & leaf_allocator() { return *this; }
+ leaf_allocator_type const& leaf_allocator() const{ return *this; }
+};
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_STATIC_HPP
diff --git a/boost/geometry/index/detail/rtree/node/node_s_mem_dynamic.hpp b/boost/geometry/index/detail/rtree/node/node_s_mem_dynamic.hpp
new file mode 100644
index 000000000..a37856c55
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/node/node_s_mem_dynamic.hpp
@@ -0,0 +1,276 @@
+// Boost.Geometry Index
+//
+// R-tree nodes based on Boost.Variant, storing std::vectors
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_VARIANT_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_VARIANT_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+// nodes default types
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
+struct static_internal_node
+{
+ typedef typename Allocators::node_allocator_type::template rebind<
+ rtree::ptr_pair<Box, typename Allocators::node_pointer>
+ >::other elements_allocator_type;
+
+ typedef boost::container::vector<
+ rtree::ptr_pair<Box, typename Allocators::node_pointer>,
+ elements_allocator_type
+ > elements_type;
+
+ template <typename Al>
+ inline static_internal_node(Al const& al)
+ : elements(al)
+ {}
+
+ elements_type elements;
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
+struct static_leaf
+{
+ typedef typename Allocators::node_allocator_type::template rebind<
+ Value
+ >::other elements_allocator_type;
+
+ typedef boost::container::vector<
+ Value,
+ elements_allocator_type
+ > elements_type;
+
+ template <typename Al>
+ inline static_leaf(Al const& al)
+ : elements(al)
+ {}
+
+ elements_type elements;
+};
+
+// nodes traits
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct node<Value, Parameters, Box, Allocators, node_s_mem_dynamic_tag>
+{
+ typedef boost::variant<
+ static_leaf<Value, Parameters, Box, Allocators, node_s_mem_dynamic_tag>,
+ static_internal_node<Value, Parameters, Box, Allocators, node_s_mem_dynamic_tag>
+ > type;
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct internal_node<Value, Parameters, Box, Allocators, node_s_mem_dynamic_tag>
+{
+ typedef static_internal_node<Value, Parameters, Box, Allocators, node_s_mem_dynamic_tag> type;
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct leaf<Value, Parameters, Box, Allocators, node_s_mem_dynamic_tag>
+{
+ typedef static_leaf<Value, Parameters, Box, Allocators, node_s_mem_dynamic_tag> type;
+};
+
+// visitor traits
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>
+struct visitor<Value, Parameters, Box, Allocators, node_s_mem_dynamic_tag, IsVisitableConst>
+{
+ typedef static_visitor<> type;
+};
+
+// allocators
+
+template <typename Allocator, typename Value, typename Parameters, typename Box>
+class allocators<Allocator, Value, Parameters, Box, node_s_mem_dynamic_tag>
+ : public Allocator::template rebind<
+ typename node<Value, Parameters, Box, allocators<Allocator, Value, Parameters, Box, node_s_mem_dynamic_tag>, node_s_mem_dynamic_tag>::type
+ >::other
+{
+ typedef typename Allocator::template rebind<
+ Value
+ >::other value_allocator_type;
+
+public:
+ typedef Allocator allocator_type;
+
+ typedef Value value_type;
+ typedef typename value_allocator_type::reference reference;
+ typedef typename value_allocator_type::const_reference const_reference;
+ typedef typename value_allocator_type::size_type size_type;
+ typedef typename value_allocator_type::difference_type difference_type;
+ typedef typename value_allocator_type::pointer pointer;
+ typedef typename value_allocator_type::const_pointer const_pointer;
+
+ typedef typename Allocator::template rebind<
+ typename node<Value, Parameters, Box, allocators, node_s_mem_dynamic_tag>::type
+ >::other::pointer node_pointer;
+
+ typedef typename Allocator::template rebind<
+ typename internal_node<Value, Parameters, Box, allocators, node_s_mem_dynamic_tag>::type
+ >::other::pointer internal_node_pointer;
+
+ typedef typename Allocator::template rebind<
+ typename node<Value, Parameters, Box, allocators, node_s_mem_dynamic_tag>::type
+ >::other node_allocator_type;
+
+ inline allocators()
+ : node_allocator_type()
+ {}
+
+ template <typename Alloc>
+ inline explicit allocators(Alloc const& alloc)
+ : node_allocator_type(alloc)
+ {}
+
+ inline allocators(BOOST_FWD_REF(allocators) a)
+ : node_allocator_type(boost::move(a.node_allocator()))
+ {}
+
+ inline allocators & operator=(BOOST_FWD_REF(allocators) a)
+ {
+ node_allocator() = boost::move(a.node_allocator());
+ return *this;
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ inline allocators & operator=(allocators const& a)
+ {
+ node_allocator() = a.node_allocator();
+ return *this;
+ }
+#endif
+
+ void swap(allocators & a)
+ {
+ boost::swap(node_allocator(), a.node_allocator());
+ }
+
+ bool operator==(allocators const& a) const { return node_allocator() == a.node_allocator(); }
+ template <typename Alloc>
+ bool operator==(Alloc const& a) const { return node_allocator() == node_allocator_type(a); }
+
+ Allocator allocator() const { return Allocator(node_allocator()); }
+
+ node_allocator_type & node_allocator() { return *this; }
+ node_allocator_type const& node_allocator() const { return *this; }
+};
+
+// create_node_variant
+
+template <typename VariantPtr, typename Node>
+struct create_static_node
+{
+ template <typename AllocNode>
+ static inline VariantPtr apply(AllocNode & alloc_node)
+ {
+ typedef boost::container::allocator_traits<AllocNode> Al;
+ typedef typename Al::pointer P;
+
+ P p = Al::allocate(alloc_node, 1);
+
+ if ( 0 == p )
+ throw_runtime_error("boost::geometry::index::rtree node creation failed");
+
+ auto_deallocator<AllocNode> deallocator(alloc_node, p);
+
+ Al::construct(alloc_node, boost::addressof(*p), Node(alloc_node)); // implicit cast to Variant
+
+ deallocator.release();
+ return p;
+ }
+};
+
+// destroy_node_variant
+
+template <typename Node>
+struct destroy_static_node
+{
+ template <typename AllocNode, typename VariantPtr>
+ static inline void apply(AllocNode & alloc_node, VariantPtr n)
+ {
+ typedef boost::container::allocator_traits<AllocNode> Al;
+
+ Al::destroy(alloc_node, boost::addressof(*n));
+ Al::deallocate(alloc_node, n, 1);
+ }
+};
+
+// create_node
+
+template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
+struct create_node<
+ Allocators,
+ static_internal_node<Value, Parameters, Box, Allocators, Tag>
+>
+{
+ static inline typename Allocators::node_pointer
+ apply(Allocators & allocators)
+ {
+ return create_static_node<
+ typename Allocators::node_pointer,
+ static_internal_node<Value, Parameters, Box, Allocators, Tag>
+ >::apply(allocators.node_allocator());
+ }
+};
+
+template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
+struct create_node<
+ Allocators,
+ static_leaf<Value, Parameters, Box, Allocators, Tag>
+>
+{
+ static inline typename Allocators::node_pointer
+ apply(Allocators & allocators)
+ {
+ return create_static_node<
+ typename Allocators::node_pointer,
+ static_leaf<Value, Parameters, Box, Allocators, Tag>
+ >::apply(allocators.node_allocator());
+ }
+};
+
+// destroy_node
+
+template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
+struct destroy_node<
+ Allocators,
+ static_internal_node<Value, Parameters, Box, Allocators, Tag>
+>
+{
+ static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)
+ {
+ destroy_static_node<
+ static_internal_node<Value, Parameters, Box, Allocators, Tag>
+ >::apply(allocators.node_allocator(), n);
+ }
+};
+
+template <typename Allocators, typename Value, typename Parameters, typename Box, typename Tag>
+struct destroy_node<
+ Allocators,
+ static_leaf<Value, Parameters, Box, Allocators, Tag>
+>
+{
+ static inline void apply(Allocators & allocators, typename Allocators::node_pointer n)
+ {
+ destroy_static_node<
+ static_leaf<Value, Parameters, Box, Allocators, Tag>
+ >::apply(allocators.node_allocator(), n);
+ }
+};
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_VARIANT_HPP
diff --git a/boost/geometry/index/detail/rtree/node/node_s_mem_static.hpp b/boost/geometry/index/detail/rtree/node/node_s_mem_static.hpp
new file mode 100644
index 000000000..fa9fb456f
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/node/node_s_mem_static.hpp
@@ -0,0 +1,202 @@
+// Boost.Geometry Index
+//
+// R-tree nodes based on Boost.Variant, storing static-size containers
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_STATIC_VARIANT_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_STATIC_VARIANT_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+// nodes default types
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct static_internal_node<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
+{
+ typedef typename Allocators::node_allocator_type::template rebind<
+ rtree::ptr_pair<Box, typename Allocators::node_pointer>
+ >::other elements_allocator_type;
+
+ typedef detail::varray<
+ rtree::ptr_pair<Box, typename Allocators::node_pointer>,
+ Parameters::max_elements + 1
+ > elements_type;
+
+ template <typename Alloc>
+ inline static_internal_node(Alloc const&) {}
+
+ elements_type elements;
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct static_leaf<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
+{
+ typedef typename Allocators::node_allocator_type::template rebind<
+ Value
+ >::other elements_allocator_type;
+
+ typedef detail::varray<
+ Value,
+ Parameters::max_elements + 1
+ > elements_type;
+
+ template <typename Alloc>
+ inline static_leaf(Alloc const&) {}
+
+ elements_type elements;
+};
+
+// nodes traits
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct node<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
+{
+ typedef boost::variant<
+ static_leaf<Value, Parameters, Box, Allocators, node_s_mem_static_tag>,
+ static_internal_node<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
+ > type;
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct internal_node<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
+{
+ typedef static_internal_node<Value, Parameters, Box, Allocators, node_s_mem_static_tag> type;
+};
+
+template <typename Value, typename Parameters, typename Box, typename Allocators>
+struct leaf<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
+{
+ typedef static_leaf<Value, Parameters, Box, Allocators, node_s_mem_static_tag> type;
+};
+
+// visitor traits
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, bool IsVisitableConst>
+struct visitor<Value, Parameters, Box, Allocators, node_s_mem_static_tag, IsVisitableConst>
+{
+ typedef static_visitor<> type;
+};
+
+// allocators
+
+template <typename Allocator, typename Value, typename Parameters, typename Box>
+struct allocators<Allocator, Value, Parameters, Box, node_s_mem_static_tag>
+ : public Allocator::template rebind<
+ typename node<Value, Parameters, Box, allocators<Allocator, Value, Parameters, Box, node_s_mem_static_tag>, node_s_mem_static_tag>::type
+ >::other
+{
+ typedef typename Allocator::template rebind<
+ Value
+ >::other value_allocator_type;
+
+public:
+ typedef Allocator allocator_type;
+
+ typedef Value value_type;
+ typedef value_type & reference;
+ typedef const value_type & const_reference;
+ typedef typename value_allocator_type::size_type size_type;
+ typedef typename value_allocator_type::difference_type difference_type;
+ typedef typename value_allocator_type::pointer pointer;
+ typedef typename value_allocator_type::const_pointer const_pointer;
+
+ typedef typename Allocator::template rebind<
+ typename node<Value, Parameters, Box, allocators, node_s_mem_static_tag>::type
+ >::other::pointer node_pointer;
+
+ typedef typename Allocator::template rebind<
+ typename internal_node<Value, Parameters, Box, allocators, node_s_mem_static_tag>::type
+ >::other::pointer internal_node_pointer;
+
+ typedef typename Allocator::template rebind<
+ typename node<Value, Parameters, Box, allocators, node_s_mem_static_tag>::type
+ >::other node_allocator_type;
+
+ inline allocators()
+ : node_allocator_type()
+ {}
+
+ template <typename Alloc>
+ inline explicit allocators(Alloc const& alloc)
+ : node_allocator_type(alloc)
+ {}
+
+ inline allocators(BOOST_FWD_REF(allocators) a)
+ : node_allocator_type(boost::move(a.node_allocator()))
+ {}
+
+ inline allocators & operator=(BOOST_FWD_REF(allocators) a)
+ {
+ node_allocator() = boost::move(a.node_allocator());
+ return *this;
+ }
+
+#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
+ inline allocators & operator=(allocators const& a)
+ {
+ node_allocator() = a.node_allocator();
+ return *this;
+ }
+#endif
+
+ void swap(allocators & a)
+ {
+ boost::swap(node_allocator(), a.node_allocator());
+ }
+
+ bool operator==(allocators const& a) const { return node_allocator() == a.node_allocator(); }
+ template <typename Alloc>
+ bool operator==(Alloc const& a) const { return node_allocator() == node_allocator_type(a); }
+
+ Allocator allocator() const { return Allocator(node_allocator()); }
+
+ node_allocator_type & node_allocator() { return *this; }
+ node_allocator_type const& node_allocator() const { return *this; }
+};
+
+// create_node
+
+template <typename Allocators, typename Value, typename Parameters, typename Box>
+struct create_node<
+ Allocators,
+ static_internal_node<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
+>
+{
+ static inline typename Allocators::node_pointer
+ apply(Allocators & allocators)
+ {
+ return create_static_node<
+ typename Allocators::node_pointer,
+ static_internal_node<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
+ >::template apply(allocators.node_allocator());
+ }
+};
+
+template <typename Allocators, typename Value, typename Parameters, typename Box>
+struct create_node<
+ Allocators,
+ static_leaf<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
+>
+{
+ static inline typename Allocators::node_pointer
+ apply(Allocators & allocators)
+ {
+ return create_static_node<
+ typename Allocators::node_pointer,
+ static_leaf<Value, Parameters, Box, Allocators, node_s_mem_static_tag>
+ >::template apply(allocators.node_allocator());
+ }
+};
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_NODE_DEFAULT_STATIC_VARIANT_HPP
diff --git a/boost/geometry/index/detail/rtree/node/pairs.hpp b/boost/geometry/index/detail/rtree/node/pairs.hpp
new file mode 100644
index 000000000..dc088ec29
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/node/pairs.hpp
@@ -0,0 +1,71 @@
+// Boost.Geometry Index
+//
+// Pairs intended to be used internally in nodes.
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_PAIRS_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_PAIRS_HPP
+
+#include <boost/move/move.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+template <typename First, typename Pointer>
+class ptr_pair
+{
+public:
+ typedef First first_type;
+ typedef Pointer second_type;
+ ptr_pair(First const& f, Pointer s) : first(f), second(s) {}
+ //ptr_pair(ptr_pair const& p) : first(p.first), second(p.second) {}
+ //ptr_pair & operator=(ptr_pair const& p) { first = p.first; second = p.second; return *this; }
+
+ first_type first;
+ second_type second;
+};
+
+template <typename First, typename Pointer> inline
+ptr_pair<First, Pointer>
+make_ptr_pair(First const& f, Pointer s)
+{
+ return ptr_pair<First, Pointer>(f, s);
+}
+
+// TODO: It this will be used, rename it to unique_ptr_pair and possibly use unique_ptr.
+
+template <typename First, typename Pointer>
+class exclusive_ptr_pair
+{
+ BOOST_MOVABLE_BUT_NOT_COPYABLE(exclusive_ptr_pair)
+public:
+ typedef First first_type;
+ typedef Pointer second_type;
+ exclusive_ptr_pair(First const& f, Pointer s) : first(f), second(s) {}
+
+ // INFO - members aren't really moved!
+ exclusive_ptr_pair(BOOST_RV_REF(exclusive_ptr_pair) p) : first(p.first), second(p.second) { p.second = 0; }
+ exclusive_ptr_pair & operator=(BOOST_RV_REF(exclusive_ptr_pair) p) { first = p.first; second = p.second; p.second = 0; return *this; }
+
+ first_type first;
+ second_type second;
+};
+
+template <typename First, typename Pointer> inline
+exclusive_ptr_pair<First, Pointer>
+make_exclusive_ptr_pair(First const& f, Pointer s)
+{
+ return exclusive_ptr_pair<First, Pointer>(f, s);
+}
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_PAIRS_HPP
diff --git a/boost/geometry/index/detail/rtree/node/static_visitor.hpp b/boost/geometry/index/detail/rtree/node/static_visitor.hpp
new file mode 100644
index 000000000..9b74b1e41
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/node/static_visitor.hpp
@@ -0,0 +1,66 @@
+// Boost.Geometry Index
+//
+// R-tree nodes static visitor related code
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_STATIC_VISITOR_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_STATIC_VISITOR_HPP
+
+#include <boost/variant.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+// nodes variants forward declarations
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
+struct static_internal_node;
+
+template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
+struct static_leaf;
+
+// nodes conversion
+
+template <typename V, typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
+inline V & get(
+ boost::variant<
+ static_leaf<Value, Parameters, Box, Allocators, Tag>,
+ static_internal_node<Value, Parameters, Box, Allocators, Tag>
+ > & v)
+{
+ return boost::get<V>(v);
+}
+
+// apply visitor
+
+template <typename Visitor, typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
+inline void apply_visitor(Visitor & v,
+ boost::variant<
+ static_leaf<Value, Parameters, Box, Allocators, Tag>,
+ static_internal_node<Value, Parameters, Box, Allocators, Tag>
+ > & n)
+{
+ boost::apply_visitor(v, n);
+}
+
+template <typename Visitor, typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
+inline void apply_visitor(Visitor & v,
+ boost::variant<
+ static_leaf<Value, Parameters, Box, Allocators, Tag>,
+ static_internal_node<Value, Parameters, Box, Allocators, Tag>
+ > const& n)
+{
+ boost::apply_visitor(v, n);
+}
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_STATIC_VISITOR_HPP
diff --git a/boost/geometry/index/detail/rtree/options.hpp b/boost/geometry/index/detail/rtree/options.hpp
new file mode 100644
index 000000000..b1bb60df1
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/options.hpp
@@ -0,0 +1,155 @@
+// Boost.Geometry Index
+//
+// R-tree options, algorithms, parameters
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_OPTIONS_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_OPTIONS_HPP
+
+#include <boost/geometry/index/parameters.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+// InsertTag
+struct insert_default_tag {};
+struct insert_reinsert_tag {};
+
+// ChooseNextNodeTag
+struct choose_by_content_diff_tag {};
+struct choose_by_overlap_diff_tag {};
+
+// SplitTag
+struct split_default_tag {};
+//struct split_kmeans_tag {};
+
+// RedistributeTag
+struct linear_tag {};
+struct quadratic_tag {};
+struct rstar_tag {};
+
+// NodeTag
+struct node_d_mem_dynamic_tag {};
+struct node_d_mem_static_tag {};
+struct node_s_mem_dynamic_tag {};
+struct node_s_mem_static_tag {};
+
+template <typename Parameters, typename InsertTag, typename ChooseNextNodeTag, typename SplitTag, typename RedistributeTag, typename NodeTag>
+struct options
+{
+ typedef Parameters parameters_type;
+ typedef InsertTag insert_tag;
+ typedef ChooseNextNodeTag choose_next_node_tag;
+ typedef SplitTag split_tag;
+ typedef RedistributeTag redistribute_tag;
+ typedef NodeTag node_tag;
+};
+
+template <typename Parameters>
+struct options_type
+{
+ // TODO: awulkiew - use static assert
+};
+
+template <size_t MaxElements, size_t MinElements>
+struct options_type< index::linear<MaxElements, MinElements> >
+{
+ typedef options<
+ index::linear<MaxElements, MinElements>,
+ insert_default_tag,
+ choose_by_content_diff_tag,
+ split_default_tag,
+ linear_tag,
+ node_d_mem_static_tag
+ > type;
+};
+
+template <size_t MaxElements, size_t MinElements>
+struct options_type< index::quadratic<MaxElements, MinElements> >
+{
+ typedef options<
+ index::quadratic<MaxElements, MinElements>,
+ insert_default_tag,
+ choose_by_content_diff_tag,
+ split_default_tag,
+ quadratic_tag,
+ node_d_mem_static_tag
+ > type;
+};
+
+template <size_t MaxElements, size_t MinElements, size_t OverlapCostThreshold, size_t ReinsertedElements>
+struct options_type< index::rstar<MaxElements, MinElements, OverlapCostThreshold, ReinsertedElements> >
+{
+ typedef options<
+ index::rstar<MaxElements, MinElements, OverlapCostThreshold, ReinsertedElements>,
+ insert_reinsert_tag,
+ choose_by_overlap_diff_tag,
+ split_default_tag,
+ rstar_tag,
+ node_d_mem_static_tag
+ > type;
+};
+
+//template <size_t MaxElements, size_t MinElements>
+//struct options_type< kmeans<MaxElements, MinElements> >
+//{
+// typedef options<
+// kmeans<MaxElements, MinElements>,
+// insert_default_tag,
+// choose_by_content_diff_tag, // change it?
+// split_kmeans_tag,
+// int, // dummy tag - not used for now
+// node_d_mem_static_tag
+// > type;
+//};
+
+template <>
+struct options_type< index::dynamic_linear >
+{
+ typedef options<
+ index::dynamic_linear,
+ insert_default_tag,
+ choose_by_content_diff_tag,
+ split_default_tag,
+ linear_tag,
+ node_d_mem_dynamic_tag
+ > type;
+};
+
+template <>
+struct options_type< index::dynamic_quadratic >
+{
+ typedef options<
+ index::dynamic_quadratic,
+ insert_default_tag,
+ choose_by_content_diff_tag,
+ split_default_tag,
+ quadratic_tag,
+ node_d_mem_dynamic_tag
+ > type;
+};
+
+template <>
+struct options_type< index::dynamic_rstar >
+{
+ typedef options<
+ index::dynamic_rstar,
+ insert_reinsert_tag,
+ choose_by_overlap_diff_tag,
+ split_default_tag,
+ rstar_tag,
+ node_d_mem_dynamic_tag
+ > type;
+};
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_OPTIONS_HPP
diff --git a/boost/geometry/index/detail/rtree/pack_create.hpp b/boost/geometry/index/detail/rtree/pack_create.hpp
new file mode 100644
index 000000000..44292f18c
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/pack_create.hpp
@@ -0,0 +1,376 @@
+// Boost.Geometry Index
+//
+// R-tree initial packing
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_PACK_CREATE_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_PACK_CREATE_HPP
+
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
+
+namespace pack_utils {
+
+template <std::size_t Dimension>
+struct biggest_edge
+{
+ BOOST_STATIC_ASSERT(0 < Dimension);
+ template <typename Box>
+ static inline void apply(Box const& box, typename coordinate_type<Box>::type & length, std::size_t & dim_index)
+ {
+ biggest_edge<Dimension-1>::apply(box, length, dim_index);
+ typename coordinate_type<Box>::type curr
+ = geometry::get<max_corner, Dimension-1>(box) - geometry::get<min_corner, Dimension-1>(box);
+ if ( length < curr )
+ {
+ dim_index = Dimension - 1;
+ length = curr;
+ }
+ }
+};
+
+template <>
+struct biggest_edge<1>
+{
+ template <typename Box>
+ static inline void apply(Box const& box, typename coordinate_type<Box>::type & length, std::size_t & dim_index)
+ {
+ dim_index = 0;
+ length = geometry::get<max_corner, 0>(box) - geometry::get<min_corner, 0>(box);
+ }
+};
+
+template <std::size_t I>
+struct point_entries_comparer
+{
+ template <typename PointEntry>
+ bool operator()(PointEntry const& e1, PointEntry const& e2) const
+ {
+ return geometry::get<I>(e1.first) < geometry::get<I>(e2.first);
+ }
+};
+
+template <std::size_t I, std::size_t Dimension>
+struct partial_sort_and_half_boxes
+{
+ template <typename EIt, typename Box>
+ static inline void apply(EIt first, EIt median, EIt last, Box const& box, Box & left, Box & right, std::size_t dim_index)
+ {
+ if ( I == dim_index )
+ {
+ std::partial_sort(first, median, last, point_entries_comparer<I>());
+
+ geometry::convert(box, left);
+ geometry::convert(box, right);
+ typename coordinate_type<Box>::type edge_len
+ = geometry::get<max_corner, I>(box) - geometry::get<min_corner, I>(box);
+ typename coordinate_type<Box>::type median
+ = geometry::get<min_corner, I>(box) + edge_len / 2;
+ geometry::set<max_corner, I>(left, median);
+ geometry::set<min_corner, I>(right, median);
+ }
+ else
+ partial_sort_and_half_boxes<I+1, Dimension>::apply(first, median, last, box, left, right, dim_index);
+ }
+};
+
+template <std::size_t Dimension>
+struct partial_sort_and_half_boxes<Dimension, Dimension>
+{
+ template <typename EIt, typename Box>
+ static inline void apply(EIt , EIt , EIt , Box const& , Box & , Box & , std::size_t ) {}
+};
+
+} // namespace pack_utils
+
+// STR leafs number are calculated as rcount/max
+// and the number of splitting planes for each dimension as (count/max)^(1/dimension)
+// <-> for dimension==2 -> sqrt(count/max)
+//
+// The main flaw of this algorithm is that the resulting tree will have bad structure for:
+// 1. non-uniformly distributed elements
+// Statistic check could be performed, e.g. based on variance of lengths of elements edges for each dimension
+// 2. elements distributed mainly along one axis
+// Calculate bounding box of all elements and then number of dividing planes for a dimension
+// from the length of BB edge for this dimension (more or less assuming that elements are uniformly-distributed squares)
+//
+// Another thing is that the last node may have less elements than Max or even Min.
+// The number of splitting planes must be chosen more carefully than count/max
+//
+// This algorithm is something between STR and TGS
+// it is more similar to the top-down recursive kd-tree creation algorithm
+// using object median split and split axis of greatest BB edge
+// BB is only used as a hint (assuming objects are distributed uniformly)
+//
+// Implemented algorithm guarantees that the number of elements in nodes will be between Min and Max
+// and that nodes are packed as tightly as possible
+// e.g. for 177 values Max = 5 and Min = 2 it will construct the following tree:
+// ROOT 177
+// L1 125 52
+// L2 25 25 25 25 25 25 17 10
+// L3 5x5 5x5 5x5 5x5 5x5 5x5 3x5+2 2x5
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class pack
+{
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef typename Allocators::node_pointer node_pointer;
+ typedef rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
+ typedef typename Allocators::size_type size_type;
+
+ typedef typename traits::point_type<Box>::type point_type;
+ typedef typename traits::coordinate_type<point_type>::type coordinate_type;
+ typedef typename detail::default_content_result<Box>::type content_type;
+ typedef typename Options::parameters_type parameters_type;
+ static const std::size_t dimension = traits::dimension<point_type>::value;
+
+ typedef typename rtree::container_from_elements_type<
+ typename rtree::elements_type<leaf>::type,
+ std::size_t
+ >::type values_counts_container;
+
+ typedef typename rtree::elements_type<internal_node>::type internal_elements;
+ typedef typename internal_elements::value_type internal_element;
+
+public:
+ // Arbitrary iterators
+ template <typename InIt> inline static
+ node_pointer apply(InIt first, InIt last, size_type & values_count, size_type & leafs_level,
+ parameters_type const& parameters, Translator const& translator, Allocators & allocators)
+ {
+ typedef typename std::iterator_traits<InIt>::difference_type diff_type;
+
+ diff_type diff = std::distance(first, last);
+ if ( diff <= 0 )
+ return node_pointer(0);
+
+ typedef std::pair<point_type, InIt> entry_type;
+ std::vector<entry_type> entries;
+
+ values_count = static_cast<size_type>(diff);
+ entries.reserve(values_count);
+
+ Box hint_box;
+ geometry::assign_inverse(hint_box);
+ for ( ; first != last ; ++first )
+ {
+ geometry::expand(hint_box, translator(*first));
+
+ point_type pt;
+ geometry::centroid(translator(*first), pt);
+ entries.push_back(std::make_pair(pt, first));
+ }
+
+ subtree_elements_counts subtree_counts = calculate_subtree_elements_counts(values_count, parameters, leafs_level);
+ internal_element el = per_level(entries.begin(), entries.end(), hint_box, values_count, subtree_counts,
+ parameters, translator, allocators);
+
+ return el.second;
+ }
+
+private:
+ struct subtree_elements_counts
+ {
+ subtree_elements_counts(std::size_t ma, std::size_t mi) : maxc(ma), minc(mi) {}
+ std::size_t maxc;
+ std::size_t minc;
+ };
+
+ template <typename EIt> inline static
+ internal_element per_level(EIt first, EIt last, Box const& hint_box, std::size_t values_count, subtree_elements_counts const& subtree_counts,
+ parameters_type const& parameters, Translator const& translator, Allocators & allocators)
+ {
+ BOOST_ASSERT(0 < std::distance(first, last) && static_cast<std::size_t>(std::distance(first, last)) == values_count);
+
+ if ( subtree_counts.maxc <= 1 )
+ {
+ // ROOT or LEAF
+ BOOST_ASSERT(values_count <= parameters.get_max_elements());
+ // if !root check m_parameters.get_min_elements() <= count
+
+ // create new leaf node
+ node_pointer n = rtree::create_node<Allocators, leaf>::apply(allocators); // MAY THROW (A)
+ node_auto_ptr auto_remover(n, allocators);
+ leaf & l = rtree::get<leaf>(*n);
+
+ // reserve space for values
+ rtree::elements(l).reserve(values_count); // MAY THROW (A)
+ // calculate values box and copy values
+ Box elements_box;
+ geometry::assign_inverse(elements_box);
+ for ( ; first != last ; ++first )
+ {
+ rtree::elements(l).push_back(*(first->second)); // MAY THROW (A?,C)
+ geometry::expand(elements_box, translator(*(first->second)));
+ }
+
+ auto_remover.release();
+ return internal_element(elements_box, n);
+ }
+
+ // calculate next max and min subtree counts
+ subtree_elements_counts next_subtree_counts = subtree_counts;
+ next_subtree_counts.maxc /= parameters.get_max_elements();
+ next_subtree_counts.minc /= parameters.get_max_elements();
+
+ // create new internal node
+ node_pointer n = rtree::create_node<Allocators, internal_node>::apply(allocators); // MAY THROW (A)
+ node_auto_ptr auto_remover(n, allocators);
+ internal_node & in = rtree::get<internal_node>(*n);
+
+ // reserve space for values
+ std::size_t nodes_count = calculate_nodes_count(values_count, subtree_counts);
+ rtree::elements(in).reserve(nodes_count); // MAY THROW (A)
+ // calculate values box and copy values
+ Box elements_box;
+ geometry::assign_inverse(elements_box);
+
+ per_level_packets(first, last, hint_box, values_count, subtree_counts, next_subtree_counts,
+ rtree::elements(in), elements_box,
+ parameters, translator, allocators);
+
+ auto_remover.release();
+ return internal_element(elements_box, n);
+ }
+
+ template <typename EIt> inline static
+ void per_level_packets(EIt first, EIt last, Box const& hint_box,
+ std::size_t values_count,
+ subtree_elements_counts const& subtree_counts,
+ subtree_elements_counts const& next_subtree_counts,
+ internal_elements & elements, Box & elements_box,
+ parameters_type const& parameters, Translator const& translator, Allocators & allocators)
+ {
+ BOOST_ASSERT(0 < std::distance(first, last) && static_cast<std::size_t>(std::distance(first, last)) == values_count);
+
+ BOOST_ASSERT_MSG( subtree_counts.minc <= values_count, "too small number of elements");
+
+ // only one packet
+ if ( values_count <= subtree_counts.maxc )
+ {
+ // the end, move to the next level
+ internal_element el = per_level(first, last, hint_box, values_count, next_subtree_counts,
+ parameters, translator, allocators);
+
+ // in case if push_back() do throw here
+ // and even if this is not probable (previously reserved memory, nonthrowing pairs copy)
+ // this case is also tested by exceptions test.
+ node_auto_ptr auto_remover(el.second, allocators);
+ // this container should have memory allocated, reserve() called outside
+ elements.push_back(el); // MAY THROW (A?,C) - however in normal conditions shouldn't
+ auto_remover.release();
+
+ geometry::expand(elements_box, el.first);
+ return;
+ }
+
+ std::size_t median_count = calculate_median_count(values_count, subtree_counts);
+ EIt median = first + median_count;
+
+ coordinate_type greatest_length;
+ std::size_t greatest_dim_index = 0;
+ pack_utils::biggest_edge<dimension>::apply(hint_box, greatest_length, greatest_dim_index);
+ Box left, right;
+ pack_utils::partial_sort_and_half_boxes<0, dimension>
+ ::apply(first, median, last, hint_box, left, right, greatest_dim_index);
+
+ per_level_packets(first, median, left,
+ median_count, subtree_counts, next_subtree_counts,
+ elements, elements_box,
+ parameters, translator, allocators);
+ per_level_packets(median, last, right,
+ values_count - median_count, subtree_counts, next_subtree_counts,
+ elements, elements_box,
+ parameters, translator, allocators);
+ }
+
+ inline static
+ subtree_elements_counts calculate_subtree_elements_counts(std::size_t elements_count, parameters_type const& parameters, size_type & leafs_level)
+ {
+ (void)parameters;
+
+ subtree_elements_counts res(1, 1);
+ leafs_level = 0;
+
+ std::size_t smax = parameters.get_max_elements();
+ for ( ; smax < elements_count ; smax *= parameters.get_max_elements(), ++leafs_level )
+ res.maxc = smax;
+
+ res.minc = parameters.get_min_elements() * (res.maxc / parameters.get_max_elements());
+
+ return res;
+ }
+
+ inline static
+ std::size_t calculate_nodes_count(std::size_t count,
+ subtree_elements_counts const& subtree_counts)
+ {
+ std::size_t n = count / subtree_counts.maxc;
+ std::size_t r = count % subtree_counts.maxc;
+
+ if ( 0 < r && r < subtree_counts.minc )
+ {
+ std::size_t count_minus_min = count - subtree_counts.minc;
+ n = count_minus_min / subtree_counts.maxc;
+ r = count_minus_min % subtree_counts.maxc;
+ ++n;
+ }
+
+ if ( 0 < r )
+ ++n;
+
+ return n;
+ }
+
+ inline static
+ std::size_t calculate_median_count(std::size_t count,
+ subtree_elements_counts const& subtree_counts)
+ {
+ // e.g. for max = 5, min = 2, count = 52, subtree_max = 25, subtree_min = 10
+
+ std::size_t n = count / subtree_counts.maxc; // e.g. 52 / 25 = 2
+ std::size_t r = count % subtree_counts.maxc; // e.g. 52 % 25 = 2
+ std::size_t median_count = (n / 2) * subtree_counts.maxc; // e.g. 2 / 2 * 25 = 25
+
+ if ( 0 != r ) // e.g. 0 != 2
+ {
+ if ( subtree_counts.minc <= r ) // e.g. 10 <= 2 == false
+ {
+ //BOOST_ASSERT_MSG(0 < n, "unexpected value");
+ median_count = ((n+1)/2) * subtree_counts.maxc; // if calculated ((2+1)/2) * 25 which would be ok, but not in all cases
+ }
+ else // r < subtree_counts.second // e.g. 2 < 10 == true
+ {
+ std::size_t count_minus_min = count - subtree_counts.minc; // e.g. 52 - 10 = 42
+ n = count_minus_min / subtree_counts.maxc; // e.g. 42 / 25 = 1
+ r = count_minus_min % subtree_counts.maxc; // e.g. 42 % 25 = 17
+ if ( r == 0 ) // e.g. false
+ {
+ // n can't be equal to 0 because then there wouldn't be any element in the other node
+ //BOOST_ASSERT_MSG(0 < n, "unexpected value");
+ median_count = ((n+1)/2) * subtree_counts.maxc; // if calculated ((1+1)/2) * 25 which would be ok, but not in all cases
+ }
+ else
+ {
+ if ( n == 0 ) // e.g. false
+ median_count = r; // if calculated -> 17 which is wrong!
+ else
+ median_count = ((n+2)/2) * subtree_counts.maxc; // e.g. ((1+2)/2) * 25 = 25
+ }
+ }
+ }
+
+ return median_count;
+ }
+};
+
+}}}}} // namespace boost::geometry::index::detail::rtree
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_PACK_CREATE_HPP
diff --git a/boost/geometry/index/detail/rtree/quadratic/quadratic.hpp b/boost/geometry/index/detail/rtree/quadratic/quadratic.hpp
new file mode 100644
index 000000000..837ddbeec
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/quadratic/quadratic.hpp
@@ -0,0 +1,16 @@
+// Boost.Geometry Index
+//
+// R-tree quadratic algorithm implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUADRATIC_QUADRATIC_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUADRATIC_QUADRATIC_HPP
+
+#include <boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp>
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUADRATIC_QUADRATIC_HPP
diff --git a/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp b/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp
new file mode 100644
index 000000000..d18998970
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp
@@ -0,0 +1,298 @@
+// Boost.Geometry Index
+//
+// R-tree quadratic split algorithm implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUADRATIC_REDISTRIBUTE_ELEMENTS_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUADRATIC_REDISTRIBUTE_ELEMENTS_HPP
+
+#include <algorithm>
+
+#include <boost/geometry/index/detail/algorithms/content.hpp>
+#include <boost/geometry/index/detail/algorithms/union_content.hpp>
+
+#include <boost/geometry/index/detail/rtree/node/node.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+namespace quadratic {
+
+template <typename Elements, typename Parameters, typename Translator, typename Box>
+struct pick_seeds
+{
+ typedef typename Elements::value_type element_type;
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
+ typedef typename coordinate_type<indexable_type>::type coordinate_type;
+ typedef Box box_type;
+ typedef typename index::detail::default_content_result<box_type>::type content_type;
+
+ static inline void apply(Elements const& elements,
+ Parameters const& parameters,
+ Translator const& tr,
+ size_t & seed1,
+ size_t & seed2)
+ {
+ const size_t elements_count = parameters.get_max_elements() + 1;
+ BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "wrong number of elements");
+ BOOST_GEOMETRY_INDEX_ASSERT(2 <= elements_count, "unexpected number of elements");
+
+ content_type greatest_free_content = 0;
+ seed1 = 0;
+ seed2 = 1;
+
+ for ( size_t i = 0 ; i < elements_count - 1 ; ++i )
+ {
+ for ( size_t j = i + 1 ; j < elements_count ; ++j )
+ {
+ indexable_type const& ind1 = rtree::element_indexable(elements[i], tr);
+ indexable_type const& ind2 = rtree::element_indexable(elements[j], tr);
+
+ box_type enlarged_box;
+ //geometry::convert(ind1, enlarged_box);
+ detail::bounds(ind1, enlarged_box);
+ geometry::expand(enlarged_box, ind2);
+
+ content_type free_content = (index::detail::content(enlarged_box) - index::detail::content(ind1)) - index::detail::content(ind2);
+
+ if ( greatest_free_content < free_content )
+ {
+ greatest_free_content = free_content;
+ seed1 = i;
+ seed2 = j;
+ }
+ }
+ }
+
+ ::boost::ignore_unused_variable_warning(parameters);
+ }
+};
+
+} // namespace quadratic
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+struct redistribute_elements<Value, Options, Translator, Box, Allocators, quadratic_tag>
+{
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef typename index::detail::default_content_result<Box>::type content_type;
+
+ template <typename Node>
+ static inline void apply(Node & n,
+ Node & second_node,
+ Box & box1,
+ Box & box2,
+ parameters_type const& parameters,
+ Translator const& translator,
+ Allocators & allocators)
+ {
+ typedef typename rtree::elements_type<Node>::type elements_type;
+ typedef typename elements_type::value_type element_type;
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
+ typedef typename coordinate_type<indexable_type>::type coordinate_type;
+
+ elements_type & elements1 = rtree::elements(n);
+ elements_type & elements2 = rtree::elements(second_node);
+
+ BOOST_GEOMETRY_INDEX_ASSERT(elements1.size() == parameters.get_max_elements() + 1, "unexpected elements number");
+
+ // copy original elements
+ elements_type elements_copy(elements1); // MAY THROW, STRONG (alloc, copy)
+ elements_type elements_backup(elements1); // MAY THROW, STRONG (alloc, copy)
+
+ // calculate initial seeds
+ size_t seed1 = 0;
+ size_t seed2 = 0;
+ quadratic::pick_seeds<
+ elements_type,
+ parameters_type,
+ Translator,
+ Box
+ >::apply(elements_copy, parameters, translator, seed1, seed2);
+
+ // prepare nodes' elements containers
+ elements1.clear();
+ BOOST_GEOMETRY_INDEX_ASSERT(elements2.empty(), "second node's elements container should be empty");
+
+ BOOST_TRY
+ {
+ // add seeds
+ elements1.push_back(elements_copy[seed1]); // MAY THROW, STRONG (copy)
+ elements2.push_back(elements_copy[seed2]); // MAY THROW, STRONG (alloc, copy)
+
+ // calculate boxes
+ //geometry::convert(rtree::element_indexable(elements_copy[seed1], translator), box1);
+ detail::bounds(rtree::element_indexable(elements_copy[seed1], translator), box1);
+ //geometry::convert(rtree::element_indexable(elements_copy[seed2], translator), box2);
+ detail::bounds(rtree::element_indexable(elements_copy[seed2], translator), box2);
+
+ // remove seeds
+ if (seed1 < seed2)
+ {
+ rtree::move_from_back(elements_copy, elements_copy.begin() + seed2); // MAY THROW, STRONG (copy)
+ elements_copy.pop_back();
+ rtree::move_from_back(elements_copy, elements_copy.begin() + seed1); // MAY THROW, STRONG (copy)
+ elements_copy.pop_back();
+ }
+ else
+ {
+ rtree::move_from_back(elements_copy, elements_copy.begin() + seed1); // MAY THROW, STRONG (copy)
+ elements_copy.pop_back();
+ rtree::move_from_back(elements_copy, elements_copy.begin() + seed2); // MAY THROW, STRONG (copy)
+ elements_copy.pop_back();
+ }
+
+ // initialize areas
+ content_type content1 = index::detail::content(box1);
+ content_type content2 = index::detail::content(box2);
+
+ size_t remaining = elements_copy.size();
+
+ // redistribute the rest of the elements
+ while ( !elements_copy.empty() )
+ {
+ typename elements_type::reverse_iterator el_it = elements_copy.rbegin();
+ bool insert_into_group1 = false;
+
+ size_t elements1_count = elements1.size();
+ size_t elements2_count = elements2.size();
+
+ // if there is small number of elements left and the number of elements in node is lesser than min_elems
+ // just insert them to this node
+ if ( elements1_count + remaining <= parameters.get_min_elements() )
+ {
+ insert_into_group1 = true;
+ }
+ else if ( elements2_count + remaining <= parameters.get_min_elements() )
+ {
+ insert_into_group1 = false;
+ }
+ // insert the best element
+ else
+ {
+ // find element with minimum groups areas increses differences
+ content_type content_increase1 = 0;
+ content_type content_increase2 = 0;
+ el_it = pick_next(elements_copy.rbegin(), elements_copy.rend(),
+ box1, box2, content1, content2, translator,
+ content_increase1, content_increase2);
+
+ if ( content_increase1 < content_increase2 ||
+ ( content_increase1 == content_increase2 && ( content1 < content2 ||
+ ( content1 == content2 && elements1_count <= elements2_count ) )
+ ) )
+ {
+ insert_into_group1 = true;
+ }
+ else
+ {
+ insert_into_group1 = false;
+ }
+ }
+
+ // move element to the choosen group
+ element_type const& elem = *el_it;
+ indexable_type const& indexable = rtree::element_indexable(elem, translator);
+
+ if ( insert_into_group1 )
+ {
+ elements1.push_back(elem); // MAY THROW, STRONG (copy)
+ geometry::expand(box1, indexable);
+ content1 = index::detail::content(box1);
+ }
+ else
+ {
+ elements2.push_back(elem); // MAY THROW, STRONG (alloc, copy)
+ geometry::expand(box2, indexable);
+ content2 = index::detail::content(box2);
+ }
+
+ BOOST_GEOMETRY_INDEX_ASSERT(!elements_copy.empty(), "expected more elements");
+ typename elements_type::iterator el_it_base = el_it.base();
+ rtree::move_from_back(elements_copy, --el_it_base); // MAY THROW, STRONG (copy)
+ elements_copy.pop_back();
+
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < remaining, "expected more remaining elements");
+ --remaining;
+ }
+ }
+ BOOST_CATCH(...)
+ {
+ //elements_copy.clear();
+ elements1.clear();
+ elements2.clear();
+
+ rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_backup, allocators);
+ //elements_backup.clear();
+
+ BOOST_RETHROW // RETHROW, BASIC
+ }
+ BOOST_CATCH_END
+ }
+
+ // TODO: awulkiew - change following function to static member of the pick_next class?
+
+ template <typename It>
+ static inline It pick_next(It first, It last,
+ Box const& box1, Box const& box2,
+ content_type const& content1, content_type const& content2,
+ Translator const& translator,
+ content_type & out_content_increase1, content_type & out_content_increase2)
+ {
+ typedef typename boost::iterator_value<It>::type element_type;
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
+
+ content_type greatest_content_incrase_diff = 0;
+ It out_it = first;
+ out_content_increase1 = 0;
+ out_content_increase2 = 0;
+
+ // find element with greatest difference between increased group's boxes areas
+ for ( It el_it = first ; el_it != last ; ++el_it )
+ {
+ indexable_type const& indexable = rtree::element_indexable(*el_it, translator);
+
+ // calculate enlarged boxes and areas
+ Box enlarged_box1(box1);
+ Box enlarged_box2(box2);
+ geometry::expand(enlarged_box1, indexable);
+ geometry::expand(enlarged_box2, indexable);
+ content_type enlarged_content1 = index::detail::content(enlarged_box1);
+ content_type enlarged_content2 = index::detail::content(enlarged_box2);
+
+ content_type content_incrase1 = (enlarged_content1 - content1);
+ content_type content_incrase2 = (enlarged_content2 - content2);
+
+ content_type content_incrase_diff = content_incrase1 < content_incrase2 ?
+ content_incrase2 - content_incrase1 : content_incrase1 - content_incrase2;
+
+ if ( greatest_content_incrase_diff < content_incrase_diff )
+ {
+ greatest_content_incrase_diff = content_incrase_diff;
+ out_it = el_it;
+ out_content_increase1 = content_incrase1;
+ out_content_increase2 = content_incrase2;
+ }
+ }
+
+ return out_it;
+ }
+};
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUADRATIC_REDISTRIBUTE_ELEMENTS_HPP
diff --git a/boost/geometry/index/detail/rtree/query_iterators.hpp b/boost/geometry/index/detail/rtree/query_iterators.hpp
new file mode 100644
index 000000000..8d0dbdd9d
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/query_iterators.hpp
@@ -0,0 +1,230 @@
+// Boost.Geometry Index
+//
+// R-tree query iterators
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+template <typename Value, typename Allocators>
+struct end_query_iterator
+{
+ typedef std::input_iterator_tag iterator_category;
+ typedef Value value_type;
+ typedef typename Allocators::const_reference reference;
+ typedef typename Allocators::difference_type difference_type;
+ typedef typename Allocators::const_pointer pointer;
+
+ reference operator*() const
+ {
+ BOOST_ASSERT_MSG(false, "iterator not dereferencable");
+ pointer p(0);
+ return *p;
+ }
+
+ const value_type * operator->() const
+ {
+ BOOST_ASSERT_MSG(false, "iterator not dereferencable");
+ const value_type * p = 0;
+ return p;
+ }
+
+ end_query_iterator & operator++()
+ {
+ BOOST_ASSERT_MSG(false, "iterator not incrementable");
+ return *this;
+ }
+
+ end_query_iterator operator++(int)
+ {
+ BOOST_ASSERT_MSG(false, "iterator not incrementable");
+ return *this;
+ }
+
+ friend bool operator==(end_query_iterator l, end_query_iterator r)
+ {
+ return true;
+ }
+
+ friend bool operator!=(end_query_iterator l, end_query_iterator r)
+ {
+ return false;
+ }
+};
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates>
+class spatial_query_iterator
+{
+ typedef visitors::spatial_query_incremental<Value, Options, Translator, Box, Allocators, Predicates> visitor_type;
+ typedef typename visitor_type::node_pointer node_pointer;
+
+public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef Value value_type;
+ typedef typename Allocators::const_reference reference;
+ typedef typename Allocators::difference_type difference_type;
+ typedef typename Allocators::const_pointer pointer;
+
+ inline spatial_query_iterator(Translator const& t, Predicates const& p)
+ : m_visitor(t, p)
+ {}
+
+ inline spatial_query_iterator(node_pointer root, Translator const& t, Predicates const& p)
+ : m_visitor(t, p)
+ {
+ detail::rtree::apply_visitor(m_visitor, *root);
+ m_visitor.increment();
+ }
+
+ reference operator*() const
+ {
+ return m_visitor.dereference();
+ }
+
+ const value_type * operator->() const
+ {
+ return boost::addressof(m_visitor.dereference());
+ }
+
+ spatial_query_iterator & operator++()
+ {
+ m_visitor.increment();
+ return *this;
+ }
+
+ spatial_query_iterator operator++(int)
+ {
+ spatial_query_iterator temp = *this;
+ this->operator++();
+ return temp;
+ }
+
+ friend bool operator==(spatial_query_iterator const& l, spatial_query_iterator const& r)
+ {
+ return l.m_visitor == r.m_visitor;
+ }
+
+ friend bool operator==(spatial_query_iterator const& l, end_query_iterator<Value, Allocators>)
+ {
+ return l.m_visitor.is_end();
+ }
+
+ friend bool operator==(end_query_iterator<Value, Allocators>, spatial_query_iterator const& r)
+ {
+ return r.m_visitor.is_end();
+ }
+
+ friend bool operator!=(spatial_query_iterator const& l, spatial_query_iterator const& r)
+ {
+ return !(l.m_visitor == r.m_visitor);
+ }
+
+ friend bool operator!=(spatial_query_iterator const& l, end_query_iterator<Value, Allocators>)
+ {
+ return !l.m_visitor.is_end();
+ }
+
+ friend bool operator!=(end_query_iterator<Value, Allocators>, spatial_query_iterator const& r)
+ {
+ return !r.m_visitor.is_end();
+ }
+
+private:
+ visitor_type m_visitor;
+};
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates, unsigned NearestPredicateIndex>
+class distance_query_iterator
+{
+ typedef visitors::distance_query_incremental<Value, Options, Translator, Box, Allocators, Predicates, NearestPredicateIndex> visitor_type;
+ typedef typename visitor_type::node_pointer node_pointer;
+
+public:
+ typedef std::input_iterator_tag iterator_category;
+ typedef Value value_type;
+ typedef typename Allocators::const_reference reference;
+ typedef typename Allocators::difference_type difference_type;
+ typedef typename Allocators::const_pointer pointer;
+
+ inline distance_query_iterator(Translator const& t, Predicates const& p)
+ : m_visitor(t, p)
+ {}
+
+ inline distance_query_iterator(node_pointer root, Translator const& t, Predicates const& p)
+ : m_visitor(t, p)
+ {
+ detail::rtree::apply_visitor(m_visitor, *root);
+ m_visitor.increment();
+ }
+
+ reference operator*() const
+ {
+ return m_visitor.dereference();
+ }
+
+ const value_type * operator->() const
+ {
+ return boost::addressof(m_visitor.dereference());
+ }
+
+ distance_query_iterator & operator++()
+ {
+ m_visitor.increment();
+ return *this;
+ }
+
+ distance_query_iterator operator++(int)
+ {
+ distance_query_iterator temp = *this;
+ this->operator++();
+ return temp;
+ }
+
+ friend bool operator==(distance_query_iterator const& l, distance_query_iterator const& r)
+ {
+ return l.m_visitor == r.m_visitor;
+ }
+
+ friend bool operator==(distance_query_iterator const& l, end_query_iterator<Value, Allocators>)
+ {
+ return l.m_visitor.is_end();
+ }
+
+ friend bool operator==(end_query_iterator<Value, Allocators>, distance_query_iterator const& r)
+ {
+ return r.m_visitor.is_end();
+ }
+
+ friend bool operator!=(distance_query_iterator const& l, distance_query_iterator const& r)
+ {
+ return !(l.m_visitor == r.m_visitor);
+ }
+
+ friend bool operator!=(distance_query_iterator const& l, end_query_iterator<Value, Allocators>)
+ {
+ return !l.m_visitor.is_end();
+ }
+
+ friend bool operator!=(end_query_iterator<Value, Allocators>, distance_query_iterator const& r)
+ {
+ return !r.m_visitor.is_end();
+ }
+
+private:
+ visitor_type m_visitor;
+};
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP
diff --git a/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp b/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp
new file mode 100644
index 000000000..89dd5e5ff
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp
@@ -0,0 +1,426 @@
+// Boost.Geometry Index
+//
+// R-tree R*-tree next node choosing algorithm implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_CHOOSE_NEXT_NODE_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_CHOOSE_NEXT_NODE_HPP
+
+#include <algorithm>
+
+#include <boost/geometry/algorithms/expand.hpp>
+
+#include <boost/geometry/index/detail/algorithms/content.hpp>
+#include <boost/geometry/index/detail/algorithms/intersection_content.hpp>
+#include <boost/geometry/index/detail/algorithms/union_content.hpp>
+
+#include <boost/geometry/index/detail/rtree/node/node.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+template <typename Value, typename Options, typename Box, typename Allocators>
+class choose_next_node<Value, Options, Box, Allocators, choose_by_overlap_diff_tag>
+{
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef typename rtree::elements_type<internal_node>::type children_type;
+ typedef typename children_type::value_type child_type;
+
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename index::detail::default_content_result<Box>::type content_type;
+
+public:
+ template <typename Indexable>
+ static inline size_t apply(internal_node & n,
+ Indexable const& indexable,
+ parameters_type const& parameters,
+ size_t node_relative_level)
+ {
+ ::boost::ignore_unused_variable_warning(parameters);
+
+ children_type & children = rtree::elements(n);
+
+ // children are leafs
+ if ( node_relative_level <= 1 )
+ {
+ /*if ( 0 < parameters.get_overlap_cost_threshold() &&
+ parameters.get_overlap_cost_threshold() < children.size() )
+ return choose_by_nearly_minimum_overlap_cost(children, indexable, parameters.get_overlap_cost_threshold());
+ else
+ return choose_by_minimum_overlap_cost(children, indexable);*/
+
+ return choose_by_minimum_overlap_cost(children, indexable, parameters.get_overlap_cost_threshold());
+ }
+ // children are internal nodes
+ else
+ return choose_by_minimum_content_cost(children, indexable);
+ }
+
+private:
+ template <typename Indexable>
+ static inline size_t choose_by_minimum_overlap_cost(children_type const& children,
+ Indexable const& indexable,
+ size_t overlap_cost_threshold)
+ {
+ const size_t children_count = children.size();
+
+ content_type min_content_diff = (std::numeric_limits<content_type>::max)();
+ content_type min_content = (std::numeric_limits<content_type>::max)();
+ size_t choosen_index = 0;
+
+ // create container of children sorted by content enlargement needed to include the new value
+ typedef boost::tuple<size_t, content_type, content_type> child_contents;
+
+ typename rtree::container_from_elements_type<children_type, child_contents>::type children_contents;
+ children_contents.resize(children_count);
+
+ for ( size_t i = 0 ; i < children_count ; ++i )
+ {
+ child_type const& ch_i = children[i];
+
+ // expanded child node's box
+ Box box_exp(ch_i.first);
+ geometry::expand(box_exp, indexable);
+
+ // areas difference
+ content_type content = index::detail::content(box_exp);
+ content_type content_diff = content - index::detail::content(ch_i.first);
+
+ children_contents[i] = boost::make_tuple(i, content_diff, content);
+
+ if ( content_diff < min_content_diff ||
+ (content_diff == min_content_diff && content < min_content) )
+ {
+ min_content_diff = content_diff;
+ min_content = content;
+ choosen_index = i;
+ }
+ }
+
+ // is this assumption ok? if min_content_diff == 0 there is no overlap increase?
+
+ if ( min_content_diff < -std::numeric_limits<double>::epsilon() || std::numeric_limits<double>::epsilon() < min_content_diff )
+ {
+ if ( 0 < overlap_cost_threshold && overlap_cost_threshold < children.size() )
+ {
+ // calculate nearly minimum overlap cost
+
+ // sort by content_diff
+ std::partial_sort(children_contents.begin(), children_contents.begin() + overlap_cost_threshold, children_contents.end(), content_diff_less);
+ choosen_index = choose_by_minimum_overlap_cost_sorted_by_content(children, indexable, children_count, overlap_cost_threshold, children_contents);
+ }
+ else
+ {
+ // calculate minimum overlap cost
+
+ choosen_index = choose_by_minimum_overlap_cost_unsorted_by_content(children, indexable, children_count, children_contents);
+ }
+ }
+
+ return choosen_index;
+ }
+
+ template <typename Indexable, typename ChildrenContents>
+ static inline size_t choose_by_minimum_overlap_cost_unsorted_by_content(children_type const& children,
+ Indexable const& indexable,
+ size_t children_count,
+ ChildrenContents const& children_contents)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(children_contents.size() == children_count, "unexpected number of elements");
+
+ // choose index with smallest overlap change value, or content change or smallest content
+ size_t choosen_index = 0;
+ content_type smallest_overlap_diff = (std::numeric_limits<content_type>::max)();
+ content_type smallest_content_diff = (std::numeric_limits<content_type>::max)();
+ content_type smallest_content = (std::numeric_limits<content_type>::max)();
+
+ // for each child node
+ for (size_t i = 0 ; i < children_count ; ++i )
+ {
+ child_type const& ch_i = children[i];
+
+ Box box_exp(ch_i.first);
+ // calculate expanded box of child node ch_i
+ geometry::expand(box_exp, indexable);
+
+ content_type overlap_diff = 0;
+
+ // calculate overlap
+ for ( size_t j = 0 ; j < children_count ; ++j )
+ {
+ if ( i != j )
+ {
+ child_type const& ch_j = children[j];
+
+ content_type overlap_exp = index::detail::intersection_content(box_exp, ch_j.first);
+ if ( overlap_exp < -std::numeric_limits<content_type>::epsilon() || std::numeric_limits<content_type>::epsilon() < overlap_exp )
+ {
+ overlap_diff += overlap_exp - index::detail::intersection_content(ch_i.first, ch_j.first);
+ }
+ }
+ }
+
+ content_type content = boost::get<2>(children_contents[i]);
+ content_type content_diff = boost::get<1>(children_contents[i]);
+
+ // update result
+ if ( overlap_diff < smallest_overlap_diff ||
+ ( overlap_diff == smallest_overlap_diff && ( content_diff < smallest_content_diff ||
+ ( content_diff == smallest_content_diff && content < smallest_content ) )
+ ) )
+ {
+ smallest_overlap_diff = overlap_diff;
+ smallest_content_diff = content_diff;
+ smallest_content = content;
+ choosen_index = i;
+ }
+ }
+
+ return choosen_index;
+ }
+
+ template <typename Indexable, typename ChildrenContents>
+ static inline size_t choose_by_minimum_overlap_cost_sorted_by_content(children_type const& children,
+ Indexable const& indexable,
+ size_t children_count,
+ size_t overlap_cost_threshold,
+ ChildrenContents const& children_contents)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(overlap_cost_threshold < children_count, "unexpected value");
+ BOOST_GEOMETRY_INDEX_ASSERT(children_count == children_contents.size(), "unexpected number of elements");
+
+ // for overlap_cost_threshold child nodes find the one with smallest overlap value
+ size_t choosen_index = 0;
+ content_type smallest_overlap_diff = (std::numeric_limits<content_type>::max)();
+
+ // for each node
+ for (size_t i = 0 ; i < overlap_cost_threshold ; ++i )
+ {
+ size_t child_index = boost::get<0>(children_contents[i]);
+
+ typedef typename children_type::value_type child_type;
+ child_type const& ch_i = children[child_index];
+
+ Box box_exp(ch_i.first);
+ // calculate expanded box of child node ch_i
+ geometry::expand(box_exp, indexable);
+
+ content_type overlap_diff = 0;
+
+ // calculate overlap
+ for ( size_t j = 0 ; j < children_count ; ++j )
+ {
+ if ( child_index != j )
+ {
+ child_type const& ch_j = children[j];
+
+ content_type overlap_exp = index::detail::intersection_content(box_exp, ch_j.first);
+ if ( overlap_exp < -std::numeric_limits<content_type>::epsilon() || std::numeric_limits<content_type>::epsilon() < overlap_exp )
+ {
+ overlap_diff += overlap_exp - index::detail::intersection_content(ch_i.first, ch_j.first);
+ }
+ }
+ }
+
+ // update result
+ if ( overlap_diff < smallest_overlap_diff )
+ {
+ smallest_overlap_diff = overlap_diff;
+ choosen_index = child_index;
+ }
+ }
+
+ return choosen_index;
+ }
+
+ //template <typename Indexable>
+ //static inline size_t choose_by_minimum_overlap_cost(children_type const& children,
+ // Indexable const& indexable)
+ //{
+ // size_t children_count = children.size();
+
+ // // choose index with smallest overlap change value, or content change or smallest content
+ // size_t choosen_index = 0;
+ // content_type smallest_overlap_diff = (std::numeric_limits<content_type>::max)();
+ // content_type smallest_content_diff = (std::numeric_limits<content_type>::max)();
+ // content_type smallest_content = (std::numeric_limits<content_type>::max)();
+
+ // // for each child node
+ // for (size_t i = 0 ; i < children_count ; ++i )
+ // {
+ // child_type const& ch_i = children[i];
+
+ // Box box_exp(ch_i.first);
+ // // calculate expanded box of child node ch_i
+ // geometry::expand(box_exp, indexable);
+
+ // // calculate content and content diff
+ // content_type content = index::detail::content(box_exp);
+ // content_type content_diff = content - index::detail::content(ch_i.first);
+
+ // content_type overlap_diff = 0;
+ //
+ // // calculate overlap
+ // for ( size_t j = 0 ; j < children_count ; ++j )
+ // {
+ // if ( i != j )
+ // {
+ // child_type const& ch_j = children[j];
+
+ // content_type overlap_exp = index::detail::intersection_content(box_exp, ch_j.first);
+ // if ( overlap_exp < -std::numeric_limits<content_type>::epsilon() || std::numeric_limits<content_type>::epsilon() < overlap_exp )
+ // {
+ // overlap_diff += overlap_exp - index::detail::intersection_content(ch_i.first, ch_j.first);
+ // }
+ // }
+ // }
+
+ // // update result
+ // if ( overlap_diff < smallest_overlap_diff ||
+ // ( overlap_diff == smallest_overlap_diff && ( content_diff < smallest_content_diff ||
+ // ( content_diff == smallest_content_diff && content < smallest_content ) )
+ // ) )
+ // {
+ // smallest_overlap_diff = overlap_diff;
+ // smallest_content_diff = content_diff;
+ // smallest_content = content;
+ // choosen_index = i;
+ // }
+ // }
+
+ // return choosen_index;
+ //}
+
+ //template <typename Indexable>
+ //static inline size_t choose_by_nearly_minimum_overlap_cost(children_type const& children,
+ // Indexable const& indexable,
+ // size_t overlap_cost_threshold)
+ //{
+ // const size_t children_count = children.size();
+
+ // // create container of children sorted by content enlargement needed to include the new value
+ // std::vector< boost::tuple<size_t, content_type, content_type> > sorted_children(children_count);
+ // for ( size_t i = 0 ; i < children_count ; ++i )
+ // {
+ // child_type const& ch_i = children[i];
+
+ // // expanded child node's box
+ // Box box_exp(ch_i.first);
+ // geometry::expand(box_exp, indexable);
+
+ // // areas difference
+ // content_type content = index::detail::content(box_exp);
+ // content_type content_diff = content - index::detail::content(ch_i.first);
+
+ // sorted_children[i] = boost::make_tuple(i, content_diff, content);
+ // }
+
+ // BOOST_GEOMETRY_INDEX_ASSERT(overlap_cost_threshold <= children_count, "there is not enough children");
+
+ // // sort by content_diff
+ // //std::sort(sorted_children.begin(), sorted_children.end(), content_diff_less);
+ // std::partial_sort(sorted_children.begin(), sorted_children.begin() + overlap_cost_threshold, sorted_children.end(), content_diff_less);
+
+ // // for overlap_cost_threshold child nodes find the one with smallest overlap value
+ // size_t choosen_index = 0;
+ // content_type smallest_overlap_diff = (std::numeric_limits<content_type>::max)();
+
+ // // for each node
+ // for (size_t i = 0 ; i < overlap_cost_threshold ; ++i )
+ // {
+ // size_t child_index = boost::get<0>(sorted_children[i]);
+
+ // typedef typename children_type::value_type child_type;
+ // child_type const& ch_i = children[child_index];
+
+ // Box box_exp(ch_i.first);
+ // // calculate expanded box of child node ch_i
+ // geometry::expand(box_exp, indexable);
+
+ // content_type overlap_diff = 0;
+
+ // // calculate overlap
+ // for ( size_t j = 0 ; j < children_count ; ++j )
+ // {
+ // if ( child_index != j )
+ // {
+ // child_type const& ch_j = children[j];
+
+ // content_type overlap_exp = index::detail::intersection_content(box_exp, ch_j.first);
+ // if ( overlap_exp < -std::numeric_limits<content_type>::epsilon() || std::numeric_limits<content_type>::epsilon() < overlap_exp )
+ // {
+ // overlap_diff += overlap_exp - index::detail::intersection_content(ch_i.first, ch_j.first);
+ // }
+ // }
+ // }
+
+ // // update result
+ // if ( overlap_diff < smallest_overlap_diff )
+ // {
+ // smallest_overlap_diff = overlap_diff;
+ // choosen_index = child_index;
+ // }
+ // }
+
+ // return choosen_index;
+ //}
+
+ static inline bool content_diff_less(boost::tuple<size_t, content_type, content_type> const& p1, boost::tuple<size_t, content_type, content_type> const& p2)
+ {
+ return boost::get<1>(p1) < boost::get<1>(p2) ||
+ (boost::get<1>(p1) == boost::get<1>(p2) && boost::get<2>(p1) < boost::get<2>(p2));
+ }
+
+ template <typename Indexable>
+ static inline size_t choose_by_minimum_content_cost(children_type const& children, Indexable const& indexable)
+ {
+ size_t children_count = children.size();
+
+ // choose index with smallest content change or smallest content
+ size_t choosen_index = 0;
+ content_type smallest_content_diff = (std::numeric_limits<content_type>::max)();
+ content_type smallest_content = (std::numeric_limits<content_type>::max)();
+
+ // choose the child which requires smallest box expansion to store the indexable
+ for ( size_t i = 0 ; i < children_count ; ++i )
+ {
+ child_type const& ch_i = children[i];
+
+ // expanded child node's box
+ Box box_exp(ch_i.first);
+ geometry::expand(box_exp, indexable);
+
+ // areas difference
+ content_type content = index::detail::content(box_exp);
+ content_type content_diff = content - index::detail::content(ch_i.first);
+
+ // update the result
+ if ( content_diff < smallest_content_diff ||
+ ( content_diff == smallest_content_diff && content < smallest_content ) )
+ {
+ smallest_content_diff = content_diff;
+ smallest_content = content;
+ choosen_index = i;
+ }
+ }
+
+ return choosen_index;
+ }
+};
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_CHOOSE_NEXT_NODE_HPP
diff --git a/boost/geometry/index/detail/rtree/rstar/insert.hpp b/boost/geometry/index/detail/rtree/rstar/insert.hpp
new file mode 100644
index 000000000..e681bbb6b
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/rstar/insert.hpp
@@ -0,0 +1,567 @@
+// Boost.Geometry Index
+//
+// R-tree R*-tree insert algorithm implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP
+
+#include <boost/geometry/index/detail/algorithms/content.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree { namespace visitors {
+
+namespace rstar {
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class remove_elements_to_reinsert
+{
+public:
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef typename Options::parameters_type parameters_type;
+ typedef typename Allocators::internal_node_pointer internal_node_pointer;
+
+ template <typename ResultElements, typename Node>
+ static inline void apply(ResultElements & result_elements,
+ Node & n,
+ internal_node_pointer parent,
+ size_t current_child_index,
+ parameters_type const& parameters,
+ Translator const& translator,
+ Allocators & allocators)
+ {
+ typedef typename rtree::elements_type<Node>::type elements_type;
+ typedef typename elements_type::value_type element_type;
+ typedef typename geometry::point_type<Box>::type point_type;
+ // TODO: awulkiew - change second point_type to the point type of the Indexable?
+ typedef typename geometry::default_distance_result<point_type>::type distance_type;
+
+ elements_type & elements = rtree::elements(n);
+
+ const size_t elements_count = parameters.get_max_elements() + 1;
+ const size_t reinserted_elements_count = (::std::min)(parameters.get_reinserted_elements(), elements_count - parameters.get_min_elements());
+
+ BOOST_GEOMETRY_INDEX_ASSERT(parent, "node shouldn't be the root node");
+ BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "unexpected elements number");
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < reinserted_elements_count, "wrong value of elements to reinsert");
+
+ // calculate current node's center
+ point_type node_center;
+ geometry::centroid(rtree::elements(*parent)[current_child_index].first, node_center);
+
+ // fill the container of centers' distances of children from current node's center
+ typedef typename index::detail::rtree::container_from_elements_type<
+ elements_type,
+ std::pair<distance_type, element_type>
+ >::type sorted_elements_type;
+ sorted_elements_type sorted_elements;
+ // If constructor is used instead of resize() MS implementation leaks here
+ sorted_elements.reserve(elements_count); // MAY THROW, STRONG (V, E: alloc, copy)
+
+ for ( typename elements_type::const_iterator it = elements.begin() ;
+ it != elements.end() ; ++it )
+ {
+ point_type element_center;
+ geometry::centroid( rtree::element_indexable(*it, translator), element_center);
+ sorted_elements.push_back(std::make_pair(
+ geometry::comparable_distance(node_center, element_center),
+ *it)); // MAY THROW (V, E: copy)
+ }
+
+ // sort elements by distances from center
+ std::partial_sort(
+ sorted_elements.begin(),
+ sorted_elements.begin() + reinserted_elements_count,
+ sorted_elements.end(),
+ distances_dsc<distance_type, element_type>); // MAY THROW, BASIC (V, E: copy)
+
+ // copy elements which will be reinserted
+ result_elements.clear();
+ result_elements.reserve(reinserted_elements_count); // MAY THROW, STRONG (V, E: alloc, copy)
+ for ( typename sorted_elements_type::const_iterator it = sorted_elements.begin() ;
+ it != sorted_elements.begin() + reinserted_elements_count ; ++it )
+ {
+ result_elements.push_back(it->second); // MAY THROW (V, E: copy)
+ }
+
+ BOOST_TRY
+ {
+ // copy remaining elements to the current node
+ elements.clear();
+ elements.reserve(elements_count - reinserted_elements_count); // SHOULDN'T THROW (new_size <= old size)
+ for ( typename sorted_elements_type::const_iterator it = sorted_elements.begin() + reinserted_elements_count;
+ it != sorted_elements.end() ; ++it )
+ {
+ elements.push_back(it->second); // MAY THROW (V, E: copy)
+ }
+ }
+ BOOST_CATCH(...)
+ {
+ elements.clear();
+
+ for ( typename sorted_elements_type::iterator it = sorted_elements.begin() ;
+ it != sorted_elements.end() ; ++it )
+ {
+ destroy_element<Value, Options, Translator, Box, Allocators>::apply(it->second, allocators);
+ }
+
+ BOOST_RETHROW // RETHROW
+ }
+ BOOST_CATCH_END
+
+ ::boost::ignore_unused_variable_warning(parameters);
+ }
+
+private:
+ template <typename Distance, typename El>
+ static inline bool distances_asc(
+ std::pair<Distance, El> const& d1,
+ std::pair<Distance, El> const& d2)
+ {
+ return d1.first < d2.first;
+ }
+
+ template <typename Distance, typename El>
+ static inline bool distances_dsc(
+ std::pair<Distance, El> const& d1,
+ std::pair<Distance, El> const& d2)
+ {
+ return d1.first > d2.first;
+ }
+};
+
+template <size_t InsertIndex, typename Element, typename Value, typename Options, typename Box, typename Allocators>
+struct level_insert_elements_type
+{
+ typedef typename rtree::elements_type<
+ typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type
+ >::type type;
+};
+
+template <typename Value, typename Options, typename Box, typename Allocators>
+struct level_insert_elements_type<0, Value, Value, Options, Box, Allocators>
+{
+ typedef typename rtree::elements_type<
+ typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type
+ >::type type;
+};
+
+template <size_t InsertIndex, typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+struct level_insert_base
+ : public detail::insert<Element, Value, Options, Translator, Box, Allocators>
+{
+ typedef detail::insert<Element, Value, Options, Translator, Box, Allocators> base;
+ typedef typename base::node node;
+ typedef typename base::internal_node internal_node;
+ typedef typename base::leaf leaf;
+
+ typedef typename level_insert_elements_type<InsertIndex, Element, Value, Options, Box, Allocators>::type elements_type;
+ typedef typename index::detail::rtree::container_from_elements_type<
+ elements_type,
+ typename elements_type::value_type
+ >::type result_elements_type;
+
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename Allocators::node_pointer node_pointer;
+
+ inline level_insert_base(node_pointer & root,
+ size_t & leafs_level,
+ Element const& element,
+ parameters_type const& parameters,
+ Translator const& translator,
+ Allocators & allocators,
+ size_t relative_level)
+ : base(root, leafs_level, element, parameters, translator, allocators, relative_level)
+ , result_relative_level(0)
+ {}
+
+ template <typename Node>
+ inline void handle_possible_reinsert_or_split_of_root(Node &n)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(result_elements.empty(), "reinsert should be handled only once for level");
+
+ result_relative_level = base::m_leafs_level - base::m_traverse_data.current_level;
+
+ // overflow
+ if ( base::m_parameters.get_max_elements() < rtree::elements(n).size() )
+ {
+ // node isn't root node
+ if ( !base::m_traverse_data.current_is_root() )
+ {
+ // NOTE: exception-safety
+ // After an exception result_elements may contain garbage, don't use it
+ rstar::remove_elements_to_reinsert<Value, Options, Translator, Box, Allocators>::apply(
+ result_elements, n,
+ base::m_traverse_data.parent, base::m_traverse_data.current_child_index,
+ base::m_parameters, base::m_translator, base::m_allocators); // MAY THROW, BASIC (V, E: alloc, copy)
+ }
+ // node is root node
+ else
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<Node>(*base::m_root_node), "node should be the root node");
+ base::split(n); // MAY THROW (V, E: alloc, copy, N: alloc)
+ }
+ }
+ }
+
+ template <typename Node>
+ inline void handle_possible_split(Node &n) const
+ {
+ // overflow
+ if ( base::m_parameters.get_max_elements() < rtree::elements(n).size() )
+ {
+ base::split(n); // MAY THROW (V, E: alloc, copy, N: alloc)
+ }
+ }
+
+ template <typename Node>
+ inline void recalculate_aabb_if_necessary(Node &n) const
+ {
+ if ( !result_elements.empty() && !base::m_traverse_data.current_is_root() )
+ {
+ // calulate node's new box
+ base::m_traverse_data.current_element().first =
+ elements_box<Box>(rtree::elements(n).begin(), rtree::elements(n).end(), base::m_translator);
+ }
+ }
+
+ size_t result_relative_level;
+ result_elements_type result_elements;
+};
+
+template <size_t InsertIndex, typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+struct level_insert
+ : public level_insert_base<InsertIndex, Element, Value, Options, Translator, Box, Allocators>
+{
+ typedef level_insert_base<InsertIndex, Element, Value, Options, Translator, Box, Allocators> base;
+ typedef typename base::node node;
+ typedef typename base::internal_node internal_node;
+ typedef typename base::leaf leaf;
+
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename Allocators::node_pointer node_pointer;
+
+ inline level_insert(node_pointer & root,
+ size_t & leafs_level,
+ Element const& element,
+ parameters_type const& parameters,
+ Translator const& translator,
+ Allocators & allocators,
+ size_t relative_level)
+ : base(root, leafs_level, element, parameters, translator, allocators, relative_level)
+ {}
+
+ inline void operator()(internal_node & n)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");
+
+ if ( base::m_traverse_data.current_level < base::m_level )
+ {
+ // next traversing step
+ base::traverse(*this, n); // MAY THROW (E: alloc, copy, N: alloc)
+
+ // further insert
+ if ( 0 < InsertIndex )
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < base::m_level, "illegal level value, level shouldn't be the root level for 0 < InsertIndex");
+
+ if ( base::m_traverse_data.current_level == base::m_level - 1 )
+ {
+ base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (E: alloc, copy, N: alloc)
+ }
+ }
+ }
+ else
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level, "unexpected level");
+
+ BOOST_TRY
+ {
+ // push new child node
+ rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (E: alloc, copy)
+ }
+ BOOST_CATCH(...)
+ {
+ // NOTE: exception-safety
+ // if the insert fails above, the element won't be stored in the tree, so delete it
+
+ rtree::visitors::destroy<Value, Options, Translator, Box, Allocators> del_v(base::m_element.second, base::m_allocators);
+ rtree::apply_visitor(del_v, *base::m_element.second);
+
+ BOOST_RETHROW // RETHROW
+ }
+ BOOST_CATCH_END
+
+ // first insert
+ if ( 0 == InsertIndex )
+ {
+ base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (E: alloc, copy, N: alloc)
+ }
+ // not the first insert
+ else
+ {
+ base::handle_possible_split(n); // MAY THROW (E: alloc, N: alloc)
+ }
+ }
+
+ base::recalculate_aabb_if_necessary(n);
+ }
+
+ inline void operator()(leaf &)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "this visitor can't be used for a leaf");
+ }
+};
+
+template <size_t InsertIndex, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+struct level_insert<InsertIndex, Value, Value, Options, Translator, Box, Allocators>
+ : public level_insert_base<InsertIndex, Value, Value, Options, Translator, Box, Allocators>
+{
+ typedef level_insert_base<InsertIndex, Value, Value, Options, Translator, Box, Allocators> base;
+ typedef typename base::node node;
+ typedef typename base::internal_node internal_node;
+ typedef typename base::leaf leaf;
+
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename Allocators::node_pointer node_pointer;
+
+ inline level_insert(node_pointer & root,
+ size_t & leafs_level,
+ Value const& v,
+ parameters_type const& parameters,
+ Translator const& translator,
+ Allocators & allocators,
+ size_t relative_level)
+ : base(root, leafs_level, v, parameters, translator, allocators, relative_level)
+ {}
+
+ inline void operator()(internal_node & n)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level, "unexpected level");
+
+ // next traversing step
+ base::traverse(*this, n); // MAY THROW (V, E: alloc, copy, N: alloc)
+
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < base::m_level, "illegal level value, level shouldn't be the root level for 0 < InsertIndex");
+
+ if ( base::m_traverse_data.current_level == base::m_level - 1 )
+ {
+ base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (E: alloc, copy, N: alloc)
+ }
+
+ base::recalculate_aabb_if_necessary(n);
+ }
+
+ inline void operator()(leaf & n)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level == base::m_leafs_level,
+ "unexpected level");
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||
+ base::m_level == (std::numeric_limits<size_t>::max)(),
+ "unexpected level");
+
+ rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (V: alloc, copy)
+
+ base::handle_possible_split(n); // MAY THROW (V: alloc, copy, N: alloc)
+ }
+};
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+struct level_insert<0, Value, Value, Options, Translator, Box, Allocators>
+ : public level_insert_base<0, Value, Value, Options, Translator, Box, Allocators>
+{
+ typedef level_insert_base<0, Value, Value, Options, Translator, Box, Allocators> base;
+ typedef typename base::node node;
+ typedef typename base::internal_node internal_node;
+ typedef typename base::leaf leaf;
+
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename Allocators::node_pointer node_pointer;
+
+ inline level_insert(node_pointer & root,
+ size_t & leafs_level,
+ Value const& v,
+ parameters_type const& parameters,
+ Translator const& translator,
+ Allocators & allocators,
+ size_t relative_level)
+ : base(root, leafs_level, v, parameters, translator, allocators, relative_level)
+ {}
+
+ inline void operator()(internal_node & n)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level,
+ "unexpected level");
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level,
+ "unexpected level");
+
+ // next traversing step
+ base::traverse(*this, n); // MAY THROW (V: alloc, copy, N: alloc)
+
+ base::recalculate_aabb_if_necessary(n);
+ }
+
+ inline void operator()(leaf & n)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level == base::m_leafs_level,
+ "unexpected level");
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||
+ base::m_level == (std::numeric_limits<size_t>::max)(),
+ "unexpected level");
+
+ rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (V: alloc, copy)
+
+ base::handle_possible_reinsert_or_split_of_root(n); // MAY THROW (V: alloc, copy, N: alloc)
+
+ base::recalculate_aabb_if_necessary(n);
+ }
+};
+
+} // namespace rstar
+
+// R*-tree insert visitor
+// After passing the Element to insert visitor the Element is managed by the tree
+// I.e. one should not delete the node passed to the insert visitor after exception is thrown
+// because this visitor may delete it
+template <typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class insert<Element, Value, Options, Translator, Box, Allocators, insert_reinsert_tag>
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type
+{
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef typename Allocators::node_pointer node_pointer;
+
+public:
+ inline insert(node_pointer & root,
+ size_t & leafs_level,
+ Element const& element,
+ parameters_type const& parameters,
+ Translator const& translator,
+ Allocators & allocators,
+ size_t relative_level = 0)
+ : m_root(root), m_leafs_level(leafs_level), m_element(element)
+ , m_parameters(parameters), m_translator(translator)
+ , m_relative_level(relative_level), m_allocators(allocators)
+ {}
+
+ inline void operator()(internal_node & BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(n))
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_root), "current node should be the root");
+
+ // Distinguish between situation when reinserts are required and use adequate visitor, otherwise use default one
+ if ( m_parameters.get_reinserted_elements() > 0 )
+ {
+ rstar::level_insert<0, Element, Value, Options, Translator, Box, Allocators> lins_v(
+ m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
+
+ rtree::apply_visitor(lins_v, *m_root); // MAY THROW (V, E: alloc, copy, N: alloc)
+
+ if ( !lins_v.result_elements.empty() )
+ {
+ recursive_reinsert(lins_v.result_elements, lins_v.result_relative_level); // MAY THROW (V, E: alloc, copy, N: alloc)
+ }
+ }
+ else
+ {
+ visitors::insert<Element, Value, Options, Translator, Box, Allocators, insert_default_tag> ins_v(
+ m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
+
+ rtree::apply_visitor(ins_v, *m_root);
+ }
+ }
+
+ inline void operator()(leaf & BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(n))
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<leaf>(*m_root), "current node should be the root");
+
+ // Distinguish between situation when reinserts are required and use adequate visitor, otherwise use default one
+ if ( m_parameters.get_reinserted_elements() > 0 )
+ {
+ rstar::level_insert<0, Element, Value, Options, Translator, Box, Allocators> lins_v(
+ m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
+
+ rtree::apply_visitor(lins_v, *m_root); // MAY THROW (V, E: alloc, copy, N: alloc)
+
+ // we're in the root, so root should be split and there should be no elements to reinsert
+ BOOST_GEOMETRY_INDEX_ASSERT(lins_v.result_elements.empty(), "unexpected state");
+ }
+ else
+ {
+ visitors::insert<Element, Value, Options, Translator, Box, Allocators, insert_default_tag> ins_v(
+ m_root, m_leafs_level, m_element, m_parameters, m_translator, m_allocators, m_relative_level);
+
+ rtree::apply_visitor(ins_v, *m_root);
+ }
+ }
+
+private:
+ template <typename Elements>
+ inline void recursive_reinsert(Elements & elements, size_t relative_level)
+ {
+ typedef typename Elements::value_type element_type;
+
+ // reinsert children starting from the minimum distance
+ typename Elements::reverse_iterator it = elements.rbegin();
+ for ( ; it != elements.rend() ; ++it)
+ {
+ rstar::level_insert<1, element_type, Value, Options, Translator, Box, Allocators> lins_v(
+ m_root, m_leafs_level, *it, m_parameters, m_translator, m_allocators, relative_level);
+
+ BOOST_TRY
+ {
+ rtree::apply_visitor(lins_v, *m_root); // MAY THROW (V, E: alloc, copy, N: alloc)
+ }
+ BOOST_CATCH(...)
+ {
+ ++it;
+ for ( ; it != elements.rend() ; ++it)
+ rtree::destroy_element<Value, Options, Translator, Box, Allocators>::apply(*it, m_allocators);
+ BOOST_RETHROW // RETHROW
+ }
+ BOOST_CATCH_END
+
+ BOOST_GEOMETRY_INDEX_ASSERT(relative_level + 1 == lins_v.result_relative_level, "unexpected level");
+
+ // non-root relative level
+ if ( lins_v.result_relative_level < m_leafs_level && !lins_v.result_elements.empty())
+ {
+ recursive_reinsert(lins_v.result_elements, lins_v.result_relative_level); // MAY THROW (V, E: alloc, copy, N: alloc)
+ }
+ }
+ }
+
+ node_pointer & m_root;
+ size_t & m_leafs_level;
+ Element const& m_element;
+
+ parameters_type const& m_parameters;
+ Translator const& m_translator;
+
+ size_t m_relative_level;
+
+ Allocators & m_allocators;
+};
+
+}}} // namespace detail::rtree::visitors
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_INSERT_HPP
diff --git a/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp b/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp
new file mode 100644
index 000000000..aedc2d1a4
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp
@@ -0,0 +1,441 @@
+// Boost.Geometry Index
+//
+// R-tree R*-tree split algorithm implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP
+
+#include <boost/geometry/index/detail/algorithms/intersection_content.hpp>
+#include <boost/geometry/index/detail/algorithms/union_content.hpp>
+#include <boost/geometry/index/detail/algorithms/margin.hpp>
+
+#include <boost/geometry/index/detail/rtree/node/node.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+namespace rstar {
+
+template <typename Element, typename Translator, typename Tag, size_t Corner, size_t AxisIndex>
+class element_axis_corner_less
+{
+ BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_TAG, (Tag));
+};
+
+template <typename Element, typename Translator, size_t Corner, size_t AxisIndex>
+class element_axis_corner_less<Element, Translator, box_tag, Corner, AxisIndex>
+{
+public:
+ element_axis_corner_less(Translator const& tr)
+ : m_tr(tr)
+ {}
+
+ bool operator()(Element const& e1, Element const& e2) const
+ {
+ return geometry::get<Corner, AxisIndex>(rtree::element_indexable(e1, m_tr))
+ < geometry::get<Corner, AxisIndex>(rtree::element_indexable(e2, m_tr));
+ }
+
+private:
+ Translator const& m_tr;
+};
+
+template <typename Element, typename Translator, size_t Corner, size_t AxisIndex>
+class element_axis_corner_less<Element, Translator, point_tag, Corner, AxisIndex>
+{
+public:
+ element_axis_corner_less(Translator const& tr)
+ : m_tr(tr)
+ {}
+
+ bool operator()(Element const& e1, Element const& e2) const
+ {
+ return geometry::get<AxisIndex>(rtree::element_indexable(e1, m_tr))
+ < geometry::get<AxisIndex>(rtree::element_indexable(e2, m_tr));
+ }
+
+private:
+ Translator const& m_tr;
+};
+
+template <typename Parameters, typename Box, size_t Corner, size_t AxisIndex>
+struct choose_split_axis_and_index_for_corner
+{
+ typedef typename index::detail::default_margin_result<Box>::type margin_type;
+ typedef typename index::detail::default_content_result<Box>::type content_type;
+
+ template <typename Elements, typename Translator>
+ static inline void apply(Elements const& elements,
+ size_t & choosen_index,
+ margin_type & sum_of_margins,
+ content_type & smallest_overlap,
+ content_type & smallest_content,
+ Parameters const& parameters,
+ Translator const& translator)
+ {
+ typedef typename Elements::value_type element_type;
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
+ typedef typename tag<indexable_type>::type indexable_tag;
+
+ BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == parameters.get_max_elements() + 1, "wrong number of elements");
+
+ // copy elements
+ Elements elements_copy(elements); // MAY THROW, STRONG (alloc, copy)
+
+ // sort elements
+ element_axis_corner_less<element_type, Translator, indexable_tag, Corner, AxisIndex> elements_less(translator);
+ std::sort(elements_copy.begin(), elements_copy.end(), elements_less); // MAY THROW, BASIC (copy)
+
+ // init outputs
+ choosen_index = parameters.get_min_elements();
+ sum_of_margins = 0;
+ smallest_overlap = (std::numeric_limits<content_type>::max)();
+ smallest_content = (std::numeric_limits<content_type>::max)();
+
+ // calculate sum of margins for all distributions
+ size_t index_last = parameters.get_max_elements() - parameters.get_min_elements() + 2;
+ for ( size_t i = parameters.get_min_elements() ; i < index_last ; ++i )
+ {
+ // TODO - awulkiew: may be optimized - box of group 1 may be initialized with
+ // box of min_elems number of elements and expanded for each iteration by another element
+
+ Box box1 = rtree::elements_box<Box>(elements_copy.begin(), elements_copy.begin() + i, translator);
+ Box box2 = rtree::elements_box<Box>(elements_copy.begin() + i, elements_copy.end(), translator);
+
+ sum_of_margins += index::detail::comparable_margin(box1) + index::detail::comparable_margin(box2);
+
+ content_type ovl = index::detail::intersection_content(box1, box2);
+ content_type con = index::detail::content(box1) + index::detail::content(box2);
+
+ // TODO - shouldn't here be < instead of <= ?
+ if ( ovl < smallest_overlap || (ovl == smallest_overlap && con <= smallest_content) )
+ {
+ choosen_index = i;
+ smallest_overlap = ovl;
+ smallest_content = con;
+ }
+ }
+
+ ::boost::ignore_unused_variable_warning(parameters);
+ }
+};
+
+template <typename Parameters, typename Box, size_t AxisIndex, typename ElementIndexableTag>
+struct choose_split_axis_and_index_for_axis
+{
+ BOOST_MPL_ASSERT_MSG(false, NOT_IMPLEMENTED_FOR_THIS_TAG, (ElementIndexableTag));
+};
+
+template <typename Parameters, typename Box, size_t AxisIndex>
+struct choose_split_axis_and_index_for_axis<Parameters, Box, AxisIndex, box_tag>
+{
+ typedef typename index::detail::default_margin_result<Box>::type margin_type;
+ typedef typename index::detail::default_content_result<Box>::type content_type;
+
+ template <typename Elements, typename Translator>
+ static inline void apply(Elements const& elements,
+ size_t & choosen_corner,
+ size_t & choosen_index,
+ margin_type & sum_of_margins,
+ content_type & smallest_overlap,
+ content_type & smallest_content,
+ Parameters const& parameters,
+ Translator const& translator)
+ {
+ size_t index1 = 0;
+ margin_type som1 = 0;
+ content_type ovl1 = (std::numeric_limits<content_type>::max)();
+ content_type con1 = (std::numeric_limits<content_type>::max)();
+
+ choose_split_axis_and_index_for_corner<Parameters, Box, min_corner, AxisIndex>::
+ apply(elements, index1,
+ som1, ovl1, con1,
+ parameters, translator); // MAY THROW, STRONG
+
+ size_t index2 = 0;
+ margin_type som2 = 0;
+ content_type ovl2 = (std::numeric_limits<content_type>::max)();
+ content_type con2 = (std::numeric_limits<content_type>::max)();
+
+ choose_split_axis_and_index_for_corner<Parameters, Box, max_corner, AxisIndex>::
+ apply(elements, index2,
+ som2, ovl2, con2,
+ parameters, translator); // MAY THROW, STRONG
+
+ sum_of_margins = som1 + som2;
+
+ if ( ovl1 < ovl2 || (ovl1 == ovl2 && con1 <= con2) )
+ {
+ choosen_corner = min_corner;
+ choosen_index = index1;
+ smallest_overlap = ovl1;
+ smallest_content = con1;
+ }
+ else
+ {
+ choosen_corner = max_corner;
+ choosen_index = index2;
+ smallest_overlap = ovl2;
+ smallest_content = con2;
+ }
+ }
+};
+
+template <typename Parameters, typename Box, size_t AxisIndex>
+struct choose_split_axis_and_index_for_axis<Parameters, Box, AxisIndex, point_tag>
+{
+ typedef typename index::detail::default_margin_result<Box>::type margin_type;
+ typedef typename index::detail::default_content_result<Box>::type content_type;
+
+ template <typename Elements, typename Translator>
+ static inline void apply(Elements const& elements,
+ size_t & choosen_corner,
+ size_t & choosen_index,
+ margin_type & sum_of_margins,
+ content_type & smallest_overlap,
+ content_type & smallest_content,
+ Parameters const& parameters,
+ Translator const& translator)
+ {
+ choose_split_axis_and_index_for_corner<Parameters, Box, min_corner, AxisIndex>::
+ apply(elements, choosen_index,
+ sum_of_margins, smallest_overlap, smallest_content,
+ parameters, translator); // MAY THROW, STRONG
+
+ choosen_corner = min_corner;
+ }
+};
+
+template <typename Parameters, typename Box, size_t Dimension>
+struct choose_split_axis_and_index
+{
+ BOOST_STATIC_ASSERT(0 < Dimension);
+
+ typedef typename index::detail::default_margin_result<Box>::type margin_type;
+ typedef typename index::detail::default_content_result<Box>::type content_type;
+
+ template <typename Elements, typename Translator>
+ static inline void apply(Elements const& elements,
+ size_t & choosen_axis,
+ size_t & choosen_corner,
+ size_t & choosen_index,
+ margin_type & smallest_sum_of_margins,
+ content_type & smallest_overlap,
+ content_type & smallest_content,
+ Parameters const& parameters,
+ Translator const& translator)
+ {
+ typedef typename rtree::element_indexable_type<typename Elements::value_type, Translator>::type element_indexable_type;
+
+ choose_split_axis_and_index<Parameters, Box, Dimension - 1>::
+ apply(elements, choosen_axis, choosen_corner, choosen_index,
+ smallest_sum_of_margins, smallest_overlap, smallest_content,
+ parameters, translator); // MAY THROW, STRONG
+
+ margin_type sum_of_margins = 0;
+
+ size_t corner = min_corner;
+ size_t index = 0;
+
+ content_type overlap_val = (std::numeric_limits<content_type>::max)();
+ content_type content_val = (std::numeric_limits<content_type>::max)();
+
+ choose_split_axis_and_index_for_axis<
+ Parameters,
+ Box,
+ Dimension - 1,
+ typename tag<element_indexable_type>::type
+ >::apply(elements, corner, index, sum_of_margins, overlap_val, content_val, parameters, translator); // MAY THROW, STRONG
+
+ if ( sum_of_margins < smallest_sum_of_margins )
+ {
+ choosen_axis = Dimension - 1;
+ choosen_corner = corner;
+ choosen_index = index;
+ smallest_sum_of_margins = sum_of_margins;
+ smallest_overlap = overlap_val;
+ smallest_content = content_val;
+ }
+ }
+};
+
+template <typename Parameters, typename Box>
+struct choose_split_axis_and_index<Parameters, Box, 1>
+{
+ typedef typename index::detail::default_margin_result<Box>::type margin_type;
+ typedef typename index::detail::default_content_result<Box>::type content_type;
+
+ template <typename Elements, typename Translator>
+ static inline void apply(Elements const& elements,
+ size_t & choosen_axis,
+ size_t & choosen_corner,
+ size_t & choosen_index,
+ margin_type & smallest_sum_of_margins,
+ content_type & smallest_overlap,
+ content_type & smallest_content,
+ Parameters const& parameters,
+ Translator const& translator)
+ {
+ typedef typename rtree::element_indexable_type<typename Elements::value_type, Translator>::type element_indexable_type;
+
+ choosen_axis = 0;
+
+ choose_split_axis_and_index_for_axis<
+ Parameters,
+ Box,
+ 0,
+ typename tag<element_indexable_type>::type
+ >::apply(elements, choosen_corner, choosen_index, smallest_sum_of_margins, smallest_overlap, smallest_content, parameters, translator); // MAY THROW
+ }
+};
+
+template <size_t Corner, size_t Dimension>
+struct partial_sort
+{
+ BOOST_STATIC_ASSERT(0 < Dimension);
+
+ template <typename Elements, typename Translator>
+ static inline void apply(Elements & elements, const size_t axis, const size_t index, Translator const& tr)
+ {
+ if ( axis < Dimension - 1 )
+ {
+ partial_sort<Corner, Dimension - 1>::apply(elements, axis, index, tr); // MAY THROW, BASIC (copy)
+ }
+ else
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(axis == Dimension - 1, "unexpected axis value");
+
+ typedef typename Elements::value_type element_type;
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
+ typedef typename tag<indexable_type>::type indexable_tag;
+
+ element_axis_corner_less<element_type, Translator, indexable_tag, Corner, Dimension - 1> less(tr);
+ std::partial_sort(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy)
+ }
+ }
+};
+
+template <size_t Corner>
+struct partial_sort<Corner, 1>
+{
+ template <typename Elements, typename Translator>
+ static inline void apply(Elements & elements,
+ const size_t BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(axis),
+ const size_t index,
+ Translator const& tr)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(axis == 0, "unexpected axis value");
+
+ typedef typename Elements::value_type element_type;
+ typedef typename rtree::element_indexable_type<element_type, Translator>::type indexable_type;
+ typedef typename tag<indexable_type>::type indexable_tag;
+
+ element_axis_corner_less<element_type, Translator, indexable_tag, Corner, 0> less(tr);
+ std::partial_sort(elements.begin(), elements.begin() + index, elements.end(), less); // MAY THROW, BASIC (copy)
+ }
+};
+
+} // namespace rstar
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+struct redistribute_elements<Value, Options, Translator, Box, Allocators, rstar_tag>
+{
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef typename Options::parameters_type parameters_type;
+
+ static const size_t dimension = geometry::dimension<Box>::value;
+
+ typedef typename index::detail::default_margin_result<Box>::type margin_type;
+ typedef typename index::detail::default_content_result<Box>::type content_type;
+
+ template <typename Node>
+ static inline void apply(
+ Node & n,
+ Node & second_node,
+ Box & box1,
+ Box & box2,
+ parameters_type const& parameters,
+ Translator const& translator,
+ Allocators & allocators)
+ {
+ typedef typename rtree::elements_type<Node>::type elements_type;
+
+ elements_type & elements1 = rtree::elements(n);
+ elements_type & elements2 = rtree::elements(second_node);
+
+ size_t split_axis = 0;
+ size_t split_corner = 0;
+ size_t split_index = parameters.get_min_elements();
+ margin_type smallest_sum_of_margins = (std::numeric_limits<margin_type>::max)();
+ content_type smallest_overlap = (std::numeric_limits<content_type>::max)();
+ content_type smallest_content = (std::numeric_limits<content_type>::max)();
+
+ rstar::choose_split_axis_and_index<
+ typename Options::parameters_type,
+ Box,
+ dimension
+ >::apply(elements1,
+ split_axis, split_corner, split_index,
+ smallest_sum_of_margins, smallest_overlap, smallest_content,
+ parameters, translator); // MAY THROW, STRONG
+
+ // TODO: awulkiew - get rid of following static_casts?
+
+ BOOST_GEOMETRY_INDEX_ASSERT(split_axis < dimension, "unexpected value");
+ BOOST_GEOMETRY_INDEX_ASSERT(split_corner == static_cast<size_t>(min_corner) || split_corner == static_cast<size_t>(max_corner), "unexpected value");
+ BOOST_GEOMETRY_INDEX_ASSERT(parameters.get_min_elements() <= split_index && split_index <= parameters.get_max_elements() - parameters.get_min_elements() + 1, "unexpected value");
+
+ // copy original elements
+ elements_type elements_copy(elements1); // MAY THROW, STRONG
+ elements_type elements_backup(elements1); // MAY THROW, STRONG
+
+ // TODO: awulkiew - check if std::partial_sort produces the same result as std::sort
+ if ( split_corner == static_cast<size_t>(min_corner) )
+ rstar::partial_sort<min_corner, dimension>
+ ::apply(elements_copy, split_axis, split_index, translator); // MAY THROW, BASIC (copy)
+ else
+ rstar::partial_sort<max_corner, dimension>
+ ::apply(elements_copy, split_axis, split_index, translator); // MAY THROW, BASIC (copy)
+
+ BOOST_TRY
+ {
+ // copy elements to nodes
+ elements1.assign(elements_copy.begin(), elements_copy.begin() + split_index); // MAY THROW, BASIC
+ elements2.assign(elements_copy.begin() + split_index, elements_copy.end()); // MAY THROW, BASIC
+
+ // calculate boxes
+ box1 = rtree::elements_box<Box>(elements1.begin(), elements1.end(), translator);
+ box2 = rtree::elements_box<Box>(elements2.begin(), elements2.end(), translator);
+ }
+ BOOST_CATCH(...)
+ {
+ //elements_copy.clear();
+ elements1.clear();
+ elements2.clear();
+
+ rtree::destroy_elements<Value, Options, Translator, Box, Allocators>::apply(elements_backup, allocators);
+ //elements_backup.clear();
+
+ BOOST_RETHROW // RETHROW, BASIC
+ }
+ BOOST_CATCH_END
+ }
+};
+
+}} // namespace detail::rtree
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_REDISTRIBUTE_ELEMENTS_HPP
diff --git a/boost/geometry/index/detail/rtree/rstar/rstar.hpp b/boost/geometry/index/detail/rtree/rstar/rstar.hpp
new file mode 100644
index 000000000..ed3959c89
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/rstar/rstar.hpp
@@ -0,0 +1,18 @@
+// Boost.Geometry Index
+//
+// R-tree R*-tree algorithm implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_RSTAR_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_RSTAR_HPP
+
+#include <boost/geometry/index/detail/rtree/rstar/insert.hpp>
+#include <boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp>
+#include <boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp>
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_RSTAR_RSTAR_HPP
diff --git a/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp b/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp
new file mode 100644
index 000000000..f283c3e5b
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp
@@ -0,0 +1,140 @@
+// Boost.Geometry Index
+//
+// R-tree boxes validating visitor implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_BOXES_OK_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_BOXES_OK_HPP
+
+#include <boost/geometry/algorithms/equals.hpp>
+#include <boost/geometry/index/detail/rtree/node/node.hpp>
+
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace utilities {
+
+namespace visitors {
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class are_boxes_ok
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
+{
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+public:
+ are_boxes_ok(Translator const& tr, bool exact_match)
+ : result(false), m_tr(tr), m_is_root(true), m_exact_match(exact_match)
+ {}
+
+ void operator()(internal_node const& n)
+ {
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ if (elements.empty())
+ {
+ result = false;
+ return;
+ }
+
+ Box box_bckup = m_box;
+ bool is_root_bckup = m_is_root;
+
+ m_is_root = false;
+
+ for ( typename elements_type::const_iterator it = elements.begin();
+ it != elements.end() ; ++it)
+ {
+ m_box = it->first;
+
+ rtree::apply_visitor(*this, *it->second);
+
+ if ( result == false )
+ return;
+ }
+
+ m_box = box_bckup;
+ m_is_root = is_root_bckup;
+
+ Box box_exp;
+ geometry::convert(elements.front().first, box_exp);
+ for( typename elements_type::const_iterator it = elements.begin() + 1;
+ it != elements.end() ; ++it)
+ {
+ geometry::expand(box_exp, it->first);
+ }
+
+ if ( m_exact_match )
+ result = m_is_root || geometry::equals(box_exp, m_box);
+ else
+ result = m_is_root || geometry::covered_by(box_exp, m_box);
+ }
+
+ void operator()(leaf const& n)
+ {
+ typedef typename rtree::elements_type<leaf>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ // non-root node
+ if (!m_is_root)
+ {
+ if ( elements.empty() )
+ {
+ result = false;
+ return;
+ }
+
+ Box box_exp;
+ geometry::convert(m_tr(elements.front()), box_exp);
+ for(typename elements_type::const_iterator it = elements.begin() + 1;
+ it != elements.end() ; ++it)
+ {
+ geometry::expand(box_exp, m_tr(*it));
+ }
+
+ if ( m_exact_match )
+ result = geometry::equals(box_exp, m_box);
+ else
+ result = geometry::covered_by(box_exp, m_box);
+ }
+ else
+ result = true;
+ }
+
+ bool result;
+
+private:
+ Translator const& m_tr;
+ Box m_box;
+ bool m_is_root;
+ bool m_exact_match;
+};
+
+} // namespace visitors
+
+template <typename Rtree> inline
+bool are_boxes_ok(Rtree const& tree, bool exact_match = true)
+{
+ typedef utilities::view<Rtree> RTV;
+ RTV rtv(tree);
+
+ visitors::are_boxes_ok<
+ typename RTV::value_type,
+ typename RTV::options_type,
+ typename RTV::translator_type,
+ typename RTV::box_type,
+ typename RTV::allocators_type
+ > v(rtv.translator(), exact_match);
+
+ rtv.apply_visitor(v);
+
+ return v.result;
+}
+
+}}}}}} // namespace boost::geometry::index::detail::rtree::utilities
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_BOXES_OK_HPP
diff --git a/boost/geometry/index/detail/rtree/utilities/are_levels_ok.hpp b/boost/geometry/index/detail/rtree/utilities/are_levels_ok.hpp
new file mode 100644
index 000000000..4860dbcb9
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/utilities/are_levels_ok.hpp
@@ -0,0 +1,109 @@
+// Boost.Geometry Index
+//
+// R-tree levels validating visitor implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_LEVELS_OK_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_LEVELS_OK_HPP
+
+#include <boost/geometry/index/detail/rtree/node/node.hpp>
+
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace utilities {
+
+namespace visitors {
+
+template <typename Value, typename Options, typename Box, typename Allocators>
+class are_levels_ok
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
+{
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+public:
+ inline are_levels_ok()
+ : result(true), m_leafs_level((std::numeric_limits<size_t>::max)()), m_current_level(0)
+ {}
+
+ inline void operator()(internal_node const& n)
+ {
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ if (elements.empty())
+ {
+ result = false;
+ return;
+ }
+
+ size_t current_level_backup = m_current_level;
+ ++m_current_level;
+
+ for ( typename elements_type::const_iterator it = elements.begin();
+ it != elements.end() ; ++it)
+ {
+ rtree::apply_visitor(*this, *it->second);
+
+ if ( result == false )
+ return;
+ }
+
+ m_current_level = current_level_backup;
+ }
+
+ inline void operator()(leaf const& n)
+ {
+ typedef typename rtree::elements_type<leaf>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ // empty leaf in non-root node
+ if (0 < m_current_level && elements.empty())
+ {
+ result = false;
+ return;
+ }
+
+ if ( m_leafs_level == (std::numeric_limits<size_t>::max)() )
+ {
+ m_leafs_level = m_current_level;
+ }
+ else if ( m_leafs_level != m_current_level )
+ {
+ result = false;
+ }
+ }
+
+ bool result;
+
+private:
+ size_t m_leafs_level;
+ size_t m_current_level;
+};
+
+} // namespace visitors
+
+template <typename Rtree> inline
+bool are_levels_ok(Rtree const& tree)
+{
+ typedef utilities::view<Rtree> RTV;
+ RTV rtv(tree);
+
+ visitors::are_levels_ok<
+ typename RTV::value_type,
+ typename RTV::options_type,
+ typename RTV::box_type,
+ typename RTV::allocators_type
+ > v;
+
+ rtv.apply_visitor(v);
+
+ return v.result;
+}
+
+}}}}}} // namespace boost::geometry::index::detail::rtree::utilities
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_LEVELS_OK_HPP
diff --git a/boost/geometry/index/detail/rtree/utilities/gl_draw.hpp b/boost/geometry/index/detail/rtree/utilities/gl_draw.hpp
new file mode 100644
index 000000000..7072a1879
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/utilities/gl_draw.hpp
@@ -0,0 +1,223 @@
+// Boost.Geometry Index
+//
+// R-tree OpenGL drawing visitor implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+namespace utilities {
+
+namespace dispatch {
+
+template <typename Point, size_t Dimension>
+struct gl_draw_point
+{};
+
+template <typename Point>
+struct gl_draw_point<Point, 2>
+{
+ static inline void apply(Point const& p, typename coordinate_type<Point>::type z)
+ {
+ glBegin(GL_POINT);
+ glVertex3f(geometry::get<0>(p), geometry::get<1>(p), z);
+ glEnd();
+ }
+};
+
+template <typename Box, size_t Dimension>
+struct gl_draw_box
+{};
+
+template <typename Box>
+struct gl_draw_box<Box, 2>
+{
+ static inline void apply(Box const& b, typename coordinate_type<Box>::type z)
+ {
+ glBegin(GL_LINE_LOOP);
+ glVertex3f(geometry::get<min_corner, 0>(b), geometry::get<min_corner, 1>(b), z);
+ glVertex3f(geometry::get<max_corner, 0>(b), geometry::get<min_corner, 1>(b), z);
+ glVertex3f(geometry::get<max_corner, 0>(b), geometry::get<max_corner, 1>(b), z);
+ glVertex3f(geometry::get<min_corner, 0>(b), geometry::get<max_corner, 1>(b), z);
+ glEnd();
+ }
+};
+
+template <typename Indexable, typename Tag>
+struct gl_draw_indexable
+{
+};
+
+template <typename Indexable>
+struct gl_draw_indexable<Indexable, box_tag>
+{
+ static const size_t dimension = dimension<Indexable>::value;
+
+ static inline void apply(Indexable const& i, typename coordinate_type<Indexable>::type z)
+ {
+ gl_draw_box<Indexable, dimension>::apply(i, z);
+ }
+};
+
+template <typename Indexable>
+struct gl_draw_indexable<Indexable, point_tag>
+{
+ static const size_t dimension = dimension<Indexable>::value;
+
+ static inline void apply(Indexable const& i, typename coordinate_type<Indexable>::type z)
+ {
+ gl_draw_point<Indexable, dimension>::apply(i, z);
+ }
+};
+
+} // namespace dispatch
+
+template <typename Indexable> inline
+void gl_draw_indexable(Indexable const& i, typename coordinate_type<Indexable>::type z)
+{
+ dispatch::gl_draw_indexable<
+ Indexable,
+ typename tag<Indexable>::type
+ >::apply(i, z);
+}
+
+} // namespace utilities
+
+namespace rtree { namespace utilities {
+
+namespace visitors {
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+struct gl_draw : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
+{
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ inline gl_draw(Translator const& t,
+ size_t level_first = 0,
+ size_t level_last = (std::numeric_limits<size_t>::max)(),
+ typename coordinate_type<Box>::type z_coord_level_multiplier = 1
+ )
+ : tr(t)
+ , level_f(level_first)
+ , level_l(level_last)
+ , z_mul(z_coord_level_multiplier)
+ , level(0)
+ {}
+
+ inline void operator()(internal_node const& n)
+ {
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ if ( level_f <= level )
+ {
+ size_t level_rel = level - level_f;
+
+ if ( level_rel == 0 )
+ glColor3f(0.75f, 0.0f, 0.0f);
+ else if ( level_rel == 1 )
+ glColor3f(0.0f, 0.75f, 0.0f);
+ else if ( level_rel == 2 )
+ glColor3f(0.0f, 0.0f, 0.75f);
+ else if ( level_rel == 3 )
+ glColor3f(0.75f, 0.75f, 0.0f);
+ else if ( level_rel == 4 )
+ glColor3f(0.75f, 0.0f, 0.75f);
+ else if ( level_rel == 5 )
+ glColor3f(0.0f, 0.75f, 0.75f);
+ else
+ glColor3f(0.5f, 0.5f, 0.5f);
+
+ for (typename elements_type::const_iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ detail::utilities::gl_draw_indexable(it->first, level_rel * z_mul);
+ }
+ }
+
+ size_t level_backup = level;
+ ++level;
+
+ if ( level < level_l )
+ {
+ for (typename elements_type::const_iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ rtree::apply_visitor(*this, *it->second);
+ }
+ }
+
+ level = level_backup;
+ }
+
+ inline void operator()(leaf const& n)
+ {
+ typedef typename rtree::elements_type<leaf>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ if ( level_f <= level )
+ {
+ size_t level_rel = level - level_f;
+
+ glColor3f(0.25f, 0.25f, 0.25f);
+
+ for (typename elements_type::const_iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ detail::utilities::gl_draw_indexable(tr(*it), level_rel * z_mul);
+ }
+ }
+ }
+
+ Translator const& tr;
+ size_t level_f;
+ size_t level_l;
+ typename coordinate_type<Box>::type z_mul;
+
+ size_t level;
+};
+
+} // namespace visitors
+
+template <typename Rtree> inline
+void gl_draw(Rtree const& tree,
+ size_t level_first = 0,
+ size_t level_last = (std::numeric_limits<size_t>::max)(),
+ typename coordinate_type<
+ typename Rtree::bounds_type
+ >::type z_coord_level_multiplier = 1
+ )
+{
+ typedef utilities::view<Rtree> RTV;
+ RTV rtv(tree);
+
+ if ( !tree.empty() )
+ {
+ glColor3f(0.75f, 0.75f, 0.75f);
+ detail::utilities::gl_draw_indexable(tree.bounds(), 0);
+ }
+
+ visitors::gl_draw<
+ typename RTV::value_type,
+ typename RTV::options_type,
+ typename RTV::translator_type,
+ typename RTV::box_type,
+ typename RTV::allocators_type
+ > gl_draw_v(rtv.translator(), level_first, level_last, z_coord_level_multiplier);
+
+ rtv.apply_visitor(gl_draw_v);
+}
+
+}} // namespace rtree::utilities
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP
diff --git a/boost/geometry/index/detail/rtree/utilities/print.hpp b/boost/geometry/index/detail/rtree/utilities/print.hpp
new file mode 100644
index 000000000..f7d503a7d
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/utilities/print.hpp
@@ -0,0 +1,203 @@
+// Boost.Geometry Index
+//
+// R-tree ostreaming visitor implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_PRINT_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_PRINT_HPP
+
+#include <iostream>
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+namespace utilities {
+
+namespace dispatch {
+
+template <typename Point, size_t Dimension>
+struct print_point
+{
+ BOOST_STATIC_ASSERT(0 < Dimension);
+
+ static inline void apply(std::ostream & os, Point const& p)
+ {
+ print_point<Point, Dimension - 1>::apply(os, p);
+
+ os << ", " << geometry::get<Dimension - 1>(p);
+ }
+};
+
+template <typename Point>
+struct print_point<Point, 1>
+{
+ static inline void apply(std::ostream & os, Point const& p)
+ {
+ os << geometry::get<0>(p);
+ }
+};
+
+template <typename Box, size_t Corner, size_t Dimension>
+struct print_corner
+{
+ BOOST_STATIC_ASSERT(0 < Dimension);
+
+ static inline void apply(std::ostream & os, Box const& b)
+ {
+ print_corner<Box, Corner, Dimension - 1>::apply(os, b);
+
+ os << ", " << geometry::get<Corner, Dimension - 1>(b);
+ }
+};
+
+template <typename Box, size_t Corner>
+struct print_corner<Box, Corner, 1>
+{
+ static inline void apply(std::ostream & os, Box const& b)
+ {
+ os << geometry::get<Corner, 0>(b);
+ }
+};
+
+template <typename Indexable, typename Tag>
+struct print_indexable
+{
+};
+
+template <typename Indexable>
+struct print_indexable<Indexable, box_tag>
+{
+ static const size_t dimension = dimension<Indexable>::value;
+
+ static inline void apply(std::ostream &os, Indexable const& i)
+ {
+ os << '(';
+ print_corner<Indexable, min_corner, dimension>::apply(os, i);
+ os << ")x(";
+ print_corner<Indexable, max_corner, dimension>::apply(os, i);
+ os << ')';
+ }
+};
+
+template <typename Indexable>
+struct print_indexable<Indexable, point_tag>
+{
+ static const size_t dimension = dimension<Indexable>::value;
+
+ static inline void apply(std::ostream &os, Indexable const& i)
+ {
+ os << '(';
+ print_point<Indexable, dimension>::apply(os, i);
+ os << ')';
+ }
+};
+
+} // namespace dispatch
+
+template <typename Indexable> inline
+void print_indexable(std::ostream & os, Indexable const& i)
+{
+ dispatch::print_indexable<
+ Indexable,
+ typename tag<Indexable>::type
+ >::apply(os, i);
+}
+
+} // namespace utilities
+
+namespace rtree { namespace utilities {
+
+namespace visitors {
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+struct print : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
+{
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ inline print(std::ostream & o, Translator const& t)
+ : os(o), tr(t), level(0)
+ {}
+
+ inline void operator()(internal_node const& n)
+ {
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ spaces(level) << "INTERNAL NODE - L:" << level << " Ch:" << elements.size() << " @:" << &n << '\n';
+
+ for (typename elements_type::const_iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ spaces(level);
+ detail::utilities::print_indexable(os, it->first);
+ os << " ->" << it->second << '\n';
+ }
+
+ size_t level_backup = level;
+ ++level;
+
+ for (typename elements_type::const_iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ rtree::apply_visitor(*this, *it->second);
+ }
+
+ level = level_backup;
+ }
+
+ inline void operator()(leaf const& n)
+ {
+ typedef typename rtree::elements_type<leaf>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ spaces(level) << "LEAF - L:" << level << " V:" << elements.size() << " @:" << &n << '\n';
+ for (typename elements_type::const_iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ spaces(level);
+ detail::utilities::print_indexable(os, tr(*it));
+ os << '\n';
+ }
+ }
+
+ inline std::ostream & spaces(size_t level)
+ {
+ for ( size_t i = 0 ; i < 2 * level ; ++i )
+ os << ' ';
+ return os;
+ }
+
+ std::ostream & os;
+ Translator const& tr;
+
+ size_t level;
+};
+
+} // namespace visitors
+
+template <typename Rtree> inline
+void print(std::ostream & os, Rtree const& tree)
+{
+ typedef utilities::view<Rtree> RTV;
+ RTV rtv(tree);
+
+ visitors::print<
+ typename RTV::value_type,
+ typename RTV::options_type,
+ typename RTV::translator_type,
+ typename RTV::box_type,
+ typename RTV::allocators_type
+ > print_v(os, rtv.translator());
+ rtv.apply_visitor(print_v);
+}
+
+}} // namespace rtree::utilities
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_PRINT_HPP
diff --git a/boost/geometry/index/detail/rtree/utilities/statistics.hpp b/boost/geometry/index/detail/rtree/utilities/statistics.hpp
new file mode 100644
index 000000000..c8e420d91
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/utilities/statistics.hpp
@@ -0,0 +1,105 @@
+// Boost.Geometry Index
+//
+// R-tree visitor collecting basic statistics
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2013 Mateusz Loskot, London, UK.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_STATISTICS_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_STATISTICS_HPP
+
+#include <algorithm>
+#include <tuple>
+
+namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace utilities {
+
+namespace visitors {
+
+template <typename Value, typename Options, typename Box, typename Allocators>
+struct statistics : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
+{
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ inline statistics()
+ : level(0)
+ , levels(1) // count root
+ , nodes(0)
+ , leaves(0)
+ , values(0)
+ , values_min(0)
+ , values_max(0)
+ {}
+
+ inline void operator()(internal_node const& n)
+ {
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ ++nodes; // count node
+
+ size_t const level_backup = level;
+ ++level;
+
+ levels += level++ > levels ? 1 : 0; // count level (root already counted)
+
+ for (typename elements_type::const_iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ rtree::apply_visitor(*this, *it->second);
+ }
+
+ level = level_backup;
+ }
+
+ inline void operator()(leaf const& n)
+ {
+ typedef typename rtree::elements_type<leaf>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ ++leaves; // count leaves
+
+ std::size_t const v = elements.size();
+ // count values spread per node and total
+ values_min = (std::min)(values_min == 0 ? v : values_min, v);
+ values_max = (std::max)(values_max, v);
+ values += v;
+ }
+
+ std::size_t level;
+ std::size_t levels;
+ std::size_t nodes;
+ std::size_t leaves;
+ std::size_t values;
+ std::size_t values_min;
+ std::size_t values_max;
+};
+
+} // namespace visitors
+
+template <typename Rtree> inline
+boost::tuple<std::size_t, std::size_t, std::size_t, std::size_t, std::size_t, std::size_t>
+statistics(Rtree const& tree)
+{
+ typedef utilities::view<Rtree> RTV;
+ RTV rtv(tree);
+
+ visitors::statistics<
+ typename RTV::value_type,
+ typename RTV::options_type,
+ typename RTV::box_type,
+ typename RTV::allocators_type
+ > stats_v;
+
+ rtv.apply_visitor(stats_v);
+
+ return boost::make_tuple(stats_v.levels, stats_v.nodes, stats_v.leaves, stats_v.values, stats_v.values_min, stats_v.values_max);
+}
+
+}}}}}} // namespace boost::geometry::index::detail::rtree::utilities
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_STATISTICS_HPP
diff --git a/boost/geometry/index/detail/rtree/utilities/view.hpp b/boost/geometry/index/detail/rtree/utilities/view.hpp
new file mode 100644
index 000000000..6dbbd07bf
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/utilities/view.hpp
@@ -0,0 +1,61 @@
+// Boost.Geometry Index
+//
+// Rtree utilities view
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_VIEW_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_VIEW_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree { namespace utilities {
+
+template <typename Rtree>
+class view
+{
+public:
+ typedef typename Rtree::size_type size_type;
+
+ typedef typename Rtree::translator_type translator_type;
+ typedef typename Rtree::value_type value_type;
+ typedef typename Rtree::options_type options_type;
+ typedef typename Rtree::box_type box_type;
+ typedef typename Rtree::allocators_type allocators_type;
+
+ view(Rtree const& rt) : m_rtree(rt) {}
+
+ template <typename Visitor>
+ void apply_visitor(Visitor & vis) const
+ {
+ m_rtree.apply_visitor(vis);
+ }
+
+ // This will most certainly be removed in the future
+ translator_type translator() const
+ {
+ return m_rtree.translator();
+ }
+
+ // This will probably be removed in the future
+ size_type depth() const
+ {
+ return m_rtree.depth();
+ }
+
+private:
+ view(view const&);
+ view & operator=(view const&);
+
+ Rtree const& m_rtree;
+};
+
+}}} // namespace detail::rtree::utilities
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_VIEW_HPP
diff --git a/boost/geometry/index/detail/rtree/visitors/children_box.hpp b/boost/geometry/index/detail/rtree/visitors/children_box.hpp
new file mode 100644
index 000000000..93726063b
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/visitors/children_box.hpp
@@ -0,0 +1,55 @@
+// Boost.Geometry Index
+//
+// R-tree node children box calculating visitor implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_CHILDREN_BOX_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_CHILDREN_BOX_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree { namespace visitors {
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class children_box
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
+{
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+public:
+ inline children_box(Box & result, Translator const& tr)
+ : m_result(result), m_tr(tr)
+ {}
+
+ inline void operator()(internal_node const& n)
+ {
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ m_result = rtree::elements_box<Box>(elements.begin(), elements.end(), m_tr);
+ }
+
+ inline void operator()(leaf const& n)
+ {
+ typedef typename rtree::elements_type<leaf>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ m_result = rtree::elements_box<Box>(elements.begin(), elements.end(), m_tr);
+ }
+
+private:
+ Box & m_result;
+ Translator const& m_tr;
+};
+
+}}} // namespace detail::rtree::visitors
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_CHILDREN_BOX_HPP
diff --git a/boost/geometry/index/detail/rtree/visitors/copy.hpp b/boost/geometry/index/detail/rtree/visitors/copy.hpp
new file mode 100644
index 000000000..8fc25ac80
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/visitors/copy.hpp
@@ -0,0 +1,92 @@
+// Boost.Geometry Index
+//
+// R-tree deep copying visitor implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COPY_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COPY_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree { namespace visitors {
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class copy
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type
+{
+public:
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
+ typedef typename Allocators::node_pointer node_pointer;
+
+ explicit inline copy(Allocators & allocators)
+ : result(0)
+ , m_allocators(allocators)
+ {}
+
+ inline void operator()(internal_node & n)
+ {
+ node_pointer raw_new_node = rtree::create_node<Allocators, internal_node>::apply(m_allocators); // MAY THROW, STRONG (N: alloc)
+ node_auto_ptr new_node(raw_new_node, m_allocators);
+
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ elements_type & elements = rtree::elements(n);
+
+ elements_type & elements_dst = rtree::elements(rtree::get<internal_node>(*new_node));
+
+ for (typename elements_type::iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ rtree::apply_visitor(*this, *it->second); // MAY THROW (V, E: alloc, copy, N: alloc)
+
+ // for exception safety
+ node_auto_ptr auto_result(result, m_allocators);
+
+ elements_dst.push_back( rtree::make_ptr_pair(it->first, result) ); // MAY THROW, STRONG (E: alloc, copy)
+
+ auto_result.release();
+ }
+
+ result = new_node.get();
+ new_node.release();
+ }
+
+ inline void operator()(leaf & l)
+ {
+ node_pointer raw_new_node = rtree::create_node<Allocators, leaf>::apply(m_allocators); // MAY THROW, STRONG (N: alloc)
+ node_auto_ptr new_node(raw_new_node, m_allocators);
+
+ typedef typename rtree::elements_type<leaf>::type elements_type;
+ elements_type & elements = rtree::elements(l);
+
+ elements_type & elements_dst = rtree::elements(rtree::get<leaf>(*new_node));
+
+ for (typename elements_type::iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ elements_dst.push_back(*it); // MAY THROW, STRONG (V: alloc, copy)
+ }
+
+ result = new_node.get();
+ new_node.release();
+ }
+
+ node_pointer result;
+
+private:
+ Allocators & m_allocators;
+};
+
+}}} // namespace detail::rtree::visitors
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COPY_HPP
diff --git a/boost/geometry/index/detail/rtree/visitors/count.hpp b/boost/geometry/index/detail/rtree/visitors/count.hpp
new file mode 100644
index 000000000..203422f33
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/visitors/count.hpp
@@ -0,0 +1,118 @@
+// Boost.Geometry Index
+//
+// R-tree count visitor implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COUNT_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COUNT_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree { namespace visitors {
+
+template <typename Indexable, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+struct count
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
+{
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ inline count(Indexable const& i, Translator const& t)
+ : indexable(i), tr(t), found_count(0)
+ {}
+
+ inline void operator()(internal_node const& n)
+ {
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ // traverse nodes meeting predicates
+ for (typename elements_type::const_iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ if ( geometry::covered_by(indexable, it->first) )
+ rtree::apply_visitor(*this, *it->second);
+ }
+ }
+
+ inline void operator()(leaf const& n)
+ {
+ typedef typename rtree::elements_type<leaf>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ // get all values meeting predicates
+ for (typename elements_type::const_iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ // if value meets predicates
+ if ( geometry::equals(indexable, tr(*it)) )
+ {
+ ++found_count;
+ }
+ }
+ }
+
+ Indexable const& indexable;
+ Translator const& tr;
+ typename Allocators::size_type found_count;
+};
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+struct count<Value, Value, Options, Translator, Box, Allocators>
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
+{
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ inline count(Value const& v, Translator const& t)
+ : value(v), tr(t), found_count(0)
+ {}
+
+ inline void operator()(internal_node const& n)
+ {
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ // traverse nodes meeting predicates
+ for (typename elements_type::const_iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ if ( geometry::covered_by(tr(value), it->first) )
+ rtree::apply_visitor(*this, *it->second);
+ }
+ }
+
+ inline void operator()(leaf const& n)
+ {
+ typedef typename rtree::elements_type<leaf>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ // get all values meeting predicates
+ for (typename elements_type::const_iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ // if value meets predicates
+ if ( tr.equals(value, *it) )
+ {
+ ++found_count;
+ }
+ }
+ }
+
+ Value const& value;
+ Translator const& tr;
+ typename Allocators::size_type found_count;
+};
+
+}}} // namespace detail::rtree::visitors
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COUNT_HPP
diff --git a/boost/geometry/index/detail/rtree/visitors/destroy.hpp b/boost/geometry/index/detail/rtree/visitors/destroy.hpp
new file mode 100644
index 000000000..62722b97a
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/visitors/destroy.hpp
@@ -0,0 +1,70 @@
+// Boost.Geometry Index
+//
+// R-tree destroying visitor implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DELETE_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DELETE_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree { namespace visitors {
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class destroy
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type
+{
+public:
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef typename Allocators::node_pointer node_pointer;
+
+ inline destroy(node_pointer root_node, Allocators & allocators)
+ : m_current_node(root_node)
+ , m_allocators(allocators)
+ {}
+
+ inline void operator()(internal_node & n)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_current_node), "invalid pointers");
+
+ node_pointer node_to_destroy = m_current_node;
+
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ elements_type & elements = rtree::elements(n);
+
+ for (typename elements_type::iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ m_current_node = it->second;
+ rtree::apply_visitor(*this, *m_current_node);
+ it->second = 0;
+ }
+
+ rtree::destroy_node<Allocators, internal_node>::apply(m_allocators, node_to_destroy);
+ }
+
+ inline void operator()(leaf & BOOST_GEOMETRY_INDEX_ASSERT_UNUSED_PARAM(l))
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(&l == &rtree::get<leaf>(*m_current_node), "invalid pointers");
+
+ rtree::destroy_node<Allocators, leaf>::apply(m_allocators, m_current_node);
+ }
+
+private:
+ node_pointer m_current_node;
+ Allocators & m_allocators;
+};
+
+}}} // namespace detail::rtree::visitors
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DELETE_HPP
diff --git a/boost/geometry/index/detail/rtree/visitors/distance_query.hpp b/boost/geometry/index/detail/rtree/visitors/distance_query.hpp
new file mode 100644
index 000000000..616150222
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/visitors/distance_query.hpp
@@ -0,0 +1,540 @@
+// Boost.Geometry Index
+//
+// R-tree distance (knn, path, etc. ) query visitor implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree { namespace visitors {
+
+template <typename Value, typename Translator, typename DistanceType, typename OutIt>
+class distance_query_result
+{
+public:
+ typedef DistanceType distance_type;
+
+ inline explicit distance_query_result(size_t k, OutIt out_it)
+ : m_count(k), m_out_it(out_it)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < m_count, "Number of neighbors should be greater than 0");
+
+ m_neighbors.reserve(m_count);
+ }
+
+ inline void store(Value const& val, distance_type const& curr_comp_dist)
+ {
+ if ( m_neighbors.size() < m_count )
+ {
+ m_neighbors.push_back(std::make_pair(curr_comp_dist, val));
+
+ if ( m_neighbors.size() == m_count )
+ std::make_heap(m_neighbors.begin(), m_neighbors.end(), neighbors_less);
+ }
+ else
+ {
+ if ( curr_comp_dist < m_neighbors.front().first )
+ {
+ std::pop_heap(m_neighbors.begin(), m_neighbors.end(), neighbors_less);
+ m_neighbors.back().first = curr_comp_dist;
+ m_neighbors.back().second = val;
+ std::push_heap(m_neighbors.begin(), m_neighbors.end(), neighbors_less);
+ }
+ }
+ }
+
+ inline bool has_enough_neighbors() const
+ {
+ return m_count <= m_neighbors.size();
+ }
+
+ inline distance_type greatest_comparable_distance() const
+ {
+ // greatest distance is in the first neighbor only
+ // if there is at least m_count values found
+ // this is just for safety reasons since is_comparable_distance_valid() is checked earlier
+ // TODO - may be replaced by ASSERT
+ return m_neighbors.size() < m_count
+ ? (std::numeric_limits<distance_type>::max)()
+ : m_neighbors.front().first;
+ }
+
+ inline size_t finish()
+ {
+ typedef typename std::vector< std::pair<distance_type, Value> >::const_iterator neighbors_iterator;
+ for ( neighbors_iterator it = m_neighbors.begin() ; it != m_neighbors.end() ; ++it, ++m_out_it )
+ *m_out_it = it->second;
+
+ return m_neighbors.size();
+ }
+
+private:
+ inline static bool neighbors_less(
+ std::pair<distance_type, Value> const& p1,
+ std::pair<distance_type, Value> const& p2)
+ {
+ return p1.first < p2.first;
+ }
+
+ size_t m_count;
+ OutIt m_out_it;
+
+ std::vector< std::pair<distance_type, Value> > m_neighbors;
+};
+
+template <
+ typename Value,
+ typename Options,
+ typename Translator,
+ typename Box,
+ typename Allocators,
+ typename Predicates,
+ unsigned DistancePredicateIndex,
+ typename OutIter
+>
+class distance_query
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
+{
+public:
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef index::detail::predicates_element<DistancePredicateIndex, Predicates> nearest_predicate_access;
+ typedef typename nearest_predicate_access::type nearest_predicate_type;
+ typedef typename indexable_type<Translator>::type indexable_type;
+
+ typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, value_tag> calculate_value_distance;
+ typedef index::detail::calculate_distance<nearest_predicate_type, Box, bounds_tag> calculate_node_distance;
+ typedef typename calculate_value_distance::result_type value_distance_type;
+ typedef typename calculate_node_distance::result_type node_distance_type;
+
+ static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
+
+ inline distance_query(parameters_type const& parameters, Translator const& translator, Predicates const& pred, OutIter out_it)
+ : m_parameters(parameters), m_translator(translator)
+ , m_pred(pred)
+ , m_result(nearest_predicate_access::get(m_pred).count, out_it)
+ {}
+
+ inline void operator()(internal_node const& n)
+ {
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+
+ // array of active nodes
+ typedef typename index::detail::rtree::container_from_elements_type<
+ elements_type,
+ std::pair<node_distance_type, typename Allocators::node_pointer>
+ >::type active_branch_list_type;
+
+ active_branch_list_type active_branch_list;
+ active_branch_list.reserve(m_parameters.get_max_elements());
+
+ elements_type const& elements = rtree::elements(n);
+
+ // fill array of nodes meeting predicates
+ for (typename elements_type::const_iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ // if current node meets predicates
+ // 0 - dummy value
+ if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(m_pred, 0, it->first) )
+ {
+ // calculate node's distance(s) for distance predicate
+ node_distance_type node_distance;
+ // if distance isn't ok - move to the next node
+ if ( !calculate_node_distance::apply(predicate(), it->first, node_distance) )
+ {
+ continue;
+ }
+
+ // if current node is further than found neighbors - don't analyze it
+ if ( m_result.has_enough_neighbors() &&
+ is_node_prunable(m_result.greatest_comparable_distance(), node_distance) )
+ {
+ continue;
+ }
+
+ // add current node's data into the list
+ active_branch_list.push_back( std::make_pair(node_distance, it->second) );
+ }
+ }
+
+ // if there aren't any nodes in ABL - return
+ if ( active_branch_list.empty() )
+ return;
+
+ // sort array
+ std::sort(active_branch_list.begin(), active_branch_list.end(), abl_less);
+
+ // recursively visit nodes
+ for ( typename active_branch_list_type::const_iterator it = active_branch_list.begin();
+ it != active_branch_list.end() ; ++it )
+ {
+ // if current node is further than furthest neighbor, the rest of nodes also will be further
+ if ( m_result.has_enough_neighbors() &&
+ is_node_prunable(m_result.greatest_comparable_distance(), it->first) )
+ break;
+
+ rtree::apply_visitor(*this, *(it->second));
+ }
+ }
+
+ inline void operator()(leaf const& n)
+ {
+ typedef typename rtree::elements_type<leaf>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ // search leaf for closest value meeting predicates
+ for (typename elements_type::const_iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ // if value meets predicates
+ if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(m_pred, *it, m_translator(*it)) )
+ {
+ // calculate values distance for distance predicate
+ value_distance_type value_distance;
+ // if distance is ok
+ if ( calculate_value_distance::apply(predicate(), m_translator(*it), value_distance) )
+ {
+ // store value
+ m_result.store(*it, value_distance);
+ }
+ }
+ }
+ }
+
+ inline size_t finish()
+ {
+ return m_result.finish();
+ }
+
+private:
+ static inline bool abl_less(
+ std::pair<node_distance_type, typename Allocators::node_pointer> const& p1,
+ std::pair<node_distance_type, typename Allocators::node_pointer> const& p2)
+ {
+ return p1.first < p2.first;
+ }
+
+ template <typename Distance>
+ static inline bool is_node_prunable(Distance const& greatest_dist, node_distance_type const& d)
+ {
+ return greatest_dist <= d;
+ }
+
+ nearest_predicate_type const& predicate() const
+ {
+ return nearest_predicate_access::get(m_pred);
+ }
+
+ parameters_type const& m_parameters;
+ Translator const& m_translator;
+
+ Predicates m_pred;
+ distance_query_result<Value, Translator, value_distance_type, OutIter> m_result;
+};
+
+template <
+ typename Value,
+ typename Options,
+ typename Translator,
+ typename Box,
+ typename Allocators,
+ typename Predicates,
+ unsigned DistancePredicateIndex
+>
+class distance_query_incremental
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
+{
+public:
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef index::detail::predicates_element<DistancePredicateIndex, Predicates> nearest_predicate_access;
+ typedef typename nearest_predicate_access::type nearest_predicate_type;
+ typedef typename indexable_type<Translator>::type indexable_type;
+
+ typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, value_tag> calculate_value_distance;
+ typedef index::detail::calculate_distance<nearest_predicate_type, Box, bounds_tag> calculate_node_distance;
+ typedef typename calculate_value_distance::result_type value_distance_type;
+ typedef typename calculate_node_distance::result_type node_distance_type;
+
+ typedef typename Allocators::size_type size_type;
+ typedef typename Allocators::const_reference const_reference;
+ typedef typename Allocators::node_pointer node_pointer;
+
+ static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
+
+ typedef typename rtree::elements_type<internal_node>::type internal_elements;
+ typedef typename internal_elements::const_iterator internal_iterator;
+ typedef typename rtree::elements_type<leaf>::type leaf_elements;
+
+ typedef std::pair<node_distance_type, node_pointer> branch_data;
+ typedef typename index::detail::rtree::container_from_elements_type<
+ internal_elements, branch_data
+ >::type active_branch_list_type;
+ struct internal_stack_element
+ {
+ internal_stack_element() : current_branch(0) {}
+#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
+ // Required in c++03 for containers using Boost.Move
+ internal_stack_element & operator=(internal_stack_element const& o)
+ {
+ branches = o.branches;
+ current_branch = o.current_branch;
+ return *this;
+ }
+#endif
+ active_branch_list_type branches;
+ typename active_branch_list_type::size_type current_branch;
+ };
+ typedef std::vector<internal_stack_element> internal_stack_type;
+
+ inline distance_query_incremental(Translator const& translator, Predicates const& pred)
+ : m_translator(::boost::addressof(translator))
+ , m_pred(pred)
+ , current_neighbor((std::numeric_limits<size_type>::max)())
+
+ , next_closest_node_distance((std::numeric_limits<node_distance_type>::max)())
+ {
+ BOOST_ASSERT_MSG(0 < max_count(), "k must be greather than 0");
+ }
+
+ const_reference dereference() const
+ {
+ return *(neighbors[current_neighbor].second);
+ }
+
+ void increment()
+ {
+ for (;;)
+ {
+ size_type new_neighbor = current_neighbor == (std::numeric_limits<size_type>::max)() ? 0 : current_neighbor + 1;
+
+ if ( internal_stack.empty() )
+ {
+ if ( new_neighbor < neighbors.size() )
+ current_neighbor = new_neighbor;
+ else
+ {
+ current_neighbor = (std::numeric_limits<size_type>::max)();
+ // clear() is used to disable the condition above
+ neighbors.clear();
+ }
+
+ return;
+ }
+ else
+ {
+ active_branch_list_type & branches = internal_stack.back().branches;
+ typename active_branch_list_type::size_type & current_branch = internal_stack.back().current_branch;
+
+ if ( branches.size() <= current_branch )
+ {
+ internal_stack.pop_back();
+ continue;
+ }
+
+ // if there are no nodes which can have closer values, set new value
+ if ( new_neighbor < neighbors.size() &&
+ // here must be < because otherwise neighbours may be sorted in different order
+ // if there is another value with equal distance
+ neighbors[new_neighbor].first < next_closest_node_distance )
+ {
+ current_neighbor = new_neighbor;
+ return;
+ }
+
+ // if node is further than the furthest neighbour, following nodes also will be further
+ BOOST_ASSERT_MSG(neighbors.size() <= max_count(), "unexpected neighbours count");
+ if ( max_count() <= neighbors.size() &&
+ is_node_prunable(neighbors.back().first, branches[current_branch].first) )
+ {
+ // stop traversing current level
+ internal_stack.pop_back();
+ continue;
+ }
+ else
+ {
+ // new level - must increment current_branch before traversing of another level (mem reallocation)
+ ++current_branch;
+ rtree::apply_visitor(*this, *(branches[current_branch - 1].second));
+
+ next_closest_node_distance = calc_closest_node_distance(internal_stack.begin(), internal_stack.end());
+ }
+ }
+ }
+ }
+
+ bool is_end() const
+ {
+ return (std::numeric_limits<size_type>::max)() == current_neighbor;
+ }
+
+ friend bool operator==(distance_query_incremental const& l, distance_query_incremental const& r)
+ {
+ BOOST_ASSERT_MSG(l.current_neighbor != r.current_neighbor ||
+ (std::numeric_limits<size_type>::max)() == l.current_neighbor ||
+ l.neighbors[l.current_neighbor].second == r.neighbors[r.current_neighbor].second,
+ "not corresponding iterators");
+ return l.current_neighbor == r.current_neighbor;
+ }
+
+ // Put node's elements into the list of active branches if those elements meets predicates
+ // and distance predicates(currently not used)
+ // and aren't further than found neighbours (if there is enough neighbours)
+ inline void operator()(internal_node const& n)
+ {
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ // add new element
+ internal_stack.resize(internal_stack.size()+1);
+
+ // fill active branch list array of nodes meeting predicates
+ for ( typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it )
+ {
+ // if current node meets predicates
+ // 0 - dummy value
+ if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(m_pred, 0, it->first) )
+ {
+ // calculate node's distance(s) for distance predicate
+ node_distance_type node_distance;
+ // if distance isn't ok - move to the next node
+ if ( !calculate_node_distance::apply(predicate(), it->first, node_distance) )
+ {
+ continue;
+ }
+
+ // if current node is further than found neighbors - don't analyze it
+ if ( max_count() <= neighbors.size() &&
+ is_node_prunable(neighbors.back().first, node_distance) )
+ {
+ continue;
+ }
+
+ // add current node's data into the list
+ internal_stack.back().branches.push_back( std::make_pair(node_distance, it->second) );
+ }
+ }
+
+ if ( internal_stack.back().branches.empty() )
+ internal_stack.pop_back();
+ else
+ // sort array
+ std::sort(internal_stack.back().branches.begin(), internal_stack.back().branches.end(), abl_less);
+ }
+
+ // Put values into the list of neighbours if those values meets predicates
+ // and distance predicates(currently not used)
+ // and aren't further than already found neighbours (if there is enough neighbours)
+ inline void operator()(leaf const& n)
+ {
+ typedef typename rtree::elements_type<leaf>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ // store distance to the furthest neighbour
+ bool not_enough_neighbors = neighbors.size() < max_count();
+ value_distance_type greatest_distance = !not_enough_neighbors ? neighbors.back().first : (std::numeric_limits<value_distance_type>::max)();
+
+ // search leaf for closest value meeting predicates
+ for ( typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it)
+ {
+ // if value meets predicates
+ if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(m_pred, *it, (*m_translator)(*it)) )
+ {
+ // calculate values distance for distance predicate
+ value_distance_type value_distance;
+ // if distance is ok
+ if ( calculate_value_distance::apply(predicate(), (*m_translator)(*it), value_distance) )
+ {
+ // if there is not enough values or current value is closer than furthest neighbour
+ if ( not_enough_neighbors || value_distance < greatest_distance )
+ {
+ neighbors.push_back(std::make_pair(value_distance, boost::addressof(*it)));
+ }
+ }
+ }
+ }
+
+ // sort array
+ std::sort(neighbors.begin(), neighbors.end(), neighbors_less);
+ // remove furthest values
+ if ( max_count() < neighbors.size() )
+ neighbors.resize(max_count());
+ }
+
+private:
+ static inline bool abl_less(std::pair<node_distance_type, typename Allocators::node_pointer> const& p1,
+ std::pair<node_distance_type, typename Allocators::node_pointer> const& p2)
+ {
+ return p1.first < p2.first;
+ }
+
+ static inline bool neighbors_less(std::pair<value_distance_type, const Value *> const& p1,
+ std::pair<value_distance_type, const Value *> const& p2)
+ {
+ return p1.first < p2.first;
+ }
+
+ node_distance_type
+ calc_closest_node_distance(typename internal_stack_type::const_iterator first,
+ typename internal_stack_type::const_iterator last)
+ {
+ node_distance_type result = (std::numeric_limits<node_distance_type>::max)();
+ for ( ; first != last ; ++first )
+ {
+ if ( first->branches.size() <= first->current_branch )
+ continue;
+
+ node_distance_type curr_dist = first->branches[first->current_branch].first;
+ if ( curr_dist < result )
+ result = curr_dist;
+ }
+ return result;
+ }
+
+ template <typename Distance>
+ static inline bool is_node_prunable(Distance const& greatest_dist, node_distance_type const& d)
+ {
+ return greatest_dist <= d;
+ }
+
+ inline unsigned max_count() const
+ {
+ return nearest_predicate_access::get(m_pred).count;
+ }
+
+ nearest_predicate_type const& predicate() const
+ {
+ return nearest_predicate_access::get(m_pred);
+ }
+
+ const Translator * m_translator;
+
+ Predicates m_pred;
+
+ internal_stack_type internal_stack;
+ std::vector< std::pair<value_distance_type, const Value *> > neighbors;
+ size_type current_neighbor;
+ node_distance_type next_closest_node_distance;
+};
+
+}}} // namespace detail::rtree::visitors
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP
diff --git a/boost/geometry/index/detail/rtree/visitors/insert.hpp b/boost/geometry/index/detail/rtree/visitors/insert.hpp
new file mode 100644
index 000000000..9ff5f0749
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/visitors/insert.hpp
@@ -0,0 +1,516 @@
+// Boost.Geometry Index
+//
+// R-tree inserting visitor implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP
+
+#include <boost/geometry/index/detail/algorithms/content.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree {
+
+// Default choose_next_node
+template <typename Value, typename Options, typename Box, typename Allocators, typename ChooseNextNodeTag>
+class choose_next_node;
+
+template <typename Value, typename Options, typename Box, typename Allocators>
+class choose_next_node<Value, Options, Box, Allocators, choose_by_content_diff_tag>
+{
+public:
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef typename rtree::elements_type<internal_node>::type children_type;
+
+ typedef typename index::detail::default_content_result<Box>::type content_type;
+
+ template <typename Indexable>
+ static inline size_t apply(internal_node & n,
+ Indexable const& indexable,
+ parameters_type const& /*parameters*/,
+ size_t /*node_relative_level*/)
+ {
+ children_type & children = rtree::elements(n);
+
+ BOOST_GEOMETRY_INDEX_ASSERT(!children.empty(), "can't choose the next node if children are empty");
+
+ size_t children_count = children.size();
+
+ // choose index with smallest content change or smallest content
+ size_t choosen_index = 0;
+ content_type smallest_content_diff = (std::numeric_limits<content_type>::max)();
+ content_type smallest_content = (std::numeric_limits<content_type>::max)();
+
+ // caculate areas and areas of all nodes' boxes
+ for ( size_t i = 0 ; i < children_count ; ++i )
+ {
+ typedef typename children_type::value_type child_type;
+ child_type const& ch_i = children[i];
+
+ // expanded child node's box
+ Box box_exp(ch_i.first);
+ geometry::expand(box_exp, indexable);
+
+ // areas difference
+ content_type content = index::detail::content(box_exp);
+ content_type content_diff = content - index::detail::content(ch_i.first);
+
+ // update the result
+ if ( content_diff < smallest_content_diff ||
+ ( content_diff == smallest_content_diff && content < smallest_content ) )
+ {
+ smallest_content_diff = content_diff;
+ smallest_content = content;
+ choosen_index = i;
+ }
+ }
+
+ return choosen_index;
+ }
+};
+
+// ----------------------------------------------------------------------- //
+
+// Not implemented here
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename RedistributeTag>
+struct redistribute_elements
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ NOT_IMPLEMENTED_FOR_THIS_REDISTRIBUTE_TAG_TYPE,
+ (redistribute_elements));
+};
+
+// ----------------------------------------------------------------------- //
+
+// Split algorithm
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename SplitTag>
+class split
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ NOT_IMPLEMENTED_FOR_THIS_SPLIT_TAG_TYPE,
+ (split));
+};
+
+// Default split algorithm
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class split<Value, Options, Translator, Box, Allocators, split_default_tag>
+{
+protected:
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
+
+public:
+ typedef index::detail::varray<
+ typename rtree::elements_type<internal_node>::type::value_type,
+ 1
+ > nodes_container_type;
+
+ template <typename Node>
+ static inline void apply(nodes_container_type & additional_nodes,
+ Node & n,
+ Box & n_box,
+ parameters_type const& parameters,
+ Translator const& translator,
+ Allocators & allocators)
+ {
+ // TODO - consider creating nodes always with sufficient memory allocated
+
+ // create additional node, use auto ptr for automatic destruction on exception
+ node_auto_ptr second_node(rtree::create_node<Allocators, Node>::apply(allocators), allocators); // MAY THROW, STRONG (N: alloc)
+ // create reference to the newly created node
+ Node & n2 = rtree::get<Node>(*second_node);
+
+ // NOTE: thread-safety
+ // After throwing an exception by redistribute_elements the original node may be not changed or
+ // both nodes may be empty. In both cases the tree won't be valid r-tree.
+ // The alternative is to create 2 (or more) additional nodes here and store backup info
+ // in the original node, then, if exception was thrown, the node would always have more than max
+ // elements.
+ // The alternative is to use moving semantics in the implementations of redistribute_elements,
+ // it will be possible to throw from boost::move() in the case of e.g. static size nodes.
+
+ // redistribute elements
+ Box box2;
+ redistribute_elements<
+ Value,
+ Options,
+ Translator,
+ Box,
+ Allocators,
+ typename Options::redistribute_tag
+ >::apply(n, n2, n_box, box2, parameters, translator, allocators); // MAY THROW (V, E: alloc, copy, copy)
+
+ // check numbers of elements
+ BOOST_GEOMETRY_INDEX_ASSERT(parameters.get_min_elements() <= rtree::elements(n).size() &&
+ rtree::elements(n).size() <= parameters.get_max_elements(),
+ "unexpected number of elements");
+ BOOST_GEOMETRY_INDEX_ASSERT(parameters.get_min_elements() <= rtree::elements(n2).size() &&
+ rtree::elements(n2).size() <= parameters.get_max_elements(),
+ "unexpected number of elements");
+
+ // return the list of newly created nodes (this algorithm returns one)
+ additional_nodes.push_back(rtree::make_ptr_pair(box2, second_node.get())); // MAY THROW, STRONG (alloc, copy)
+
+ // release the ptr
+ second_node.release();
+ }
+};
+
+// ----------------------------------------------------------------------- //
+
+namespace visitors { namespace detail {
+
+template <typename InternalNode, typename InternalNodePtr>
+struct insert_traverse_data
+{
+ typedef typename rtree::elements_type<InternalNode>::type elements_type;
+ typedef typename elements_type::value_type element_type;
+
+ insert_traverse_data()
+ : parent(0), current_child_index(0), current_level(0)
+ {}
+
+ void move_to_next_level(InternalNodePtr new_parent, size_t new_child_index)
+ {
+ parent = new_parent;
+ current_child_index = new_child_index;
+ ++current_level;
+ }
+
+ bool current_is_root() const
+ {
+ return 0 == parent;
+ }
+
+ elements_type & parent_elements() const
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(parent, "null pointer");
+ return rtree::elements(*parent);
+ }
+
+ element_type & current_element() const
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(parent, "null pointer");
+ return rtree::elements(*parent)[current_child_index];
+ }
+
+ InternalNodePtr parent;
+ size_t current_child_index;
+ size_t current_level;
+};
+
+// Default insert visitor
+template <typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class insert
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type
+{
+protected:
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
+ typedef typename Allocators::node_pointer node_pointer;
+ typedef typename Allocators::internal_node_pointer internal_node_pointer;
+
+ inline insert(node_pointer & root,
+ size_t & leafs_level,
+ Element const& element,
+ parameters_type const& parameters,
+ Translator const& translator,
+ Allocators & allocators,
+ size_t relative_level = 0
+ )
+ : m_element(element)
+ , m_parameters(parameters)
+ , m_translator(translator)
+ , m_relative_level(relative_level)
+ , m_level(leafs_level - relative_level)
+ , m_root_node(root)
+ , m_leafs_level(leafs_level)
+ , m_traverse_data()
+ , m_allocators(allocators)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(m_relative_level <= leafs_level, "unexpected level value");
+ BOOST_GEOMETRY_INDEX_ASSERT(m_level <= m_leafs_level, "unexpected level value");
+ BOOST_GEOMETRY_INDEX_ASSERT(0 != m_root_node, "there is no root node");
+ // TODO
+ // assert - check if Box is correct
+ }
+
+ template <typename Visitor>
+ inline void traverse(Visitor & visitor, internal_node & n)
+ {
+ // choose next node
+ size_t choosen_node_index = rtree::choose_next_node<Value, Options, Box, Allocators, typename Options::choose_next_node_tag>::
+ apply(n, rtree::element_indexable(m_element, m_translator), m_parameters, m_leafs_level - m_traverse_data.current_level);
+
+ // expand the node to contain value
+ geometry::expand(
+ rtree::elements(n)[choosen_node_index].first,
+ rtree::element_indexable(m_element, m_translator));
+
+ // next traversing step
+ traverse_apply_visitor(visitor, n, choosen_node_index); // MAY THROW (V, E: alloc, copy, N:alloc)
+ }
+
+ // TODO: awulkiew - change post_traverse name to handle_overflow or overflow_treatment?
+
+ template <typename Node>
+ inline void post_traverse(Node &n)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(m_traverse_data.current_is_root() ||
+ &n == &rtree::get<Node>(*m_traverse_data.current_element().second),
+ "if node isn't the root current_child_index should be valid");
+
+ // handle overflow
+ if ( m_parameters.get_max_elements() < rtree::elements(n).size() )
+ {
+ split(n); // MAY THROW (V, E: alloc, copy, N:alloc)
+ }
+ }
+
+ template <typename Visitor>
+ inline void traverse_apply_visitor(Visitor & visitor, internal_node &n, size_t choosen_node_index)
+ {
+ // save previous traverse inputs and set new ones
+ insert_traverse_data<internal_node, internal_node_pointer> backup_traverse_data = m_traverse_data;
+
+ // calculate new traverse inputs
+ m_traverse_data.move_to_next_level(&n, choosen_node_index);
+
+ // next traversing step
+ rtree::apply_visitor(visitor, *rtree::elements(n)[choosen_node_index].second); // MAY THROW (V, E: alloc, copy, N:alloc)
+
+ // restore previous traverse inputs
+ m_traverse_data = backup_traverse_data;
+ }
+
+ // TODO: consider - split result returned as OutIter is faster than reference to the container. Why?
+
+ template <typename Node>
+ inline void split(Node & n) const
+ {
+ typedef rtree::split<Value, Options, Translator, Box, Allocators, typename Options::split_tag> split_algo;
+
+ typename split_algo::nodes_container_type additional_nodes;
+ Box n_box;
+
+ split_algo::apply(additional_nodes, n, n_box, m_parameters, m_translator, m_allocators); // MAY THROW (V, E: alloc, copy, N:alloc)
+
+ BOOST_GEOMETRY_INDEX_ASSERT(additional_nodes.size() == 1, "unexpected number of additional nodes");
+
+ // TODO add all additional nodes
+ // For kmeans algorithm:
+ // elements number may be greater than node max elements count
+ // split and reinsert must take node with some elements count
+ // and container of additional elements (std::pair<Box, node*>s or Values)
+ // and translator + allocators
+ // where node_elements_count + additional_elements > node_max_elements_count
+ // What with elements other than std::pair<Box, node*> ?
+ // Implement template <node_tag> struct node_element_type or something like that
+
+ // for exception safety
+ node_auto_ptr additional_node_ptr(additional_nodes[0].second, m_allocators);
+
+ // node is not the root - just add the new node
+ if ( !m_traverse_data.current_is_root() )
+ {
+ // update old node's box
+ m_traverse_data.current_element().first = n_box;
+ // add new node to parent's children
+ m_traverse_data.parent_elements().push_back(additional_nodes[0]); // MAY THROW, STRONG (V, E: alloc, copy)
+ }
+ // node is the root - add level
+ else
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<Node>(*m_root_node), "node should be the root");
+
+ // create new root and add nodes
+ node_auto_ptr new_root(rtree::create_node<Allocators, internal_node>::apply(m_allocators), m_allocators); // MAY THROW, STRONG (N:alloc)
+
+ BOOST_TRY
+ {
+ rtree::elements(rtree::get<internal_node>(*new_root)).push_back(rtree::make_ptr_pair(n_box, m_root_node)); // MAY THROW, STRONG (E:alloc, copy)
+ rtree::elements(rtree::get<internal_node>(*new_root)).push_back(additional_nodes[0]); // MAY THROW, STRONG (E:alloc, copy)
+ }
+ BOOST_CATCH(...)
+ {
+ // clear new root to not delete in the ~node_auto_ptr() potentially stored old root node
+ rtree::elements(rtree::get<internal_node>(*new_root)).clear();
+ BOOST_RETHROW // RETHROW
+ }
+ BOOST_CATCH_END
+
+ m_root_node = new_root.get();
+ ++m_leafs_level;
+
+ new_root.release();
+ }
+
+ additional_node_ptr.release();
+ }
+
+ // TODO: awulkiew - implement dispatchable split::apply to enable additional nodes creation
+
+ Element const& m_element;
+ parameters_type const& m_parameters;
+ Translator const& m_translator;
+ const size_t m_relative_level;
+ const size_t m_level;
+
+ node_pointer & m_root_node;
+ size_t & m_leafs_level;
+
+ // traversing input parameters
+ insert_traverse_data<internal_node, internal_node_pointer> m_traverse_data;
+
+ Allocators & m_allocators;
+};
+
+} // namespace detail
+
+// Insert visitor forward declaration
+template <typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename InsertTag>
+class insert;
+
+// Default insert visitor used for nodes elements
+// After passing the Element to insert visitor the Element is managed by the tree
+// I.e. one should not delete the node passed to the insert visitor after exception is thrown
+// because this visitor may delete it
+template <typename Element, typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class insert<Element, Value, Options, Translator, Box, Allocators, insert_default_tag>
+ : public detail::insert<Element, Value, Options, Translator, Box, Allocators>
+{
+public:
+ typedef detail::insert<Element, Value, Options, Translator, Box, Allocators> base;
+ typedef typename base::node node;
+ typedef typename base::internal_node internal_node;
+ typedef typename base::leaf leaf;
+
+ typedef typename Options::parameters_type parameters_type;
+ typedef typename base::node_pointer node_pointer;
+
+ inline insert(node_pointer & root,
+ size_t & leafs_level,
+ Element const& element,
+ parameters_type const& parameters,
+ Translator const& translator,
+ Allocators & allocators,
+ size_t relative_level = 0
+ )
+ : base(root, leafs_level, element, parameters, translator, allocators, relative_level)
+ {}
+
+ inline void operator()(internal_node & n)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");
+
+ if ( base::m_traverse_data.current_level < base::m_level )
+ {
+ // next traversing step
+ base::traverse(*this, n); // MAY THROW (E: alloc, copy, N: alloc)
+ }
+ else
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level, "unexpected level");
+
+ BOOST_TRY
+ {
+ // push new child node
+ rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (E: alloc, copy)
+ }
+ BOOST_CATCH(...)
+ {
+ // if the insert fails above, the element won't be stored in the tree
+
+ rtree::visitors::destroy<Value, Options, Translator, Box, Allocators> del_v(base::m_element.second, base::m_allocators);
+ rtree::apply_visitor(del_v, *base::m_element.second);
+
+ BOOST_RETHROW // RETHROW
+ }
+ BOOST_CATCH_END
+ }
+
+ base::post_traverse(n); // MAY THROW (E: alloc, copy, N: alloc)
+ }
+
+ inline void operator()(leaf &)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(false, "this visitor can't be used for a leaf");
+ }
+};
+
+// Default insert visitor specialized for Values elements
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class insert<Value, Value, Options, Translator, Box, Allocators, insert_default_tag>
+ : public detail::insert<Value, Value, Options, Translator, Box, Allocators>
+{
+public:
+ typedef detail::insert<Value, Value, Options, Translator, Box, Allocators> base;
+ typedef typename base::node node;
+ typedef typename base::internal_node internal_node;
+ typedef typename base::leaf leaf;
+
+ typedef typename Options::parameters_type parameters_type;
+ typedef typename base::node_pointer node_pointer;
+
+ inline insert(node_pointer & root,
+ size_t & leafs_level,
+ Value const& value,
+ parameters_type const& parameters,
+ Translator const& translator,
+ Allocators & allocators,
+ size_t relative_level = 0
+ )
+ : base(root, leafs_level, value, parameters, translator, allocators, relative_level)
+ {}
+
+ inline void operator()(internal_node & n)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_leafs_level, "unexpected level");
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level < base::m_level, "unexpected level");
+
+ // next traversing step
+ base::traverse(*this, n); // MAY THROW (V, E: alloc, copy, N: alloc)
+
+ base::post_traverse(n); // MAY THROW (E: alloc, copy, N: alloc)
+ }
+
+ inline void operator()(leaf & n)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_traverse_data.current_level == base::m_leafs_level, "unexpected level");
+ BOOST_GEOMETRY_INDEX_ASSERT(base::m_level == base::m_traverse_data.current_level ||
+ base::m_level == (std::numeric_limits<size_t>::max)(), "unexpected level");
+
+ rtree::elements(n).push_back(base::m_element); // MAY THROW, STRONG (V: alloc, copy)
+
+ base::post_traverse(n); // MAY THROW (V: alloc, copy, N: alloc)
+ }
+};
+
+}}} // namespace detail::rtree::visitors
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_INSERT_HPP
diff --git a/boost/geometry/index/detail/rtree/visitors/is_leaf.hpp b/boost/geometry/index/detail/rtree/visitors/is_leaf.hpp
new file mode 100644
index 000000000..6d21afd99
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/visitors/is_leaf.hpp
@@ -0,0 +1,41 @@
+// Boost.Geometry Index
+//
+// R-tree leaf node checking visitor implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_IS_LEAF_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_IS_LEAF_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree { namespace visitors {
+
+template <typename Value, typename Options, typename Box, typename Allocators>
+struct is_leaf : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
+{
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ inline void operator()(internal_node const&)
+ {
+ result = false;
+ }
+
+ inline void operator()(leaf const&)
+ {
+ result = true;
+ }
+
+ bool result;
+};
+
+}}} // namespace detail::rtree::visitors
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_IS_LEAF_HPP
diff --git a/boost/geometry/index/detail/rtree/visitors/remove.hpp b/boost/geometry/index/detail/rtree/visitors/remove.hpp
new file mode 100644
index 000000000..5b77b5acb
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/visitors/remove.hpp
@@ -0,0 +1,316 @@
+// Boost.Geometry Index
+//
+// R-tree removing visitor implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP
+
+#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
+
+#include <boost/geometry/algorithms/covered_by.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree { namespace visitors {
+
+// Default remove algorithm
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators>
+class remove
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, false>::type
+{
+ typedef typename Options::parameters_type parameters_type;
+
+ typedef typename rtree::node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef rtree::node_auto_ptr<Value, Options, Translator, Box, Allocators> node_auto_ptr;
+ typedef typename Allocators::node_pointer node_pointer;
+ typedef typename Allocators::internal_node_pointer internal_node_pointer;
+
+public:
+ inline remove(node_pointer & root,
+ size_t & leafs_level,
+ Value const& value,
+ parameters_type const& parameters,
+ Translator const& translator,
+ Allocators & allocators)
+ : m_value(value)
+ , m_parameters(parameters)
+ , m_translator(translator)
+ , m_allocators(allocators)
+ , m_root_node(root)
+ , m_leafs_level(leafs_level)
+ , m_is_value_removed(false)
+ , m_parent(0)
+ , m_current_child_index(0)
+ , m_current_level(0)
+ , m_is_underflow(false)
+ {
+ // TODO
+ // assert - check if Value/Box is correct
+ }
+
+ inline void operator()(internal_node & n)
+ {
+ typedef typename rtree::elements_type<internal_node>::type children_type;
+ children_type & children = rtree::elements(n);
+
+ // traverse children which boxes intersects value's box
+ size_t child_node_index = 0;
+ for ( ; child_node_index < children.size() ; ++child_node_index )
+ {
+ if ( geometry::covered_by(m_translator(m_value), children[child_node_index].first) )
+ {
+ // next traversing step
+ traverse_apply_visitor(n, child_node_index); // MAY THROW
+
+ if ( m_is_value_removed )
+ break;
+ }
+ }
+
+ // value was found and removed
+ if ( m_is_value_removed )
+ {
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ typedef typename elements_type::iterator element_iterator;
+ elements_type & elements = rtree::elements(n);
+
+ // underflow occured - child node should be removed
+ if ( m_is_underflow )
+ {
+ element_iterator underfl_el_it = elements.begin() + child_node_index;
+ size_t relative_level = m_leafs_level - m_current_level;
+
+ // move node to the container - store node's relative level as well and return new underflow state
+ m_is_underflow = store_underflowed_node(elements, underfl_el_it, relative_level); // MAY THROW (E: alloc, copy)
+ }
+
+ // n is not root - adjust aabb
+ if ( 0 != m_parent )
+ {
+ // underflow state should be ok here
+ // note that there may be less than min_elems elements in root
+ // so this condition should be checked only here
+ BOOST_GEOMETRY_INDEX_ASSERT((elements.size() < m_parameters.get_min_elements()) == m_is_underflow, "unexpected state");
+
+ rtree::elements(*m_parent)[m_current_child_index].first
+ = rtree::elements_box<Box>(elements.begin(), elements.end(), m_translator);
+ }
+ // n is root node
+ else
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(&n == &rtree::get<internal_node>(*m_root_node), "node must be the root");
+
+ // reinsert elements from removed nodes (underflows)
+ reinsert_removed_nodes_elements(); // MAY THROW (V, E: alloc, copy, N: alloc)
+
+ // shorten the tree
+ if ( rtree::elements(n).size() == 1 )
+ {
+ node_pointer root_to_destroy = m_root_node;
+ m_root_node = rtree::elements(n)[0].second;
+ --m_leafs_level;
+
+ rtree::destroy_node<Allocators, internal_node>::apply(m_allocators, root_to_destroy);
+ }
+ }
+ }
+ }
+
+ inline void operator()(leaf & n)
+ {
+ typedef typename rtree::elements_type<leaf>::type elements_type;
+ elements_type & elements = rtree::elements(n);
+
+ // find value and remove it
+ for ( typename elements_type::iterator it = elements.begin() ; it != elements.end() ; ++it )
+ {
+ if ( m_translator.equals(*it, m_value) )
+ {
+ rtree::move_from_back(elements, it); // MAY THROW (V: copy)
+ elements.pop_back();
+ m_is_value_removed = true;
+ break;
+ }
+ }
+
+ // if value was removed
+ if ( m_is_value_removed )
+ {
+ BOOST_ASSERT_MSG(0 < m_parameters.get_min_elements(), "min number of elements is too small");
+
+ // calc underflow
+ m_is_underflow = elements.size() < m_parameters.get_min_elements();
+
+ // n is not root - adjust aabb
+ if ( 0 != m_parent )
+ {
+ rtree::elements(*m_parent)[m_current_child_index].first
+ = rtree::elements_box<Box>(elements.begin(), elements.end(), m_translator);
+ }
+ }
+ }
+
+ bool is_value_removed() const
+ {
+ return m_is_value_removed;
+ }
+
+private:
+
+ typedef std::vector< std::pair<size_t, node_pointer> > UnderflowNodes;
+
+ void traverse_apply_visitor(internal_node &n, size_t choosen_node_index)
+ {
+ // save previous traverse inputs and set new ones
+ internal_node_pointer parent_bckup = m_parent;
+ size_t current_child_index_bckup = m_current_child_index;
+ size_t current_level_bckup = m_current_level;
+
+ m_parent = &n;
+ m_current_child_index = choosen_node_index;
+ ++m_current_level;
+
+ // next traversing step
+ rtree::apply_visitor(*this, *rtree::elements(n)[choosen_node_index].second); // MAY THROW (V, E: alloc, copy, N: alloc)
+
+ // restore previous traverse inputs
+ m_parent = parent_bckup;
+ m_current_child_index = current_child_index_bckup;
+ m_current_level = current_level_bckup;
+ }
+
+ bool store_underflowed_node(
+ typename rtree::elements_type<internal_node>::type & elements,
+ typename rtree::elements_type<internal_node>::type::iterator underfl_el_it,
+ size_t relative_level)
+ {
+ // move node to the container - store node's relative level as well
+ m_underflowed_nodes.push_back(std::make_pair(relative_level, underfl_el_it->second)); // MAY THROW (E: alloc, copy)
+
+ BOOST_TRY
+ {
+ rtree::move_from_back(elements, underfl_el_it); // MAY THROW (E: copy)
+ elements.pop_back();
+ }
+ BOOST_CATCH(...)
+ {
+ m_underflowed_nodes.pop_back();
+ BOOST_RETHROW // RETHROW
+ }
+ BOOST_CATCH_END
+
+ // calc underflow
+ return elements.size() < m_parameters.get_min_elements();
+ }
+
+ void reinsert_removed_nodes_elements()
+ {
+ typename UnderflowNodes::reverse_iterator it = m_underflowed_nodes.rbegin();
+
+ BOOST_TRY
+ {
+ // reinsert elements from removed nodes
+ // begin with levels closer to the root
+ for ( ; it != m_underflowed_nodes.rend() ; ++it )
+ {
+ is_leaf<Value, Options, Box, Allocators> ilv;
+ rtree::apply_visitor(ilv, *it->second);
+ if ( ilv.result )
+ {
+ reinsert_node_elements(rtree::get<leaf>(*it->second), it->first); // MAY THROW (V, E: alloc, copy, N: alloc)
+
+ rtree::destroy_node<Allocators, leaf>::apply(m_allocators, it->second);
+ }
+ else
+ {
+ reinsert_node_elements(rtree::get<internal_node>(*it->second), it->first); // MAY THROW (V, E: alloc, copy, N: alloc)
+
+ rtree::destroy_node<Allocators, internal_node>::apply(m_allocators, it->second);
+ }
+ }
+
+ //m_underflowed_nodes.clear();
+ }
+ BOOST_CATCH(...)
+ {
+ // destroy current and remaining nodes
+ for ( ; it != m_underflowed_nodes.rend() ; ++it )
+ {
+ node_auto_ptr dummy(it->second, m_allocators);
+ }
+
+ //m_underflowed_nodes.clear();
+
+ BOOST_RETHROW // RETHROW
+ }
+ BOOST_CATCH_END
+ }
+
+ template <typename Node>
+ void reinsert_node_elements(Node &n, size_t node_relative_level)
+ {
+ typedef typename rtree::elements_type<Node>::type elements_type;
+ elements_type & elements = rtree::elements(n);
+
+ typename elements_type::iterator it = elements.begin();
+ BOOST_TRY
+ {
+ for ( ; it != elements.end() ; ++it )
+ {
+ visitors::insert<
+ typename elements_type::value_type,
+ Value, Options, Translator, Box, Allocators,
+ typename Options::insert_tag
+ > insert_v(
+ m_root_node, m_leafs_level, *it,
+ m_parameters, m_translator, m_allocators,
+ node_relative_level - 1);
+
+ rtree::apply_visitor(insert_v, *m_root_node); // MAY THROW (V, E: alloc, copy, N: alloc)
+ }
+ }
+ BOOST_CATCH(...)
+ {
+ ++it;
+ rtree::destroy_elements<Value, Options, Translator, Box, Allocators>
+ ::apply(it, elements.end(), m_allocators);
+ elements.clear();
+ BOOST_RETHROW // RETHROW
+ }
+ BOOST_CATCH_END
+ }
+
+ Value const& m_value;
+ parameters_type const& m_parameters;
+ Translator const& m_translator;
+ Allocators & m_allocators;
+
+ node_pointer & m_root_node;
+ size_t & m_leafs_level;
+
+ bool m_is_value_removed;
+ UnderflowNodes m_underflowed_nodes;
+
+ // traversing input parameters
+ internal_node_pointer m_parent;
+ size_t m_current_child_index;
+ size_t m_current_level;
+
+ // traversing output parameters
+ bool m_is_underflow;
+};
+
+}}} // namespace detail::rtree::visitors
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP
diff --git a/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp b/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp
new file mode 100644
index 000000000..48d9c3d3c
--- /dev/null
+++ b/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp
@@ -0,0 +1,198 @@
+// Boost.Geometry Index
+//
+// R-tree spatial query visitor implementation
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_SPATIAL_QUERY_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_SPATIAL_QUERY_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail { namespace rtree { namespace visitors {
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates, typename OutIter>
+struct spatial_query
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
+{
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef typename Allocators::size_type size_type;
+
+ static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
+
+ inline spatial_query(Translator const& t, Predicates const& p, OutIter out_it)
+ : tr(t), pred(p), out_iter(out_it), found_count(0)
+ {}
+
+ inline void operator()(internal_node const& n)
+ {
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ // traverse nodes meeting predicates
+ for (typename elements_type::const_iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ // if node meets predicates
+ // 0 - dummy value
+ if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(pred, 0, it->first) )
+ rtree::apply_visitor(*this, *it->second);
+ }
+ }
+
+ inline void operator()(leaf const& n)
+ {
+ typedef typename rtree::elements_type<leaf>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ // get all values meeting predicates
+ for (typename elements_type::const_iterator it = elements.begin();
+ it != elements.end(); ++it)
+ {
+ // if value meets predicates
+ if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(pred, *it, tr(*it)) )
+ {
+ *out_iter = *it;
+ ++out_iter;
+
+ ++found_count;
+ }
+ }
+ }
+
+ Translator const& tr;
+
+ Predicates pred;
+
+ OutIter out_iter;
+ size_type found_count;
+};
+
+template <typename Value, typename Options, typename Translator, typename Box, typename Allocators, typename Predicates>
+class spatial_query_incremental
+ : public rtree::visitor<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag, true>::type
+{
+public:
+ typedef typename rtree::node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type node;
+ typedef typename rtree::internal_node<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type internal_node;
+ typedef typename rtree::leaf<Value, typename Options::parameters_type, Box, Allocators, typename Options::node_tag>::type leaf;
+
+ typedef typename Allocators::size_type size_type;
+ typedef typename Allocators::const_reference const_reference;
+ typedef typename Allocators::node_pointer node_pointer;
+
+ typedef typename rtree::elements_type<internal_node>::type::const_iterator internal_iterator;
+ typedef typename rtree::elements_type<leaf>::type leaf_elements;
+ typedef typename rtree::elements_type<leaf>::type::const_iterator leaf_iterator;
+
+ static const unsigned predicates_len = index::detail::predicates_length<Predicates>::value;
+
+ inline spatial_query_incremental(Translator const& t, Predicates const& p)
+ : m_translator(::boost::addressof(t))
+ , m_pred(p)
+ , m_values(0)
+ {}
+
+ inline void operator()(internal_node const& n)
+ {
+ typedef typename rtree::elements_type<internal_node>::type elements_type;
+ elements_type const& elements = rtree::elements(n);
+
+ m_internal_stack.push_back(std::make_pair(elements.begin(), elements.end()));
+ }
+
+ inline void operator()(leaf const& n)
+ {
+ m_values = ::boost::addressof(rtree::elements(n));
+ m_current = rtree::elements(n).begin();
+ m_last = rtree::elements(n).end();
+ }
+
+ const_reference dereference() const
+ {
+ BOOST_ASSERT_MSG(m_values, "not dereferencable");
+ return *m_current;
+ }
+
+ void increment()
+ {
+ if ( m_values )
+ ++m_current;
+
+ for (;;)
+ {
+ // if leaf is choosen, move to the next value in leaf
+ if ( m_values )
+ {
+ if ( m_current != m_last )
+ {
+ // return if next value is found
+ Value const& v = *m_current;
+ if ( index::detail::predicates_check<index::detail::value_tag, 0, predicates_len>(m_pred, v, (*m_translator)(v)) )
+ return;
+
+ ++m_current;
+ }
+ // no more values, clear current leaf
+ else
+ {
+ m_values = 0;
+ }
+ }
+ // if leaf isn't choosen, move to the next leaf
+ else
+ {
+ // return if there is no more nodes to traverse
+ if ( m_internal_stack.empty() )
+ return;
+
+ // no more children in current node, remove it from stack
+ if ( m_internal_stack.back().first == m_internal_stack.back().second )
+ {
+ m_internal_stack.pop_back();
+ continue;
+ }
+
+ internal_iterator it = m_internal_stack.back().first;
+ ++m_internal_stack.back().first;
+
+ // next node is found, push it to the stack
+ if ( index::detail::predicates_check<index::detail::bounds_tag, 0, predicates_len>(m_pred, 0, it->first) )
+ rtree::apply_visitor(*this, *(it->second));
+ }
+ }
+ }
+
+ bool is_end() const
+ {
+ return 0 == m_values;
+ }
+
+ friend bool operator==(spatial_query_incremental const& l, spatial_query_incremental const& r)
+ {
+ return (l.m_values == r.m_values) && (0 == l.m_values || l.m_current == r.m_current );
+ }
+
+private:
+
+ const Translator * m_translator;
+
+ Predicates m_pred;
+
+ std::vector< std::pair<internal_iterator, internal_iterator> > m_internal_stack;
+ const leaf_elements * m_values;
+ leaf_iterator m_current, m_last;
+};
+
+}}} // namespace detail::rtree::visitors
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_SPATIAL_QUERY_HPP
diff --git a/boost/geometry/index/detail/tags.hpp b/boost/geometry/index/detail/tags.hpp
new file mode 100644
index 000000000..e1a1716be
--- /dev/null
+++ b/boost/geometry/index/detail/tags.hpp
@@ -0,0 +1,25 @@
+// Boost.Geometry Index
+//
+// Tags used by the predicates checks implementation.
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_TAGS_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_TAGS_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail {
+
+struct value_tag {};
+struct bounds_tag {};
+
+} // namespace detail
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_RTREE_TAGS_HPP
diff --git a/boost/geometry/index/detail/translator.hpp b/boost/geometry/index/detail/translator.hpp
new file mode 100644
index 000000000..f377c720a
--- /dev/null
+++ b/boost/geometry/index/detail/translator.hpp
@@ -0,0 +1,60 @@
+// Boost.Geometry Index
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_TRANSLATOR_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_TRANSLATOR_HPP
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail {
+
+template <typename IndexableGetter, typename EqualTo>
+struct translator
+ : public IndexableGetter
+ , public EqualTo
+{
+ typedef typename IndexableGetter::result_type result_type;
+
+ translator(IndexableGetter const& i, EqualTo const& e)
+ : IndexableGetter(i), EqualTo(e)
+ {}
+
+ template <typename Value>
+ result_type operator()(Value const& value) const
+ {
+ return IndexableGetter::operator()(value);
+ }
+
+ template <typename Value>
+ bool equals(Value const& v1, Value const& v2) const
+ {
+ return EqualTo::operator()(v1, v2);
+ }
+};
+
+template <typename IndexableGetter>
+struct result_type
+{
+ typedef typename IndexableGetter::result_type type;
+};
+
+template <typename IndexableGetter>
+struct indexable_type
+{
+ typedef typename boost::remove_const<
+ typename boost::remove_reference<
+ typename result_type<IndexableGetter>::type
+ >::type
+ >::type type;
+};
+
+} // namespace detail
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_TRANSLATOR_HPP
diff --git a/boost/geometry/index/detail/tuples.hpp b/boost/geometry/index/detail/tuples.hpp
new file mode 100644
index 000000000..28e347bed
--- /dev/null
+++ b/boost/geometry/index/detail/tuples.hpp
@@ -0,0 +1,201 @@
+// Boost.Geometry Index
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_TUPLES_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_TUPLES_HPP
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+// TODO move this to index/tuples and separate algorithms
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+namespace tuples {
+
+// find_index
+
+namespace detail {
+
+template <typename Tuple, typename El, size_t N>
+struct find_index;
+
+template <typename Tuple, typename El, size_t N, typename CurrentEl>
+struct find_index_impl
+{
+ static const size_t value = find_index<Tuple, El, N - 1>::value;
+};
+
+template <typename Tuple, typename El, size_t N>
+struct find_index_impl<Tuple, El, N, El>
+{
+ static const size_t value = N - 1;
+};
+
+template <typename Tuple, typename El, typename CurrentEl>
+struct find_index_impl<Tuple, El, 1, CurrentEl>
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ ELEMENT_NOT_FOUND,
+ (find_index_impl));
+};
+
+template <typename Tuple, typename El>
+struct find_index_impl<Tuple, El, 1, El>
+{
+ static const size_t value = 0;
+};
+
+template <typename Tuple, typename El, size_t N>
+struct find_index
+{
+ static const size_t value =
+ find_index_impl<
+ Tuple,
+ El,
+ N,
+ typename boost::tuples::element<N - 1, Tuple>::type
+ >::value;
+};
+
+} // namespace detail
+
+template <typename Tuple, typename El>
+struct find_index
+{
+ static const size_t value =
+ detail::find_index<
+ Tuple,
+ El,
+ boost::tuples::length<Tuple>::value
+ >::value;
+};
+
+// has
+
+namespace detail {
+
+template <typename Tuple, typename El, size_t N>
+struct has
+{
+ static const bool value
+ = boost::is_same<
+ typename boost::tuples::element<N - 1, Tuple>::type,
+ El
+ >::value
+ || has<Tuple, El, N - 1>::value;
+};
+
+template <typename Tuple, typename El>
+struct has<Tuple, El, 1>
+{
+ static const bool value
+ = boost::is_same<
+ typename boost::tuples::element<0, Tuple>::type,
+ El
+ >::value;
+};
+
+} // namespace detail
+
+template <typename Tuple, typename El>
+struct has
+{
+ static const bool value
+ = detail::has<
+ Tuple,
+ El,
+ boost::tuples::length<Tuple>::value
+ >::value;
+};
+
+// add
+
+template <typename Tuple, typename El>
+struct add
+{
+ BOOST_MPL_ASSERT_MSG(
+ (false),
+ NOT_IMPLEMENTED_FOR_THIS_TUPLE_TYPE,
+ (add));
+};
+
+template <typename T1, typename T>
+struct add<boost::tuple<T1>, T>
+{
+ typedef boost::tuple<T1, T> type;
+};
+
+template <typename T1, typename T2, typename T>
+struct add<boost::tuple<T1, T2>, T>
+{
+ typedef boost::tuple<T1, T2, T> type;
+};
+
+// add_if
+
+template <typename Tuple, typename El, bool Cond>
+struct add_if
+{
+ typedef Tuple type;
+};
+
+template <typename Tuple, typename El>
+struct add_if<Tuple, El, true>
+{
+ typedef typename add<Tuple, El>::type type;
+};
+
+// add_unique
+
+template <typename Tuple, typename El>
+struct add_unique
+{
+ typedef typename add_if<
+ Tuple,
+ El,
+ !has<Tuple, El>::value
+ >::type type;
+};
+
+template <typename Tuple, typename T, size_t I, size_t N>
+struct push_back_impl
+{
+ typedef
+ boost::tuples::cons<
+ typename boost::tuples::element<I, Tuple>::type,
+ typename push_back_impl<Tuple, T, I+1, N>::type
+ > type;
+
+ static type apply(Tuple const& tup, T const& t)
+ {
+ return
+ type(
+ boost::get<I>(tup),
+ push_back_impl<Tuple, T, I+1, N>::apply(tup, t)
+ );
+ }
+};
+
+template <typename Tuple, typename T, size_t N>
+struct push_back_impl<Tuple, T, N, N>
+{
+ typedef boost::tuples::cons<T, boost::tuples::null_type> type;
+
+ static type apply(Tuple const&, T const& t)
+ {
+ return type(t, boost::tuples::null_type());
+ }
+};
+
+} // namespace tuples
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_RTREE_TAGS_HPP
diff --git a/boost/geometry/index/detail/type_erased_iterators.hpp b/boost/geometry/index/detail/type_erased_iterators.hpp
new file mode 100644
index 000000000..92867a4ce
--- /dev/null
+++ b/boost/geometry/index/detail/type_erased_iterators.hpp
@@ -0,0 +1,60 @@
+// Boost.Geometry Index
+//
+// Type-erased iterators
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_TYPE_ERASED_ITERATORS_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_TYPE_ERASED_ITERATORS_HPP
+
+#include <boost/type_erasure/any.hpp>
+#include <boost/type_erasure/operators.hpp>
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+template<typename T, typename ValueType, typename Reference, typename Pointer, typename DifferenceType>
+struct single_pass_iterator_concept :
+ ::boost::mpl::vector<
+ ::boost::type_erasure::copy_constructible<T>,
+ ::boost::type_erasure::equality_comparable<T>,
+ ::boost::type_erasure::dereferenceable<Reference, T>,
+ ::boost::type_erasure::assignable<T>,
+ ::boost::type_erasure::incrementable<T>
+ >
+{};
+
+template <typename ValueType, typename Reference, typename Pointer, typename DifferenceType>
+struct single_pass_iterator_type
+{
+ typedef ::boost::type_erasure::any<
+ single_pass_iterator_concept<
+ ::boost::type_erasure::_self, ValueType, Reference, Pointer, DifferenceType
+ >
+ > type;
+};
+
+}}}} // namespace boost::geometry::index::detail
+
+namespace boost { namespace type_erasure {
+
+template<typename T, typename ValueType, typename Reference, typename Pointer, typename DifferenceType, typename Base>
+struct concept_interface<
+ ::boost::geometry::index::detail::single_pass_iterator_concept<
+ T, ValueType, Reference, Pointer, DifferenceType
+ >, Base, T>
+ : Base
+{
+ typedef ValueType value_type;
+ typedef Reference reference;
+ typedef Pointer pointer;
+ typedef DifferenceType difference_type;
+ typedef ::std::input_iterator_tag iterator_category;
+};
+
+}} // namespace boost::type_erasure
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_TYPE_ERASED_ITERATORS_HPP
diff --git a/boost/geometry/index/detail/utilities.hpp b/boost/geometry/index/detail/utilities.hpp
new file mode 100644
index 000000000..26f078001
--- /dev/null
+++ b/boost/geometry/index/detail/utilities.hpp
@@ -0,0 +1,46 @@
+// Boost.Geometry Index
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/swap.hpp>
+//#include <boost/type_traits/is_empty.hpp>
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_UTILITIES_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_UTILITIES_HPP
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+template<class T>
+static inline void assign_cond(T & l, T const& r, boost::mpl::bool_<true> const&)
+{
+ l = r;
+}
+
+template<class T>
+static inline void assign_cond(T &, T const&, boost::mpl::bool_<false> const&) {}
+
+template<class T>
+static inline void move_cond(T & l, T & r, boost::mpl::bool_<true> const&)
+{
+ l = ::boost::move(r);
+}
+
+template<class T>
+static inline void move_cond(T &, T &, boost::mpl::bool_<false> const&) {}
+
+template <typename T> inline
+void swap_cond(T & l, T & r, boost::mpl::bool_<true> const&)
+{
+ ::boost::swap(l, r);
+}
+
+template <typename T> inline
+void swap_cond(T &, T &, boost::mpl::bool_<false> const&) {}
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_UTILITIES_HPP
diff --git a/boost/geometry/index/detail/varray.hpp b/boost/geometry/index/detail/varray.hpp
new file mode 100644
index 000000000..9570c21ce
--- /dev/null
+++ b/boost/geometry/index/detail/varray.hpp
@@ -0,0 +1,2209 @@
+// Boost.Container varray
+//
+// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2013 Andrew Hundt.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_HPP
+
+// TODO - REMOVE/CHANGE
+#include <boost/container/detail/config_begin.hpp>
+#include <boost/container/detail/workaround.hpp>
+#include <boost/container/detail/preprocessor.hpp>
+
+#include <boost/config.hpp>
+#include <boost/swap.hpp>
+#include <boost/integer.hpp>
+
+#include <boost/mpl/assert.hpp>
+
+#include <boost/type_traits/is_unsigned.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/aligned_storage.hpp>
+
+// TODO - use std::reverse_iterator and std::iterator_traits
+// instead Boost.Iterator to remove dependency?
+// or boost/detail/iterator.hpp ?
+#include <boost/iterator/reverse_iterator.hpp>
+#include <boost/iterator/iterator_concepts.hpp>
+
+#include <boost/geometry/index/detail/assert.hpp>
+
+#include <boost/geometry/index/detail/assert.hpp>
+#include <boost/geometry/index/detail/varray_detail.hpp>
+
+#include <boost/concept_check.hpp>
+
+/*!
+\defgroup varray_non_member varray non-member functions
+*/
+
+namespace boost { namespace geometry { namespace index { namespace detail {
+
+namespace varray_detail {
+
+template <typename Value, std::size_t Capacity>
+struct varray_traits
+{
+ typedef Value value_type;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef Value * pointer;
+ typedef const Value * const_pointer;
+ typedef Value & reference;
+ typedef const Value & const_reference;
+
+ typedef boost::false_type use_memop_in_swap_and_move;
+ typedef boost::false_type use_optimized_swap;
+ typedef boost::false_type disable_trivial_init;
+};
+
+template <typename Varray>
+struct checker
+{
+ typedef typename Varray::size_type size_type;
+ typedef typename Varray::const_iterator const_iterator;
+
+ static inline void check_capacity(Varray const& v, size_type s)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(s <= v.capacity(), "size too big");
+
+ ::boost::ignore_unused_variable_warning(v);
+ ::boost::ignore_unused_variable_warning(s);
+ }
+
+ static inline void throw_out_of_bounds(Varray const& v, size_type i)
+ {
+//#ifndef BOOST_NO_EXCEPTIONS
+ if ( v.size() <= i )
+ BOOST_THROW_EXCEPTION(std::out_of_range("index out of bounds"));
+//#else // BOOST_NO_EXCEPTIONS
+// BOOST_GEOMETRY_INDEX_ASSERT(i < v.size(), "index out of bounds");
+//#endif // BOOST_NO_EXCEPTIONS
+
+ ::boost::ignore_unused_variable_warning(v);
+ ::boost::ignore_unused_variable_warning(i);
+ }
+
+ static inline void check_index(Varray const& v, size_type i)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(i < v.size(), "index out of bounds");
+
+ ::boost::ignore_unused_variable_warning(v);
+ ::boost::ignore_unused_variable_warning(i);
+ }
+
+ static inline void check_not_empty(Varray const& v)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(!v.empty(), "the container is empty");
+
+ ::boost::ignore_unused_variable_warning(v);
+ }
+
+ static inline void check_iterator_end_neq(Varray const& v, const_iterator position)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(v.begin() <= position && position < v.end(), "iterator out of bounds");
+
+ ::boost::ignore_unused_variable_warning(v);
+ ::boost::ignore_unused_variable_warning(position);
+ }
+
+ static inline void check_iterator_end_eq(Varray const& v, const_iterator position)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(v.begin() <= position && position <= v.end(), "iterator out of bounds");
+
+ ::boost::ignore_unused_variable_warning(v);
+ ::boost::ignore_unused_variable_warning(position);
+ }
+};
+
+} // namespace varray_detail
+
+/*!
+\brief A variable-size array container with fixed capacity.
+
+varray is a sequence container like boost::container::vector with contiguous storage that can
+change in size, along with the static allocation, low overhead, and fixed capacity of boost::array.
+
+A varray is a sequence that supports random access to elements, constant time insertion and
+removal of elements at the end, and linear time insertion and removal of elements at the beginning or
+in the middle. The number of elements in a varray may vary dynamically up to a fixed capacity
+because elements are stored within the object itself similarly to an array. However, objects are
+initialized as they are inserted into varray unlike C arrays or std::array which must construct
+all elements on instantiation. The behavior of varray enables the use of statically allocated
+elements in cases with complex object lifetime requirements that would otherwise not be trivially
+possible.
+
+\par Error Handling
+ Insertion beyond the capacity and out of bounds errors result in undefined behavior unless
+ otherwise specified. In this respect if size() == capacity(), then varray::push_back()
+ behaves like std::vector pop_front() if size() == empty(). The reason for this difference
+ is because unlike vectors, varray does not perform allocation.
+
+\par Advanced Usage
+ Error handling behavior can be modified to more closely match std::vector exception behavior
+ when exceeding bounds by providing an alternate Strategy and varray_traits instantiation.
+
+\tparam Value The type of element that will be stored.
+\tparam Capacity The maximum number of elements varray can store, fixed at compile time.
+\tparam Strategy Defines the public typedefs and error handlers,
+ implements StaticVectorStrategy and has some similarities
+ to an Allocator.
+*/
+template <typename Value, std::size_t Capacity>
+class varray
+{
+ typedef varray_detail::varray_traits<Value, Capacity> vt;
+ typedef varray_detail::checker<varray> errh;
+
+ BOOST_MPL_ASSERT_MSG(
+ ( boost::is_unsigned<typename vt::size_type>::value &&
+ sizeof(typename boost::uint_value_t<Capacity>::least) <= sizeof(typename vt::size_type) ),
+ SIZE_TYPE_IS_TOO_SMALL_FOR_SPECIFIED_CAPACITY,
+ (varray)
+ );
+
+ typedef boost::aligned_storage<
+ sizeof(Value[Capacity]),
+ boost::alignment_of<Value[Capacity]>::value
+ > aligned_storage_type;
+
+ template <typename V, std::size_t C>
+ friend class varray;
+
+ BOOST_COPYABLE_AND_MOVABLE(varray)
+
+#ifdef BOOST_NO_RVALUE_REFERENCES
+public:
+ template <std::size_t C>
+ varray & operator=(varray<Value, C> & sv)
+ {
+ typedef varray<Value, C> other;
+ this->operator=(static_cast<const ::boost::rv<other> &>(const_cast<const other &>(sv)));
+ return *this;
+ }
+#endif
+
+public:
+ //! @brief The type of elements stored in the container.
+ typedef typename vt::value_type value_type;
+ //! @brief The unsigned integral type used by the container.
+ typedef typename vt::size_type size_type;
+ //! @brief The pointers difference type.
+ typedef typename vt::difference_type difference_type;
+ //! @brief The pointer type.
+ typedef typename vt::pointer pointer;
+ //! @brief The const pointer type.
+ typedef typename vt::const_pointer const_pointer;
+ //! @brief The value reference type.
+ typedef typename vt::reference reference;
+ //! @brief The value const reference type.
+ typedef typename vt::const_reference const_reference;
+
+ //! @brief The iterator type.
+ typedef pointer iterator;
+ //! @brief The const iterator type.
+ typedef const_pointer const_iterator;
+ //! @brief The reverse iterator type.
+ typedef boost::reverse_iterator<iterator> reverse_iterator;
+ //! @brief The const reverse iterator.
+ typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ //! @brief Constructs an empty varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ varray()
+ : m_size(0)
+ {}
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Constructs a varray containing count default constructed Values.
+ //!
+ //! @param count The number of values which will be contained in the container.
+ //!
+ //! @par Throws
+ //! If Value's default constructor throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ explicit varray(size_type count)
+ : m_size(0)
+ {
+ this->resize(count); // may throw
+ }
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Constructs a varray containing count copies of value.
+ //!
+ //! @param count The number of copies of a values that will be contained in the container.
+ //! @param value The value which will be used to copy construct values.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ varray(size_type count, value_type const& value)
+ : m_size(0)
+ {
+ this->resize(count, value); // may throw
+ }
+
+ //! @pre
+ //! @li <tt>distance(first, last) <= capacity()</tt>
+ //! @li Iterator must meet the \c ForwardTraversalIterator concept.
+ //!
+ //! @brief Constructs a varray containing copy of a range <tt>[first, last)</tt>.
+ //!
+ //! @param first The iterator to the first element in range.
+ //! @param last The iterator to the one after the last element in range.
+ //!
+ //! @par Throws
+ //! If Value's constructor taking a dereferenced Iterator throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <typename Iterator>
+ varray(Iterator first, Iterator last)
+ : m_size(0)
+ {
+ BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<Iterator>)); // Make sure you passed a ForwardIterator
+
+ this->assign(first, last); // may throw
+ }
+
+ //! @brief Constructs a copy of other varray.
+ //!
+ //! @param other The varray which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ varray(varray const& other)
+ : m_size(other.size())
+ {
+ namespace sv = varray_detail;
+ sv::uninitialized_copy(other.begin(), other.end(), this->begin()); // may throw
+ }
+
+ //! @pre <tt>other.size() <= capacity()</tt>.
+ //!
+ //! @brief Constructs a copy of other varray.
+ //!
+ //! @param other The varray which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+ varray(varray<value_type, C> const& other)
+ : m_size(other.size())
+ {
+ errh::check_capacity(*this, other.size()); // may throw
+
+ namespace sv = varray_detail;
+ sv::uninitialized_copy(other.begin(), other.end(), this->begin()); // may throw
+ }
+
+ //! @brief Copy assigns Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ varray & operator=(BOOST_COPY_ASSIGN_REF(varray) other)
+ {
+ this->assign(other.begin(), other.end()); // may throw
+
+ return *this;
+ }
+
+ //! @pre <tt>other.size() <= capacity()</tt>
+ //!
+ //! @brief Copy assigns Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be copied to this one.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+// TEMPORARY WORKAROUND
+#if defined(BOOST_NO_RVALUE_REFERENCES)
+ varray & operator=(::boost::rv< varray<value_type, C> > const& other)
+#else
+ varray & operator=(varray<value_type, C> const& other)
+#endif
+ {
+ this->assign(other.begin(), other.end()); // may throw
+
+ return *this;
+ }
+
+ //! @brief Move constructor. Moves Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be moved to this one.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor throws.
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.
+ //! @internal
+ //! @li It throws only if \c use_memop_in_swap_and_move is \c false_type - default.
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ varray(BOOST_RV_REF(varray) other)
+ {
+ typedef typename
+ vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;
+
+ this->move_ctor_dispatch(other, use_memop_in_swap_and_move());
+ }
+
+ //! @pre <tt>other.size() <= capacity()</tt>
+ //!
+ //! @brief Move constructor. Moves Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be moved to this one.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor throws.
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor throws.
+ //! @internal
+ //! @li It throws only if \c use_memop_in_swap_and_move is false_type - default.
+ //! @endinternal
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+ varray(BOOST_RV_REF_2_TEMPL_ARGS(varray, value_type, C) other)
+ : m_size(other.m_size)
+ {
+ errh::check_capacity(*this, other.size()); // may throw
+
+ typedef typename
+ vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;
+
+ this->move_ctor_dispatch(other, use_memop_in_swap_and_move());
+ }
+
+ //! @brief Move assignment. Moves Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be moved to this one.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.
+ //! @internal
+ //! @li It throws only if \c use_memop_in_swap_and_move is \c false_type - default.
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ varray & operator=(BOOST_RV_REF(varray) other)
+ {
+ if ( &other == this )
+ return *this;
+
+ typedef typename
+ vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;
+
+ this->move_assign_dispatch(other, use_memop_in_swap_and_move());
+
+ return *this;
+ }
+
+ //! @pre <tt>other.size() <= capacity()</tt>
+ //!
+ //! @brief Move assignment. Moves Values stored in the other varray to this one.
+ //!
+ //! @param other The varray which content will be moved to this one.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws.
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws.
+ //! @internal
+ //! @li It throws only if \c use_memop_in_swap_and_move is \c false_type - default.
+ //! @endinternal
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+ varray & operator=(BOOST_RV_REF_2_TEMPL_ARGS(varray, value_type, C) other)
+ {
+ errh::check_capacity(*this, other.size()); // may throw
+
+ typedef typename
+ vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;
+
+ this->move_assign_dispatch(other, use_memop_in_swap_and_move());
+
+ return *this;
+ }
+
+ //! @brief Destructor. Destroys Values stored in this container.
+ //!
+ //! @par Throws
+ //! Nothing
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ ~varray()
+ {
+ namespace sv = varray_detail;
+ sv::destroy(this->begin(), this->end());
+ }
+
+ //! @brief Swaps contents of the other varray and this one.
+ //!
+ //! @param other The varray which content will be swapped with this one's content.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,
+ //! @internal
+ //! @li It throws only if \c use_memop_in_swap_and_move and \c use_optimized_swap are \c false_type - default.
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void swap(varray & other)
+ {
+ typedef typename
+ vt::use_optimized_swap use_optimized_swap;
+
+ this->swap_dispatch(other, use_optimized_swap());
+ }
+
+ //! @pre <tt>other.size() <= capacity() && size() <= other.capacity()</tt>
+ //!
+ //! @brief Swaps contents of the other varray and this one.
+ //!
+ //! @param other The varray which content will be swapped with this one's content.
+ //!
+ //! @par Throws
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c true and Value's move constructor or move assignment throws,
+ //! @li If \c boost::has_nothrow_move<Value>::value is \c false and Value's copy constructor or copy assignment throws,
+ //! @internal
+ //! @li It throws only if \c use_memop_in_swap_and_move and \c use_optimized_swap are \c false_type - default.
+ //! @endinternal
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <std::size_t C>
+ void swap(varray<value_type, C> & other)
+ {
+ errh::check_capacity(*this, other.size());
+ errh::check_capacity(other, this->size());
+
+ typedef typename
+ vt::use_optimized_swap use_optimized_swap;
+
+ this->swap_dispatch(other, use_optimized_swap());
+ }
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Inserts or erases elements at the end such that
+ //! the size becomes count. New elements are default constructed.
+ //!
+ //! @param count The number of elements which will be stored in the container.
+ //!
+ //! @par Throws
+ //! If Value's default constructor throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void resize(size_type count)
+ {
+ namespace sv = varray_detail;
+ typedef typename vt::disable_trivial_init dti;
+
+ if ( count < m_size )
+ {
+ sv::destroy(this->begin() + count, this->end());
+ }
+ else
+ {
+ errh::check_capacity(*this, count); // may throw
+
+ sv::uninitialized_fill(this->end(), this->begin() + count, dti()); // may throw
+ }
+ m_size = count; // update end
+ }
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Inserts or erases elements at the end such that
+ //! the size becomes count. New elements are copy constructed from value.
+ //!
+ //! @param count The number of elements which will be stored in the container.
+ //! @param value The value used to copy construct the new element.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void resize(size_type count, value_type const& value)
+ {
+ if ( count < m_size )
+ {
+ namespace sv = varray_detail;
+ sv::destroy(this->begin() + count, this->end());
+ }
+ else
+ {
+ errh::check_capacity(*this, count); // may throw
+
+ std::uninitialized_fill(this->end(), this->begin() + count, value); // may throw
+ }
+ m_size = count; // update end
+ }
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief This call has no effect because the Capacity of this container is constant.
+ //!
+ //! @param count The number of elements which the container should be able to contain.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void reserve(size_type count)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ //! @pre <tt>size() < capacity()</tt>
+ //!
+ //! @brief Adds a copy of value at the end.
+ //!
+ //! @param value The value used to copy construct the new element.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void push_back(value_type const& value)
+ {
+ typedef typename vt::disable_trivial_init dti;
+
+ errh::check_capacity(*this, m_size + 1); // may throw
+
+ namespace sv = varray_detail;
+ sv::construct(dti(), this->end(), value); // may throw
+ ++m_size; // update end
+ }
+
+ //! @pre <tt>size() < capacity()</tt>
+ //!
+ //! @brief Moves value to the end.
+ //!
+ //! @param value The value to move construct the new element.
+ //!
+ //! @par Throws
+ //! If Value's move constructor throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void push_back(BOOST_RV_REF(value_type) value)
+ {
+ typedef typename vt::disable_trivial_init dti;
+
+ errh::check_capacity(*this, m_size + 1); // may throw
+
+ namespace sv = varray_detail;
+ sv::construct(dti(), this->end(), ::boost::move(value)); // may throw
+ ++m_size; // update end
+ }
+
+ //! @pre <tt>!empty()</tt>
+ //!
+ //! @brief Destroys last value and decreases the size.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void pop_back()
+ {
+ errh::check_not_empty(*this);
+
+ namespace sv = varray_detail;
+ sv::destroy(this->end() - 1);
+ --m_size; // update end
+ }
+
+ //! @pre
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>size() < capacity()</tt>
+ //!
+ //! @brief Inserts a copy of element at position.
+ //!
+ //! @param position The position at which the new value will be inserted.
+ //! @param value The value used to copy construct the new element.
+ //!
+ //! @par Throws
+ //! @li If Value's copy constructor or copy assignment throws
+ //! @li If Value's move constructor or move assignment throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Constant or linear.
+ iterator insert(iterator position, value_type const& value)
+ {
+ typedef typename vt::disable_trivial_init dti;
+ namespace sv = varray_detail;
+
+ errh::check_iterator_end_eq(*this, position);
+ errh::check_capacity(*this, m_size + 1); // may throw
+
+ if ( position == this->end() )
+ {
+ sv::construct(dti(), position, value); // may throw
+ ++m_size; // update end
+ }
+ else
+ {
+ // TODO - should move be used only if it's nonthrowing?
+ value_type & r = *(this->end() - 1);
+ sv::construct(dti(), this->end(), boost::move(r)); // may throw
+ ++m_size; // update end
+ sv::move_backward(position, this->end() - 2, this->end() - 1); // may throw
+ sv::assign(position, value); // may throw
+ }
+
+ return position;
+ }
+
+ //! @pre
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>size() < capacity()</tt>
+ //!
+ //! @brief Inserts a move-constructed element at position.
+ //!
+ //! @param position The position at which the new value will be inserted.
+ //! @param value The value used to move construct the new element.
+ //!
+ //! @par Throws
+ //! If Value's move constructor or move assignment throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Constant or linear.
+ iterator insert(iterator position, BOOST_RV_REF(value_type) value)
+ {
+ typedef typename vt::disable_trivial_init dti;
+ namespace sv = varray_detail;
+
+ errh::check_iterator_end_eq(*this, position);
+ errh::check_capacity(*this, m_size + 1); // may throw
+
+ if ( position == this->end() )
+ {
+ sv::construct(dti(), position, boost::move(value)); // may throw
+ ++m_size; // update end
+ }
+ else
+ {
+ // TODO - should move be used only if it's nonthrowing?
+ value_type & r = *(this->end() - 1);
+ sv::construct(dti(), this->end(), boost::move(r)); // may throw
+ ++m_size; // update end
+ sv::move_backward(position, this->end() - 2, this->end() - 1); // may throw
+ sv::assign(position, boost::move(value)); // may throw
+ }
+
+ return position;
+ }
+
+ //! @pre
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>size() + count <= capacity()</tt>
+ //!
+ //! @brief Inserts a count copies of value at position.
+ //!
+ //! @param position The position at which new elements will be inserted.
+ //! @param count The number of new elements which will be inserted.
+ //! @param value The value used to copy construct new elements.
+ //!
+ //! @par Throws
+ //! @li If Value's copy constructor or copy assignment throws.
+ //! @li If Value's move constructor or move assignment throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ iterator insert(iterator position, size_type count, value_type const& value)
+ {
+ errh::check_iterator_end_eq(*this, position);
+ errh::check_capacity(*this, m_size + count); // may throw
+
+ if ( position == this->end() )
+ {
+ std::uninitialized_fill(position, position + count, value); // may throw
+ m_size += count; // update end
+ }
+ else
+ {
+ namespace sv = varray_detail;
+
+ difference_type to_move = std::distance(position, this->end());
+
+ // TODO - should following lines check for exception and revert to the old size?
+
+ if ( count < static_cast<size_type>(to_move) )
+ {
+ sv::uninitialized_move(this->end() - count, this->end(), this->end()); // may throw
+ m_size += count; // update end
+ sv::move_backward(position, position + to_move - count, this->end() - count); // may throw
+ std::fill_n(position, count, value); // may throw
+ }
+ else
+ {
+ std::uninitialized_fill(this->end(), position + count, value); // may throw
+ m_size += count - to_move; // update end
+ sv::uninitialized_move(position, position + to_move, position + count); // may throw
+ m_size += to_move; // update end
+ std::fill_n(position, to_move, value); // may throw
+ }
+ }
+
+ return position;
+ }
+
+ //! @pre
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>.
+ //! @li <tt>distance(first, last) <= capacity()</tt>
+ //! @li \c Iterator must meet the \c ForwardTraversalIterator concept.
+ //!
+ //! @brief Inserts a copy of a range <tt>[first, last)</tt> at position.
+ //!
+ //! @param position The position at which new elements will be inserted.
+ //! @param first The iterator to the first element of a range used to construct new elements.
+ //! @param last The iterator to the one after the last element of a range used to construct new elements.
+ //!
+ //! @par Throws
+ //! @li If Value's constructor and assignment taking a dereferenced \c Iterator.
+ //! @li If Value's move constructor or move assignment throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <typename Iterator>
+ iterator insert(iterator position, Iterator first, Iterator last)
+ {
+ BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<Iterator>)); // Make sure you passed a ForwardIterator
+
+ typedef typename boost::iterator_traversal<Iterator>::type traversal;
+ this->insert_dispatch(position, first, last, traversal());
+
+ return position;
+ }
+
+ //! @pre \c position must be a valid iterator of \c *this in range <tt>[begin(), end())</tt>
+ //!
+ //! @brief Erases Value from position.
+ //!
+ //! @param position The position of the element which will be erased from the container.
+ //!
+ //! @par Throws
+ //! If Value's move assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ iterator erase(iterator position)
+ {
+ namespace sv = varray_detail;
+
+ errh::check_iterator_end_neq(*this, position);
+
+ //TODO - add empty check?
+ //errh::check_empty(*this);
+
+ sv::move(position + 1, this->end(), position); // may throw
+ sv::destroy(this->end() - 1);
+ --m_size;
+
+ return position;
+ }
+
+ //! @pre
+ //! @li \c first and \c last must define a valid range
+ //! @li iterators must be in range <tt>[begin(), end()]</tt>
+ //!
+ //! @brief Erases Values from a range <tt>[first, last)</tt>.
+ //!
+ //! @param first The position of the first element of a range which will be erased from the container.
+ //! @param last The position of the one after the last element of a range which will be erased from the container.
+ //!
+ //! @par Throws
+ //! If Value's move assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ iterator erase(iterator first, iterator last)
+ {
+ namespace sv = varray_detail;
+
+ errh::check_iterator_end_eq(*this, first);
+ errh::check_iterator_end_eq(*this, last);
+
+ difference_type n = std::distance(first, last);
+
+ //TODO - add invalid range check?
+ //BOOST_ASSERT_MSG(0 <= n, "invalid range");
+ //TODO - add this->size() check?
+ //BOOST_ASSERT_MSG(n <= this->size(), "invalid range");
+
+ sv::move(last, this->end(), first); // may throw
+ sv::destroy(this->end() - n, this->end());
+ m_size -= n;
+
+ return first;
+ }
+
+ //! @pre <tt>distance(first, last) <= capacity()</tt>
+ //!
+ //! @brief Assigns a range <tt>[first, last)</tt> of Values to this container.
+ //!
+ //! @param first The iterator to the first element of a range used to construct new content of this container.
+ //! @param last The iterator to the one after the last element of a range used to construct new content of this container.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws,
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ template <typename Iterator>
+ void assign(Iterator first, Iterator last)
+ {
+ BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<Iterator>)); // Make sure you passed a ForwardIterator
+
+ typedef typename boost::iterator_traversal<Iterator>::type traversal;
+ this->assign_dispatch(first, last, traversal()); // may throw
+ }
+
+ //! @pre <tt>count <= capacity()</tt>
+ //!
+ //! @brief Assigns a count copies of value to this container.
+ //!
+ //! @param count The new number of elements which will be container in the container.
+ //! @param value The value which will be used to copy construct the new content.
+ //!
+ //! @par Throws
+ //! If Value's copy constructor or copy assignment throws.
+ //!
+ //! @par Complexity
+ //! Linear O(N).
+ void assign(size_type count, value_type const& value)
+ {
+ if ( count < m_size )
+ {
+ namespace sv = varray_detail;
+
+ std::fill_n(this->begin(), count, value); // may throw
+ sv::destroy(this->begin() + count, this->end());
+ }
+ else
+ {
+ errh::check_capacity(*this, count); // may throw
+
+ std::fill_n(this->begin(), m_size, value); // may throw
+ std::uninitialized_fill(this->end(), this->begin() + count, value); // may throw
+ }
+ m_size = count; // update end
+ }
+
+#if !defined(BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE)
+#if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+ //! @pre <tt>size() < capacity()</tt>
+ //!
+ //! @brief Inserts a Value constructed with
+ //! \c std::forward<Args>(args)... in the end of the container.
+ //!
+ //! @param args The arguments of the constructor of the new element which will be created at the end of the container.
+ //!
+ //! @par Throws
+ //! If in-place constructor throws or Value's move constructor throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ template<class ...Args>
+ void emplace_back(BOOST_FWD_REF(Args) ...args)
+ {
+ typedef typename vt::disable_trivial_init dti;
+
+ errh::check_capacity(*this, m_size + 1); // may throw
+
+ namespace sv = varray_detail;
+ sv::construct(dti(), this->end(), ::boost::forward<Args>(args)...); // may throw
+ ++m_size; // update end
+ }
+
+ //! @pre
+ //! @li \c position must be a valid iterator of \c *this in range <tt>[begin(), end()]</tt>
+ //! @li <tt>size() < capacity()</tt>
+ //!
+ //! @brief Inserts a Value constructed with
+ //! \c std::forward<Args>(args)... before position
+ //!
+ //! @param position The position at which new elements will be inserted.
+ //! @param args The arguments of the constructor of the new element.
+ //!
+ //! @par Throws
+ //! If in-place constructor throws or if Value's move constructor or move assignment throws.
+ //! @internal
+ //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default).
+ //! @endinternal
+ //!
+ //! @par Complexity
+ //! Constant or linear.
+ template<class ...Args>
+ iterator emplace(iterator position, BOOST_FWD_REF(Args) ...args)
+ {
+ typedef typename vt::disable_trivial_init dti;
+
+ namespace sv = varray_detail;
+
+ errh::check_iterator_end_eq(*this, position);
+ errh::check_capacity(*this, m_size + 1); // may throw
+
+ if ( position == this->end() )
+ {
+ sv::construct(dti(), position, ::boost::forward<Args>(args)...); // may throw
+ ++m_size; // update end
+ }
+ else
+ {
+ // TODO - should following lines check for exception and revert to the old size?
+
+ // TODO - should move be used only if it's nonthrowing?
+ value_type & r = *(this->end() - 1);
+ sv::construct(dti(), this->end(), boost::move(r)); // may throw
+ ++m_size; // update end
+ sv::move_backward(position, this->end() - 2, this->end() - 1); // may throw
+
+ aligned_storage<sizeof(value_type), alignment_of<value_type>::value> temp_storage;
+ value_type * val_p = static_cast<value_type *>(temp_storage.address());
+ sv::construct(dti(), val_p, ::boost::forward<Args>(args)...); // may throw
+ sv::scoped_destructor<value_type> d(val_p);
+ sv::assign(position, ::boost::move(*val_p)); // may throw
+ }
+
+ return position;
+ }
+
+#else // BOOST_CONTAINER_PERFECT_FORWARDING || BOOST_CONTAINER_DOXYGEN_INVOKED
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { \
+ typedef typename vt::disable_trivial_init dti; \
+ \
+ errh::check_capacity(*this, m_size + 1); /*may throw*/\
+ \
+ namespace sv = varray_detail; \
+ sv::construct(dti(), this->end() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); /*may throw*/\
+ ++m_size; /*update end*/ \
+ } \
+ //
+ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+ #define BOOST_PP_LOCAL_MACRO(n) \
+ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \
+ iterator emplace(iterator position BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+ { \
+ typedef typename vt::disable_trivial_init dti; \
+ namespace sv = varray_detail; \
+ \
+ errh::check_iterator_end_eq(*this, position); \
+ errh::check_capacity(*this, m_size + 1); /*may throw*/\
+ \
+ if ( position == this->end() ) \
+ { \
+ sv::construct(dti(), position BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); /*may throw*/\
+ ++m_size; /*update end*/ \
+ } \
+ else \
+ { \
+ /* TODO - should following lines check for exception and revert to the old size? */ \
+ /* TODO - should move be used only if it's nonthrowing? */ \
+ \
+ value_type & r = *(this->end() - 1); \
+ sv::construct(dti(), this->end(), boost::move(r)); /*may throw*/\
+ ++m_size; /*update end*/ \
+ sv::move_backward(position, this->end() - 2, this->end() - 1); /*may throw*/\
+ \
+ aligned_storage<sizeof(value_type), alignment_of<value_type>::value> temp_storage; \
+ value_type * val_p = static_cast<value_type *>(temp_storage.address()); \
+ sv::construct(dti(), val_p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); /*may throw*/\
+ sv::scoped_destructor<value_type> d(val_p); \
+ sv::assign(position, ::boost::move(*val_p)); /*may throw*/\
+ } \
+ \
+ return position; \
+ } \
+ //
+ #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+ #include BOOST_PP_LOCAL_ITERATE()
+
+#endif // BOOST_CONTAINER_PERFECT_FORWARDING || BOOST_CONTAINER_DOXYGEN_INVOKED
+#endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE
+
+ //! @brief Removes all elements from the container.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ void clear()
+ {
+ namespace sv = varray_detail;
+ sv::destroy(this->begin(), this->end());
+ m_size = 0; // update end
+ }
+
+ //! @pre <tt>i < size()</tt>
+ //!
+ //! @brief Returns reference to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return reference to the i-th element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! \c std::out_of_range exception by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reference at(size_type i)
+ {
+ errh::throw_out_of_bounds(*this, i); // may throw
+ return *(this->begin() + i);
+ }
+
+ //! @pre <tt>i < size()</tt>
+ //!
+ //! @brief Returns const reference to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return const reference to the i-th element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! \c std::out_of_range exception by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reference at(size_type i) const
+ {
+ errh::throw_out_of_bounds(*this, i); // may throw
+ return *(this->begin() + i);
+ }
+
+ //! @pre <tt>i < size()</tt>
+ //!
+ //! @brief Returns reference to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return reference to the i-th element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reference operator[](size_type i)
+ {
+ // TODO: Remove bounds check? std::vector and std::array operator[] don't check.
+ errh::check_index(*this, i);
+ return *(this->begin() + i);
+ }
+
+ //! @pre <tt>i < size()</tt>
+ //!
+ //! @brief Returns const reference to the i-th element.
+ //!
+ //! @param i The element's index.
+ //!
+ //! @return const reference to the i-th element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reference operator[](size_type i) const
+ {
+ errh::check_index(*this, i);
+ return *(this->begin() + i);
+ }
+
+ //! @pre \c !empty()
+ //!
+ //! @brief Returns reference to the first element.
+ //!
+ //! @return reference to the first element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reference front()
+ {
+ errh::check_not_empty(*this);
+ return *(this->begin());
+ }
+
+ //! @pre \c !empty()
+ //!
+ //! @brief Returns const reference to the first element.
+ //!
+ //! @return const reference to the first element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reference front() const
+ {
+ errh::check_not_empty(*this);
+ return *(this->begin());
+ }
+
+ //! @pre \c !empty()
+ //!
+ //! @brief Returns reference to the last element.
+ //!
+ //! @return reference to the last element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reference back()
+ {
+ errh::check_not_empty(*this);
+ return *(this->end() - 1);
+ }
+
+ //! @pre \c !empty()
+ //!
+ //! @brief Returns const reference to the first element.
+ //!
+ //! @return const reference to the last element
+ //! from the beginning of the container.
+ //!
+ //! @par Throws
+ //! Nothing by default.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reference back() const
+ {
+ errh::check_not_empty(*this);
+ return *(this->end() - 1);
+ }
+
+ //! @brief Pointer such that <tt>[data(), data() + size())</tt> is a valid range.
+ //! For a non-empty vector <tt>data() == &front()</tt>.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ Value * data()
+ {
+ return boost::addressof(*(this->ptr()));
+ }
+
+ //! @brief Const pointer such that <tt>[data(), data() + size())</tt> is a valid range.
+ //! For a non-empty vector <tt>data() == &front()</tt>.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const Value * data() const
+ {
+ return boost::addressof(*(this->ptr()));
+ }
+
+
+ //! @brief Returns iterator to the first element.
+ //!
+ //! @return iterator to the first element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ iterator begin() { return this->ptr(); }
+
+ //! @brief Returns const iterator to the first element.
+ //!
+ //! @return const_iterator to the first element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator begin() const { return this->ptr(); }
+
+ //! @brief Returns const iterator to the first element.
+ //!
+ //! @return const_iterator to the first element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator cbegin() const { return this->ptr(); }
+
+ //! @brief Returns iterator to the one after the last element.
+ //!
+ //! @return iterator pointing to the one after the last element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ iterator end() { return this->begin() + m_size; }
+
+ //! @brief Returns const iterator to the one after the last element.
+ //!
+ //! @return const_iterator pointing to the one after the last element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator end() const { return this->begin() + m_size; }
+
+ //! @brief Returns const iterator to the one after the last element.
+ //!
+ //! @return const_iterator pointing to the one after the last element contained in the vector.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_iterator cend() const { return this->cbegin() + m_size; }
+
+ //! @brief Returns reverse iterator to the first element of the reversed container.
+ //!
+ //! @return reverse_iterator pointing to the beginning
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reverse_iterator rbegin() { return reverse_iterator(this->end()); }
+
+ //! @brief Returns const reverse iterator to the first element of the reversed container.
+ //!
+ //! @return const_reverse_iterator pointing to the beginning
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reverse_iterator rbegin() const { return reverse_iterator(this->end()); }
+
+ //! @brief Returns const reverse iterator to the first element of the reversed container.
+ //!
+ //! @return const_reverse_iterator pointing to the beginning
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reverse_iterator crbegin() const { return reverse_iterator(this->end()); }
+
+ //! @brief Returns reverse iterator to the one after the last element of the reversed container.
+ //!
+ //! @return reverse_iterator pointing to the one after the last element
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ reverse_iterator rend() { return reverse_iterator(this->begin()); }
+
+ //! @brief Returns const reverse iterator to the one after the last element of the reversed container.
+ //!
+ //! @return const_reverse_iterator pointing to the one after the last element
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reverse_iterator rend() const { return reverse_iterator(this->begin()); }
+
+ //! @brief Returns const reverse iterator to the one after the last element of the reversed container.
+ //!
+ //! @return const_reverse_iterator pointing to the one after the last element
+ //! of the reversed varray.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ const_reverse_iterator crend() const { return reverse_iterator(this->begin()); }
+
+ //! @brief Returns container's capacity.
+ //!
+ //! @return container's capacity.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ static size_type capacity() { return Capacity; }
+
+ //! @brief Returns container's capacity.
+ //!
+ //! @return container's capacity.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ static size_type max_size() { return Capacity; }
+
+ //! @brief Returns the number of stored elements.
+ //!
+ //! @return Number of elements contained in the container.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ size_type size() const { return m_size; }
+
+ //! @brief Queries if the container contains elements.
+ //!
+ //! @return true if the number of elements contained in the
+ //! container is equal to 0.
+ //!
+ //! @par Throws
+ //! Nothing.
+ //!
+ //! @par Complexity
+ //! Constant O(1).
+ bool empty() const { return 0 == m_size; }
+
+private:
+
+ // @par Throws
+ // Nothing.
+ // @par Complexity
+ // Linear O(N).
+ template <std::size_t C>
+ void move_ctor_dispatch(varray<value_type, C> & other, boost::true_type /*use_memop*/)
+ {
+ ::memcpy(this->data(), other.data(), sizeof(Value) * other.m_size);
+ m_size = other.m_size;
+ }
+
+ // @par Throws
+ // @li If boost::has_nothrow_move<Value>::value is true and Value's move constructor throws
+ // @li If boost::has_nothrow_move<Value>::value is false and Value's copy constructor throws.
+ // @par Complexity
+ // Linear O(N).
+ template <std::size_t C>
+ void move_ctor_dispatch(varray<value_type, C> & other, boost::false_type /*use_memop*/)
+ {
+ namespace sv = varray_detail;
+ sv::uninitialized_move_if_noexcept(other.begin(), other.end(), this->begin()); // may throw
+ m_size = other.m_size;
+ }
+
+ // @par Throws
+ // Nothing.
+ // @par Complexity
+ // Linear O(N).
+ template <std::size_t C>
+ void move_assign_dispatch(varray<value_type, C> & other, boost::true_type /*use_memop*/)
+ {
+ this->clear();
+
+ ::memcpy(this->data(), other.data(), sizeof(Value) * other.m_size);
+ std::swap(m_size, other.m_size);
+ }
+
+ // @par Throws
+ // @li If boost::has_nothrow_move<Value>::value is true and Value's move constructor or move assignment throws
+ // @li If boost::has_nothrow_move<Value>::value is false and Value's copy constructor or move assignment throws.
+ // @par Complexity
+ // Linear O(N).
+ template <std::size_t C>
+ void move_assign_dispatch(varray<value_type, C> & other, boost::false_type /*use_memop*/)
+ {
+ namespace sv = varray_detail;
+ if ( m_size <= static_cast<size_type>(other.size()) )
+ {
+ sv::move_if_noexcept(other.begin(), other.begin() + m_size, this->begin()); // may throw
+ // TODO - perform uninitialized_copy first?
+ sv::uninitialized_move_if_noexcept(other.begin() + m_size, other.end(), this->end()); // may throw
+ }
+ else
+ {
+ sv::move_if_noexcept(other.begin(), other.end(), this->begin()); // may throw
+ sv::destroy(this->begin() + other.size(), this->end());
+ }
+ m_size = other.size(); // update end
+ }
+
+ // @par Throws
+ // Nothing.
+ // @par Complexity
+ // Linear O(N).
+ template <std::size_t C>
+ void swap_dispatch(varray<value_type, C> & other, boost::true_type const& /*use_optimized_swap*/)
+ {
+ typedef typename
+ boost::mpl::if_c<
+ Capacity < C,
+ aligned_storage_type,
+ typename varray<value_type, C>::aligned_storage_type
+ >::type
+ storage_type;
+
+ storage_type temp;
+ Value * temp_ptr = reinterpret_cast<Value*>(temp.address());
+
+ ::memcpy(temp_ptr, this->data(), sizeof(Value) * this->size());
+ ::memcpy(this->data(), other.data(), sizeof(Value) * other.size());
+ ::memcpy(other.data(), temp_ptr, sizeof(Value) * this->size());
+
+ std::swap(m_size, other.m_size);
+ }
+
+ // @par Throws
+ // If Value's move constructor or move assignment throws
+ // but only if use_memop_in_swap_and_move is false_type - default.
+ // @par Complexity
+ // Linear O(N).
+ template <std::size_t C>
+ void swap_dispatch(varray<value_type, C> & other, boost::false_type const& /*use_optimized_swap*/)
+ {
+ namespace sv = varray_detail;
+
+ typedef typename
+ vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;
+
+ if ( this->size() < other.size() )
+ swap_dispatch_impl(this->begin(), this->end(), other.begin(), other.end(), use_memop_in_swap_and_move()); // may throw
+ else
+ swap_dispatch_impl(other.begin(), other.end(), this->begin(), this->end(), use_memop_in_swap_and_move()); // may throw
+ std::swap(m_size, other.m_size);
+ }
+
+ // @par Throws
+ // Nothing.
+ // @par Complexity
+ // Linear O(N).
+ void swap_dispatch_impl(iterator first_sm, iterator last_sm, iterator first_la, iterator last_la, boost::true_type const& /*use_memop*/)
+ {
+ //BOOST_ASSERT_MSG(std::distance(first_sm, last_sm) <= std::distance(first_la, last_la));
+
+ namespace sv = varray_detail;
+ for (; first_sm != last_sm ; ++first_sm, ++first_la)
+ {
+ boost::aligned_storage<
+ sizeof(value_type),
+ boost::alignment_of<value_type>::value
+ > temp_storage;
+ value_type * temp_ptr = reinterpret_cast<value_type*>(temp_storage.address());
+
+ ::memcpy(temp_ptr, boost::addressof(*first_sm), sizeof(value_type));
+ ::memcpy(boost::addressof(*first_sm), boost::addressof(*first_la), sizeof(value_type));
+ ::memcpy(boost::addressof(*first_la), temp_ptr, sizeof(value_type));
+ }
+
+ ::memcpy(first_sm, first_la, sizeof(value_type) * std::distance(first_la, last_la));
+ }
+
+ // @par Throws
+ // If Value's move constructor or move assignment throws.
+ // @par Complexity
+ // Linear O(N).
+ void swap_dispatch_impl(iterator first_sm, iterator last_sm, iterator first_la, iterator last_la, boost::false_type const& /*use_memop*/)
+ {
+ //BOOST_ASSERT_MSG(std::distance(first_sm, last_sm) <= std::distance(first_la, last_la));
+
+ namespace sv = varray_detail;
+ for (; first_sm != last_sm ; ++first_sm, ++first_la)
+ {
+ //boost::swap(*first_sm, *first_la); // may throw
+ value_type temp(boost::move(*first_sm)); // may throw
+ *first_sm = boost::move(*first_la); // may throw
+ *first_la = boost::move(temp); // may throw
+ }
+ sv::uninitialized_move(first_la, last_la, first_sm); // may throw
+ sv::destroy(first_la, last_la);
+ }
+
+ // insert
+
+ // @par Throws
+ // If Value's move constructor, move assignment throws
+ // or if Value's copy constructor or copy assignment throws.
+ // @par Complexity
+ // Linear O(N).
+ template <typename Iterator>
+ void insert_dispatch(iterator position, Iterator first, Iterator last, boost::random_access_traversal_tag const&)
+ {
+ BOOST_CONCEPT_ASSERT((boost_concepts::RandomAccessTraversal<Iterator>)); // Make sure you passed a RandomAccessIterator
+
+ errh::check_iterator_end_eq(*this, position);
+
+ typename boost::iterator_difference<Iterator>::type
+ count = std::distance(first, last);
+
+ errh::check_capacity(*this, m_size + count); // may throw
+
+ if ( position == this->end() )
+ {
+ namespace sv = varray_detail;
+
+ sv::uninitialized_copy(first, last, position); // may throw
+ m_size += count; // update end
+ }
+ else
+ {
+ this->insert_in_the_middle(position, first, last, count); // may throw
+ }
+ }
+
+ // @par Throws
+ // If Value's move constructor, move assignment throws
+ // or if Value's copy constructor or copy assignment throws.
+ // @par Complexity
+ // Linear O(N).
+ template <typename Iterator, typename Traversal>
+ void insert_dispatch(iterator position, Iterator first, Iterator last, Traversal const& /*not_random_access*/)
+ {
+ errh::check_iterator_end_eq(*this, position);
+
+ if ( position == this->end() )
+ {
+ namespace sv = varray_detail;
+
+ std::ptrdiff_t d = std::distance(position, this->begin() + Capacity);
+ std::size_t count = sv::uninitialized_copy_s(first, last, position, d); // may throw
+
+ errh::check_capacity(*this, count <= static_cast<std::size_t>(d) ? m_size + count : Capacity + 1); // may throw
+
+ m_size += count;
+ }
+ else
+ {
+ typename boost::iterator_difference<Iterator>::type
+ count = std::distance(first, last);
+
+ errh::check_capacity(*this, m_size + count); // may throw
+
+ this->insert_in_the_middle(position, first, last, count); // may throw
+ }
+ }
+
+ // @par Throws
+ // If Value's move constructor, move assignment throws
+ // or if Value's copy constructor or copy assignment throws.
+ // @par Complexity
+ // Linear O(N).
+ template <typename Iterator>
+ void insert_in_the_middle(iterator position, Iterator first, Iterator last, difference_type count)
+ {
+ namespace sv = varray_detail;
+
+ difference_type to_move = std::distance(position, this->end());
+
+ // TODO - should following lines check for exception and revert to the old size?
+
+ if ( count < to_move )
+ {
+ sv::uninitialized_move(this->end() - count, this->end(), this->end()); // may throw
+ m_size += count; // update end
+ sv::move_backward(position, position + to_move - count, this->end() - count); // may throw
+ sv::copy(first, last, position); // may throw
+ }
+ else
+ {
+ Iterator middle_iter = first;
+ std::advance(middle_iter, to_move);
+
+ sv::uninitialized_copy(middle_iter, last, this->end()); // may throw
+ m_size += count - to_move; // update end
+ sv::uninitialized_move(position, position + to_move, position + count); // may throw
+ m_size += to_move; // update end
+ sv::copy(first, middle_iter, position); // may throw
+ }
+ }
+
+ // assign
+
+ // @par Throws
+ // If Value's constructor or assignment taking dereferenced Iterator throws.
+ // @par Complexity
+ // Linear O(N).
+ template <typename Iterator>
+ void assign_dispatch(Iterator first, Iterator last, boost::random_access_traversal_tag const& /*not_random_access*/)
+ {
+ namespace sv = varray_detail;
+
+ typename boost::iterator_difference<Iterator>::type
+ s = std::distance(first, last);
+
+ errh::check_capacity(*this, s); // may throw
+
+ if ( m_size <= static_cast<size_type>(s) )
+ {
+ sv::copy(first, first + m_size, this->begin()); // may throw
+ // TODO - perform uninitialized_copy first?
+ sv::uninitialized_copy(first + m_size, last, this->end()); // may throw
+ }
+ else
+ {
+ sv::copy(first, last, this->begin()); // may throw
+ sv::destroy(this->begin() + s, this->end());
+ }
+ m_size = s; // update end
+ }
+
+ // @par Throws
+ // If Value's constructor or assignment taking dereferenced Iterator throws.
+ // @par Complexity
+ // Linear O(N).
+ template <typename Iterator, typename Traversal>
+ void assign_dispatch(Iterator first, Iterator last, Traversal const& /*not_random_access*/)
+ {
+ namespace sv = varray_detail;
+
+ size_type s = 0;
+ iterator it = this->begin();
+
+ for ( ; it != this->end() && first != last ; ++it, ++first, ++s )
+ *it = *first; // may throw
+
+ sv::destroy(it, this->end());
+
+ std::ptrdiff_t d = std::distance(it, this->begin() + Capacity);
+ std::size_t count = sv::uninitialized_copy_s(first, last, it, d); // may throw
+ s += count;
+
+ errh::check_capacity(*this, count <= static_cast<std::size_t>(d) ? s : Capacity + 1); // may throw
+
+ m_size = s; // update end
+ }
+
+ pointer ptr()
+ {
+ return pointer(static_cast<Value*>(m_storage.address()));
+ }
+
+ const_pointer ptr() const
+ {
+ return const_pointer(static_cast<const Value*>(m_storage.address()));
+ }
+
+ size_type m_size;
+ aligned_storage_type m_storage;
+};
+
+#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
+
+template<typename Value>
+class varray<Value, 0>
+{
+ typedef varray_detail::varray_traits<Value, 0> vt;
+ typedef varray_detail::checker<varray> errh;
+
+public:
+ typedef typename vt::value_type value_type;
+ typedef typename vt::size_type size_type;
+ typedef typename vt::difference_type difference_type;
+ typedef typename vt::pointer pointer;
+ typedef typename vt::const_pointer const_pointer;
+ typedef typename vt::reference reference;
+ typedef typename vt::const_reference const_reference;
+
+ typedef pointer iterator;
+ typedef const_pointer const_iterator;
+ typedef boost::reverse_iterator<iterator> reverse_iterator;
+ typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
+
+ // nothrow
+ varray() {}
+
+ // strong
+ explicit varray(size_type count)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // strong
+ varray(size_type count, value_type const&)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // strong
+ varray(varray const& /*other*/)
+ {
+ //errh::check_capacity(*this, count);
+ }
+
+ // strong
+ template <std::size_t C>
+ varray(varray<value_type, C> const& other)
+ {
+ errh::check_capacity(*this, other.size()); // may throw
+ }
+
+ // strong
+ template <typename Iterator>
+ varray(Iterator first, Iterator last)
+ {
+ errh::check_capacity(*this, std::distance(first, last)); // may throw
+ }
+
+ // basic
+ varray & operator=(varray const& /*other*/)
+ {
+ //errh::check_capacity(*this, other.size());
+ return *this;
+ }
+
+ // basic
+ template <size_t C>
+ varray & operator=(varray<value_type, C> const& other)
+ {
+ errh::check_capacity(*this, other.size()); // may throw
+ return *this;
+ }
+
+ // nothrow
+ ~varray() {}
+
+ // strong
+ void resize(size_type count)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // strong
+ void resize(size_type count, value_type const&)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+
+ // nothrow
+ void reserve(size_type count)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // strong
+ void push_back(value_type const&)
+ {
+ errh::check_capacity(*this, 1); // may throw
+ }
+
+ // nothrow
+ void pop_back()
+ {
+ errh::check_not_empty(*this);
+ }
+
+ // basic
+ void insert(iterator position, value_type const&)
+ {
+ errh::check_iterator_end_eq(*this, position);
+ errh::check_capacity(*this, 1); // may throw
+ }
+
+ // basic
+ void insert(iterator position, size_type count, value_type const&)
+ {
+ errh::check_iterator_end_eq(*this, position);
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // basic
+ template <typename Iterator>
+ void insert(iterator, Iterator first, Iterator last)
+ {
+ // TODO - add MPL_ASSERT, check if Iterator is really an iterator
+ typedef typename boost::iterator_traversal<Iterator>::type traversal;
+ errh::check_capacity(*this, std::distance(first, last)); // may throw
+ }
+
+ // basic
+ void erase(iterator position)
+ {
+ errh::check_iterator_end_neq(*this, position);
+ }
+
+ // basic
+ void erase(iterator first, iterator last)
+ {
+ errh::check_iterator_end_eq(*this, first);
+ errh::check_iterator_end_eq(*this, last);
+
+ //BOOST_ASSERT_MSG(0 <= n, "invalid range");
+ }
+
+ // basic
+ template <typename Iterator>
+ void assign(Iterator first, Iterator last)
+ {
+ // TODO - add MPL_ASSERT, check if Iterator is really an iterator
+ typedef typename boost::iterator_traversal<Iterator>::type traversal;
+ errh::check_capacity(*this, std::distance(first, last)); // may throw
+ }
+
+ // basic
+ void assign(size_type count, value_type const&)
+ {
+ errh::check_capacity(*this, count); // may throw
+ }
+
+ // nothrow
+ void clear() {}
+
+ // strong
+ reference at(size_type i)
+ {
+ errh::throw_out_of_bounds(*this, i); // may throw
+ return *(this->begin() + i);
+ }
+
+ // strong
+ const_reference at(size_type i) const
+ {
+ errh::throw_out_of_bounds(*this, i); // may throw
+ return *(this->begin() + i);
+ }
+
+ // nothrow
+ reference operator[](size_type i)
+ {
+ errh::check_index(*this, i);
+ return *(this->begin() + i);
+ }
+
+ // nothrow
+ const_reference operator[](size_type i) const
+ {
+ errh::check_index(*this, i);
+ return *(this->begin() + i);
+ }
+
+ // nothrow
+ reference front()
+ {
+ errh::check_not_empty(*this);
+ return *(this->begin());
+ }
+
+ // nothrow
+ const_reference front() const
+ {
+ errh::check_not_empty(*this);
+ return *(this->begin());
+ }
+
+ // nothrow
+ reference back()
+ {
+ errh::check_not_empty(*this);
+ return *(this->end() - 1);
+ }
+
+ // nothrow
+ const_reference back() const
+ {
+ errh::check_not_empty(*this);
+ return *(this->end() - 1);
+ }
+
+ // nothrow
+ Value * data() { return boost::addressof(*(this->ptr())); }
+ const Value * data() const { return boost::addressof(*(this->ptr())); }
+
+ // nothrow
+ iterator begin() { return this->ptr(); }
+ const_iterator begin() const { return this->ptr(); }
+ const_iterator cbegin() const { return this->ptr(); }
+ iterator end() { return this->begin(); }
+ const_iterator end() const { return this->begin(); }
+ const_iterator cend() const { return this->cbegin(); }
+ // nothrow
+ reverse_iterator rbegin() { return reverse_iterator(this->end()); }
+ const_reverse_iterator rbegin() const { return reverse_iterator(this->end()); }
+ const_reverse_iterator crbegin() const { return reverse_iterator(this->end()); }
+ reverse_iterator rend() { return reverse_iterator(this->begin()); }
+ const_reverse_iterator rend() const { return reverse_iterator(this->begin()); }
+ const_reverse_iterator crend() const { return reverse_iterator(this->begin()); }
+
+ // nothrow
+ size_type capacity() const { return 0; }
+ size_type max_size() const { return 0; }
+ size_type size() const { return 0; }
+ bool empty() const { return true; }
+
+private:
+ pointer ptr()
+ {
+ return pointer(reinterpret_cast<Value*>(this));
+ }
+
+ const_pointer ptr() const
+ {
+ return const_pointer(reinterpret_cast<const Value*>(this));
+ }
+};
+
+#endif // !BOOST_CONTAINER_DOXYGEN_INVOKED
+
+//! @brief Checks if contents of two varrays are equal.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if containers have the same size and elements in both containers are equal.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator== (varray<V, C1> const& x, varray<V, C2> const& y)
+{
+ return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin());
+}
+
+//! @brief Checks if contents of two varrays are not equal.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if containers have different size or elements in both containers are not equal.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator!= (varray<V, C1> const& x, varray<V, C2> const& y)
+{
+ return !(x==y);
+}
+
+//! @brief Lexicographically compares varrays.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if x compares lexicographically less than y.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator< (varray<V, C1> const& x, varray<V, C2> const& y)
+{
+ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
+}
+
+//! @brief Lexicographically compares varrays.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if y compares lexicographically less than x.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator> (varray<V, C1> const& x, varray<V, C2> const& y)
+{
+ return y<x;
+}
+
+//! @brief Lexicographically compares varrays.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if y don't compare lexicographically less than x.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator<= (varray<V, C1> const& x, varray<V, C2> const& y)
+{
+ return !(y<x);
+}
+
+//! @brief Lexicographically compares varrays.
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @return \c true if x don't compare lexicographically less than y.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+bool operator>= (varray<V, C1> const& x, varray<V, C2> const& y)
+{
+ return !(x<y);
+}
+
+//! @brief Swaps contents of two varrays.
+//!
+//! This function calls varray::swap().
+//!
+//! @ingroup varray_non_member
+//!
+//! @param x The first varray.
+//! @param y The second varray.
+//!
+//! @par Complexity
+//! Linear O(N).
+template<typename V, std::size_t C1, std::size_t C2>
+inline void swap(varray<V, C1> & x, varray<V, C2> & y)
+{
+ x.swap(y);
+}
+
+}}}} // namespace boost::geometry::index::detail
+
+// TODO - REMOVE/CHANGE
+#include <boost/container/detail/config_end.hpp>
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_HPP
diff --git a/boost/geometry/index/detail/varray_detail.hpp b/boost/geometry/index/detail/varray_detail.hpp
new file mode 100644
index 000000000..4e16cc97d
--- /dev/null
+++ b/boost/geometry/index/detail/varray_detail.hpp
@@ -0,0 +1,714 @@
+// Boost.Geometry
+//
+// varray details
+//
+// Copyright (c) 2012-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2013 Andrew Hundt.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_HPP
+
+#include <cstddef>
+#include <cstring>
+#include <memory>
+#include <limits>
+
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/int.hpp>
+
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/type_traits/has_trivial_assign.hpp>
+#include <boost/type_traits/has_trivial_copy.hpp>
+#include <boost/type_traits/has_trivial_constructor.hpp>
+#include <boost/type_traits/has_trivial_destructor.hpp>
+//#include <boost/type_traits/has_nothrow_constructor.hpp>
+//#include <boost/type_traits/has_nothrow_copy.hpp>
+//#include <boost/type_traits/has_nothrow_assign.hpp>
+//#include <boost/type_traits/has_nothrow_destructor.hpp>
+
+#include <boost/detail/no_exceptions_support.hpp>
+#include <boost/config.hpp>
+#include <boost/move/move.hpp>
+#include <boost/utility/addressof.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+
+// TODO - move vectors iterators optimization to the other, optional file instead of checking defines?
+
+#if defined(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)
+#include <vector>
+#include <boost/container/vector.hpp>
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION && !BOOST_NO_EXCEPTIONS
+
+namespace boost { namespace geometry { namespace index { namespace detail { namespace varray_detail {
+
+template <typename I>
+struct are_elements_contiguous : boost::is_pointer<I>
+{};
+
+// EXPERIMENTAL - not finished
+// Conditional setup - mark vector iterators defined in known implementations
+// as iterators pointing to contiguous ranges
+
+#if defined(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION) && !defined(BOOST_NO_EXCEPTIONS)
+
+template <typename Pointer>
+struct are_elements_contiguous<
+ boost::container::container_detail::vector_const_iterator<Pointer>
+> : boost::true_type
+{};
+
+template <typename Pointer>
+struct are_elements_contiguous<
+ boost::container::container_detail::vector_iterator<Pointer>
+> : boost::true_type
+{};
+
+#if defined(BOOST_DINKUMWARE_STDLIB)
+
+template <typename T>
+struct are_elements_contiguous<
+ std::_Vector_const_iterator<T>
+> : boost::true_type
+{};
+
+template <typename T>
+struct are_elements_contiguous<
+ std::_Vector_iterator<T>
+> : boost::true_type
+{};
+
+#elif defined(BOOST_GNU_STDLIB)
+
+template <typename P, typename T, typename A>
+struct are_elements_contiguous<
+ __gnu_cxx::__normal_iterator<P, std::vector<T, A> >
+> : boost::true_type
+{};
+
+#elif defined(_LIBCPP_VERSION)
+
+// TODO - test it first
+//template <typename P>
+//struct are_elements_contiguous<
+// __wrap_iter<P>
+//> : boost::true_type
+//{};
+
+#else // OTHER_STDLIB
+
+// TODO - add other iterators implementations
+
+#endif // STDLIB
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION && !BOOST_NO_EXCEPTIONS
+
+// True if iterator values are the same and both iterators points to the ranges of contiguous elements
+
+template <typename I, typename O>
+struct are_corresponding :
+ ::boost::mpl::and_<
+ ::boost::is_same<
+ ::boost::remove_const<
+ typename ::boost::iterator_value<I>::type
+ >,
+ ::boost::remove_const<
+ typename ::boost::iterator_value<O>::type
+ >
+ >,
+ are_elements_contiguous<I>,
+ are_elements_contiguous<O>
+ >
+{};
+
+template <typename I, typename V>
+struct is_corresponding_value :
+ ::boost::is_same<
+ ::boost::remove_const<
+ typename ::boost::iterator_value<I>::type
+ >,
+ ::boost::remove_const<V>
+ >
+{};
+
+// destroy(I, I)
+
+template <typename I>
+void destroy_dispatch(I /*first*/, I /*last*/,
+ boost::true_type const& /*has_trivial_destructor*/)
+{}
+
+template <typename I>
+void destroy_dispatch(I first, I last,
+ boost::false_type const& /*has_trivial_destructor*/)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ for ( ; first != last ; ++first )
+ first->~value_type();
+}
+
+template <typename I>
+void destroy(I first, I last)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ destroy_dispatch(first, last, has_trivial_destructor<value_type>());
+}
+
+// destroy(I)
+
+template <typename I>
+void destroy_dispatch(I /*pos*/,
+ boost::true_type const& /*has_trivial_destructor*/)
+{}
+
+template <typename I>
+void destroy_dispatch(I pos,
+ boost::false_type const& /*has_trivial_destructor*/)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ pos->~value_type();
+}
+
+template <typename I>
+void destroy(I pos)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ destroy_dispatch(pos, has_trivial_destructor<value_type>());
+}
+
+// copy(I, I, O)
+
+template <typename I, typename O>
+inline O copy_dispatch(I first, I last, O dst,
+ boost::mpl::bool_<true> const& /*use_memmove*/)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ typename boost::iterator_difference<I>::type d = std::distance(first, last);
+
+ ::memmove(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
+ return dst + d;
+}
+
+template <typename I, typename O>
+inline O copy_dispatch(I first, I last, O dst,
+ boost::mpl::bool_<false> const& /*use_memmove*/)
+{
+ return std::copy(first, last, dst); // may throw
+}
+
+template <typename I, typename O>
+inline O copy(I first, I last, O dst)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ are_corresponding<I, O>,
+ ::boost::has_trivial_assign<
+ typename ::boost::iterator_value<O>::type
+ >
+ >::type
+ use_memmove;
+
+ return copy_dispatch(first, last, dst, use_memmove()); // may throw
+}
+
+// uninitialized_copy(I, I, O)
+
+template <typename I, typename O>
+inline
+O uninitialized_copy_dispatch(I first, I last, O dst,
+ boost::mpl::bool_<true> const& /*use_memcpy*/)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ typename boost::iterator_difference<I>::type d = std::distance(first, last);
+
+ ::memcpy(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
+ return dst + d;
+}
+
+template <typename I, typename F>
+inline
+F uninitialized_copy_dispatch(I first, I last, F dst,
+ boost::mpl::bool_<false> const& /*use_memcpy*/)
+{
+ return std::uninitialized_copy(first, last, dst); // may throw
+}
+
+template <typename I, typename F>
+inline
+F uninitialized_copy(I first, I last, F dst)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ are_corresponding<I, F>,
+ ::boost::has_trivial_copy<
+ typename ::boost::iterator_value<F>::type
+ >
+ >::type
+ use_memcpy;
+
+ return uninitialized_copy_dispatch(first, last, dst, use_memcpy()); // may throw
+}
+
+// uninitialized_move(I, I, O)
+
+template <typename I, typename O>
+inline
+O uninitialized_move_dispatch(I first, I last, O dst,
+ boost::mpl::bool_<true> const& /*use_memcpy*/)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ typename boost::iterator_difference<I>::type d = std::distance(first, last);
+
+ ::memcpy(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
+ return dst + d;
+}
+
+template <typename I, typename O>
+inline
+O uninitialized_move_dispatch(I first, I last, O dst,
+ boost::mpl::bool_<false> const& /*use_memcpy*/)
+{
+ //return boost::uninitialized_move(first, last, dst); // may throw
+
+ O o = dst;
+
+ BOOST_TRY
+ {
+ typedef typename std::iterator_traits<O>::value_type value_type;
+ for (; first != last; ++first, ++o )
+ new (boost::addressof(*o)) value_type(boost::move(*first));
+ }
+ BOOST_CATCH(...)
+ {
+ destroy(dst, o);
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+
+ return dst;
+}
+
+template <typename I, typename O>
+inline
+O uninitialized_move(I first, I last, O dst)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ are_corresponding<I, O>,
+ ::boost::has_trivial_copy<
+ typename ::boost::iterator_value<O>::type
+ >
+ >::type
+ use_memcpy;
+
+ return uninitialized_move_dispatch(first, last, dst, use_memcpy()); // may throw
+}
+
+// TODO - move uses memmove - implement 2nd version using memcpy?
+
+// move(I, I, O)
+
+template <typename I, typename O>
+inline
+O move_dispatch(I first, I last, O dst,
+ boost::mpl::bool_<true> const& /*use_memmove*/)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ typename boost::iterator_difference<I>::type d = std::distance(first, last);
+
+ ::memmove(boost::addressof(*dst), boost::addressof(*first), sizeof(value_type) * d);
+ return dst + d;
+}
+
+template <typename I, typename O>
+inline
+O move_dispatch(I first, I last, O dst,
+ boost::mpl::bool_<false> const& /*use_memmove*/)
+{
+ return boost::move(first, last, dst); // may throw
+}
+
+template <typename I, typename O>
+inline
+O move(I first, I last, O dst)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ are_corresponding<I, O>,
+ ::boost::has_trivial_assign<
+ typename ::boost::iterator_value<O>::type
+ >
+ >::type
+ use_memmove;
+
+ return move_dispatch(first, last, dst, use_memmove()); // may throw
+}
+
+// move_backward(BDI, BDI, BDO)
+
+template <typename BDI, typename BDO>
+inline
+BDO move_backward_dispatch(BDI first, BDI last, BDO dst,
+ boost::mpl::bool_<true> const& /*use_memmove*/)
+{
+ typedef typename boost::iterator_value<BDI>::type value_type;
+ typename boost::iterator_difference<BDI>::type d = std::distance(first, last);
+
+ BDO foo(dst - d);
+ ::memmove(boost::addressof(*foo), boost::addressof(*first), sizeof(value_type) * d);
+ return foo;
+}
+
+template <typename BDI, typename BDO>
+inline
+BDO move_backward_dispatch(BDI first, BDI last, BDO dst,
+ boost::mpl::bool_<false> const& /*use_memmove*/)
+{
+ return boost::move_backward(first, last, dst); // may throw
+}
+
+template <typename BDI, typename BDO>
+inline
+BDO move_backward(BDI first, BDI last, BDO dst)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ are_corresponding<BDI, BDO>,
+ ::boost::has_trivial_assign<
+ typename ::boost::iterator_value<BDO>::type
+ >
+ >::type
+ use_memmove;
+
+ return move_backward_dispatch(first, last, dst, use_memmove()); // may throw
+}
+
+template <typename T>
+struct has_nothrow_move : public
+ ::boost::mpl::or_<
+ boost::mpl::bool_<
+ ::boost::has_nothrow_move<
+ typename ::boost::remove_const<T>::type
+ >::value
+ >,
+ boost::mpl::bool_<
+ ::boost::has_nothrow_move<T>::value
+ >
+ >
+{};
+
+// uninitialized_move_if_noexcept(I, I, O)
+
+template <typename I, typename O>
+inline
+O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<true> const& /*use_move*/)
+{ return uninitialized_move(first, last, dst); }
+
+template <typename I, typename O>
+inline
+O uninitialized_move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<false> const& /*use_move*/)
+{ return uninitialized_copy(first, last, dst); }
+
+template <typename I, typename O>
+inline
+O uninitialized_move_if_noexcept(I first, I last, O dst)
+{
+ typedef typename has_nothrow_move<
+ typename ::boost::iterator_value<O>::type
+ >::type use_move;
+
+ return uninitialized_move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw
+}
+
+// move_if_noexcept(I, I, O)
+
+template <typename I, typename O>
+inline
+O move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<true> const& /*use_move*/)
+{ return move(first, last, dst); }
+
+template <typename I, typename O>
+inline
+O move_if_noexcept_dispatch(I first, I last, O dst, boost::mpl::bool_<false> const& /*use_move*/)
+{ return copy(first, last, dst); }
+
+template <typename I, typename O>
+inline
+O move_if_noexcept(I first, I last, O dst)
+{
+ typedef typename has_nothrow_move<
+ typename ::boost::iterator_value<O>::type
+ >::type use_move;
+
+ return move_if_noexcept_dispatch(first, last, dst, use_move()); // may throw
+}
+
+// uninitialized_fill(I, I)
+
+template <typename I>
+inline
+void uninitialized_fill_dispatch(I /*first*/, I /*last*/,
+ boost::true_type const& /*has_trivial_constructor*/,
+ boost::true_type const& /*disable_trivial_init*/)
+{}
+
+template <typename I>
+inline
+void uninitialized_fill_dispatch(I first, I last,
+ boost::true_type const& /*has_trivial_constructor*/,
+ boost::false_type const& /*disable_trivial_init*/)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ for ( ; first != last ; ++first )
+ new (boost::addressof(*first)) value_type();
+}
+
+template <typename I, typename DisableTrivialInit>
+inline
+void uninitialized_fill_dispatch(I first, I last,
+ boost::false_type const& /*has_trivial_constructor*/,
+ DisableTrivialInit const& /*not_used*/)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ I it = first;
+
+ BOOST_TRY
+ {
+ for ( ; it != last ; ++it )
+ new (boost::addressof(*it)) value_type(); // may throw
+ }
+ BOOST_CATCH(...)
+ {
+ destroy(first, it);
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+}
+
+template <typename I, typename DisableTrivialInit>
+inline
+void uninitialized_fill(I first, I last, DisableTrivialInit const& disable_trivial_init)
+{
+ typedef typename boost::iterator_value<I>::type value_type;
+ uninitialized_fill_dispatch(first, last, boost::has_trivial_constructor<value_type>(), disable_trivial_init); // may throw
+}
+
+// construct(I)
+
+template <typename I>
+inline
+void construct_dispatch(boost::mpl::bool_<true> const& /*dont_init*/, I /*pos*/)
+{}
+
+template <typename I>
+inline
+void construct_dispatch(boost::mpl::bool_<false> const& /*dont_init*/, I pos)
+{
+ typedef typename ::boost::iterator_value<I>::type value_type;
+ new (static_cast<void*>(::boost::addressof(*pos))) value_type(); // may throw
+}
+
+template <typename DisableTrivialInit, typename I>
+inline
+void construct(DisableTrivialInit const&, I pos)
+{
+ typedef typename ::boost::iterator_value<I>::type value_type;
+ typedef typename ::boost::mpl::and_<
+ boost::has_trivial_constructor<value_type>,
+ DisableTrivialInit
+ >::type dont_init;
+
+ construct_dispatch(dont_init(), pos); // may throw
+}
+
+// construct(I, V)
+
+template <typename I, typename V>
+inline
+void construct_dispatch(I pos, V const& v,
+ boost::mpl::bool_<true> const& /*use_memcpy*/)
+{
+ ::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));
+}
+
+template <typename I, typename P>
+inline
+void construct_dispatch(I pos, P const& p,
+ boost::mpl::bool_<false> const& /*use_memcpy*/)
+{
+ typedef typename boost::iterator_value<I>::type V;
+ new (static_cast<void*>(boost::addressof(*pos))) V(p); // may throw
+}
+
+template <typename DisableTrivialInit, typename I, typename P>
+inline
+void construct(DisableTrivialInit const&,
+ I pos, P const& p)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ is_corresponding_value<I, P>,
+ ::boost::has_trivial_copy<P>
+ >::type
+ use_memcpy;
+
+ construct_dispatch(pos, p, use_memcpy()); // may throw
+}
+
+// Needed by push_back(V &&)
+
+template <typename DisableTrivialInit, typename I, typename P>
+inline
+void construct(DisableTrivialInit const&, I pos, BOOST_RV_REF(P) p)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ is_corresponding_value<I, P>,
+ ::boost::has_trivial_copy<P>
+ >::type
+ use_memcpy;
+
+ typedef typename boost::iterator_value<I>::type V;
+ new (static_cast<void*>(boost::addressof(*pos))) V(::boost::move(p)); // may throw
+}
+
+// Needed by emplace_back() and emplace()
+
+#if !defined(BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE)
+#if !defined(BOOST_NO_VARIADIC_TEMPLATES)
+
+template <typename DisableTrivialInit, typename I, class ...Args>
+inline
+void construct(DisableTrivialInit const&,
+ I pos,
+ BOOST_FWD_REF(Args) ...args)
+{
+ typedef typename boost::iterator_value<I>::type V;
+ new (static_cast<void*>(boost::addressof(*pos))) V(::boost::forward<Args>(args)...); // may throw
+}
+
+#else // !BOOST_NO_VARIADIC_TEMPLATES
+
+// BOOST_NO_RVALUE_REFERENCES -> P0 const& p0
+// !BOOST_NO_RVALUE_REFERENCES -> P0 && p0
+// which means that version with one parameter may take V const& v
+
+#define BOOST_PP_LOCAL_MACRO(n) \
+template <typename DisableTrivialInit, typename I, typename P BOOST_PP_ENUM_TRAILING_PARAMS(n, typename P) > \
+inline \
+void construct(DisableTrivialInit const&, \
+ I pos, \
+ BOOST_CONTAINER_PP_PARAM(P, p) \
+ BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
+{ \
+ typedef typename boost::iterator_value<I>::type V; \
+ new \
+ (static_cast<void*>(boost::addressof(*pos))) \
+ V(p, BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); /*may throw*/ \
+} \
+//
+#define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
+#include BOOST_PP_LOCAL_ITERATE()
+
+#endif // !BOOST_NO_VARIADIC_TEMPLATES
+#endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE
+
+// assign(I, V)
+
+template <typename I, typename V>
+inline
+void assign_dispatch(I pos, V const& v,
+ boost::mpl::bool_<true> const& /*use_memcpy*/)
+{
+ ::memcpy(boost::addressof(*pos), boost::addressof(v), sizeof(V));
+}
+
+template <typename I, typename V>
+inline
+void assign_dispatch(I pos, V const& v,
+ boost::mpl::bool_<false> const& /*use_memcpy*/)
+{
+ *pos = v; // may throw
+}
+
+template <typename I, typename V>
+inline
+void assign(I pos, V const& v)
+{
+ typedef typename
+ ::boost::mpl::and_<
+ is_corresponding_value<I, V>,
+ ::boost::has_trivial_assign<V>
+ >::type
+ use_memcpy;
+
+ assign_dispatch(pos, v, use_memcpy()); // may throw
+}
+
+template <typename I, typename V>
+inline
+void assign(I pos, BOOST_RV_REF(V) v)
+{
+ *pos = boost::move(v); // may throw
+}
+
+
+// uninitialized_copy_s
+
+template <typename I, typename F>
+inline std::size_t uninitialized_copy_s(I first, I last, F dest, std::size_t max_count)
+{
+ std::size_t count = 0;
+ F it = dest;
+
+ BOOST_TRY
+ {
+ for ( ; first != last ; ++it, ++first, ++count )
+ {
+ if ( max_count <= count )
+ return (std::numeric_limits<std::size_t>::max)();
+
+ // dummy 0 as DisableTrivialInit
+ construct(0, it, *first); // may throw
+ }
+ }
+ BOOST_CATCH(...)
+ {
+ destroy(dest, it);
+ BOOST_RETHROW;
+ }
+ BOOST_CATCH_END
+
+ return count;
+}
+
+// scoped_destructor
+
+template<class T>
+class scoped_destructor
+{
+public:
+ scoped_destructor(T * ptr) : m_ptr(ptr) {}
+
+ ~scoped_destructor()
+ {
+ if(m_ptr)
+ destroy(m_ptr);
+ }
+
+ void release() { m_ptr = 0; }
+
+private:
+ T * m_ptr;
+};
+
+}}}}} // namespace boost::geometry::index::detail::varray_detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_HPP
diff --git a/boost/geometry/index/distance_predicates.hpp b/boost/geometry/index/distance_predicates.hpp
new file mode 100644
index 000000000..59b32af47
--- /dev/null
+++ b/boost/geometry/index/distance_predicates.hpp
@@ -0,0 +1,204 @@
+// Boost.Geometry Index
+//
+// Spatial index distance predicates, calculators and checkers used in nearest neighbor query
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_DISTANCE_PREDICATES_HPP
+#define BOOST_GEOMETRY_INDEX_DISTANCE_PREDICATES_HPP
+
+#include <boost/geometry/index/detail/distance_predicates.hpp>
+
+/*!
+\defgroup nearest_relations Nearest relations (boost::geometry::index::)
+*/
+
+namespace boost { namespace geometry { namespace index {
+
+// relations generators
+
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+
+/*!
+\brief Generate to_nearest() relationship.
+
+Generate a nearest query Point and Value's Indexable relationship while calculating
+distances. This function may be used to define that knn query should calculate distances
+as smallest as possible between query Point and Indexable's points. In other words it
+should be the distance to the nearest Indexable's point. This function may be also used
+to define distances bounds which indicates that Indexable's nearest point should be
+closer or further than value v. This is default relation.
+
+\ingroup nearest_relations
+
+\tparam T Type of wrapped object. This may be a Point for PointRelation or CoordinateType for
+ MinRelation or MaxRelation
+
+\param v Point or distance value.
+*/
+template <typename T>
+detail::to_nearest<T> to_nearest(T const& v)
+{
+ return detail::to_nearest<T>(v);
+}
+
+/*!
+\brief Generate to_centroid() relationship.
+
+Generate a nearest query Point and Value's Indexable relationship while calculating
+distances. This function may be used to define that knn query should calculate distances
+between query Point and Indexable's centroid. This function may be also used
+to define distances bounds which indicates that Indexable's centroid should be
+closer or further than value v.
+
+\ingroup nearest_relations
+
+\tparam T Type of wrapped object. This may be a Point for PointRelation or some CoordinateType for
+ MinRelation or MaxRelation
+
+\param v Point or distance value.
+*/
+template <typename T>
+detail::to_centroid<T> to_centroid(T const& v)
+{
+ return detail::to_centroid<T>(v);
+}
+
+/*!
+\brief Generate to_furthest() relationship.
+
+Generate a nearest query Point and Value's Indexable relationship while calculating
+distances. This function may be used to define that knn query should calculate distances
+as biggest as possible between query Point and Indexable's points. In other words it
+should be the distance to the furthest Indexable's point. This function may be also used
+to define distances bounds which indicates that Indexable's furthest point should be
+closer or further than value v.
+
+\ingroup nearest_relations
+
+\tparam T Type of wrapped object. This may be a Point for PointRelation or some CoordinateType for
+ MinRelation or MaxRelation
+
+\param v Point or distance value.
+*/
+template <typename T>
+detail::to_furthest<T> to_furthest(T const& v)
+{
+ return detail::to_furthest<T>(v);
+}
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+
+// distance predicates generators
+
+/*!
+\brief Generate unbounded() distance predicate.
+
+Generate a distance predicate. This defines distances bounds which are used by knn query.
+This function indicates that there is no distance bounds and Values should be returned
+if distances between Point and Indexable are the smallest. Distance calculation is defined
+by PointRelation. This is default nearest predicate.
+
+\ingroup distance_predicates
+
+\tparam PointRelation PointRelation type.
+
+\param pr The point relation. This may be generated by \c index::to_nearest(),
+ \c index::to_centroid() or \c index::to_furthest() with \c Point passed as a parameter.
+*/
+//template <typename PointRelation>
+//inline detail::unbounded<PointRelation>
+//unbounded(PointRelation const& pr)
+//{
+// return detail::unbounded<PointRelation>(pr);
+//}
+
+/*!
+\brief Generate min_bounded() distance predicate.
+
+Generate a distance predicate. This defines distances bounds which are used by knn query.
+This function indicates that Values should be returned only if distances between Point and
+Indexable are greater or equal to some min_distance passed in MinRelation. Check for closest Value is
+defined by PointRelation. So it is possible e.g. to return Values with centroids closest to some
+Point but only if nearest points are further than some distance.
+
+\ingroup distance_predicates
+
+\tparam PointRelation PointRelation type.
+\tparam MinRelation MinRelation type.
+
+\param pr The point relation. This may be generated by \c to_nearest(),
+ \c to_centroid() or \c to_furthest() with \c Point passed as a parameter.
+\param minr The minimum bound relation. This may be generated by \c to_nearest(),
+ \c to_centroid() or \c to_furthest() with distance value passed as a parameter.
+*/
+//template <typename PointRelation, typename MinRelation>
+//inline detail::min_bounded<PointRelation, MinRelation>
+//min_bounded(PointRelation const& pr, MinRelation const& minr)
+//{
+// return detail::min_bounded<PointRelation, MinRelation>(pr, minr);
+//}
+
+/*!
+\brief Generate max_bounded() distance predicate.
+
+Generate a distance predicate. This defines distances bounds which are used by knn query.
+This function indicates that Values should be returned only if distances between Point and
+Indexable are lesser or equal to some max_distance passed in MaxRelation. Check for closest Value is
+defined by PointRelation. So it is possible e.g. to return Values with centroids closest to some
+Point but only if nearest points are closer than some distance.
+
+\ingroup distance_predicates
+
+\tparam PointRelation PointRelation type.
+\tparam MaxRelation MaxRelation type.
+
+\param pr The point relation. This may be generated by \c to_nearest(),
+ \c to_centroid() or \c to_furthest() with \c Point passed as a parameter.
+\param maxr The maximum bound relation. This may be generated by \c to_nearest(),
+ \c to_centroid() or \c to_furthest() with distance value passed as a parameter.
+*/
+//template <typename PointRelation, typename MaxRelation>
+//inline detail::max_bounded<PointRelation, MaxRelation>
+//max_bounded(PointRelation const& pr, MaxRelation const& maxr)
+//{
+// return detail::max_bounded<PointRelation, MaxRelation>(pr, maxr);
+//}
+
+/*!
+\brief Generate bounded() distance predicate.
+
+Generate a distance predicate. This defines distances bounds which are used by knn query.
+This function indicates that Values should be returned only if distances between Point and
+Indexable are greater or equal to some min_distance passed in MinRelation and lesser or equal to
+some max_distance passed in MaxRelation. Check for closest Value is defined by PointRelation.
+So it is possible e.g. to return Values with centroids closest to some Point but only if nearest
+points are further than some distance and closer than some other distance.
+
+\ingroup distance_predicates
+
+\tparam PointRelation PointRelation type.
+\tparam MinRelation MinRelation type.
+\tparam MaxRelation MaxRelation type.
+
+\param pr The point relation. This may be generated by \c to_nearest(),
+ \c to_centroid() or \c to_furthest() with \c Point passed as a parameter.
+\param minr The minimum bound relation. This may be generated by \c to_nearest(),
+ \c to_centroid() or \c to_furthest() with distance value passed as a parameter.
+\param maxr The maximum bound relation. This may be generated by \c to_nearest(),
+ \c to_centroid() or \c to_furthest() with distance value passed as a parameter.
+*/
+//template <typename PointRelation, typename MinRelation, typename MaxRelation>
+//inline detail::bounded<PointRelation, MinRelation, MaxRelation>
+//bounded(PointRelation const& pr, MinRelation const& minr, MaxRelation const& maxr)
+//{
+// return detail::bounded<PointRelation, MinRelation, MaxRelation>(pr, minr, maxr);
+//}
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_DISTANCE_PREDICATES_HPP
diff --git a/boost/geometry/index/equal_to.hpp b/boost/geometry/index/equal_to.hpp
new file mode 100644
index 000000000..8ce5074c3
--- /dev/null
+++ b/boost/geometry/index/equal_to.hpp
@@ -0,0 +1,221 @@
+// Boost.Geometry Index
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_EQUAL_TO_HPP
+#define BOOST_GEOMETRY_INDEX_EQUAL_TO_HPP
+
+#include <boost/geometry/algorithms/equals.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail {
+
+template <typename Geometry, typename Tag>
+struct equals
+{
+ static bool apply(Geometry const& g1, Geometry const& g2)
+ {
+ return geometry::equals(g1, g2);
+ }
+};
+
+template <typename T>
+struct equals<T, void>
+{
+ static bool apply(T const& v1, T const& v2)
+ {
+ return v1 == v2;
+ }
+};
+
+template <typename Tuple, size_t I, size_t N>
+struct tuple_equals
+{
+ inline static bool apply(Tuple const& t1, Tuple const& t2)
+ {
+ typedef typename boost::tuples::element<I, Tuple>::type T;
+ return
+ equals<
+ T, typename geometry::traits::tag<T>::type
+ >::apply(boost::get<I>(t1), boost::get<I>(t2))
+ &&
+ tuple_equals<Tuple, I+1, N>::apply(t1, t2);
+ }
+};
+
+template <typename Tuple, size_t I>
+struct tuple_equals<Tuple, I, I>
+{
+ inline static bool apply(Tuple const&, Tuple const&)
+ {
+ return true;
+ }
+};
+
+} // namespace detail
+
+/*!
+\brief The function object comparing Values.
+
+It compares Geometries using geometry::equals() function. Other types are compared using operator==.
+The default version handles Values which are Indexables.
+This template is also specialized for std::pair<T1, T2> and boost::tuple<...>.
+
+\tparam Value The type of objects which are compared by this function object.
+*/
+template <typename Value>
+struct equal_to
+{
+ /*! \brief The type of result returned by function object. */
+ typedef bool result_type;
+
+ /*!
+ \brief Compare values. If Value is a Geometry geometry::equals() function is used.
+
+ \param l First value.
+ \param r Second value.
+ \return true if values are equal.
+ */
+ bool operator()(Value const& l, Value const& r) const
+ {
+ return detail::equals<Value, typename geometry::traits::tag<Value>::type>::apply(l ,r);
+ }
+};
+
+/*!
+\brief The function object comparing Values.
+
+This specialization compares values of type std::pair<T1, T2>.
+It compares pairs' first values, then second values.
+
+\tparam T1 The first type.
+\tparam T2 The second type.
+*/
+template <typename T1, typename T2>
+struct equal_to< std::pair<T1, T2> >
+{
+ /*! \brief The type of result returned by function object. */
+ typedef bool result_type;
+
+ /*!
+ \brief Compare values. If pair<> Value member is a Geometry geometry::equals() function is used.
+
+ \param l First value.
+ \param r Second value.
+ \return true if values are equal.
+ */
+ bool operator()(std::pair<T1, T2> const& l, std::pair<T1, T2> const& r) const
+ {
+ typedef detail::equals<T1, typename geometry::traits::tag<T1>::type> equals1;
+ typedef detail::equals<T2, typename geometry::traits::tag<T2>::type> equals2;
+
+ return equals1::apply(l.first, r.first) && equals2::apply(l.second, r.second);
+ }
+};
+
+/*!
+\brief The function object comparing Values.
+
+This specialization compares values of type boost::tuple<...>.
+It compares all members of the tuple from the first one to the last one.
+*/
+template <typename T0, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6, typename T7, typename T8, typename T9>
+struct equal_to< boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
+{
+ typedef boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> value_type;
+
+ /*! \brief The type of result returned by function object. */
+ typedef bool result_type;
+
+ /*!
+ \brief Compare values. If tuple<> Value member is a Geometry geometry::equals() function is used.
+
+ \param l First value.
+ \param r Second value.
+ \return true if values are equal.
+ */
+ bool operator()(value_type const& l, value_type const& r) const
+ {
+ return detail::tuple_equals<
+ value_type, 0, boost::tuples::length<value_type>::value
+ >::apply(l ,r);
+ }
+};
+
+}}} // namespace boost::geometry::index
+
+#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#include <tuple>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail {
+
+template <typename Tuple, size_t I, size_t N>
+struct std_tuple_equals
+{
+ inline static bool apply(Tuple const& t1, Tuple const& t2)
+ {
+ typedef typename std::tuple_element<I, Tuple>::type T;
+ return
+ equals<
+ T, typename geometry::traits::tag<T>::type
+ >::apply(std::get<I>(t1), std::get<I>(t2))
+ &&
+ std_tuple_equals<Tuple, I+1, N>::apply(t1, t2);
+ }
+};
+
+template <typename Tuple, size_t I>
+struct std_tuple_equals<Tuple, I, I>
+{
+ inline static bool apply(Tuple const&, Tuple const&)
+ {
+ return true;
+ }
+};
+
+} // namespace detail
+
+/*!
+\brief The function object comparing Values.
+
+This specialization compares values of type std::tuple<Args...>.
+It's defined if the compiler supports tuples and variadic templates.
+It compares all members of the tuple from the first one to the last one.
+*/
+template <typename ...Args>
+struct equal_to< std::tuple<Args...> >
+{
+ typedef std::tuple<Args...> value_type;
+
+ /*! \brief The type of result returned by function object. */
+ typedef bool result_type;
+
+ /*!
+ \brief Compare values. If tuple<> Value member is a Geometry geometry::equals() function is used.
+
+ \param l First value.
+ \param r Second value.
+ \return true if values are equal.
+ */
+ bool operator()(value_type const& l, value_type const& r) const
+ {
+ return detail::std_tuple_equals<
+ value_type, 0, std::tuple_size<value_type>::value
+ >::apply(l ,r);
+ }
+};
+
+}}} // namespace boost::geometry::index
+
+#endif // !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#endif // BOOST_GEOMETRY_INDEX_EQUAL_TO_HPP
diff --git a/boost/geometry/index/indexable.hpp b/boost/geometry/index/indexable.hpp
new file mode 100644
index 000000000..9533fcf9e
--- /dev/null
+++ b/boost/geometry/index/indexable.hpp
@@ -0,0 +1,179 @@
+// Boost.Geometry Index
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_INDEXABLE_HPP
+#define BOOST_GEOMETRY_INDEX_INDEXABLE_HPP
+
+#include <boost/mpl/assert.hpp>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail {
+
+template <typename Geometry, typename GeometryTag>
+struct is_indexable_impl { static const bool value = false; };
+
+template <typename Point>
+struct is_indexable_impl<Point, geometry::point_tag> { static const bool value = true; };
+
+template <typename Box>
+struct is_indexable_impl<Box, geometry::box_tag> { static const bool value = true; };
+
+template <typename Indexable>
+struct is_indexable
+{
+ static const bool value =
+ is_indexable_impl<Indexable, typename geometry::traits::tag<Indexable>::type>::value;
+};
+
+} // namespace detail
+
+/*!
+\brief The function object extracting Indexable from Value.
+
+It translates Value object to Indexable object. The default version handles Values which are Indexables.
+This template is also specialized for std::pair<Indexable, T2> and boost::tuple<Indexable, ...>.
+
+\tparam Value The Value type which may be translated directly to the Indexable.
+*/
+template <typename Value>
+struct indexable
+{
+ BOOST_MPL_ASSERT_MSG(
+ (detail::is_indexable<Value>::value),
+ NOT_VALID_INDEXABLE_TYPE,
+ (Value)
+ );
+ /*! \brief The type of result returned by function object. */
+ typedef Value const& result_type;
+
+ /*!
+ \brief Return indexable extracted from the value.
+
+ \param v The value.
+ \return The indexable.
+ */
+ result_type operator()(Value const& v) const
+ {
+ return v;
+ }
+};
+
+/*!
+\brief The function object extracting Indexable from Value.
+
+This specialization translates from std::pair<Indexable, T2>.
+
+\tparam Indexable The Indexable type.
+\tparam T2 The second type.
+*/
+template <typename Indexable, typename T2>
+struct indexable< std::pair<Indexable, T2> >
+{
+ BOOST_MPL_ASSERT_MSG(
+ (detail::is_indexable<Indexable>::value),
+ NOT_VALID_INDEXABLE_TYPE,
+ (Indexable)
+ );
+
+ /*! \brief The type of result returned by function object. */
+ typedef Indexable const& result_type;
+
+ /*!
+ \brief Return indexable extracted from the value.
+
+ \param v The value.
+ \return The indexable.
+ */
+ result_type operator()(std::pair<Indexable, T2> const& v) const
+ {
+ return v.first;
+ }
+};
+
+/*!
+\brief The function object extracting Indexable from Value.
+
+This specialization translates from boost::tuple<Indexable, ...>.
+
+\tparam Indexable The Indexable type.
+*/
+template <typename Indexable, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6, typename T7, typename T8, typename T9>
+struct indexable< boost::tuple<Indexable, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
+{
+ typedef boost::tuple<Indexable, T1, T2, T3, T4, T5, T6, T7, T8, T9> value_type;
+
+ BOOST_MPL_ASSERT_MSG(
+ (detail::is_indexable<Indexable>::value),
+ NOT_VALID_INDEXABLE_TYPE,
+ (Indexable)
+ );
+
+ /*! \brief The type of result returned by function object. */
+ typedef Indexable const& result_type;
+
+ /*!
+ \brief Return indexable extracted from the value.
+
+ \param v The value.
+ \return The indexable.
+ */
+ result_type operator()(value_type const& v) const
+ {
+ return boost::get<0>(v);
+ }
+};
+
+}}} // namespace boost::geometry::index
+
+#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#include <tuple>
+
+namespace boost { namespace geometry { namespace index {
+
+/*!
+\brief The function object extracting Indexable from Value.
+
+This specialization translates from std::tuple<Indexable, Args...>.
+It's defined if the compiler supports tuples and variadic templates.
+
+\tparam Indexable The Indexable type.
+*/
+template <typename Indexable, typename ...Args>
+struct indexable< std::tuple<Indexable, Args...> >
+{
+ typedef std::tuple<Indexable, Args...> value_type;
+
+ BOOST_MPL_ASSERT_MSG(
+ (detail::is_indexable<Indexable>::value),
+ NOT_VALID_INDEXABLE_TYPE,
+ (Indexable)
+ );
+
+ /*! \brief The type of result returned by function object. */
+ typedef Indexable const& result_type;
+
+ /*!
+ \brief Return indexable extracted from the value.
+
+ \param v The value.
+ \return The indexable.
+ */
+ result_type operator()(value_type const& v) const
+ {
+ return std::get<0>(v);
+ }
+};
+
+}}} // namespace boost::geometry::index
+
+#endif // !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
+
+#endif // BOOST_GEOMETRY_INDEX_INDEXABLE_HPP
diff --git a/boost/geometry/index/inserter.hpp b/boost/geometry/index/inserter.hpp
new file mode 100644
index 000000000..7c489bc3f
--- /dev/null
+++ b/boost/geometry/index/inserter.hpp
@@ -0,0 +1,78 @@
+// Boost.Geometry Index
+//
+// Insert iterator
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_INSERTER_HPP
+#define BOOST_GEOMETRY_INDEX_INSERTER_HPP
+
+#include <iterator>
+
+/*!
+\defgroup inserters Inserters (boost::geometry::index::)
+*/
+
+namespace boost { namespace geometry { namespace index {
+
+template <class Container>
+class insert_iterator :
+ public std::iterator<std::output_iterator_tag, void, void, void, void>
+{
+public:
+ typedef Container container_type;
+
+ inline explicit insert_iterator(Container & c)
+ : container(&c)
+ {}
+
+ insert_iterator & operator=(typename Container::value_type const& value)
+ {
+ container->insert(value);
+ return *this;
+ }
+
+ insert_iterator & operator* ()
+ {
+ return *this;
+ }
+
+ insert_iterator & operator++ ()
+ {
+ return *this;
+ }
+
+ insert_iterator operator++(int)
+ {
+ return *this;
+ }
+
+private:
+ Container * container;
+};
+
+/*!
+\brief Insert iterator generator.
+
+Returns insert iterator capable to insert values to the container
+(spatial index) which has member function insert(value_type const&) defined.
+
+\ingroup inserters
+
+\param c The reference to the container (spatial index) to which values will be inserted.
+
+\return The insert iterator inserting values to the container.
+*/
+template <typename Container>
+insert_iterator<Container> inserter(Container & c)
+{
+ return insert_iterator<Container>(c);
+}
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_INSERTER_HPP
diff --git a/boost/geometry/index/parameters.hpp b/boost/geometry/index/parameters.hpp
new file mode 100644
index 000000000..2516e6d71
--- /dev/null
+++ b/boost/geometry/index/parameters.hpp
@@ -0,0 +1,257 @@
+// Boost.Geometry Index
+//
+// R-tree algorithms parameters
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_PARAMETERS_HPP
+#define BOOST_GEOMETRY_INDEX_PARAMETERS_HPP
+
+#include <limits>
+
+namespace boost { namespace geometry { namespace index {
+
+namespace detail {
+
+template <size_t MaxElements>
+struct default_min_elements_s
+{
+ // TODO - assert MaxElements <= (std::numeric_limits<size_t>::max)()/3
+ static const size_t raw_value = (MaxElements * 3) / 10;
+ static const size_t value = 1 <= raw_value ? raw_value : 1;
+};
+
+inline size_t default_min_elements_d()
+{
+ return (std::numeric_limits<size_t>::max)();
+}
+
+inline size_t default_min_elements_d_calc(size_t max_elements, size_t min_elements)
+{
+ if ( default_min_elements_d() == min_elements )
+ {
+ // TODO - assert MaxElements <= (std::numeric_limits<size_t>::max)()/3
+ size_t raw_value = (max_elements * 3) / 10;
+ return 1 <= raw_value ? raw_value : 1;
+ }
+
+ return min_elements;
+}
+
+template <size_t MaxElements>
+struct default_rstar_reinserted_elements_s
+{
+ // TODO - assert MaxElements <= (std::numeric_limits<size_t>::max)()/3
+ static const size_t value = (MaxElements * 3) / 10;
+};
+
+inline size_t default_rstar_reinserted_elements_d()
+{
+ return (std::numeric_limits<size_t>::max)();
+}
+
+inline size_t default_rstar_reinserted_elements_d_calc(size_t max_elements, size_t reinserted_elements)
+{
+ if ( default_rstar_reinserted_elements_d() == reinserted_elements )
+ {
+ // TODO - assert MaxElements <= (std::numeric_limits<size_t>::max)()/3
+ return (max_elements * 3) / 10;
+ }
+
+ return reinserted_elements;
+}
+
+} // namespace detail
+
+/*!
+\brief Linear r-tree creation algorithm parameters.
+
+\tparam MaxElements Maximum number of elements in nodes.
+\tparam MinElements Minimum number of elements in nodes. Default: 0.3*Max.
+*/
+template <size_t MaxElements,
+ size_t MinElements = detail::default_min_elements_s<MaxElements>::value
+>
+struct linear
+{
+ BOOST_MPL_ASSERT_MSG((0 < MinElements && 2*MinElements <= MaxElements+1),
+ INVALID_STATIC_MIN_MAX_PARAMETERS, (linear));
+
+ static const size_t max_elements = MaxElements;
+ static const size_t min_elements = MinElements;
+
+ static size_t get_max_elements() { return MaxElements; }
+ static size_t get_min_elements() { return MinElements; }
+};
+
+/*!
+\brief Quadratic r-tree creation algorithm parameters.
+
+\tparam MaxElements Maximum number of elements in nodes.
+\tparam MinElements Minimum number of elements in nodes. Default: 0.3*Max.
+*/
+template <size_t MaxElements,
+ size_t MinElements = detail::default_min_elements_s<MaxElements>::value>
+struct quadratic
+{
+ BOOST_MPL_ASSERT_MSG((0 < MinElements && 2*MinElements <= MaxElements+1),
+ INVALID_STATIC_MIN_MAX_PARAMETERS, (quadratic));
+
+ static const size_t max_elements = MaxElements;
+ static const size_t min_elements = MinElements;
+
+ static size_t get_max_elements() { return MaxElements; }
+ static size_t get_min_elements() { return MinElements; }
+};
+
+/*!
+\brief R*-tree creation algorithm parameters.
+
+\tparam MaxElements Maximum number of elements in nodes.
+\tparam MinElements Minimum number of elements in nodes. Default: 0.3*Max.
+\tparam ReinsertedElements The number of elements reinserted by forced reinsertions algorithm.
+ If 0 forced reinsertions are disabled. Maximum value is Max+1-Min.
+ Greater values are truncated. Default: 0.3*Max.
+\tparam OverlapCostThreshold The number of most suitable leafs taken into account while choosing
+ the leaf node to which currently inserted value will be added. If
+ value is in range (0, MaxElements) - the algorithm calculates
+ nearly minimum overlap cost, otherwise all leafs are analyzed
+ and true minimum overlap cost is calculated. Default: 32.
+*/
+template <size_t MaxElements,
+ size_t MinElements = detail::default_min_elements_s<MaxElements>::value,
+ size_t ReinsertedElements = detail::default_rstar_reinserted_elements_s<MaxElements>::value,
+ size_t OverlapCostThreshold = 32>
+struct rstar
+{
+ BOOST_MPL_ASSERT_MSG((0 < MinElements && 2*MinElements <= MaxElements+1),
+ INVALID_STATIC_MIN_MAX_PARAMETERS, (rstar));
+
+ static const size_t max_elements = MaxElements;
+ static const size_t min_elements = MinElements;
+ static const size_t reinserted_elements = ReinsertedElements;
+ static const size_t overlap_cost_threshold = OverlapCostThreshold;
+
+ static size_t get_max_elements() { return MaxElements; }
+ static size_t get_min_elements() { return MinElements; }
+ static size_t get_reinserted_elements() { return ReinsertedElements; }
+ static size_t get_overlap_cost_threshold() { return OverlapCostThreshold; }
+};
+
+//template <size_t MaxElements, size_t MinElements>
+//struct kmeans
+//{
+// static const size_t max_elements = MaxElements;
+// static const size_t min_elements = MinElements;
+//};
+
+/*!
+\brief Linear r-tree creation algorithm parameters - run-time version.
+*/
+class dynamic_linear
+{
+public:
+ /*!
+ \brief The constructor.
+
+ \param max_elements Maximum number of elements in nodes.
+ \param min_elements Minimum number of elements in nodes. Default: 0.3*Max.
+ */
+ dynamic_linear(size_t max_elements,
+ size_t min_elements = detail::default_min_elements_d())
+ : m_max_elements(max_elements)
+ , m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))
+ {
+ if (!(0 < m_min_elements && 2*m_min_elements <= m_max_elements+1))
+ detail::throw_invalid_argument("invalid min or/and max parameters of dynamic_linear");
+ }
+
+ size_t get_max_elements() const { return m_max_elements; }
+ size_t get_min_elements() const { return m_min_elements; }
+
+private:
+ size_t m_max_elements;
+ size_t m_min_elements;
+};
+
+/*!
+\brief Quadratic r-tree creation algorithm parameters - run-time version.
+*/
+class dynamic_quadratic
+{
+public:
+ /*!
+ \brief The constructor.
+
+ \param max_elements Maximum number of elements in nodes.
+ \param min_elements Minimum number of elements in nodes. Default: 0.3*Max.
+ */
+ dynamic_quadratic(size_t max_elements,
+ size_t min_elements = detail::default_min_elements_d())
+ : m_max_elements(max_elements)
+ , m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))
+ {
+ if (!(0 < m_min_elements && 2*m_min_elements <= m_max_elements+1))
+ detail::throw_invalid_argument("invalid min or/and max parameters of dynamic_quadratic");
+ }
+
+ size_t get_max_elements() const { return m_max_elements; }
+ size_t get_min_elements() const { return m_min_elements; }
+
+private:
+ size_t m_max_elements;
+ size_t m_min_elements;
+};
+
+/*!
+\brief R*-tree creation algorithm parameters - run-time version.
+*/
+class dynamic_rstar
+{
+public:
+ /*!
+ \brief The constructor.
+
+ \param max_elements Maximum number of elements in nodes.
+ \param min_elements Minimum number of elements in nodes. Default: 0.3*Max.
+ \param reinserted_elements The number of elements reinserted by forced reinsertions algorithm.
+ If 0 forced reinsertions are disabled. Maximum value is Max-Min+1.
+ Greater values are truncated. Default: 0.3*Max.
+ \param overlap_cost_threshold The number of most suitable leafs taken into account while choosing
+ the leaf node to which currently inserted value will be added. If
+ value is in range (0, MaxElements) - the algorithm calculates
+ nearly minimum overlap cost, otherwise all leafs are analyzed
+ and true minimum overlap cost is calculated. Default: 32.
+ */
+ dynamic_rstar(size_t max_elements,
+ size_t min_elements = detail::default_min_elements_d(),
+ size_t reinserted_elements = detail::default_rstar_reinserted_elements_d(),
+ size_t overlap_cost_threshold = 32)
+ : m_max_elements(max_elements)
+ , m_min_elements(detail::default_min_elements_d_calc(max_elements, min_elements))
+ , m_reinserted_elements(detail::default_rstar_reinserted_elements_d_calc(max_elements, reinserted_elements))
+ , m_overlap_cost_threshold(overlap_cost_threshold)
+ {
+ if (!(0 < m_min_elements && 2*m_min_elements <= m_max_elements+1))
+ detail::throw_invalid_argument("invalid min or/and max parameters of dynamic_rstar");
+ }
+
+ size_t get_max_elements() const { return m_max_elements; }
+ size_t get_min_elements() const { return m_min_elements; }
+ size_t get_reinserted_elements() const { return m_reinserted_elements; }
+ size_t get_overlap_cost_threshold() const { return m_overlap_cost_threshold; }
+
+private:
+ size_t m_max_elements;
+ size_t m_min_elements;
+ size_t m_reinserted_elements;
+ size_t m_overlap_cost_threshold;
+};
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_PARAMETERS_HPP
diff --git a/boost/geometry/index/predicates.hpp b/boost/geometry/index/predicates.hpp
new file mode 100644
index 000000000..5bf88df05
--- /dev/null
+++ b/boost/geometry/index/predicates.hpp
@@ -0,0 +1,394 @@
+// Boost.Geometry Index
+//
+// Spatial query predicates
+//
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_PREDICATES_HPP
+#define BOOST_GEOMETRY_INDEX_PREDICATES_HPP
+
+#include <utility>
+#include <boost/tuple/tuple.hpp>
+#include <boost/mpl/assert.hpp>
+
+#include <boost/geometry/index/detail/predicates.hpp>
+#include <boost/geometry/index/detail/tuples.hpp>
+
+/*!
+\defgroup predicates Predicates (boost::geometry::index::)
+*/
+
+namespace boost { namespace geometry { namespace index {
+
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+
+/*!
+\brief Generate \c contains() predicate.
+
+Generate a predicate defining Value and Geometry relationship.
+Value will be returned by the query if <tt>bg::within(Geometry, Indexable)</tt>
+returns true.
+
+\par Example
+\verbatim
+bgi::query(spatial_index, bgi::contains(box), std::back_inserter(result));
+\endverbatim
+
+\ingroup predicates
+
+\tparam Geometry The Geometry type.
+
+\param g The Geometry object.
+*/
+template <typename Geometry> inline
+detail::spatial_predicate<Geometry, detail::contains_tag, false>
+contains(Geometry const& g)
+{
+ return detail::spatial_predicate<Geometry, detail::contains_tag, false>(g);
+}
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+
+/*!
+\brief Generate \c covered_by() predicate.
+
+Generate a predicate defining Value and Geometry relationship.
+Value will be returned by the query if <tt>bg::covered_by(Indexable, Geometry)</tt>
+returns true.
+
+\par Example
+\verbatim
+bgi::query(spatial_index, bgi::covered_by(box), std::back_inserter(result));
+\endverbatim
+
+\ingroup predicates
+
+\tparam Geometry The Geometry type.
+
+\param g The Geometry object.
+*/
+template <typename Geometry> inline
+detail::spatial_predicate<Geometry, detail::covered_by_tag, false>
+covered_by(Geometry const& g)
+{
+ return detail::spatial_predicate<Geometry, detail::covered_by_tag, false>(g);
+}
+
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+
+/*!
+\brief Generate \c covers() predicate.
+
+Generate a predicate defining Value and Geometry relationship.
+Value will be returned by the query if <tt>bg::covered_by(Geometry, Indexable)</tt>
+returns true.
+
+\par Example
+\verbatim
+bgi::query(spatial_index, bgi::covers(box), std::back_inserter(result));
+\endverbatim
+
+\ingroup predicates
+
+\tparam Geometry The Geometry type.
+
+\param g The Geometry object.
+*/
+template <typename Geometry> inline
+detail::spatial_predicate<Geometry, detail::covers_tag, false>
+covers(Geometry const& g)
+{
+ return detail::spatial_predicate<Geometry, detail::covers_tag, false>(g);
+}
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+
+/*!
+\brief Generate \c disjoint() predicate.
+
+Generate a predicate defining Value and Geometry relationship.
+Value will be returned by the query if <tt>bg::disjoint(Indexable, Geometry)</tt>
+returns true.
+
+\par Example
+\verbatim
+bgi::query(spatial_index, bgi::disjoint(box), std::back_inserter(result));
+\endverbatim
+
+\ingroup predicates
+
+\tparam Geometry The Geometry type.
+
+\param g The Geometry object.
+*/
+template <typename Geometry> inline
+detail::spatial_predicate<Geometry, detail::disjoint_tag, false>
+disjoint(Geometry const& g)
+{
+ return detail::spatial_predicate<Geometry, detail::disjoint_tag, false>(g);
+}
+
+/*!
+\brief Generate \c intersects() predicate.
+
+Generate a predicate defining Value and Geometry relationship.
+Value will be returned by the query if <tt>bg::intersects(Indexable, Geometry)</tt>
+returns true.
+
+\par Example
+\verbatim
+bgi::query(spatial_index, bgi::intersects(box), std::back_inserter(result));
+bgi::query(spatial_index, bgi::intersects(ring), std::back_inserter(result));
+bgi::query(spatial_index, bgi::intersects(polygon), std::back_inserter(result));
+\endverbatim
+
+\ingroup predicates
+
+\tparam Geometry The Geometry type.
+
+\param g The Geometry object.
+*/
+template <typename Geometry> inline
+detail::spatial_predicate<Geometry, detail::intersects_tag, false>
+intersects(Geometry const& g)
+{
+ return detail::spatial_predicate<Geometry, detail::intersects_tag, false>(g);
+}
+
+/*!
+\brief Generate \c overlaps() predicate.
+
+Generate a predicate defining Value and Geometry relationship.
+Value will be returned by the query if <tt>bg::overlaps(Indexable, Geometry)</tt>
+returns true.
+
+\par Example
+\verbatim
+bgi::query(spatial_index, bgi::overlaps(box), std::back_inserter(result));
+\endverbatim
+
+\ingroup predicates
+
+\tparam Geometry The Geometry type.
+
+\param g The Geometry object.
+*/
+template <typename Geometry> inline
+detail::spatial_predicate<Geometry, detail::overlaps_tag, false>
+overlaps(Geometry const& g)
+{
+ return detail::spatial_predicate<Geometry, detail::overlaps_tag, false>(g);
+}
+
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+
+/*!
+\brief Generate \c touches() predicate.
+
+Generate a predicate defining Value and Geometry relationship.
+Value will be returned by the query if <tt>bg::touches(Indexable, Geometry)</tt>
+returns true.
+
+\ingroup predicates
+
+\tparam Geometry The Geometry type.
+
+\param g The Geometry object.
+*/
+template <typename Geometry> inline
+detail::spatial_predicate<Geometry, detail::touches_tag, false>
+touches(Geometry const& g)
+{
+ return detail::spatial_predicate<Geometry, detail::touches_tag, false>(g);
+}
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+
+/*!
+\brief Generate \c within() predicate.
+
+Generate a predicate defining Value and Geometry relationship.
+Value will be returned by the query if <tt>bg::within(Indexable, Geometry)</tt>
+returns true.
+
+\par Example
+\verbatim
+bgi::query(spatial_index, bgi::within(box), std::back_inserter(result));
+\endverbatim
+
+\ingroup predicates
+
+\tparam Geometry The Geometry type.
+
+\param g The Geometry object.
+*/
+template <typename Geometry> inline
+detail::spatial_predicate<Geometry, detail::within_tag, false>
+within(Geometry const& g)
+{
+ return detail::spatial_predicate<Geometry, detail::within_tag, false>(g);
+}
+
+/*!
+\brief Generate satisfies() predicate.
+
+A wrapper around user-defined UnaryPredicate checking if Value should be returned by spatial query.
+
+\par Example
+\verbatim
+bool is_red(Value const& v) { return v.is_red(); }
+
+struct is_red_o {
+template <typename Value> bool operator()(Value const& v) { return v.is_red(); }
+}
+
+// ...
+
+rt.query(index::intersects(box) && index::satisfies(is_red),
+std::back_inserter(result));
+
+rt.query(index::intersects(box) && index::satisfies(is_red_o()),
+std::back_inserter(result));
+
+#ifndef BOOST_NO_CXX11_LAMBDAS
+rt.query(index::intersects(box) && index::satisfies([](Value const& v) { return v.is_red(); }),
+std::back_inserter(result));
+#endif
+\endverbatim
+
+\ingroup predicates
+
+\tparam UnaryPredicate A type of unary predicate function or function object.
+
+\param pred The unary predicate function or function object.
+*/
+template <typename UnaryPredicate> inline
+detail::satisfies<UnaryPredicate, false>
+satisfies(UnaryPredicate const& pred)
+{
+ return detail::satisfies<UnaryPredicate, false>(pred);
+}
+
+/*!
+\brief Generate nearest() predicate.
+
+When nearest predicate is passed to the query, k-nearest neighbour search will be performed.
+\c nearest() predicate takes a \c Point from which distance to \c Values is calculated
+and the maximum number of \c Values that should be returned.
+
+\par Example
+\verbatim
+bgi::query(spatial_index, bgi::nearest(pt, 5), std::back_inserter(result));
+bgi::query(spatial_index, bgi::nearest(pt, 5) && bgi::intersects(box), std::back_inserter(result));
+\endverbatim
+
+\warning
+Only one \c nearest() predicate may be used in a query.
+
+\ingroup predicates
+
+\param point The point from which distance is calculated.
+\param k The maximum number of values to return.
+*/
+template <typename Point> inline
+detail::nearest<Point>
+nearest(Point const& point, unsigned k)
+{
+ return detail::nearest<Point>(point, k);
+}
+
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+
+/*!
+\brief Generate path() predicate.
+
+When path predicate is passed to the query, the returned values are k values along the path closest to
+its begin. \c path() predicate takes a \c Segment or a \c Linestring defining the path and the maximum
+number of \c Values that should be returned.
+
+\par Example
+\verbatim
+bgi::query(spatial_index, bgi::path(segment, 5), std::back_inserter(result));
+bgi::query(spatial_index, bgi::path(linestring, 5) && bgi::intersects(box), std::back_inserter(result));
+\endverbatim
+
+\warning
+Only one distance predicate (\c nearest() or \c path()) may be used in a query.
+
+\ingroup predicates
+
+\param linestring The path along which distance is calculated.
+\param k The maximum number of values to return.
+*/
+template <typename SegmentOrLinestring> inline
+detail::path<SegmentOrLinestring>
+path(SegmentOrLinestring const& linestring, unsigned k)
+{
+ return detail::path<SegmentOrLinestring>(linestring, k);
+}
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+
+namespace detail {
+
+// operator! generators
+
+template <typename Fun, bool Negated> inline
+satisfies<Fun, !Negated>
+operator!(satisfies<Fun, Negated> const& p)
+{
+ return satisfies<Fun, !Negated>(p);
+}
+
+template <typename Geometry, typename Tag, bool Negated> inline
+spatial_predicate<Geometry, Tag, !Negated>
+operator!(spatial_predicate<Geometry, Tag, Negated> const& p)
+{
+ return spatial_predicate<Geometry, Tag, !Negated>(p.geometry);
+}
+
+// operator&& generators
+
+template <typename Pred1, typename Pred2> inline
+boost::tuples::cons<
+ Pred1,
+ boost::tuples::cons<Pred2, boost::tuples::null_type>
+>
+operator&&(Pred1 const& p1, Pred2 const& p2)
+{
+ /*typedef typename boost::mpl::if_c<is_predicate<Pred1>::value, Pred1, Pred1 const&>::type stored1;
+ typedef typename boost::mpl::if_c<is_predicate<Pred2>::value, Pred2, Pred2 const&>::type stored2;*/
+ namespace bt = boost::tuples;
+
+ return
+ bt::cons< Pred1, bt::cons<Pred2, bt::null_type> >
+ ( p1, bt::cons<Pred2, bt::null_type>(p2, bt::null_type()) );
+}
+
+template <typename Head, typename Tail, typename Pred> inline
+typename tuples::push_back_impl<
+ boost::tuples::cons<Head, Tail>,
+ Pred,
+ 0,
+ boost::tuples::length<boost::tuples::cons<Head, Tail> >::value
+>::type
+operator&&(boost::tuples::cons<Head, Tail> const& t, Pred const& p)
+{
+ //typedef typename boost::mpl::if_c<is_predicate<Pred>::value, Pred, Pred const&>::type stored;
+ namespace bt = boost::tuples;
+
+ return
+ tuples::push_back_impl<
+ bt::cons<Head, Tail>, Pred, 0, bt::length< bt::cons<Head, Tail> >::value
+ >::apply(t, p);
+}
+
+} // namespace detail
+
+}}} // namespace boost::geometry::index
+
+#endif // BOOST_GEOMETRY_INDEX_PREDICATES_HPP
diff --git a/boost/geometry/index/rtree.hpp b/boost/geometry/index/rtree.hpp
new file mode 100644
index 000000000..018d508f6
--- /dev/null
+++ b/boost/geometry/index/rtree.hpp
@@ -0,0 +1,1550 @@
+// Boost.Geometry Index
+//
+// R-tree implementation
+//
+// Copyright (c) 2008 Federico J. Fernandez.
+// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+//
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_INDEX_RTREE_HPP
+#define BOOST_GEOMETRY_INDEX_RTREE_HPP
+
+#include <algorithm>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/move/move.hpp>
+
+#include <boost/geometry/geometry.hpp>
+
+#include <boost/geometry/index/detail/config_begin.hpp>
+
+#include <boost/geometry/index/detail/assert.hpp>
+#include <boost/geometry/index/detail/exception.hpp>
+
+#include <boost/geometry/index/detail/rtree/options.hpp>
+
+#include <boost/geometry/index/indexable.hpp>
+#include <boost/geometry/index/equal_to.hpp>
+
+#include <boost/geometry/index/detail/translator.hpp>
+
+#include <boost/geometry/index/predicates.hpp>
+#include <boost/geometry/index/distance_predicates.hpp>
+#include <boost/geometry/index/detail/rtree/adaptors.hpp>
+
+#include <boost/geometry/index/detail/meta.hpp>
+#include <boost/geometry/index/detail/utilities.hpp>
+#include <boost/geometry/index/detail/rtree/node/node.hpp>
+
+#include <boost/geometry/index/detail/algorithms/is_valid.hpp>
+
+#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/remove.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/copy.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/destroy.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/spatial_query.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/distance_query.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/count.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/children_box.hpp>
+
+#include <boost/geometry/index/detail/rtree/linear/linear.hpp>
+#include <boost/geometry/index/detail/rtree/quadratic/quadratic.hpp>
+#include <boost/geometry/index/detail/rtree/rstar/rstar.hpp>
+//#include <boost/geometry/extensions/index/detail/rtree/kmeans/kmeans.hpp>
+
+#include <boost/geometry/index/detail/rtree/pack_create.hpp>
+
+#include <boost/geometry/index/inserter.hpp>
+
+#include <boost/geometry/index/detail/rtree/utilities/view.hpp>
+
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+#include <boost/geometry/index/detail/rtree/query_iterators.hpp>
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_ENABLE_TYPE_ERASED_ITERATORS
+#include <boost/geometry/index/detail/type_erased_iterators.hpp>
+#endif
+#endif
+
+// TODO change the name to bounding_tree
+
+/*!
+\defgroup rtree_functions R-tree free functions (boost::geometry::index::)
+*/
+
+namespace boost { namespace geometry { namespace index {
+
+/*!
+\brief The R-tree spatial index.
+
+This is self-balancing spatial index capable to store various types of Values and balancing algorithms.
+
+\par Parameters
+The user must pass a type defining the Parameters which will
+be used in rtree creation process. This type is used e.g. to specify balancing algorithm
+with specific parameters like min and max number of elements in node.
+
+\par
+Predefined algorithms with compile-time parameters are:
+\li <tt>boost::geometry::index::linear</tt>,
+ \li <tt>boost::geometry::index::quadratic</tt>,
+ \li <tt>boost::geometry::index::rstar</tt>.
+
+\par
+Predefined algorithms with run-time parameters are:
+ \li \c boost::geometry::index::dynamic_linear,
+ \li \c boost::geometry::index::dynamic_quadratic,
+ \li \c boost::geometry::index::dynamic_rstar.
+
+\par Translator
+The Translator translates from Value to Indexable each time r-tree requires it. Which means that this
+operation is done for each Value access. Therefore the Translator should return the Indexable by
+const reference instead of a value. Default translator can translate all types adapted to Point
+or Box concepts (called Indexables). It also handles <tt>std::pair<Indexable, T></tt> and
+<tt>boost::tuple<Indexable, ...></tt>. For example, if <tt>std::pair<Box, int></tt> is stored in the
+container, the default translator translates from <tt>std::pair<Box, int> const&</tt> to <tt>Box const&</tt>.
+
+\tparam Value The type of objects stored in the container.
+\tparam Parameters Compile-time parameters.
+\tparam IndexableGetter The function object extracting Indexable from Value.
+\tparam EqualTo The function object comparing objects of type Value.
+\tparam Allocator The allocator used to allocate/deallocate memory, construct/destroy nodes and Values.
+*/
+template <
+ typename Value,
+ typename Parameters,
+ typename IndexableGetter = index::indexable<Value>,
+ typename EqualTo = index::equal_to<Value>,
+ typename Allocator = std::allocator<Value>
+>
+class rtree
+{
+ BOOST_COPYABLE_AND_MOVABLE(rtree)
+
+public:
+ /*! \brief The type of Value stored in the container. */
+ typedef Value value_type;
+ /*! \brief R-tree parameters type. */
+ typedef Parameters parameters_type;
+ /*! \brief The function object extracting Indexable from Value. */
+ typedef IndexableGetter indexable_getter;
+ /*! \brief The function object comparing objects of type Value. */
+ typedef EqualTo value_equal;
+ /*! \brief The type of allocator used by the container. */
+ typedef Allocator allocator_type;
+
+ // TODO: SHOULD THIS TYPE BE REMOVED?
+ /*! \brief The Indexable type to which Value is translated. */
+ typedef typename index::detail::indexable_type<
+ detail::translator<IndexableGetter, EqualTo>
+ >::type indexable_type;
+
+ /*! \brief The Box type used by the R-tree. */
+ typedef geometry::model::box<
+ geometry::model::point<
+ typename coordinate_type<indexable_type>::type,
+ dimension<indexable_type>::value,
+ typename coordinate_system<indexable_type>::type
+ >
+ >
+ bounds_type;
+
+private:
+
+ typedef detail::translator<IndexableGetter, EqualTo> translator_type;
+
+ typedef bounds_type box_type;
+ typedef typename detail::rtree::options_type<Parameters>::type options_type;
+ typedef typename options_type::node_tag node_tag;
+ typedef detail::rtree::allocators<allocator_type, value_type, typename options_type::parameters_type, box_type, node_tag> allocators_type;
+
+ typedef typename detail::rtree::node<value_type, typename options_type::parameters_type, box_type, allocators_type, node_tag>::type node;
+ typedef typename detail::rtree::internal_node<value_type, typename options_type::parameters_type, box_type, allocators_type, node_tag>::type internal_node;
+ typedef typename detail::rtree::leaf<value_type, typename options_type::parameters_type, box_type, allocators_type, node_tag>::type leaf;
+
+ typedef typename allocators_type::node_pointer node_pointer;
+ typedef ::boost::container::allocator_traits<Allocator> allocator_traits_type;
+
+ friend class detail::rtree::utilities::view<rtree>;
+
+public:
+
+ /*! \brief Type of reference to Value. */
+ typedef typename allocators_type::reference reference;
+ /*! \brief Type of reference to const Value. */
+ typedef typename allocators_type::const_reference const_reference;
+ /*! \brief Type of pointer to Value. */
+ typedef typename allocators_type::pointer pointer;
+ /*! \brief Type of pointer to const Value. */
+ typedef typename allocators_type::const_pointer const_pointer;
+ /*! \brief Type of difference type. */
+ typedef typename allocators_type::difference_type difference_type;
+ /*! \brief Unsigned integral type used by the container. */
+ typedef typename allocators_type::size_type size_type;
+
+public:
+
+ /*!
+ \brief The constructor.
+
+ \param parameters The parameters object.
+ \param getter The function object extracting Indexable from Value.
+ \param equal The function object comparing Values.
+
+ \par Throws
+ If allocator default constructor throws.
+ */
+ inline explicit rtree(parameters_type const& parameters = parameters_type(),
+ indexable_getter const& getter = indexable_getter(),
+ value_equal const& equal = value_equal())
+ : m_members(getter, equal, parameters)
+ {}
+
+ /*!
+ \brief The constructor.
+
+ \param parameters The parameters object.
+ \param getter The function object extracting Indexable from Value.
+ \param equal The function object comparing Values.
+ \param allocator The allocator object.
+
+ \par Throws
+ If allocator copy constructor throws.
+ */
+ inline rtree(parameters_type const& parameters,
+ indexable_getter const& getter,
+ value_equal const& equal,
+ allocator_type const& allocator)
+ : m_members(getter, equal, parameters, allocator)
+ {}
+
+ /*!
+ \brief The constructor.
+
+ \param first The beginning of the range of Values.
+ \param last The end of the range of Values.
+ \param parameters The parameters object.
+ \param getter The function object extracting Indexable from Value.
+ \param equal The function object comparing Values.
+ \param allocator The allocator object.
+
+ \par Throws
+ \li If allocator copy constructor throws.
+ \li If Value copy constructor or copy assignment throws.
+ \li If allocation throws or returns invalid value.
+ */
+ template<typename Iterator>
+ inline rtree(Iterator first, Iterator last,
+ parameters_type const& parameters = parameters_type(),
+ indexable_getter const& getter = indexable_getter(),
+ value_equal const& equal = value_equal(),
+ allocator_type const& allocator = allocator_type())
+ : m_members(getter, equal, parameters, allocator)
+ {
+ typedef detail::rtree::pack<value_type, options_type, translator_type, box_type, allocators_type> pack;
+ size_type vc = 0, ll = 0;
+ m_members.root = pack::apply(first, last, vc, ll,
+ m_members.parameters(), m_members.translator(), m_members.allocators());
+ m_members.values_count = vc;
+ m_members.leafs_level = ll;
+ }
+
+ /*!
+ \brief The constructor.
+
+ \param rng The range of Values.
+ \param parameters The parameters object.
+ \param getter The function object extracting Indexable from Value.
+ \param equal The function object comparing Values.
+ \param allocator The allocator object.
+
+ \par Throws
+ \li If allocator copy constructor throws.
+ \li If Value copy constructor or copy assignment throws.
+ \li If allocation throws or returns invalid value.
+ */
+ template<typename Range>
+ inline explicit rtree(Range const& rng,
+ parameters_type const& parameters = parameters_type(),
+ indexable_getter const& getter = indexable_getter(),
+ value_equal const& equal = value_equal(),
+ allocator_type const& allocator = allocator_type())
+ : m_members(getter, equal, parameters, allocator)
+ {
+ typedef detail::rtree::pack<value_type, options_type, translator_type, box_type, allocators_type> pack;
+ size_type vc = 0, ll = 0;
+ m_members.root = pack::apply(::boost::begin(rng), ::boost::end(rng), vc, ll,
+ m_members.parameters(), m_members.translator(), m_members.allocators());
+ m_members.values_count = vc;
+ m_members.leafs_level = ll;
+ }
+
+ /*!
+ \brief The destructor.
+
+ \par Throws
+ Nothing.
+ */
+ inline ~rtree()
+ {
+ this->raw_destroy(*this);
+ }
+
+ /*!
+ \brief The copy constructor.
+
+ It uses parameters, translator and allocator from the source tree.
+
+ \param src The rtree which content will be copied.
+
+ \par Throws
+ \li If allocator copy constructor throws.
+ \li If Value copy constructor throws.
+ \li If allocation throws or returns invalid value.
+ */
+ inline rtree(rtree const& src)
+ : m_members(src.m_members.indexable_getter(),
+ src.m_members.equal_to(),
+ src.m_members.parameters(),
+ allocator_traits_type::select_on_container_copy_construction(src.get_allocator()))
+ {
+ this->raw_copy(src, *this, false);
+ }
+
+ /*!
+ \brief The copy constructor.
+
+ It uses Parameters and translator from the source tree.
+
+ \param src The rtree which content will be copied.
+ \param allocator The allocator which will be used.
+
+ \par Throws
+ \li If allocator copy constructor throws.
+ \li If Value copy constructor throws.
+ \li If allocation throws or returns invalid value.
+ */
+ inline rtree(rtree const& src, allocator_type const& allocator)
+ : m_members(src.m_members.indexable_getter(),
+ src.m_members.equal_to(),
+ src.m_members.parameters(), allocator)
+ {
+ this->raw_copy(src, *this, false);
+ }
+
+ /*!
+ \brief The moving constructor.
+
+ It uses parameters, translator and allocator from the source tree.
+
+ \param src The rtree which content will be moved.
+
+ \par Throws
+ Nothing.
+ */
+ inline rtree(BOOST_RV_REF(rtree) src)
+ : m_members(src.m_members.indexable_getter(),
+ src.m_members.equal_to(),
+ src.m_members.parameters(),
+ boost::move(src.m_members.allocators()))
+ {
+ boost::swap(m_members.values_count, src.m_members.values_count);
+ boost::swap(m_members.leafs_level, src.m_members.leafs_level);
+ boost::swap(m_members.root, src.m_members.root);
+ }
+
+ /*!
+ \brief The moving constructor.
+
+ It uses parameters and translator from the source tree.
+
+ \param src The rtree which content will be moved.
+ \param allocator The allocator.
+
+ \par Throws
+ \li If allocator copy constructor throws.
+ \li If Value copy constructor throws (only if allocators aren't equal).
+ \li If allocation throws or returns invalid value (only if allocators aren't equal).
+ */
+ inline rtree(BOOST_RV_REF(rtree) src, allocator_type const& allocator)
+ : m_members(src.m_members.indexable_getter(),
+ src.m_members.equal_to(),
+ src.m_members.parameters(),
+ allocator)
+ {
+ if ( src.m_members.allocators() == allocator )
+ {
+ boost::swap(m_members.values_count, src.m_members.values_count);
+ boost::swap(m_members.leafs_level, src.m_members.leafs_level);
+ boost::swap(m_members.root, src.m_members.root);
+ }
+ else
+ {
+ this->raw_copy(src, *this, false);
+ }
+ }
+
+ /*!
+ \brief The assignment operator.
+
+ It uses parameters and translator from the source tree.
+
+ \param src The rtree which content will be copied.
+
+ \par Throws
+ \li If Value copy constructor throws.
+ \li If allocation throws.
+ \li If allocation throws or returns invalid value.
+ */
+ inline rtree & operator=(BOOST_COPY_ASSIGN_REF(rtree) src)
+ {
+ if ( &src != this )
+ {
+ allocators_type & this_allocs = m_members.allocators();
+ allocators_type const& src_allocs = src.m_members.allocators();
+
+ // NOTE: if propagate is true for std allocators on darwin 4.2.1, glibc++
+ // (allocators stored as base classes of members_holder)
+ // copying them changes values_count, in this case it doesn't cause errors since data must be copied
+
+ typedef boost::mpl::bool_<
+ allocator_traits_type::propagate_on_container_copy_assignment::value
+ > propagate;
+
+ if ( propagate::value && !(this_allocs == src_allocs) )
+ this->raw_destroy(*this);
+ detail::assign_cond(this_allocs, src_allocs, propagate());
+
+ // It uses m_allocators
+ this->raw_copy(src, *this, true);
+ }
+
+ return *this;
+ }
+
+ /*!
+ \brief The moving assignment.
+
+ It uses parameters and translator from the source tree.
+
+ \param src The rtree which content will be moved.
+
+ \par Throws
+ Only if allocators aren't equal.
+ \li If Value copy constructor throws.
+ \li If allocation throws or returns invalid value.
+ */
+ inline rtree & operator=(BOOST_RV_REF(rtree) src)
+ {
+ if ( &src != this )
+ {
+ allocators_type & this_allocs = m_members.allocators();
+ allocators_type & src_allocs = src.m_members.allocators();
+
+ if ( this_allocs == src_allocs )
+ {
+ this->raw_destroy(*this);
+
+ m_members.indexable_getter() = src.m_members.indexable_getter();
+ m_members.equal_to() = src.m_members.equal_to();
+ m_members.parameters() = src.m_members.parameters();
+
+ boost::swap(m_members.values_count, src.m_members.values_count);
+ boost::swap(m_members.leafs_level, src.m_members.leafs_level);
+ boost::swap(m_members.root, src.m_members.root);
+
+ // NOTE: if propagate is true for std allocators on darwin 4.2.1, glibc++
+ // (allocators stored as base classes of members_holder)
+ // moving them changes values_count
+
+ typedef boost::mpl::bool_<
+ allocator_traits_type::propagate_on_container_move_assignment::value
+ > propagate;
+ detail::move_cond(this_allocs, src_allocs, propagate());
+ }
+ else
+ {
+// TODO - shouldn't here propagate_on_container_copy_assignment be checked like in operator=(const&)?
+
+ // It uses m_allocators
+ this->raw_copy(src, *this, true);
+ }
+ }
+
+ return *this;
+ }
+
+ /*!
+ \brief Swaps contents of two rtrees.
+
+ Parameters, translator and allocators are swapped as well.
+
+ \param other The rtree which content will be swapped with this rtree content.
+
+ \par Throws
+ If allocators swap throws.
+ */
+ void swap(rtree & other)
+ {
+ boost::swap(m_members.indexable_getter(), other.m_members.indexable_getter());
+ boost::swap(m_members.equal_to(), other.m_members.equal_to());
+ boost::swap(m_members.parameters(), other.m_members.parameters());
+
+ // NOTE: if propagate is true for std allocators on darwin 4.2.1, glibc++
+ // (allocators stored as base classes of members_holder)
+ // swapping them changes values_count
+
+ typedef boost::mpl::bool_<
+ allocator_traits_type::propagate_on_container_swap::value
+ > propagate;
+ detail::swap_cond(m_members.allocators(), other.m_members.allocators(), propagate());
+
+ boost::swap(m_members.values_count, other.m_members.values_count);
+ boost::swap(m_members.leafs_level, other.m_members.leafs_level);
+ boost::swap(m_members.root, other.m_members.root);
+ }
+
+ /*!
+ \brief Insert a value to the index.
+
+ \param value The value which will be stored in the container.
+
+ \par Throws
+ \li If Value copy constructor or copy assignment throws.
+ \li If allocation throws or returns invalid value.
+
+ \warning
+ This operation only guarantees that there will be no memory leaks.
+ After an exception is thrown the R-tree may be left in an inconsistent state,
+ elements must not be inserted or removed. Other operations are allowed however
+ some of them may return invalid data.
+ */
+ inline void insert(value_type const& value)
+ {
+ if ( !m_members.root )
+ this->raw_create();
+
+ this->raw_insert(value);
+ }
+
+ /*!
+ \brief Insert a range of values to the index.
+
+ \param first The beginning of the range of values.
+ \param last The end of the range of values.
+
+ \par Throws
+ \li If Value copy constructor or copy assignment throws.
+ \li If allocation throws or returns invalid value.
+
+ \warning
+ This operation only guarantees that there will be no memory leaks.
+ After an exception is thrown the R-tree may be left in an inconsistent state,
+ elements must not be inserted or removed. Other operations are allowed however
+ some of them may return invalid data.
+ */
+ template <typename Iterator>
+ inline void insert(Iterator first, Iterator last)
+ {
+ if ( !m_members.root )
+ this->raw_create();
+
+ for ( ; first != last ; ++first )
+ this->raw_insert(*first);
+ }
+
+ /*!
+ \brief Insert a range of values to the index.
+
+ \param rng The range of values.
+
+ \par Throws
+ \li If Value copy constructor or copy assignment throws.
+ \li If allocation throws or returns invalid value.
+
+ \warning
+ This operation only guarantees that there will be no memory leaks.
+ After an exception is thrown the R-tree may be left in an inconsistent state,
+ elements must not be inserted or removed. Other operations are allowed however
+ some of them may return invalid data.
+ */
+ template <typename Range>
+ inline void insert(Range const& rng)
+ {
+ BOOST_MPL_ASSERT_MSG((detail::is_range<Range>::value), PASSED_OBJECT_IS_NOT_A_RANGE, (Range));
+
+ if ( !m_members.root )
+ this->raw_create();
+
+ typedef typename boost::range_const_iterator<Range>::type It;
+ for ( It it = boost::const_begin(rng); it != boost::const_end(rng) ; ++it )
+ this->raw_insert(*it);
+ }
+
+ /*!
+ \brief Remove a value from the container.
+
+ In contrast to the \c std::set or <tt>std::map erase()</tt> method
+ this method removes only one value from the container.
+
+ \param value The value which will be removed from the container.
+
+ \return 1 if the value was removed, 0 otherwise.
+
+ \par Throws
+ \li If Value copy constructor or copy assignment throws.
+ \li If allocation throws or returns invalid value.
+
+ \warning
+ This operation only guarantees that there will be no memory leaks.
+ After an exception is thrown the R-tree may be left in an inconsistent state,
+ elements must not be inserted or removed. Other operations are allowed however
+ some of them may return invalid data.
+ */
+ inline size_type remove(value_type const& value)
+ {
+ return this->raw_remove(value);
+ }
+
+ /*!
+ \brief Remove a range of values from the container.
+
+ In contrast to the \c std::set or <tt>std::map erase()</tt> method
+ it doesn't take iterators pointing to values stored in this container. It removes values equal
+ to these passed as a range. Furthermore this method removes only one value for each one passed
+ in the range, not all equal values.
+
+ \param first The beginning of the range of values.
+ \param last The end of the range of values.
+
+ \return The number of removed values.
+
+ \par Throws
+ \li If Value copy constructor or copy assignment throws.
+ \li If allocation throws or returns invalid value.
+
+ \warning
+ This operation only guarantees that there will be no memory leaks.
+ After an exception is thrown the R-tree may be left in an inconsistent state,
+ elements must not be inserted or removed. Other operations are allowed however
+ some of them may return invalid data.
+ */
+ template <typename Iterator>
+ inline size_type remove(Iterator first, Iterator last)
+ {
+ size_type result = 0;
+ for ( ; first != last ; ++first )
+ result += this->raw_remove(*first);
+ return result;
+ }
+
+ /*!
+ \brief Remove a range of values from the container.
+
+ In contrast to the \c std::set or <tt>std::map erase()</tt> method
+ it removes values equal to these passed as a range. Furthermore, this method removes only
+ one value for each one passed in the range, not all equal values.
+
+ \param rng The range of values.
+
+ \return The number of removed values.
+
+ \par Throws
+ \li If Value copy constructor or copy assignment throws.
+ \li If allocation throws or returns invalid value.
+
+ \warning
+ This operation only guarantees that there will be no memory leaks.
+ After an exception is thrown the R-tree may be left in an inconsistent state,
+ elements must not be inserted or removed. Other operations are allowed however
+ some of them may return invalid data.
+ */
+ template <typename Range>
+ inline size_type remove(Range const& rng)
+ {
+ BOOST_MPL_ASSERT_MSG((detail::is_range<Range>::value), PASSED_OBJECT_IS_NOT_A_RANGE, (Range));
+
+ size_type result = 0;
+ typedef typename boost::range_const_iterator<Range>::type It;
+ for ( It it = boost::const_begin(rng); it != boost::const_end(rng) ; ++it )
+ result += this->raw_remove(*it);
+ return result;
+ }
+
+ /*!
+ \brief Finds values meeting passed predicates e.g. nearest to some Point and/or intersecting some Box.
+
+ This query function performs spatial and k-nearest neighbor searches. It allows to pass a set of predicates.
+ Values will be returned only if all predicates are met.
+
+ <b>Spatial predicates</b>
+
+ Spatial predicates may be generated by one of the functions listed below:
+ \li \c boost::geometry::index::covered_by(),
+ \li \c boost::geometry::index::disjoint(),
+ \li \c boost::geometry::index::intersects(),
+ \li \c boost::geometry::index::overlaps(),
+ \li \c boost::geometry::index::within(),
+
+ It is possible to negate spatial predicates:
+ \li <tt>! boost::geometry::index::covered_by()</tt>,
+ \li <tt>! boost::geometry::index::disjoint()</tt>,
+ \li <tt>! boost::geometry::index::intersects()</tt>,
+ \li <tt>! boost::geometry::index::overlaps()</tt>,
+ \li <tt>! boost::geometry::index::within()</tt>
+
+ <b>Satisfies predicate</b>
+
+ This is a special kind of predicate which allows to pass a user-defined function or function object which checks
+ if Value should be returned by the query. It's generated by:
+ \li \c boost::geometry::index::satisfies().
+
+ <b>Nearest predicate</b>
+
+ If the nearest predicate is passed a k-nearest neighbor search will be performed. This query will result
+ in returning k values to the output iterator. Only one nearest predicate may be passed to the query.
+ It may be generated by:
+ \li \c boost::geometry::index::nearest().
+
+ <b>Connecting predicates</b>
+
+ Predicates may be passed together connected with \c operator&&().
+
+ \par Example
+ \verbatim
+ // return elements intersecting box
+ tree.query(bgi::intersects(box), std::back_inserter(result));
+ // return elements intersecting poly but not within box
+ tree.query(bgi::intersects(poly) && !bgi::within(box), std::back_inserter(result));
+ // return elements overlapping box and meeting my_fun unary predicate
+ tree.query(bgi::overlaps(box) && bgi::satisfies(my_fun), std::back_inserter(result));
+ // return 5 elements nearest to pt and elements are intersecting box
+ tree.query(bgi::nearest(pt, 5) && bgi::intersects(box), std::back_inserter(result));
+ \endverbatim
+
+ \par Throws
+ If Value copy constructor or copy assignment throws.
+
+ \warning
+ Only one \c nearest() perdicate may be passed to the query. Passing more of them results in compile-time error.
+
+ \param predicates Predicates.
+ \param out_it The output iterator, e.g. generated by std::back_inserter().
+
+ \return The number of values found.
+ */
+ template <typename Predicates, typename OutIter>
+ size_type query(Predicates const& predicates, OutIter out_it) const
+ {
+ if ( !m_members.root )
+ return 0;
+
+ static const unsigned distance_predicates_count = detail::predicates_count_distance<Predicates>::value;
+ static const bool is_distance_predicate = 0 < distance_predicates_count;
+ BOOST_MPL_ASSERT_MSG((distance_predicates_count <= 1), PASS_ONLY_ONE_DISTANCE_PREDICATE, (Predicates));
+
+ return query_dispatch(predicates, out_it, boost::mpl::bool_<is_distance_predicate>());
+ }
+
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_ENABLE_TYPE_ERASED_ITERATORS
+
+ // BEWARE!
+ // Don't use this type-erased iterator after assigning values returned by qbegin(Pred) and qend()
+ // e.g. don't pass them into the std::copy() or compare them like this:
+ // const_query_iterator i1 = qbegin(...);
+ // const_query_iterator i2 = qend();
+ // i1 == i2; // BAM!
+ // now this will cause undefined behaviour.
+ // using native types is ok:
+ // qbegin(...) == qend();
+
+ typedef typename index::detail::single_pass_iterator_type<
+ value_type, const_reference, const_pointer, difference_type
+ >::type const_query_iterator;
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_ENABLE_TYPE_ERASED_ITERATORS
+
+ template <typename Predicates>
+ typename boost::mpl::if_c<
+ detail::predicates_count_distance<Predicates>::value == 0,
+ detail::rtree::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
+ detail::rtree::distance_query_iterator<
+ value_type, options_type, translator_type, box_type, allocators_type, Predicates,
+ detail::predicates_find_distance<Predicates>::value
+ >
+ >::type
+ qbegin(Predicates const& predicates) const
+ {
+ static const unsigned distance_predicates_count = detail::predicates_count_distance<Predicates>::value;
+ BOOST_MPL_ASSERT_MSG((distance_predicates_count <= 1), PASS_ONLY_ONE_DISTANCE_PREDICATE, (Predicates));
+
+ typedef typename boost::mpl::if_c<
+ detail::predicates_count_distance<Predicates>::value == 0,
+ detail::rtree::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
+ detail::rtree::distance_query_iterator<
+ value_type, options_type, translator_type, box_type, allocators_type, Predicates,
+ detail::predicates_find_distance<Predicates>::value
+ >
+ >::type iterator_type;
+
+ if ( !m_members.root )
+ return iterator_type(m_members.translator(), predicates);
+
+ return iterator_type(m_members.root, m_members.translator(), predicates);
+ }
+
+ template <typename Predicates>
+ typename boost::mpl::if_c<
+ detail::predicates_count_distance<Predicates>::value == 0,
+ detail::rtree::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
+ detail::rtree::distance_query_iterator<
+ value_type, options_type, translator_type, box_type, allocators_type, Predicates,
+ detail::predicates_find_distance<Predicates>::value
+ >
+ >::type
+ qend(Predicates const& predicates) const
+ {
+ static const unsigned distance_predicates_count = detail::predicates_count_distance<Predicates>::value;
+ BOOST_MPL_ASSERT_MSG((distance_predicates_count <= 1), PASS_ONLY_ONE_DISTANCE_PREDICATE, (Predicates));
+
+ typedef typename boost::mpl::if_c<
+ detail::predicates_count_distance<Predicates>::value == 0,
+ detail::rtree::spatial_query_iterator<value_type, options_type, translator_type, box_type, allocators_type, Predicates>,
+ detail::rtree::distance_query_iterator<
+ value_type, options_type, translator_type, box_type, allocators_type, Predicates,
+ detail::predicates_find_distance<Predicates>::value
+ >
+ >::type iterator_type;
+
+ return iterator_type(m_members.translator(), predicates);
+ }
+
+ detail::rtree::end_query_iterator<value_type, allocators_type>
+ qend() const
+ {
+ return detail::rtree::end_query_iterator<value_type, allocators_type>();
+ }
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+
+ /*!
+ \brief Returns the number of stored values.
+
+ \return The number of stored values.
+
+ \par Throws
+ Nothing.
+ */
+ inline size_type size() const
+ {
+ return m_members.values_count;
+ }
+
+ /*!
+ \brief Query if the container is empty.
+
+ \return true if the container is empty.
+
+ \par Throws
+ Nothing.
+ */
+ inline bool empty() const
+ {
+ return 0 == m_members.values_count;
+ }
+
+ /*!
+ \brief Removes all values stored in the container.
+
+ \par Throws
+ Nothing.
+ */
+ inline void clear()
+ {
+ this->raw_destroy(*this);
+ }
+
+ /*!
+ \brief Returns the box able to contain all values stored in the container.
+
+ Returns the box able to contain all values stored in the container.
+ If the container is empty the result of \c geometry::assign_inverse() is returned.
+
+ \return The box able to contain all values stored in the container or an invalid box if
+ there are no values in the container.
+
+ \par Throws
+ Nothing.
+ */
+ inline bounds_type bounds() const
+ {
+ bounds_type result;
+ if ( !m_members.root )
+ {
+ geometry::assign_inverse(result);
+ return result;
+ }
+
+ detail::rtree::visitors::children_box<value_type, options_type, translator_type, box_type, allocators_type>
+ box_v(result, m_members.translator());
+ detail::rtree::apply_visitor(box_v, *m_members.root);
+
+ return result;
+ }
+
+ /*!
+ \brief Count Values or Indexables stored in the container.
+
+ For indexable_type it returns the number of values which indexables equals the parameter.
+ For value_type it returns the number of values which equals the parameter.
+
+ \param vori The value or indexable which will be counted.
+
+ \return The number of values found.
+
+ \par Throws
+ Nothing.
+ */
+ template <typename ValueOrIndexable>
+ size_type count(ValueOrIndexable const& vori) const
+ {
+ if ( !m_members.root )
+ return 0;
+
+ detail::rtree::visitors::count<ValueOrIndexable, value_type, options_type, translator_type, box_type, allocators_type>
+ count_v(vori, m_members.translator());
+
+ detail::rtree::apply_visitor(count_v, *m_members.root);
+
+ return count_v.found_count;
+ }
+
+ /*!
+ \brief Returns parameters.
+
+ \return The parameters object.
+
+ \par Throws
+ Nothing.
+ */
+ inline parameters_type parameters() const
+ {
+ return m_members.parameters();
+ }
+
+ /*!
+ \brief Returns function retrieving Indexable from Value.
+
+ \return The indexable_getter object.
+
+ \par Throws
+ Nothing.
+ */
+ indexable_getter indexable_get() const
+ {
+ return m_members.indexable_getter();
+ }
+
+ /*!
+ \brief Returns function comparing Values
+
+ \return The value_equal function.
+
+ \par Throws
+ Nothing.
+ */
+ value_equal value_eq() const
+ {
+ return m_members.equal_to();
+ }
+
+ /*!
+ \brief Returns allocator used by the rtree.
+
+ \return The allocator.
+
+ \par Throws
+ If allocator copy constructor throws.
+ */
+ allocator_type get_allocator() const
+ {
+ return m_members.allocators().allocator();
+ }
+
+private:
+
+ /*!
+ \brief Returns the translator object.
+
+ \return The translator object.
+
+ \par Throws
+ Nothing.
+ */
+ inline translator_type translator() const
+ {
+ return m_members.translator();
+ }
+
+ /*!
+ \brief Apply a visitor to the nodes structure in order to perform some operator.
+
+ This function is not a part of the 'official' interface. However it makes
+ possible e.g. to pass a visitor drawing the tree structure.
+
+ \param visitor The visitor object.
+
+ \par Throws
+ If Visitor::operator() throws.
+ */
+ template <typename Visitor>
+ inline void apply_visitor(Visitor & visitor) const
+ {
+ if ( m_members.root )
+ detail::rtree::apply_visitor(visitor, *m_members.root);
+ }
+
+ /*!
+ \brief Returns the depth of the R-tree.
+
+ This function is not a part of the 'official' interface.
+
+ \return The depth of the R-tree.
+
+ \par Throws
+ Nothing.
+ */
+ inline size_type depth() const
+ {
+ return m_members.leafs_level;
+ }
+
+private:
+
+ /*!
+ \pre Root node must exist - m_root != 0.
+
+ \brief Insert a value to the index.
+
+ \param value The value which will be stored in the container.
+
+ \par Exception-safety
+ basic
+ */
+ inline void raw_insert(value_type const& value)
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(m_members.root, "The root must exist");
+ BOOST_GEOMETRY_INDEX_ASSERT(detail::is_valid(m_members.translator()(value)), "Indexable is invalid");
+
+ detail::rtree::visitors::insert<
+ value_type,
+ value_type, options_type, translator_type, box_type, allocators_type,
+ typename options_type::insert_tag
+ > insert_v(m_members.root, m_members.leafs_level, value,
+ m_members.parameters(), m_members.translator(), m_members.allocators());
+
+ detail::rtree::apply_visitor(insert_v, *m_members.root);
+
+// TODO
+// Think about this: If exception is thrown, may the root be removed?
+// Or it is just cleared?
+
+// TODO
+// If exception is thrown, m_values_count may be invalid
+ ++m_members.values_count;
+ }
+
+ /*!
+ \brief Remove the value from the container.
+
+ \param value The value which will be removed from the container.
+
+ \par Exception-safety
+ basic
+ */
+ inline size_type raw_remove(value_type const& value)
+ {
+ // TODO: awulkiew - assert for correct value (indexable) ?
+ BOOST_GEOMETRY_INDEX_ASSERT(m_members.root, "The root must exist");
+
+ detail::rtree::visitors::remove<
+ value_type, options_type, translator_type, box_type, allocators_type
+ > remove_v(m_members.root, m_members.leafs_level, value,
+ m_members.parameters(), m_members.translator(), m_members.allocators());
+
+ detail::rtree::apply_visitor(remove_v, *m_members.root);
+
+ // If exception is thrown, m_values_count may be invalid
+
+ if ( remove_v.is_value_removed() )
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(0 < m_members.values_count, "unexpected state");
+
+ --m_members.values_count;
+
+ return 1;
+ }
+
+ return 0;
+ }
+
+ /*!
+ \brief Create an empty R-tree i.e. new empty root node and clear other attributes.
+
+ \par Exception-safety
+ strong
+ */
+ inline void raw_create()
+ {
+ BOOST_GEOMETRY_INDEX_ASSERT(0 == m_members.root, "the tree is already created");
+
+ m_members.root = detail::rtree::create_node<allocators_type, leaf>::apply(m_members.allocators()); // MAY THROW (N: alloc)
+ m_members.values_count = 0;
+ m_members.leafs_level = 0;
+ }
+
+ /*!
+ \brief Destroy the R-tree i.e. all nodes and clear attributes.
+
+ \param t The container which is going to be destroyed.
+
+ \par Exception-safety
+ nothrow
+ */
+ inline void raw_destroy(rtree & t)
+ {
+ if ( t.m_members.root )
+ {
+ detail::rtree::visitors::destroy<value_type, options_type, translator_type, box_type, allocators_type>
+ del_v(t.m_members.root, t.m_members.allocators());
+ detail::rtree::apply_visitor(del_v, *t.m_members.root);
+
+ t.m_members.root = 0;
+ }
+ t.m_members.values_count = 0;
+ t.m_members.leafs_level = 0;
+ }
+
+ /*!
+ \brief Copy the R-tree i.e. whole nodes structure, values and other attributes.
+ It uses destination's allocators to create the new structure.
+
+ \param src The source R-tree.
+ \param dst The destination R-tree.
+ \param copy_tr_and_params If true, translator and parameters will also be copied.
+
+ \par Exception-safety
+ strong
+ */
+ inline void raw_copy(rtree const& src, rtree & dst, bool copy_tr_and_params) const
+ {
+ detail::rtree::visitors::copy<value_type, options_type, translator_type, box_type, allocators_type>
+ copy_v(dst.m_members.allocators());
+
+ if ( src.m_members.root )
+ detail::rtree::apply_visitor(copy_v, *src.m_members.root); // MAY THROW (V, E: alloc, copy, N: alloc)
+
+ if ( copy_tr_and_params )
+ {
+ dst.m_members.indexable_getter() = src.m_members.indexable_getter();
+ dst.m_members.equal_to() = src.m_members.equal_to();
+ dst.m_members.parameters() = src.m_members.parameters();
+ }
+
+ if ( dst.m_members.root )
+ {
+ detail::rtree::visitors::destroy<value_type, options_type, translator_type, box_type, allocators_type>
+ del_v(dst.m_members.root, dst.m_members.allocators());
+ detail::rtree::apply_visitor(del_v, *dst.m_members.root);
+ dst.m_members.root = 0;
+ }
+
+ dst.m_members.root = copy_v.result;
+ dst.m_members.values_count = src.m_members.values_count;
+ dst.m_members.leafs_level = src.m_members.leafs_level;
+ }
+
+ /*!
+ \brief Return values meeting predicates.
+
+ \par Exception-safety
+ strong
+ */
+ template <typename Predicates, typename OutIter>
+ size_type query_dispatch(Predicates const& predicates, OutIter out_it, boost::mpl::bool_<false> const& /*is_distance_predicate*/) const
+ {
+ detail::rtree::visitors::spatial_query<value_type, options_type, translator_type, box_type, allocators_type, Predicates, OutIter>
+ find_v(m_members.translator(), predicates, out_it);
+
+ detail::rtree::apply_visitor(find_v, *m_members.root);
+
+ return find_v.found_count;
+ }
+
+ /*!
+ \brief Perform nearest neighbour search.
+
+ \par Exception-safety
+ strong
+ */
+ template <typename Predicates, typename OutIter>
+ size_type query_dispatch(Predicates const& predicates, OutIter out_it, boost::mpl::bool_<true> const& /*is_distance_predicate*/) const
+ {
+ static const unsigned distance_predicate_index = detail::predicates_find_distance<Predicates>::value;
+ detail::rtree::visitors::distance_query<
+ value_type,
+ options_type,
+ translator_type,
+ box_type,
+ allocators_type,
+ Predicates,
+ distance_predicate_index,
+ OutIter
+ > distance_v(m_members.parameters(), m_members.translator(), predicates, out_it);
+
+ detail::rtree::apply_visitor(distance_v, *m_members.root);
+
+ return distance_v.finish();
+ }
+
+ struct members_holder
+ : public translator_type
+ , public Parameters
+ , public allocators_type
+ {
+ private:
+ members_holder(members_holder const&);
+ members_holder & operator=(members_holder const&);
+
+ public:
+ template <typename IndGet, typename ValEq, typename Alloc>
+ members_holder(IndGet const& ind_get,
+ ValEq const& val_eq,
+ Parameters const& parameters,
+ BOOST_FWD_REF(Alloc) alloc)
+ : translator_type(ind_get, val_eq)
+ , Parameters(parameters)
+ , allocators_type(boost::forward<Alloc>(alloc))
+ , values_count(0)
+ , leafs_level(0)
+ , root(0)
+ {}
+
+ template <typename IndGet, typename ValEq>
+ members_holder(IndGet const& ind_get,
+ ValEq const& val_eq,
+ Parameters const& parameters)
+ : translator_type(ind_get, val_eq)
+ , Parameters(parameters)
+ , allocators_type()
+ , values_count(0)
+ , leafs_level(0)
+ , root(0)
+ {}
+
+ translator_type const& translator() const { return *this; }
+
+ IndexableGetter const& indexable_getter() const { return *this; }
+ IndexableGetter & indexable_getter() { return *this; }
+ EqualTo const& equal_to() const { return *this; }
+ EqualTo & equal_to() { return *this; }
+ Parameters const& parameters() const { return *this; }
+ Parameters & parameters() { return *this; }
+ allocators_type const& allocators() const { return *this; }
+ allocators_type & allocators() { return *this; }
+
+ size_type values_count;
+ size_type leafs_level;
+ node_pointer root;
+ };
+
+ members_holder m_members;
+};
+
+/*!
+\brief Insert a value to the index.
+
+It calls <tt>rtree::insert(value_type const&)</tt>.
+
+\ingroup rtree_functions
+
+\param tree The spatial index.
+\param v The value which will be stored in the index.
+*/
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>
+inline void insert(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & tree, Value const& v)
+{
+ tree.insert(v);
+}
+
+/*!
+\brief Insert a range of values to the index.
+
+It calls <tt>rtree::insert(Iterator, Iterator)</tt>.
+
+\ingroup rtree_functions
+
+\param tree The spatial index.
+\param first The beginning of the range of values.
+\param last The end of the range of values.
+*/
+template<typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator, typename Iterator>
+inline void insert(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & tree, Iterator first, Iterator last)
+{
+ tree.insert(first, last);
+}
+
+/*!
+\brief Insert a range of values to the index.
+
+It calls <tt>rtree::insert(Range const&)</tt>.
+
+\ingroup rtree_functions
+
+\param tree The spatial index.
+\param rng The range of values.
+*/
+template<typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator, typename Range>
+inline void insert(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & tree, Range const& rng)
+{
+ tree.insert(rng);
+}
+
+/*!
+\brief Remove a value from the container.
+
+Remove a value from the container. In contrast to the \c std::set or <tt>std::map erase()</tt> method
+this function removes only one value from the container.
+
+It calls <tt>rtree::remove(value_type const&)</tt>.
+
+\ingroup rtree_functions
+
+\param tree The spatial index.
+\param v The value which will be removed from the index.
+
+\return 1 if value was removed, 0 otherwise.
+*/
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>
+inline typename rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>::size_type
+remove(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & tree, Value const& v)
+{
+ return tree.remove(v);
+}
+
+/*!
+\brief Remove a range of values from the container.
+
+Remove a range of values from the container. In contrast to the \c std::set or <tt>std::map erase()</tt> method
+it doesn't take iterators pointing to values stored in this container. It removes values equal
+to these passed as a range. Furthermore this function removes only one value for each one passed
+in the range, not all equal values.
+
+It calls <tt>rtree::remove(Iterator, Iterator)</tt>.
+
+\ingroup rtree_functions
+
+\param tree The spatial index.
+\param first The beginning of the range of values.
+\param last The end of the range of values.
+
+\return The number of removed values.
+*/
+template<typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator, typename Iterator>
+inline typename rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>::size_type
+remove(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & tree, Iterator first, Iterator last)
+{
+ return tree.remove(first, last);
+}
+
+/*!
+\brief Remove a range of values from the container.
+
+Remove a range of values from the container. In contrast to the \c std::set or <tt>std::map erase()</tt> method
+it removes values equal to these passed as a range. Furthermore this method removes only
+one value for each one passed in the range, not all equal values.
+
+It calls <tt>rtree::remove(Range const&)</tt>.
+
+\ingroup rtree_functions
+
+\param tree The spatial index.
+\param rng The range of values.
+
+\return The number of removed values.
+*/
+template<typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator, typename Range>
+inline typename rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>::size_type
+remove(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & tree, Range const& rng)
+{
+ return tree.remove(rng);
+}
+
+/*!
+\brief Finds values meeting passed predicates e.g. nearest to some Point and/or intersecting some Box.
+
+This query function performs spatial and k-nearest neighbor searches. It allows to pass a set of predicates.
+Values will be returned only if all predicates are met.
+
+<b>Spatial predicates</b>
+
+Spatial predicates may be generated by one of the functions listed below:
+\li \c boost::geometry::index::covered_by(),
+\li \c boost::geometry::index::disjoint(),
+\li \c boost::geometry::index::intersects(),
+\li \c boost::geometry::index::overlaps(),
+\li \c boost::geometry::index::within(),
+
+It is possible to negate spatial predicates:
+\li <tt>! boost::geometry::index::covered_by()</tt>,
+\li <tt>! boost::geometry::index::disjoint()</tt>,
+\li <tt>! boost::geometry::index::intersects()</tt>,
+\li <tt>! boost::geometry::index::overlaps()</tt>,
+\li <tt>! boost::geometry::index::within()</tt>
+
+<b>Satisfies predicate</b>
+
+This is a special kind of predicate which allows to pass a user-defined function or function object which checks
+if Value should be returned by the query. It's generated by:
+\li \c boost::geometry::index::satisfies().
+
+<b>Nearest predicate</b>
+
+If the nearest predicate is passed a k-nearest neighbor search will be performed. This query will result
+in returning k values to the output iterator. Only one nearest predicate may be passed to the query.
+It may be generated by:
+\li \c boost::geometry::index::nearest().
+
+<b>Connecting predicates</b>
+
+Predicates may be passed together connected with \c operator&&().
+
+\par Example
+\verbatim
+// return elements intersecting box
+bgi::query(tree, bgi::intersects(box), std::back_inserter(result));
+// return elements intersecting poly but not within box
+bgi::query(tree, bgi::intersects(poly) && !bgi::within(box), std::back_inserter(result));
+// return elements overlapping box and meeting my_fun value predicate
+bgi::query(tree, bgi::overlaps(box) && bgi::satisfies(my_fun), std::back_inserter(result));
+// return 5 elements nearest to pt and elements are intersecting box
+bgi::query(tree, bgi::nearest(pt, 5) && bgi::intersects(box), std::back_inserter(result));
+\endverbatim
+
+\par Throws
+If Value copy constructor or copy assignment throws.
+
+\warning
+Only one \c nearest() perdicate may be passed to the query. Passing more of them results in compile-time error.
+
+\ingroup rtree_functions
+
+\param tree The rtree.
+\param predicates Predicates.
+\param out_it The output iterator, e.g. generated by std::back_inserter().
+
+\return The number of values found.
+*/
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator,
+ typename Predicates, typename OutIter> inline
+typename rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>::size_type
+query(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree,
+ Predicates const& predicates,
+ OutIter out_it)
+{
+ return tree.query(predicates, out_it);
+}
+
+/*!
+\brief Remove all values from the index.
+
+It calls \c rtree::clear().
+
+\ingroup rtree_functions
+
+\param tree The spatial index.
+*/
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>
+inline void clear(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & tree)
+{
+ return tree.clear();
+}
+
+/*!
+\brief Get the number of values stored in the index.
+
+It calls \c rtree::size().
+
+\ingroup rtree_functions
+
+\param tree The spatial index.
+
+\return The number of values stored in the index.
+*/
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>
+inline size_t size(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree)
+{
+ return tree.size();
+}
+
+/*!
+\brief Query if there are no values stored in the index.
+
+It calls \c rtree::empty().
+
+\ingroup rtree_functions
+
+\param tree The spatial index.
+
+\return true if there are no values in the index.
+*/
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>
+inline bool empty(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree)
+{
+ return tree.bounds();
+}
+
+/*!
+\brief Get the box containing all stored values or an invalid box if the index has no values.
+
+It calls \c rtree::envelope().
+
+\ingroup rtree_functions
+
+\param tree The spatial index.
+
+\return The box containing all stored values or an invalid box.
+*/
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>
+inline typename rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator>::bounds_type
+bounds(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree)
+{
+ return tree.bounds();
+}
+
+/*!
+\brief Exchanges the contents of the container with those of other.
+
+It calls \c rtree::swap().
+
+\ingroup rtree_functions
+
+\param l The first rtree.
+\param r The second rtree.
+*/
+template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator>
+inline void swap(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & l,
+ rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> & r)
+{
+ return l.swap(r);
+}
+
+}}} // namespace boost::geometry::index
+
+#include <boost/geometry/index/detail/config_end.hpp>
+
+#endif // BOOST_GEOMETRY_INDEX_RTREE_HPP
diff --git a/boost/geometry/io/dsv/write.hpp b/boost/geometry/io/dsv/write.hpp
new file mode 100644
index 000000000..62929f807
--- /dev/null
+++ b/boost/geometry/io/dsv/write.hpp
@@ -0,0 +1,375 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_DSV_WRITE_HPP
+#define BOOST_GEOMETRY_IO_DSV_WRITE_HPP
+
+#include <cstddef>
+#include <ostream>
+#include <string>
+
+#include <boost/concept_check.hpp>
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace dsv
+{
+
+struct dsv_settings
+{
+ std::string coordinate_separator;
+ std::string point_open;
+ std::string point_close;
+ std::string point_separator;
+ std::string list_open;
+ std::string list_close;
+ std::string list_separator;
+
+ dsv_settings(std::string const& sep
+ , std::string const& open
+ , std::string const& close
+ , std::string const& psep
+ , std::string const& lopen
+ , std::string const& lclose
+ , std::string const& lsep
+ )
+ : coordinate_separator(sep)
+ , point_open(open)
+ , point_close(close)
+ , point_separator(psep)
+ , list_open(lopen)
+ , list_close(lclose)
+ , list_separator(lsep)
+ {}
+};
+
+/*!
+\brief Stream coordinate of a point as \ref DSV
+*/
+template <typename Point, std::size_t Dimension, std::size_t Count>
+struct stream_coordinate
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Point const& point,
+ dsv_settings const& settings)
+ {
+ os << (Dimension > 0 ? settings.coordinate_separator : "")
+ << get<Dimension>(point);
+
+ stream_coordinate
+ <
+ Point, Dimension + 1, Count
+ >::apply(os, point, settings);
+ }
+};
+
+template <typename Point, std::size_t Count>
+struct stream_coordinate<Point, Count, Count>
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>&,
+ Point const&,
+ dsv_settings const& )
+ {
+ }
+};
+
+/*!
+\brief Stream indexed coordinate of a box/segment as \ref DSV
+*/
+template
+<
+ typename Geometry,
+ std::size_t Index,
+ std::size_t Dimension,
+ std::size_t Count
+>
+struct stream_indexed
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Geometry const& geometry,
+ dsv_settings const& settings)
+ {
+ os << (Dimension > 0 ? settings.coordinate_separator : "")
+ << get<Index, Dimension>(geometry);
+ stream_indexed
+ <
+ Geometry, Index, Dimension + 1, Count
+ >::apply(os, geometry, settings);
+ }
+};
+
+template <typename Geometry, std::size_t Index, std::size_t Count>
+struct stream_indexed<Geometry, Index, Count, Count>
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>&, Geometry const&,
+ dsv_settings const& )
+ {
+ }
+};
+
+/*!
+\brief Stream points as \ref DSV
+*/
+template <typename Point>
+struct dsv_point
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Point const& p,
+ dsv_settings const& settings)
+ {
+ os << settings.point_open;
+ stream_coordinate<Point, 0, dimension<Point>::type::value>::apply(os, p, settings);
+ os << settings.point_close;
+ }
+};
+
+/*!
+\brief Stream ranges as DSV
+\note policy is used to stream prefix/postfix, enabling derived classes to override this
+*/
+template <typename Range>
+struct dsv_range
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Range const& range,
+ dsv_settings const& settings)
+ {
+ typedef typename boost::range_iterator<Range const>::type iterator_type;
+
+ bool first = true;
+
+ os << settings.list_open;
+
+ for (iterator_type it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ os << (first ? "" : settings.point_separator)
+ << settings.point_open;
+
+ stream_coordinate
+ <
+ point_type, 0, dimension<point_type>::type::value
+ >::apply(os, *it, settings);
+ os << settings.point_close;
+
+ first = false;
+ }
+
+ os << settings.list_close;
+ }
+
+private:
+ typedef typename boost::range_value<Range>::type point_type;
+};
+
+/*!
+\brief Stream sequence of points as DSV-part, e.g. (1 2),(3 4)
+\note Used in polygon, all multi-geometries
+*/
+
+template <typename Polygon>
+struct dsv_poly
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Polygon const& poly,
+ dsv_settings const& settings)
+ {
+ typedef typename ring_type<Polygon>::type ring;
+
+ os << settings.list_open;
+
+ dsv_range<ring>::apply(os, exterior_ring(poly), settings);
+
+ typename interior_return_type<Polygon const>::type rings
+ = interior_rings(poly);
+ for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++it)
+ {
+ os << settings.list_separator;
+ dsv_range<ring>::apply(os, *it, settings);
+ }
+ os << settings.list_close;
+ }
+};
+
+template <typename Geometry, std::size_t Index>
+struct dsv_per_index
+{
+ typedef typename point_type<Geometry>::type point_type;
+
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Geometry const& geometry,
+ dsv_settings const& settings)
+ {
+ os << settings.point_open;
+ stream_indexed
+ <
+ Geometry, Index, 0, dimension<Geometry>::type::value
+ >::apply(os, geometry, settings);
+ os << settings.point_close;
+ }
+};
+
+template <typename Geometry>
+struct dsv_indexed
+{
+ typedef typename point_type<Geometry>::type point_type;
+
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Geometry const& geometry,
+ dsv_settings const& settings)
+ {
+ os << settings.list_open;
+ dsv_per_index<Geometry, 0>::apply(os, geometry, settings);
+ os << settings.point_separator;
+ dsv_per_index<Geometry, 1>::apply(os, geometry, settings);
+ os << settings.list_close;
+ }
+};
+
+}} // namespace detail::dsv
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, typename Geometry>
+struct dsv {};
+
+template <typename Point>
+struct dsv<point_tag, Point>
+ : detail::dsv::dsv_point<Point>
+{};
+
+template <typename Linestring>
+struct dsv<linestring_tag, Linestring>
+ : detail::dsv::dsv_range<Linestring>
+{};
+
+template <typename Box>
+struct dsv<box_tag, Box>
+ : detail::dsv::dsv_indexed<Box>
+{};
+
+template <typename Segment>
+struct dsv<segment_tag, Segment>
+ : detail::dsv::dsv_indexed<Segment>
+{};
+
+template <typename Ring>
+struct dsv<ring_tag, Ring>
+ : detail::dsv::dsv_range<Ring>
+{};
+
+template <typename Polygon>
+struct dsv<polygon_tag, Polygon>
+ : detail::dsv::dsv_poly<Polygon>
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace dsv
+{
+
+// FIXME: This class is not copyable/assignable but it is used as such --mloskot
+template <typename Geometry>
+class dsv_manipulator
+{
+public:
+
+ inline dsv_manipulator(Geometry const& g,
+ dsv_settings const& settings)
+ : m_geometry(g)
+ , m_settings(settings)
+ {}
+
+ template <typename Char, typename Traits>
+ inline friend std::basic_ostream<Char, Traits>& operator<<(
+ std::basic_ostream<Char, Traits>& os,
+ dsv_manipulator const& m)
+ {
+ dispatch::dsv
+ <
+ typename tag_cast
+ <
+ typename tag<Geometry>::type,
+ multi_tag
+ >::type,
+ Geometry
+ >::apply(os, m.m_geometry, m.m_settings);
+ os.flush();
+ return os;
+ }
+
+private:
+ Geometry const& m_geometry;
+ dsv_settings m_settings;
+};
+
+}} // namespace detail::dsv
+#endif // DOXYGEN_NO_DETAIL
+
+/*!
+\brief Main DSV-streaming function
+\details DSV stands for Delimiter Separated Values. Geometries can be streamed
+ as DSV. There are defaults for all separators.
+\note Useful for examples and testing purposes
+\note With this function GeoJSON objects can be created, using the right
+ delimiters
+\ingroup utility
+*/
+template <typename Geometry>
+inline detail::dsv::dsv_manipulator<Geometry> dsv(Geometry const& geometry
+ , std::string const& coordinate_separator = ", "
+ , std::string const& point_open = "("
+ , std::string const& point_close = ")"
+ , std::string const& point_separator = ", "
+ , std::string const& list_open = "("
+ , std::string const& list_close = ")"
+ , std::string const& list_separator = ", "
+ )
+{
+ concept::check<Geometry const>();
+
+ return detail::dsv::dsv_manipulator<Geometry>(geometry,
+ detail::dsv::dsv_settings(coordinate_separator,
+ point_open, point_close, point_separator,
+ list_open, list_close, list_separator));
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_IO_DSV_WRITE_HPP
diff --git a/boost/geometry/io/io.hpp b/boost/geometry/io/io.hpp
new file mode 100644
index 000000000..934006077
--- /dev/null
+++ b/boost/geometry/io/io.hpp
@@ -0,0 +1,58 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_HPP
+#define BOOST_GEOMETRY_IO_HPP
+
+#include <boost/geometry/io/wkt/read.hpp>
+#include <boost/geometry/io/wkt/write.hpp>
+
+namespace boost { namespace geometry
+{
+
+struct format_wkt {};
+struct format_wkb {}; // TODO
+struct format_dsv {}; // TODO
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+template <typename Tag, typename Geometry>
+struct read
+{
+};
+
+template <typename Geometry>
+struct read<format_wkt, Geometry>
+{
+ static inline void apply(Geometry& geometry, std::string const& wkt)
+ {
+ read_wkt<typename tag<Geometry>::type, Geometry>::apply(wkt, geometry);
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+template <typename Format, typename Geometry>
+inline void read(Geometry& geometry, std::string const& wkt)
+{
+ geometry::concept::check<Geometry>();
+ dispatch::read<Format, Geometry>::apply(geometry, wkt);
+}
+
+// TODO: wriite
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_IO_HPP
diff --git a/boost/geometry/io/svg/svg_mapper.hpp b/boost/geometry/io/svg/svg_mapper.hpp
new file mode 100644
index 000000000..1252cc806
--- /dev/null
+++ b/boost/geometry/io/svg/svg_mapper.hpp
@@ -0,0 +1,392 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_SVG_MAPPER_HPP
+#define BOOST_GEOMETRY_IO_SVG_MAPPER_HPP
+
+#include <cstdio>
+
+#include <vector>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/classification.hpp>
+
+
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+
+#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/algorithms/expand.hpp>
+#include <boost/geometry/algorithms/transform.hpp>
+#include <boost/geometry/algorithms/num_points.hpp>
+#include <boost/geometry/strategies/transform.hpp>
+#include <boost/geometry/strategies/transform/map_transformer.hpp>
+#include <boost/geometry/views/segment_view.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/algorithms/envelope.hpp>
+#include <boost/geometry/multi/algorithms/num_points.hpp>
+
+#include <boost/geometry/io/svg/write_svg.hpp>
+
+// Helper geometries (all points are transformed to integer-points)
+#include <boost/geometry/geometries/geometries.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace svg
+{
+ typedef model::point<int, 2, cs::cartesian> svg_point_type;
+}}
+#endif
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+
+template <typename GeometryTag, typename Geometry>
+struct svg_map
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (Geometry)
+ );
+};
+
+
+template <typename Point>
+struct svg_map<point_tag, Point>
+{
+ template <typename TransformStrategy>
+ static inline void apply(std::ostream& stream,
+ std::string const& style, int size,
+ Point const& point, TransformStrategy const& strategy)
+ {
+ detail::svg::svg_point_type ipoint;
+ geometry::transform(point, ipoint, strategy);
+ stream << geometry::svg(ipoint, style, size) << std::endl;
+ }
+};
+
+template <typename Box>
+struct svg_map<box_tag, Box>
+{
+ template <typename TransformStrategy>
+ static inline void apply(std::ostream& stream,
+ std::string const& style, int size,
+ Box const& box, TransformStrategy const& strategy)
+ {
+ model::box<detail::svg::svg_point_type> ibox;
+ geometry::transform(box, ibox, strategy);
+
+ stream << geometry::svg(ibox, style, size) << std::endl;
+ }
+};
+
+
+template <typename Range1, typename Range2>
+struct svg_map_range
+{
+ template <typename TransformStrategy>
+ static inline void apply(std::ostream& stream,
+ std::string const& style, int size,
+ Range1 const& range, TransformStrategy const& strategy)
+ {
+ Range2 irange;
+ geometry::transform(range, irange, strategy);
+ stream << geometry::svg(irange, style, size) << std::endl;
+ }
+};
+
+template <typename Segment>
+struct svg_map<segment_tag, Segment>
+{
+ template <typename TransformStrategy>
+ static inline void apply(std::ostream& stream,
+ std::string const& style, int size,
+ Segment const& segment, TransformStrategy const& strategy)
+ {
+ typedef segment_view<Segment> view_type;
+ view_type range(segment);
+ svg_map_range
+ <
+ view_type,
+ model::linestring<detail::svg::svg_point_type>
+ >::apply(stream, style, size, range, strategy);
+ }
+};
+
+
+template <typename Ring>
+struct svg_map<ring_tag, Ring>
+ : svg_map_range<Ring, model::ring<detail::svg::svg_point_type> >
+{};
+
+
+template <typename Linestring>
+struct svg_map<linestring_tag, Linestring>
+ : svg_map_range<Linestring, model::linestring<detail::svg::svg_point_type> >
+{};
+
+
+template <typename Polygon>
+struct svg_map<polygon_tag, Polygon>
+{
+ template <typename TransformStrategy>
+ static inline void apply(std::ostream& stream,
+ std::string const& style, int size,
+ Polygon const& polygon, TransformStrategy const& strategy)
+ {
+ model::polygon<detail::svg::svg_point_type> ipoly;
+ geometry::transform(polygon, ipoly, strategy);
+ stream << geometry::svg(ipoly, style, size) << std::endl;
+ }
+};
+
+
+template <typename Multi>
+struct svg_map<multi_tag, Multi>
+{
+ typedef typename single_tag_of
+ <
+ typename geometry::tag<Multi>::type
+ >::type stag;
+
+ template <typename TransformStrategy>
+ static inline void apply(std::ostream& stream,
+ std::string const& style, int size,
+ Multi const& multi, TransformStrategy const& strategy)
+ {
+ for (typename boost::range_iterator<Multi const>::type it
+ = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ svg_map
+ <
+ stag,
+ typename boost::range_value<Multi>::type
+ >::apply(stream, style, size, *it, strategy);
+ }
+ }
+};
+
+
+} // namespace dispatch
+#endif
+
+
+template <typename Geometry, typename TransformStrategy>
+inline void svg_map(std::ostream& stream,
+ std::string const& style, int size,
+ Geometry const& geometry, TransformStrategy const& strategy)
+{
+ dispatch::svg_map
+ <
+ typename tag_cast
+ <
+ typename tag<Geometry>::type,
+ multi_tag
+ >::type,
+ typename boost::remove_const<Geometry>::type
+ >::apply(stream, style, size, geometry, strategy);
+}
+
+
+/*!
+\brief Helper class to create SVG maps
+\tparam Point Point type, for input geometries.
+\tparam SameScale Boolean flag indicating if horizontal and vertical scale should
+ be the same. The default value is true
+\ingroup svg
+
+\qbk{[include reference/io/svg.qbk]}
+*/
+template <typename Point, bool SameScale = true>
+class svg_mapper : boost::noncopyable
+{
+ typedef strategy::transform::map_transformer
+ <
+ Point,
+ detail::svg::svg_point_type,
+ true,
+ SameScale
+ > transformer_type;
+
+ model::box<Point> m_bounding_box;
+ boost::scoped_ptr<transformer_type> m_matrix;
+ std::ostream& m_stream;
+ int m_width, m_height;
+ std::string m_width_height; // for <svg> tag only, defaults to 2x 100%
+
+ void init_matrix()
+ {
+ if (! m_matrix)
+ {
+ m_matrix.reset(new transformer_type(m_bounding_box,
+ m_width, m_height));
+
+ m_stream << "<?xml version=\"1.0\" standalone=\"no\"?>"
+ << std::endl
+ << "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\""
+ << std::endl
+ << "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">"
+ << std::endl
+ << "<svg " << m_width_height << " version=\"1.1\""
+ << std::endl
+ << "xmlns=\"http://www.w3.org/2000/svg\">"
+ << std::endl;
+ }
+ }
+
+public :
+
+ /*!
+ \brief Constructor, initializing the SVG map. Opens and initializes the SVG.
+ Should be called explicitly.
+ \param stream Output stream, should be a stream already open
+ \param width Width of the SVG map (in SVG pixels)
+ \param height Height of the SVG map (in SVG pixels)
+ \param width_height Optional information to increase width and/or height
+ */
+ explicit svg_mapper(std::ostream& stream, int width, int height
+ , std::string const& width_height = "width=\"100%\" height=\"100%\"")
+ : m_stream(stream)
+ , m_width(width)
+ , m_height(height)
+ , m_width_height(width_height)
+ {
+ assign_inverse(m_bounding_box);
+ }
+
+ /*!
+ \brief Destructor, called automatically. Closes the SVG by streaming <\/svg>
+ */
+ virtual ~svg_mapper()
+ {
+ m_stream << "</svg>" << std::endl;
+ }
+
+ /*!
+ \brief Adds a geometry to the transformation matrix. After doing this,
+ the specified geometry can be mapped fully into the SVG map
+ \tparam Geometry \tparam_geometry
+ \param geometry \param_geometry
+ */
+ template <typename Geometry>
+ void add(Geometry const& geometry)
+ {
+ if (num_points(geometry) > 0)
+ {
+ expand(m_bounding_box,
+ return_envelope
+ <
+ model::box<Point>
+ >(geometry));
+ }
+ }
+
+ /*!
+ \brief Maps a geometry into the SVG map using the specified style
+ \tparam Geometry \tparam_geometry
+ \param geometry \param_geometry
+ \param style String containing verbatim SVG style information
+ \param size Optional size (used for SVG points) in SVG pixels. For linestrings,
+ specify linewidth in the SVG style information
+ */
+ template <typename Geometry>
+ void map(Geometry const& geometry, std::string const& style,
+ int size = -1)
+ {
+ BOOST_MPL_ASSERT_MSG
+ (
+ ( boost::is_same
+ <
+ Point,
+ typename point_type<Geometry>::type
+ >::value )
+ , POINT_TYPES_ARE_NOT_SAME_FOR_MAPPER_AND_MAP
+ , (types<Point, typename point_type<Geometry>::type>)
+ );
+
+
+ init_matrix();
+ svg_map(m_stream, style, size, geometry, *m_matrix);
+ }
+
+ /*!
+ \brief Adds a text to the SVG map
+ \tparam TextPoint \tparam_point
+ \param point Location of the text (in map units)
+ \param s The text itself
+ \param style String containing verbatim SVG style information, of the text
+ \param offset_x Offset in SVG pixels, defaults to 0
+ \param offset_y Offset in SVG pixels, defaults to 0
+ \param lineheight Line height in SVG pixels, in case the text contains \n
+ */
+ template <typename TextPoint>
+ void text(TextPoint const& point, std::string const& s,
+ std::string const& style,
+ int offset_x = 0, int offset_y = 0, int lineheight = 10)
+ {
+ init_matrix();
+ detail::svg::svg_point_type map_point;
+ transform(point, map_point, *m_matrix);
+ m_stream
+ << "<text style=\"" << style << "\""
+ << " x=\"" << get<0>(map_point) + offset_x << "\""
+ << " y=\"" << get<1>(map_point) + offset_y << "\""
+ << ">";
+ if (s.find("\n") == std::string::npos)
+ {
+ m_stream << s;
+ }
+ else
+ {
+ // Multi-line modus
+
+ std::vector<std::string> splitted;
+ boost::split(splitted, s, boost::is_any_of("\n"));
+ for (std::vector<std::string>::const_iterator it
+ = splitted.begin();
+ it != splitted.end();
+ ++it, offset_y += lineheight)
+ {
+ m_stream
+ << "<tspan x=\"" << get<0>(map_point) + offset_x
+ << "\""
+ << " y=\"" << get<1>(map_point) + offset_y
+ << "\""
+ << ">" << *it << "</tspan>";
+ }
+ }
+ m_stream << "</text>" << std::endl;
+ }
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_IO_SVG_MAPPER_HPP
diff --git a/boost/geometry/io/svg/write_svg.hpp b/boost/geometry/io/svg/write_svg.hpp
new file mode 100644
index 000000000..15fa9c11c
--- /dev/null
+++ b/boost/geometry/io/svg/write_svg.hpp
@@ -0,0 +1,277 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP
+#define BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP
+
+#include <ostream>
+#include <string>
+
+#include <boost/config.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace svg
+{
+
+
+template <typename Point>
+struct svg_point
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Point const& p, std::string const& style, int size)
+ {
+ os << "<circle cx=\"" << geometry::get<0>(p)
+ << "\" cy=\"" << geometry::get<1>(p)
+ << "\" 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 )
+ {
+ // Prevent invisible boxes, making them >=1, using "max"
+ BOOST_USING_STD_MAX();
+
+ typedef typename coordinate_type<Box>::type ct;
+ ct x = geometry::get<geometry::min_corner, 0>(box);
+ ct y = geometry::get<geometry::min_corner, 1>(box);
+ ct width = max BOOST_PREVENT_MACRO_SUBSTITUTION(1,
+ geometry::get<geometry::max_corner, 0>(box) - x);
+ ct height = max BOOST_PREVENT_MACRO_SUBSTITUTION (1,
+ geometry::get<geometry::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 )
+ {
+ typedef typename boost::range_iterator<Range const>::type iterator;
+
+ bool first = true;
+
+ os << "<" << Policy::prefix() << " points=\"";
+
+ for (iterator it = boost::begin(range);
+ it != boost::end(range);
+ ++it, first = false)
+ {
+ os << (first ? "" : " " )
+ << geometry::get<0>(*it)
+ << ","
+ << geometry::get<1>(*it);
+ }
+ 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 )
+ {
+ typedef typename geometry::ring_type<Polygon>::type ring_type;
+ typedef typename boost::range_iterator<ring_type const>::type iterator_type;
+
+ bool first = true;
+ os << "<g fill-rule=\"evenodd\"><path d=\"";
+
+ ring_type const& ring = geometry::exterior_ring(polygon);
+ for (iterator_type it = boost::begin(ring);
+ it != boost::end(ring);
+ ++it, first = false)
+ {
+ os << (first ? "M" : " L") << " "
+ << geometry::get<0>(*it)
+ << ","
+ << geometry::get<1>(*it);
+ }
+
+ // Inner rings:
+ {
+ typename interior_return_type<Polygon const>::type rings
+ = interior_rings(polygon);
+ for (BOOST_AUTO_TPL(rit, boost::begin(rings));
+ rit != boost::end(rings); ++rit)
+ {
+ first = true;
+ for (BOOST_AUTO_TPL(it, boost::begin(*rit)); it != boost::end(*rit);
+ ++it, first = false)
+ {
+ os << (first ? "M" : " L") << " "
+ << geometry::get<0>(*it)
+ << ","
+ << geometry::get<1>(*it);
+ }
+ }
+ }
+ 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, G const& geometry)
+*/
+template <typename GeometryTag, typename Geometry>
+struct svg
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (Geometry)
+ );
+};
+
+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 SVG (Scalable Vector Graphics)
+*/
+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 Manipulator to stream geometries as SVG
+\tparam Geometry \tparam_geometry
+\param geometry \param_geometry
+\param style String containing verbatim SVG style information
+\param size Optional size (used for SVG points) in SVG pixels. For linestrings,
+ specify linewidth in the SVG style information
+\ingroup svg
+*/
+template <typename Geometry>
+inline svg_manipulator<Geometry> svg(Geometry const& geometry, std::string const& style, int size = -1)
+{
+ concept::check<Geometry const>();
+
+ return svg_manipulator<Geometry>(geometry, style, size);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_IO_SVG_WRITE_SVG_HPP
diff --git a/boost/geometry/io/svg/write_svg_multi.hpp b/boost/geometry/io/svg/write_svg_multi.hpp
new file mode 100644
index 000000000..a794120c0
--- /dev/null
+++ b/boost/geometry/io/svg/write_svg_multi.hpp
@@ -0,0 +1,78 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_SVG_WRITE_SVG_MULTI_HPP
+#define BOOST_GEOMETRY_IO_SVG_WRITE_SVG_MULTI_HPP
+
+
+#include <boost/geometry/io/svg/write_svg.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace svg
+{
+
+
+template <typename MultiGeometry, typename Policy>
+struct svg_multi
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ MultiGeometry const& multi, std::string const& style, int size)
+ {
+ for (typename boost::range_iterator<MultiGeometry const>::type
+ it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ Policy::apply(os, *it, style, size);
+ }
+
+ }
+
+};
+
+
+
+}} // namespace detail::svg
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename MultiPolygon>
+struct svg<multi_polygon_tag, MultiPolygon>
+ : detail::svg::svg_multi
+ <
+ MultiPolygon,
+ detail::svg::svg_poly
+ <
+ typename boost::range_value<MultiPolygon>::type
+ >
+
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_IO_SVG_WRITE_SVG_MULTI_HPP
diff --git a/boost/geometry/io/wkt/detail/prefix.hpp b/boost/geometry/io/wkt/detail/prefix.hpp
new file mode 100644
index 000000000..45e43b88d
--- /dev/null
+++ b/boost/geometry/io/wkt/detail/prefix.hpp
@@ -0,0 +1,45 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_WKT_DETAIL_PREFIX_HPP
+#define BOOST_GEOMETRY_IO_WKT_DETAIL_PREFIX_HPP
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace wkt
+{
+
+struct prefix_point
+{
+ static inline const char* apply() { return "POINT"; }
+};
+
+struct prefix_polygon
+{
+ static inline const char* apply() { return "POLYGON"; }
+};
+
+struct prefix_linestring
+{
+ static inline const char* apply() { return "LINESTRING"; }
+};
+
+}} // namespace wkt::impl
+#endif
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_IO_WKT_DETAIL_PREFIX_HPP
diff --git a/boost/geometry/io/wkt/detail/wkt_multi.hpp b/boost/geometry/io/wkt/detail/wkt_multi.hpp
new file mode 100644
index 000000000..0e5abbca8
--- /dev/null
+++ b/boost/geometry/io/wkt/detail/wkt_multi.hpp
@@ -0,0 +1,57 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP
+#define BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP
+
+
+#include <boost/geometry/domains/gis/io/wkt/write.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace wkt
+{
+
+struct prefix_null
+{
+ static inline const char* apply() { return ""; }
+};
+
+struct prefix_multipoint
+{
+ static inline const char* apply() { return "MULTIPOINT"; }
+};
+
+struct prefix_multilinestring
+{
+ static inline const char* apply() { return "MULTILINESTRING"; }
+};
+
+struct prefix_multipolygon
+{
+ static inline const char* apply() { return "MULTIPOLYGON"; }
+};
+
+
+
+}} // namespace wkt::impl
+#endif
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_DOMAINS_GIS_IO_WKT_DETAIL_WKT_MULTI_HPP
diff --git a/boost/geometry/io/wkt/read.hpp b/boost/geometry/io/wkt/read.hpp
new file mode 100644
index 000000000..24e93a02f
--- /dev/null
+++ b/boost/geometry/io/wkt/read.hpp
@@ -0,0 +1,697 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_WKT_READ_HPP
+#define BOOST_GEOMETRY_IO_WKT_READ_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.hpp>
+
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/append.hpp>
+#include <boost/geometry/algorithms/clear.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/exception.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/geometry_id.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/mutable_range.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/util/coordinate_cast.hpp>
+
+#include <boost/geometry/io/wkt/detail/prefix.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+\brief Exception showing things wrong with WKT parsing
+\ingroup wkt
+*/
+struct read_wkt_exception : public geometry::exception
+{
+ template <typename Iterator>
+ read_wkt_exception(std::string const& msg,
+ Iterator const& it, Iterator const& end, std::string const& wkt)
+ : message(msg)
+ , wkt(wkt)
+ {
+ if (it != end)
+ {
+ source = " at '";
+ source += it->c_str();
+ source += "'";
+ }
+ complete = message + source + " in '" + wkt.substr(0, 100) + "'";
+ }
+
+ read_wkt_exception(std::string const& msg, std::string const& wkt)
+ : message(msg)
+ , wkt(wkt)
+ {
+ complete = message + "' in (" + wkt.substr(0, 100) + ")";
+ }
+
+ virtual ~read_wkt_exception() throw() {}
+
+ virtual const char* what() const throw()
+ {
+ return complete.c_str();
+ }
+private :
+ std::string source;
+ std::string message;
+ std::string wkt;
+ std::string complete;
+};
+
+
+#ifndef DOXYGEN_NO_DETAIL
+// (wkt: Well Known Text, defined by OGC for all geometries and implemented by e.g. databases (MySQL, PostGIS))
+namespace detail { namespace wkt
+{
+
+typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+
+template <typename Point, std::size_t Dimension, std::size_t DimensionCount>
+struct parsing_assigner
+{
+ static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
+ Point& point, std::string const& wkt)
+ {
+ typedef typename coordinate_type<Point>::type coordinate_type;
+
+ // 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
+ ? coordinate_type()
+ : coordinate_cast<coordinate_type>::apply(*it));
+ }
+ 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);
+ }
+};
+
+
+// Geometry is a value-type or reference-type
+template <typename Geometry>
+struct container_appender
+{
+ typedef typename geometry::point_type
+ <
+ typename boost::remove_reference<Geometry>::type
+ >::type point_type;
+
+ static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
+ std::string const& wkt, Geometry out)
+ {
+ handle_open_parenthesis(it, end, wkt);
+
+ point_type point;
+
+ // Parse points until closing parenthesis
+
+ while (it != end && *it != ")")
+ {
+ parsing_assigner
+ <
+ point_type,
+ 0,
+ dimension<point_type>::value
+ >::apply(it, end, point, wkt);
+
+ geometry::append(out, point);
+ 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_appender<Geometry&>::apply(it, end, wkt, 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_appender<Ring&>::apply(it, end, wkt, 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
+{
+ typedef typename ring_return_type<Polygon>::type ring_return_type;
+ typedef container_appender<ring_return_type> appender;
+
+ static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
+ std::string const& wkt, Polygon& poly)
+ {
+
+ handle_open_parenthesis(it, end, wkt);
+
+ int n = -1;
+
+ // Stop at ")"
+ while (it != end && *it != ")")
+ {
+ // Parse ring
+ if (++n == 0)
+ {
+ appender::apply(it, end, wkt, exterior_ring(poly));
+ }
+ else
+ {
+ typename ring_type<Polygon>::type ring;
+ appender::apply(it, end, wkt, ring);
+ traits::push_back
+ <
+ typename boost::remove_reference
+ <
+ typename traits::interior_mutable_type<Polygon>::type
+ >::type
+ >::apply(interior_rings(poly), ring);
+ }
+
+ 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);
+
+// Silence warning C4127: conditional expression is constant
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4127)
+#endif
+
+ if (has_z && dimension<Geometry>::type::value < 3)
+ {
+ throw read_wkt_exception("Z only allowed for 3 or more dimensions", wkt);
+ }
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+ if (has_empty)
+ {
+ check_end(it, tokens.end(), wkt);
+ return false;
+ }
+ // M is ignored at all.
+
+ return true;
+ }
+ throw read_wkt_exception(std::string("Should start with '") + geometry_name + "'", wkt);
+}
+
+
+template <typename Geometry, template<typename> class Parser, typename PrefixPolicy>
+struct geometry_parser
+{
+ static inline void apply(std::string const& wkt, Geometry& geometry)
+ {
+ geometry::clear(geometry);
+
+ tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
+ tokenizer::iterator it;
+ if (initialize<Geometry>(tokens, PrefixPolicy::apply(), wkt, it))
+ {
+ Parser<Geometry>::apply(it, tokens.end(), wkt, geometry);
+ check_end(it, tokens.end(), wkt);
+ }
+ }
+};
+
+
+
+
+
+/*!
+\brief Supports box parsing
+\note OGC does not define the box geometry, and WKT does not support boxes.
+ However, to be generic GGL supports reading and writing from and to boxes.
+ Boxes are outputted as a standard POLYGON. GGL can read boxes from
+ a standard POLYGON, from a POLYGON with 2 points of from a BOX
+\tparam Box the box
+*/
+template <typename Box>
+struct box_parser
+{
+ static inline void apply(std::string const& wkt, Box& box)
+ {
+ bool should_close = false;
+ tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
+ tokenizer::iterator it = tokens.begin();
+ tokenizer::iterator end = tokens.end();
+ if (it != end && boost::iequals(*it, "POLYGON"))
+ {
+ ++it;
+ bool has_empty, has_z, has_m;
+ handle_empty_z_m(it, end, has_empty, has_z, has_m);
+ if (has_empty)
+ {
+ assign_zero(box);
+ return;
+ }
+ handle_open_parenthesis(it, end, wkt);
+ should_close = true;
+ }
+ else if (it != end && boost::iequals(*it, "BOX"))
+ {
+ ++it;
+ }
+ else
+ {
+ throw read_wkt_exception("Should start with 'POLYGON' or 'BOX'", wkt);
+ }
+
+ typedef typename point_type<Box>::type point_type;
+ std::vector<point_type> points;
+ container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points));
+
+ if (should_close)
+ {
+ handle_close_parenthesis(it, end, wkt);
+ }
+ check_end(it, end, wkt);
+
+ int index = 0;
+ int n = boost::size(points);
+ if (n == 2)
+ {
+ index = 1;
+ }
+ else if (n == 4 || n == 5)
+ {
+ // In case of 4 or 5 points, we do not check the other ones, just
+ // take the opposite corner which is always 2
+ index = 2;
+ }
+ else
+ {
+ throw read_wkt_exception("Box should have 2,4 or 5 points", wkt);
+ }
+
+ geometry::detail::assign_point_to_index<min_corner>(points.front(), box);
+ geometry::detail::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)
+ {
+ geometry::detail::assign_point_to_index<0>(points.front(), segment);
+ geometry::detail::assign_point_to_index<1>(points.back(), segment);
+ }
+ else
+ {
+ throw read_wkt_exception("Segment should have 2 points", wkt);
+ }
+
+ }
+};
+
+
+
+}} // namespace detail::wkt
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Tag, typename Geometry>
+struct read_wkt {};
+
+
+template <typename Point>
+struct read_wkt<point_tag, Point>
+ : detail::wkt::geometry_parser
+ <
+ Point,
+ detail::wkt::point_parser,
+ detail::wkt::prefix_point
+ >
+{};
+
+
+template <typename L>
+struct read_wkt<linestring_tag, L>
+ : detail::wkt::geometry_parser
+ <
+ L,
+ detail::wkt::linestring_parser,
+ detail::wkt::prefix_linestring
+ >
+{};
+
+template <typename Ring>
+struct read_wkt<ring_tag, Ring>
+ : detail::wkt::geometry_parser
+ <
+ Ring,
+ detail::wkt::ring_parser,
+ detail::wkt::prefix_polygon
+ >
+{};
+
+template <typename Geometry>
+struct read_wkt<polygon_tag, Geometry>
+ : detail::wkt::geometry_parser
+ <
+ Geometry,
+ detail::wkt::polygon_parser,
+ detail::wkt::prefix_polygon
+ >
+{};
+
+
+// Box (Non-OGC)
+template <typename Box>
+struct read_wkt<box_tag, Box>
+ : detail::wkt::box_parser<Box>
+{};
+
+// Segment (Non-OGC)
+template <typename Segment>
+struct read_wkt<segment_tag, Segment>
+ : detail::wkt::segment_parser<Segment>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+/*!
+\brief Parses OGC Well-Known Text (\ref WKT) into a geometry (any geometry)
+\ingroup wkt
+\param wkt string containing \ref WKT
+\param geometry output geometry
+\par Example:
+\note It is case insensitive and can have the WKT forms "point", "point m", "point z", "point zm", "point mz"
+\note Empty sequences can have forms as "LINESTRING ()" or "POLYGON(())"
+Small example showing how to use read_wkt to build a point
+\dontinclude doxygen_1.cpp
+\skip example_from_wkt_point
+\line {
+\until }
+\par Example:
+Small example showing how to use read_wkt to build a linestring
+\dontinclude doxygen_1.cpp
+\skip example_from_wkt_linestring
+\line {
+\until }
+\par Example:
+Small example showing how to use read_wkt to build a polygon
+\dontinclude doxygen_1.cpp
+\skip example_from_wkt_polygon
+\line {
+\until }
+*/
+template <typename Geometry>
+inline void read_wkt(std::string const& wkt, Geometry& geometry)
+{
+ geometry::concept::check<Geometry>();
+ dispatch::read_wkt<typename tag<Geometry>::type, Geometry>::apply(wkt, geometry);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_IO_WKT_READ_HPP
diff --git a/boost/geometry/io/wkt/stream.hpp b/boost/geometry/io/wkt/stream.hpp
new file mode 100644
index 000000000..86e49fdaf
--- /dev/null
+++ b/boost/geometry/io/wkt/stream.hpp
@@ -0,0 +1,40 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_WKT_STREAM_HPP
+#define BOOST_GEOMETRY_IO_WKT_STREAM_HPP
+
+#include <boost/geometry/io/wkt/write.hpp>
+
+// This short file contains only one manipulator, streaming as WKT
+// Don't include this in any standard-included header file.
+
+// Don't use namespace boost::geometry, to enable the library to stream custom
+// geometries which are living outside the namespace boost::geometry
+
+/*!
+\brief Streams a geometry as Well-Known Text
+\ingroup wkt
+*/
+template<typename Char, typename Traits, typename Geometry>
+inline std::basic_ostream<Char, Traits>& operator<<
+ (
+ std::basic_ostream<Char, Traits> &os,
+ Geometry const& geom
+ )
+{
+ os << boost::geometry::wkt(geom);
+ return os;
+}
+
+#endif // BOOST_GEOMETRY_IO_WKT_STREAM_HPP
diff --git a/boost/geometry/io/wkt/wkt.hpp b/boost/geometry/io/wkt/wkt.hpp
new file mode 100644
index 000000000..28bd1e42a
--- /dev/null
+++ b/boost/geometry/io/wkt/wkt.hpp
@@ -0,0 +1,25 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_WKT_WKT_HPP
+#define BOOST_GEOMETRY_IO_WKT_WKT_HPP
+
+#include <boost/geometry/io/wkt/read.hpp>
+#include <boost/geometry/io/wkt/write.hpp>
+
+// BSG 2011-02-03
+// We don't include stream.hpp by default. That tries to stream anything not known
+// by default (such as ttmath) and reports errors.
+// Users can include stream.hpp themselves (if they want to)
+
+#endif // BOOST_GEOMETRY_IO_WKT_WKT_HPP
diff --git a/boost/geometry/io/wkt/write.hpp b/boost/geometry/io/wkt/write.hpp
new file mode 100644
index 000000000..4ed02e0f8
--- /dev/null
+++ b/boost/geometry/io/wkt/write.hpp
@@ -0,0 +1,421 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_IO_WKT_WRITE_HPP
+#define BOOST_GEOMETRY_IO_WKT_WRITE_HPP
+
+#include <ostream>
+#include <string>
+
+#include <boost/array.hpp>
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/geometries/ring.hpp>
+
+#include <boost/geometry/io/wkt/detail/prefix.hpp>
+
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant_fwd.hpp>
+
+namespace boost { namespace geometry
+{
+
+// Silence warning C4512: 'boost::geometry::wkt_manipulator<Geometry>' : assignment operator could not be generated
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4512)
+#endif
+
+#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_iterator<Range const>::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 const>::type ring;
+
+ os << PrefixPolicy::apply();
+ // TODO: check EMPTY here
+ os << "(";
+ wkt_sequence<ring>::apply(os, exterior_ring(poly));
+
+ typename interior_return_type<Polygon const>::type rings
+ = interior_rings(poly);
+ for (BOOST_AUTO_TPL(it, boost::begin(rings)); it != boost::end(rings); ++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 ring, then stream
+ typedef model::ring<point_type> ring_type;
+ ring_type ring;
+ geometry::convert(box, ring);
+ os << "POLYGON(";
+ wkt_sequence<ring_type>::apply(os, ring);
+ os << ")";
+ }
+
+ private:
+
+ inline wkt_box()
+ {
+ // Only streaming of boxes with two dimensions is support, otherwise it is a polyhedron!
+ //assert_dimension<B, 2>();
+ }
+};
+
+
+template <typename Segment>
+struct wkt_segment
+{
+ typedef typename point_type<Segment>::type point_type;
+
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Segment const& segment)
+ {
+ // Convert to two points, then stream
+ typedef boost::array<point_type, 2> sequence;
+
+ sequence points;
+ geometry::detail::assign_point_from_index<0>(segment, points[0]);
+ geometry::detail::assign_point_from_index<1>(segment, points[1]);
+
+ // In Boost.Geometry a segment is represented
+ // in WKT-format like (for 2D): LINESTRING(x y,x y)
+ os << "LINESTRING";
+ wkt_sequence<sequence>::apply(os, points);
+ }
+
+ private:
+
+ inline wkt_segment()
+ {}
+};
+
+}} // namespace detail::wkt
+#endif // DOXYGEN_NO_DETAIL
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct wkt: not_implemented<Tag>
+{};
+
+template <typename Point>
+struct wkt<Point, point_tag>
+ : detail::wkt::wkt_point
+ <
+ Point,
+ detail::wkt::prefix_point
+ >
+{};
+
+template <typename Linestring>
+struct wkt<Linestring, linestring_tag>
+ : 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, box_tag>
+ : detail::wkt::wkt_box<Box>
+{};
+
+template <typename Segment>
+struct wkt<Segment, segment_tag>
+ : detail::wkt::wkt_segment<Segment>
+{};
+
+/*!
+\brief Specialization to stream a ring as WKT
+\details A ring or "linear_ring" does not exist in WKT.
+A ring is equivalent to a polygon without inner rings
+It is therefore streamed as a polygon
+*/
+template <typename Ring>
+struct wkt<Ring, ring_tag>
+ : 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, polygon_tag>
+ : detail::wkt::wkt_poly
+ <
+ Polygon,
+ detail::wkt::prefix_polygon
+ >
+{};
+
+
+template <typename Geometry>
+struct devarianted_wkt
+{
+ template <typename OutputStream>
+ static inline void apply(OutputStream& os, Geometry const& geometry)
+ {
+ wkt<Geometry>::apply(os, geometry);
+ }
+};
+
+template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+struct devarianted_wkt<variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+{
+ template <typename OutputStream>
+ struct visitor: static_visitor<void>
+ {
+ OutputStream& m_os;
+
+ visitor(OutputStream& os)
+ : m_os(os)
+ {}
+
+ template <typename Geometry>
+ inline void operator()(Geometry const& geometry) const
+ {
+ devarianted_wkt<Geometry>::apply(m_os, geometry);
+ }
+ };
+
+ template <typename OutputStream>
+ static inline void apply(
+ OutputStream& os,
+ variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry
+ )
+ {
+ apply_visitor(visitor<OutputStream>(os), geometry);
+ }
+};
+
+
+} // 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::devarianted_wkt<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<Geometry const>();
+
+ return wkt_manipulator<Geometry>(geometry);
+}
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_IO_WKT_WRITE_HPP
diff --git a/boost/geometry/iterators/base.hpp b/boost/geometry/iterators/base.hpp
new file mode 100644
index 000000000..1e824654e
--- /dev/null
+++ b/boost/geometry/iterators/base.hpp
@@ -0,0 +1,70 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ITERATORS_BASE_HPP
+#define BOOST_GEOMETRY_ITERATORS_BASE_HPP
+
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+#include <boost/mpl/if.hpp>
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace boost { namespace geometry { namespace detail { namespace iterators
+{
+
+template
+<
+ typename DerivedClass,
+ typename Iterator,
+ typename TraversalFlag = boost::bidirectional_traversal_tag
+>
+struct iterator_base
+ : public boost::iterator_adaptor
+ <
+ DerivedClass,
+ Iterator,
+ boost::use_default,
+ typename boost::mpl::if_
+ <
+ boost::is_convertible
+ <
+ typename boost::iterator_traversal<Iterator>::type,
+ boost::random_access_traversal_tag
+ >,
+ TraversalFlag,
+ 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==(Iterator const& other) const
+ {
+ return this->base() == other;
+ }
+ inline bool operator!=(Iterator const& other) const
+ {
+ return ! operator==(other);
+ }*/
+};
+
+}}}} // namespace boost::geometry::detail::iterators
+#endif
+
+
+#endif // BOOST_GEOMETRY_ITERATORS_BASE_HPP
diff --git a/boost/geometry/iterators/closing_iterator.hpp b/boost/geometry/iterators/closing_iterator.hpp
new file mode 100644
index 000000000..7cd8fa015
--- /dev/null
+++ b/boost/geometry/iterators/closing_iterator.hpp
@@ -0,0 +1,157 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ITERATORS_CLOSING_ITERATOR_HPP
+#define BOOST_GEOMETRY_ITERATORS_CLOSING_ITERATOR_HPP
+
+#include <boost/range.hpp>
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+/*!
+\brief Iterator which iterates through a range, but adds first element at end of the range
+\tparam Range range on which this class is based on
+\ingroup iterators
+\note Use with "closing_iterator<Range> or "closing_iterator<Range const>
+ to get non-const / const behaviour
+\note This class is normally used from "closeable_view" if Close==true
+*/
+template <typename Range>
+struct closing_iterator
+ : public boost::iterator_facade
+ <
+ closing_iterator<Range>,
+ typename boost::range_value<Range>::type const,
+ boost::random_access_traversal_tag
+ >
+{
+ /// Constructor including the range it is based on
+ explicit inline closing_iterator(Range& range)
+ : m_range(&range)
+ , m_iterator(boost::begin(range))
+ , m_end(boost::end(range))
+ , m_size(boost::size(range))
+ , m_index(0)
+ {}
+
+ /// Constructor to indicate the end of a range
+ explicit inline closing_iterator(Range& range, bool)
+ : m_range(&range)
+ , m_iterator(boost::end(range))
+ , m_end(boost::end(range))
+ , m_size(boost::size(range))
+ , m_index(m_size + 1)
+ {}
+
+ /// Default constructor
+ explicit inline closing_iterator()
+ : m_range(NULL)
+ , m_size(0)
+ , m_index(0)
+ {}
+
+ inline closing_iterator<Range>& operator=(closing_iterator<Range> const& source)
+ {
+ m_range = source.m_range;
+ m_iterator = source.m_iterator;
+ m_end = source.m_end;
+ m_size = source.m_size;
+ m_index = source.m_index;
+ return *this;
+ }
+
+ typedef std::ptrdiff_t difference_type;
+
+private:
+ friend class boost::iterator_core_access;
+
+ inline typename boost::range_value<Range>::type const& dereference() const
+ {
+ return *m_iterator;
+ }
+
+ inline difference_type distance_to(closing_iterator<Range> const& other) const
+ {
+ return other.m_index - this->m_index;
+ }
+
+ inline bool equal(closing_iterator<Range> const& other) const
+ {
+ return this->m_range == other.m_range
+ && this->m_index == other.m_index;
+ }
+
+ inline void increment()
+ {
+ if (++m_index < m_size)
+ {
+ ++m_iterator;
+ }
+ else
+ {
+ update_iterator();
+ }
+ }
+
+ inline void decrement()
+ {
+ if (m_index-- < m_size)
+ {
+ --m_iterator;
+ }
+ else
+ {
+ update_iterator();
+ }
+ }
+
+ inline void advance(difference_type n)
+ {
+ if (m_index < m_size && m_index + n < m_size)
+ {
+ m_index += n;
+ m_iterator += n;
+ }
+ else
+ {
+ m_index += n;
+ update_iterator();
+ }
+ }
+
+ inline void update_iterator()
+ {
+ this->m_iterator = m_index <= m_size
+ ? boost::begin(*m_range) + (m_index % m_size)
+ : boost::end(*m_range)
+ ;
+ }
+
+ Range* m_range;
+ typename boost::range_iterator<Range>::type m_iterator;
+ typename boost::range_iterator<Range>::type m_end;
+ difference_type m_size;
+ difference_type m_index;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ITERATORS_CLOSING_ITERATOR_HPP
diff --git a/boost/geometry/iterators/ever_circling_iterator.hpp b/boost/geometry/iterators/ever_circling_iterator.hpp
new file mode 100644
index 000000000..8119a73b5
--- /dev/null
+++ b/boost/geometry/iterators/ever_circling_iterator.hpp
@@ -0,0 +1,212 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
+#define BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
+
+#include <boost/range.hpp>
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+
+#include <boost/geometry/iterators/base.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief Iterator which ever circles through a range
+ \tparam Iterator iterator on which this class is based on
+ \ingroup iterators
+ \details If the iterator arrives at range.end() it restarts from the
+ beginning. So it has to be stopped in another way.
+ Don't call for(....; it++) because it will turn in an endless loop
+ \note Name inspired on David Bowie's
+ "Chant Of The Ever Circling Skeletal Family"
+*/
+template <typename Iterator>
+struct ever_circling_iterator :
+ public detail::iterators::iterator_base
+ <
+ ever_circling_iterator<Iterator>,
+ Iterator
+ >
+{
+ friend class boost::iterator_core_access;
+
+ explicit inline ever_circling_iterator(Iterator begin, Iterator end,
+ bool skip_first = false)
+ : m_begin(begin)
+ , m_end(end)
+ , m_skip_first(skip_first)
+ {
+ this->base_reference() = begin;
+ }
+
+ explicit inline ever_circling_iterator(Iterator begin, Iterator end, Iterator start,
+ bool skip_first = false)
+ : m_begin(begin)
+ , m_end(end)
+ , m_skip_first(skip_first)
+ {
+ this->base_reference() = start;
+ }
+
+ /// Navigate to a certain position, should be in [start .. end], if at end
+ /// it will circle again.
+ inline void moveto(Iterator it)
+ {
+ this->base_reference() = it;
+ check_end();
+ }
+
+private:
+
+ inline void increment(bool possibly_skip = true)
+ {
+ (this->base_reference())++;
+ check_end(possibly_skip);
+ }
+
+ inline void check_end(bool possibly_skip = true)
+ {
+ if (this->base() == this->m_end)
+ {
+ this->base_reference() = this->m_begin;
+ if (m_skip_first && possibly_skip)
+ {
+ increment(false);
+ }
+ }
+ }
+
+ Iterator m_begin;
+ Iterator m_end;
+ bool m_skip_first;
+};
+
+template <typename Range>
+struct ever_circling_range_iterator
+ : public boost::iterator_facade
+ <
+ ever_circling_range_iterator<Range>,
+ typename boost::range_value<Range>::type const,
+ boost::random_access_traversal_tag
+ >
+{
+ /// Constructor including the range it is based on
+ explicit inline ever_circling_range_iterator(Range& range)
+ : m_range(&range)
+ , m_iterator(boost::begin(range))
+ , m_size(boost::size(range))
+ , m_index(0)
+ {}
+
+ /// Default constructor
+ explicit inline ever_circling_range_iterator()
+ : m_range(NULL)
+ , m_size(0)
+ , m_index(0)
+ {}
+
+ inline ever_circling_range_iterator<Range>& operator=(ever_circling_range_iterator<Range> const& source)
+ {
+ m_range = source.m_range;
+ m_iterator = source.m_iterator;
+ m_size = source.m_size;
+ m_index = source.m_index;
+ return *this;
+ }
+
+ typedef std::ptrdiff_t difference_type;
+
+private:
+ friend class boost::iterator_core_access;
+
+ inline typename boost::range_value<Range>::type const& dereference() const
+ {
+ return *m_iterator;
+ }
+
+ inline difference_type distance_to(ever_circling_range_iterator<Range> const& other) const
+ {
+ return other.m_index - this->m_index;
+ }
+
+ inline bool equal(ever_circling_range_iterator<Range> const& other) const
+ {
+ return this->m_range == other.m_range
+ && this->m_index == other.m_index;
+ }
+
+ inline void increment()
+ {
+ ++m_index;
+ if (m_index >= 0 && m_index < m_size)
+ {
+ ++m_iterator;
+ }
+ else
+ {
+ update_iterator();
+ }
+ }
+
+ inline void decrement()
+ {
+ --m_index;
+ if (m_index >= 0 && m_index < m_size)
+ {
+ --m_iterator;
+ }
+ else
+ {
+ update_iterator();
+ }
+ }
+
+ inline void advance(difference_type n)
+ {
+ if (m_index >= 0 && m_index < m_size
+ && m_index + n >= 0 && m_index + n < m_size)
+ {
+ m_index += n;
+ m_iterator += n;
+ }
+ else
+ {
+ m_index += n;
+ update_iterator();
+ }
+ }
+
+ inline void update_iterator()
+ {
+ while (m_index < 0)
+ {
+ m_index += m_size;
+ }
+ m_index = m_index % m_size;
+ this->m_iterator = boost::begin(*m_range) + m_index;
+ }
+
+ Range* m_range;
+ typename boost::range_iterator<Range>::type m_iterator;
+ difference_type m_size;
+ difference_type m_index;
+};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ITERATORS_EVER_CIRCLING_ITERATOR_HPP
diff --git a/boost/geometry/multi/algorithms/append.hpp b/boost/geometry/multi/algorithms/append.hpp
new file mode 100644
index 000000000..bb97af1aa
--- /dev/null
+++ b/boost/geometry/multi/algorithms/append.hpp
@@ -0,0 +1,53 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_APPEND_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_APPEND_HPP
+
+#include <boost/geometry/algorithms/append.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+namespace splitted_dispatch
+{
+
+template <typename Geometry, typename Point>
+struct append_point<multi_point_tag, Geometry, Point>
+ : detail::append::append_point<Geometry, Point>
+{};
+
+template <typename Geometry, typename Range>
+struct append_range<multi_point_tag, Geometry, Range>
+ : detail::append::append_range<Geometry, Range>
+{};
+
+}
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_APPEND_HPP
diff --git a/boost/geometry/multi/algorithms/area.hpp b/boost/geometry/multi/algorithms/area.hpp
new file mode 100644
index 000000000..333499748
--- /dev/null
+++ b/boost/geometry/multi/algorithms/area.hpp
@@ -0,0 +1,58 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_AREA_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_AREA_HPP
+
+
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/area.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/core/point_type.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+#include <boost/geometry/multi/algorithms/detail/multi_sum.hpp>
+#include <boost/geometry/multi/algorithms/num_points.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+template <typename MultiGeometry>
+struct area<MultiGeometry, multi_polygon_tag> : detail::multi_sum
+{
+ template <typename Strategy>
+ static inline typename Strategy::return_type
+ apply(MultiGeometry const& multi, Strategy const& strategy)
+ {
+ return multi_sum::apply
+ <
+ typename Strategy::return_type,
+ area<typename boost::range_value<MultiGeometry>::type>
+ >(multi, strategy);
+ }
+};
+
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_AREA_HPP
diff --git a/boost/geometry/multi/algorithms/centroid.hpp b/boost/geometry/multi/algorithms/centroid.hpp
new file mode 100644
index 000000000..82e6a8af8
--- /dev/null
+++ b/boost/geometry/multi/algorithms/centroid.hpp
@@ -0,0 +1,134 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_CENTROID_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_CENTROID_HPP
+
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/centroid.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/core/point_type.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+#include <boost/geometry/multi/algorithms/num_points.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace centroid
+{
+
+
+/*!
+ \brief Building block of a multi-point, to be used as Policy in the
+ more generec centroid_multi
+*/
+struct centroid_multi_point_state
+{
+ template <typename Point, typename Strategy>
+ 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 Policy>
+struct centroid_multi
+{
+ template <typename Multi, typename Point, typename Strategy>
+ static inline void apply(Multi const& multi, Point& centroid,
+ Strategy const& strategy)
+ {
+#if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)
+ // If there is nothing in any of the ranges, it is not possible
+ // to calculate the centroid
+ if (geometry::num_points(multi) == 0)
+ {
+ throw centroid_exception();
+ }
+#endif
+
+ typename Strategy::state_type state;
+
+ for (typename boost::range_iterator<Multi const>::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 MultiLinestring>
+struct centroid<MultiLinestring, multi_linestring_tag>
+ : detail::centroid::centroid_multi
+ <
+ detail::centroid::centroid_range_state<closed>
+ >
+{};
+
+template <typename MultiPolygon>
+struct centroid<MultiPolygon, multi_polygon_tag>
+ : detail::centroid::centroid_multi
+ <
+ detail::centroid::centroid_polygon_state
+ >
+{};
+
+
+template <typename MultiPoint>
+struct centroid<MultiPoint, multi_point_tag>
+ : detail::centroid::centroid_multi
+ <
+ detail::centroid::centroid_multi_point_state
+ >
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_CENTROID_HPP
+
diff --git a/boost/geometry/multi/algorithms/clear.hpp b/boost/geometry/multi/algorithms/clear.hpp
new file mode 100644
index 000000000..ea32ee8b4
--- /dev/null
+++ b/boost/geometry/multi/algorithms/clear.hpp
@@ -0,0 +1,44 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_CLEAR_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_CLEAR_HPP
+
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/clear.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Geometry>
+struct clear<Geometry, multi_tag>
+ : detail::clear::collection_clear<Geometry>
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_CLEAR_HPP
diff --git a/boost/geometry/multi/algorithms/convert.hpp b/boost/geometry/multi/algorithms/convert.hpp
new file mode 100644
index 000000000..1712964d4
--- /dev/null
+++ b/boost/geometry/multi/algorithms/convert.hpp
@@ -0,0 +1,129 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_CONVERT_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_CONVERT_HPP
+
+
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/convert.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace conversion
+{
+
+template <typename Single, typename Multi, typename Policy>
+struct single_to_multi: private Policy
+{
+ static inline void apply(Single const& single, Multi& multi)
+ {
+ traits::resize<Multi>::apply(multi, 1);
+ Policy::apply(single, *boost::begin(multi));
+ }
+};
+
+
+
+template <typename Multi1, typename Multi2, typename Policy>
+struct multi_to_multi: private Policy
+{
+ static inline void apply(Multi1 const& multi1, Multi2& multi2)
+ {
+ traits::resize<Multi2>::apply(multi2, boost::size(multi1));
+
+ typename boost::range_iterator<Multi1 const>::type it1
+ = boost::begin(multi1);
+ typename boost::range_iterator<Multi2>::type it2
+ = boost::begin(multi2);
+
+ for (; it1 != boost::end(multi1); ++it1, ++it2)
+ {
+ Policy::apply(*it1, *it2);
+ }
+ }
+};
+
+
+}} // namespace detail::convert
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// Dispatch for multi <-> multi, specifying their single-version as policy.
+// Note that, even if the multi-types are mutually different, their single
+// version types might be the same and therefore we call boost::is_same again
+
+template <typename Multi1, typename Multi2, std::size_t DimensionCount>
+struct convert<Multi1, Multi2, multi_tag, multi_tag, DimensionCount, false>
+ : detail::conversion::multi_to_multi
+ <
+ Multi1,
+ Multi2,
+ convert
+ <
+ typename boost::range_value<Multi1>::type,
+ typename boost::range_value<Multi2>::type,
+ typename single_tag_of
+ <
+ typename tag<Multi1>::type
+ >::type,
+ typename single_tag_of
+ <
+ typename tag<Multi2>::type
+ >::type,
+ DimensionCount
+ >
+ >
+{};
+
+template <typename Single, typename Multi, typename SingleTag, std::size_t DimensionCount>
+struct convert<Single, Multi, SingleTag, multi_tag, DimensionCount, false>
+ : detail::conversion::single_to_multi
+ <
+ Single,
+ Multi,
+ convert
+ <
+ Single,
+ typename boost::range_value<Multi>::type,
+ typename tag<Single>::type,
+ typename single_tag_of
+ <
+ typename tag<Multi>::type
+ >::type,
+ DimensionCount,
+ false
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_CONVERT_HPP
diff --git a/boost/geometry/multi/algorithms/correct.hpp b/boost/geometry/multi/algorithms/correct.hpp
new file mode 100644
index 000000000..d28d1e78e
--- /dev/null
+++ b/boost/geometry/multi/algorithms/correct.hpp
@@ -0,0 +1,67 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_CORRECT_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_CORRECT_HPP
+
+
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/correct.hpp>
+#include <boost/geometry/multi/algorithms/detail/modify.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename MultiPoint>
+struct correct<MultiPoint, multi_point_tag>
+ : detail::correct::correct_nop<MultiPoint>
+{};
+
+
+template <typename MultiLineString>
+struct correct<MultiLineString, multi_linestring_tag>
+ : detail::correct::correct_nop<MultiLineString>
+{};
+
+
+template <typename Geometry>
+struct correct<Geometry, multi_polygon_tag>
+ : detail::multi_modify
+ <
+ Geometry,
+ detail::correct::correct_polygon
+ <
+ typename boost::range_value<Geometry>::type
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_CORRECT_HPP
diff --git a/boost/geometry/multi/algorithms/covered_by.hpp b/boost/geometry/multi/algorithms/covered_by.hpp
new file mode 100644
index 000000000..c957c485b
--- /dev/null
+++ b/boost/geometry/multi/algorithms/covered_by.hpp
@@ -0,0 +1,71 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_COVERED_BY_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_COVERED_BY_HPP
+
+
+#include <boost/geometry/algorithms/covered_by.hpp>
+#include <boost/geometry/multi/core/closure.hpp>
+#include <boost/geometry/multi/core/point_order.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+#include <boost/geometry/multi/algorithms/within.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Point, typename MultiPolygon>
+struct covered_by<Point, MultiPolygon, point_tag, multi_polygon_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Point const& point,
+ MultiPolygon const& multi_polygon, Strategy const& strategy)
+ {
+ return detail::within::geometry_multi_within_code
+ <
+ Point,
+ MultiPolygon,
+ Strategy,
+ detail::within::point_in_polygon
+ <
+ Point,
+ typename boost::range_value<MultiPolygon>::type,
+ order_as_direction
+ <
+ geometry::point_order<MultiPolygon>::value
+ >::value,
+ geometry::closure<MultiPolygon>::value,
+ Strategy
+ >
+ >::apply(point, multi_polygon, strategy) >= 0;
+ }
+};
+
+
+} // namespace dispatch
+
+
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_COVERED_BY_HPP
diff --git a/boost/geometry/multi/algorithms/detail/for_each_range.hpp b/boost/geometry/multi/algorithms/detail/for_each_range.hpp
new file mode 100644
index 000000000..0938d6a2e
--- /dev/null
+++ b/boost/geometry/multi/algorithms/detail/for_each_range.hpp
@@ -0,0 +1,87 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_FOR_EACH_RANGE_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_FOR_EACH_RANGE_HPP
+
+
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/algorithms/detail/for_each_range.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace for_each
+{
+
+
+template <typename Multi, typename Actor, bool IsConst>
+struct fe_range_multi
+{
+ static inline void apply(
+ typename add_const_if_c<IsConst, Multi>::type& multi,
+ Actor& actor)
+ {
+ for(BOOST_AUTO_TPL(it, boost::begin(multi)); it != boost::end(multi); ++it)
+ {
+ geometry::detail::for_each_range(*it, actor);
+ }
+ }
+};
+
+
+
+}} // namespace detail::for_each
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename MultiPoint, typename Actor, bool IsConst>
+struct for_each_range<multi_point_tag, MultiPoint, Actor, IsConst>
+ : detail::for_each::fe_range_range<MultiPoint, Actor, IsConst>
+{};
+
+template <typename Geometry, typename Actor, bool IsConst>
+struct for_each_range<multi_linestring_tag, 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, Geometry, Actor, IsConst>
+ :
+ detail::for_each::fe_range_multi<Geometry, Actor, IsConst>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_FOR_EACH_RANGE_HPP
diff --git a/boost/geometry/multi/algorithms/detail/modify.hpp b/boost/geometry/multi/algorithms/detail/modify.hpp
new file mode 100644
index 000000000..b52efd251
--- /dev/null
+++ b/boost/geometry/multi/algorithms/detail/modify.hpp
@@ -0,0 +1,53 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MODIFY_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MODIFY_HPP
+
+
+#include <boost/range.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template <typename MultiGeometry, typename Policy>
+struct multi_modify
+{
+ static inline void apply(MultiGeometry& multi)
+ {
+ typedef typename boost::range_iterator<MultiGeometry>::type iterator_type;
+ for (iterator_type it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ Policy::apply(*it);
+ }
+ }
+};
+
+
+} // namespace detail
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MODIFY_HPP
diff --git a/boost/geometry/multi/algorithms/detail/modify_with_predicate.hpp b/boost/geometry/multi/algorithms/detail/modify_with_predicate.hpp
new file mode 100644
index 000000000..4ae79058d
--- /dev/null
+++ b/boost/geometry/multi/algorithms/detail/modify_with_predicate.hpp
@@ -0,0 +1,52 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MODIFY_WITH_PREDICATE_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MODIFY_WITH_PREDICATE_HPP
+
+
+#include <boost/range.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename MultiGeometry, typename Predicate, typename Policy>
+struct multi_modify_with_predicate
+{
+ static inline void apply(MultiGeometry& multi, Predicate const& predicate)
+ {
+ typedef typename boost::range_iterator<MultiGeometry>::type iterator_type;
+ for (iterator_type it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ Policy::apply(*it, predicate);
+ }
+ }
+};
+
+
+} // namespace detail
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_MODIFY_WITH_PREDICATE_HPP
diff --git a/boost/geometry/multi/algorithms/detail/multi_sum.hpp b/boost/geometry/multi/algorithms/detail/multi_sum.hpp
new file mode 100644
index 000000000..704c3e6a9
--- /dev/null
+++ b/boost/geometry/multi/algorithms/detail/multi_sum.hpp
@@ -0,0 +1,52 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_SUM_HPP
+#define BOOST_GEOMETRY_MULTI_SUM_HPP
+
+#include <boost/range.hpp>
+
+
+namespace boost { namespace geometry
+{
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+struct multi_sum
+{
+ template <typename ReturnType, typename Policy, typename MultiGeometry, typename Strategy>
+ static inline ReturnType apply(MultiGeometry const& geometry, Strategy const& strategy)
+ {
+ ReturnType sum = ReturnType();
+ for (typename boost::range_iterator
+ <
+ MultiGeometry const
+ >::type it = boost::begin(geometry);
+ it != boost::end(geometry);
+ ++it)
+ {
+ sum += Policy::apply(*it, strategy);
+ }
+ return sum;
+ }
+};
+
+
+} // namespace detail
+#endif
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_SUM_HPP
diff --git a/boost/geometry/multi/algorithms/detail/overlay/copy_segment_point.hpp b/boost/geometry/multi/algorithms/detail/overlay/copy_segment_point.hpp
new file mode 100644
index 000000000..940480b3c
--- /dev/null
+++ b/boost/geometry/multi/algorithms/detail/overlay/copy_segment_point.hpp
@@ -0,0 +1,102 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP
+
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace copy_segments
+{
+
+
+template
+<
+ typename MultiGeometry,
+ typename SegmentIdentifier,
+ typename PointOut,
+ typename Policy
+>
+struct copy_segment_point_multi
+{
+ static inline bool apply(MultiGeometry const& multi,
+ SegmentIdentifier const& seg_id, bool second,
+ PointOut& point)
+ {
+
+ BOOST_ASSERT
+ (
+ seg_id.multi_index >= 0
+ && seg_id.multi_index < int(boost::size(multi))
+ );
+
+ // Call the single-version
+ return Policy::apply(multi[seg_id.multi_index], seg_id, second, point);
+ }
+};
+
+
+}} // namespace detail::copy_segments
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename MultiGeometry,
+ bool Reverse,
+ typename SegmentIdentifier,
+ typename PointOut
+>
+struct copy_segment_point
+ <
+ multi_polygon_tag,
+ MultiGeometry,
+ Reverse,
+ SegmentIdentifier,
+ PointOut
+ >
+ : detail::copy_segments::copy_segment_point_multi
+ <
+ MultiGeometry,
+ SegmentIdentifier,
+ PointOut,
+ detail::copy_segments::copy_segment_point_polygon
+ <
+ typename boost::range_value<MultiGeometry>::type,
+ Reverse,
+ SegmentIdentifier,
+ PointOut
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP
diff --git a/boost/geometry/multi/algorithms/detail/overlay/copy_segments.hpp b/boost/geometry/multi/algorithms/detail/overlay/copy_segments.hpp
new file mode 100644
index 000000000..f3a0532ac
--- /dev/null
+++ b/boost/geometry/multi/algorithms/detail/overlay/copy_segments.hpp
@@ -0,0 +1,105 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP
+
+
+#include <boost/assert.hpp>
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
+
+#include <boost/geometry/multi/core/ring_type.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace copy_segments
+{
+
+
+template
+<
+ typename MultiGeometry,
+ typename SegmentIdentifier,
+ typename RangeOut,
+ typename Policy
+>
+struct copy_segments_multi
+{
+ static inline void apply(MultiGeometry const& multi_geometry,
+ SegmentIdentifier const& seg_id, int to_index,
+ RangeOut& current_output)
+ {
+
+ BOOST_ASSERT
+ (
+ seg_id.multi_index >= 0
+ && seg_id.multi_index < int(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,
+ bool Reverse,
+ typename SegmentIdentifier,
+ typename RangeOut
+>
+struct copy_segments
+ <
+ multi_polygon_tag,
+ MultiPolygon,
+ Reverse,
+ SegmentIdentifier,
+ RangeOut
+ >
+ : detail::copy_segments::copy_segments_multi
+ <
+ MultiPolygon,
+ SegmentIdentifier,
+ RangeOut,
+ detail::copy_segments::copy_segments_polygon
+ <
+ typename boost::range_value<MultiPolygon>::type,
+ Reverse,
+ SegmentIdentifier,
+ RangeOut
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP
diff --git a/boost/geometry/multi/algorithms/detail/overlay/get_ring.hpp b/boost/geometry/multi/algorithms/detail/overlay/get_ring.hpp
new file mode 100644
index 000000000..2d04f7ccd
--- /dev/null
+++ b/boost/geometry/multi/algorithms/detail/overlay/get_ring.hpp
@@ -0,0 +1,56 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP
+
+
+#include <boost/assert.hpp>
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
+#include <boost/geometry/multi/core/ring_type.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+template<>
+struct get_ring<multi_polygon_tag>
+{
+ template<typename MultiPolygon>
+ static inline typename ring_type<MultiPolygon>::type const& apply(
+ ring_identifier const& id,
+ MultiPolygon const& multi_polygon)
+ {
+ BOOST_ASSERT
+ (
+ id.multi_index >= 0
+ && id.multi_index < int(boost::size(multi_polygon))
+ );
+ return get_ring<polygon_tag>::apply(id,
+ multi_polygon[id.multi_index]);
+ }
+};
+
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP
diff --git a/boost/geometry/multi/algorithms/detail/overlay/get_turns.hpp b/boost/geometry/multi/algorithms/detail/overlay/get_turns.hpp
new file mode 100644
index 000000000..6bc0aae25
--- /dev/null
+++ b/boost/geometry/multi/algorithms/detail/overlay/get_turns.hpp
@@ -0,0 +1,113 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP
+
+
+#include <boost/geometry/multi/core/ring_type.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
+
+#include <boost/geometry/multi/algorithms/distance.hpp>
+#include <boost/geometry/multi/views/detail/range_type.hpp>
+
+#include <boost/geometry/multi/algorithms/detail/sections/range_by_section.hpp>
+#include <boost/geometry/multi/algorithms/detail/sections/sectionalize.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace get_turns
+{
+
+template
+<
+ typename Multi, typename Box,
+ bool Reverse, bool ReverseBox,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+struct get_turns_multi_polygon_cs
+{
+ static inline void apply(
+ int source_id1, Multi const& multi,
+ int source_id2, Box const& box,
+ Turns& turns, InterruptPolicy& interrupt_policy)
+ {
+ typedef typename boost::range_iterator
+ <
+ Multi const
+ >::type iterator_type;
+
+ int i = 0;
+ for (iterator_type it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it, ++i)
+ {
+ // Call its single version
+ get_turns_polygon_cs
+ <
+ typename boost::range_value<Multi>::type, Box,
+ Reverse, ReverseBox,
+ Turns, TurnPolicy, InterruptPolicy
+ >::apply(source_id1, *it, source_id2, box,
+ turns, interrupt_policy, i);
+ }
+ }
+};
+
+}} // namespace detail::get_turns
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename MultiPolygon,
+ typename Box,
+ bool ReverseMultiPolygon, bool ReverseBox,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+struct get_turns
+ <
+ multi_polygon_tag, box_tag,
+ MultiPolygon, Box,
+ ReverseMultiPolygon, ReverseBox,
+ Turns,
+ TurnPolicy, InterruptPolicy
+ >
+ : detail::get_turns::get_turns_multi_polygon_cs
+ <
+ MultiPolygon, Box,
+ ReverseMultiPolygon, ReverseBox,
+ Turns,
+ TurnPolicy, InterruptPolicy
+ >
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP
diff --git a/boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp b/boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp
new file mode 100644
index 000000000..acb91f7dd
--- /dev/null
+++ b/boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp
@@ -0,0 +1,65 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP
+
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/detail/overlay/select_rings.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+namespace dispatch
+{
+
+ template <typename Multi>
+ struct select_rings<multi_polygon_tag, Multi>
+ {
+ template <typename Geometry, typename Map>
+ static inline void apply(Multi const& multi, Geometry const& geometry,
+ ring_identifier id, Map& map, bool midpoint)
+ {
+ typedef typename boost::range_iterator
+ <
+ Multi const
+ >::type iterator_type;
+
+ typedef select_rings<polygon_tag, typename boost::range_value<Multi>::type> per_polygon;
+
+ id.multi_index = 0;
+ for (iterator_type it = boost::begin(multi); it != boost::end(multi); ++it)
+ {
+ id.ring_index = -1;
+ per_polygon::apply(*it, geometry, id, map, midpoint);
+ id.multi_index++;
+ }
+ }
+ };
+}
+
+
+}} // namespace detail::overlay
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_SELECT_RINGS_HPP
diff --git a/boost/geometry/multi/algorithms/detail/overlay/self_turn_points.hpp b/boost/geometry/multi/algorithms/detail/overlay/self_turn_points.hpp
new file mode 100644
index 000000000..d9820837b
--- /dev/null
+++ b/boost/geometry/multi/algorithms/detail/overlay/self_turn_points.hpp
@@ -0,0 +1,57 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP
+
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename MultiPolygon,
+ typename Turns,
+ typename TurnPolicy,
+ typename InterruptPolicy
+>
+struct self_get_turn_points
+ <
+ multi_polygon_tag, MultiPolygon,
+ Turns,
+ TurnPolicy, InterruptPolicy
+ >
+ : detail::self_get_turn_points::get_turns
+ <
+ MultiPolygon,
+ Turns,
+ TurnPolicy,
+ InterruptPolicy
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_OVERLAY_SELF_TURN_POINTS_HPP
diff --git a/boost/geometry/multi/algorithms/detail/point_on_border.hpp b/boost/geometry/multi/algorithms/detail/point_on_border.hpp
new file mode 100644
index 000000000..dd3bcd5d1
--- /dev/null
+++ b/boost/geometry/multi/algorithms/detail/point_on_border.hpp
@@ -0,0 +1,96 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace point_on_border
+{
+
+
+template
+<
+ typename Point,
+ typename MultiGeometry,
+ typename Policy
+>
+struct point_on_multi
+{
+ static inline bool apply(Point& point, MultiGeometry const& multi, bool midpoint)
+ {
+ // Take a point on the first multi-geometry
+ // (i.e. the first that is not empty)
+ for (typename boost::range_iterator
+ <
+ MultiGeometry const
+ >::type it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ if (Policy::apply(point, *it, midpoint))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+
+
+
+}} // namespace detail::point_on_border
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template<typename Point, typename Multi>
+struct point_on_border<multi_polygon_tag, Point, Multi>
+ : detail::point_on_border::point_on_multi
+ <
+ Point,
+ Multi,
+ detail::point_on_border::point_on_polygon
+ <
+ Point,
+ typename boost::range_value<Multi>::type
+ >
+ >
+{};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_POINT_ON_BORDER_HPP
diff --git a/boost/geometry/multi/algorithms/detail/sections/range_by_section.hpp b/boost/geometry/multi/algorithms/detail/sections/range_by_section.hpp
new file mode 100644
index 000000000..47bc8a863
--- /dev/null
+++ b/boost/geometry/multi/algorithms/detail/sections/range_by_section.hpp
@@ -0,0 +1,91 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP
+
+
+#include <boost/assert.hpp>
+#include <boost/range.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+#include <boost/geometry/multi/core/ring_type.hpp>
+#include <boost/geometry/algorithms/detail/sections/range_by_section.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace section
+{
+
+
+template
+<
+ typename MultiGeometry,
+ typename Section,
+ typename Policy
+>
+struct full_section_multi
+{
+ static inline typename ring_return_type<MultiGeometry const>::type apply(
+ MultiGeometry const& multi, Section const& section)
+ {
+ BOOST_ASSERT
+ (
+ section.ring_id.multi_index >= 0
+ && section.ring_id.multi_index < int(boost::size(multi))
+ );
+
+ return Policy::apply(multi[section.ring_id.multi_index], section);
+ }
+};
+
+
+}} // namespace detail::section
+#endif
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename MultiPolygon, typename Section>
+struct range_by_section<multi_polygon_tag, MultiPolygon, Section>
+ : detail::section::full_section_multi
+ <
+ MultiPolygon,
+ Section,
+ detail::section::full_section_polygon
+ <
+ typename boost::range_value<MultiPolygon>::type,
+ Section
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP
diff --git a/boost/geometry/multi/algorithms/detail/sections/sectionalize.hpp b/boost/geometry/multi/algorithms/detail/sections/sectionalize.hpp
new file mode 100644
index 000000000..1e1056f37
--- /dev/null
+++ b/boost/geometry/multi/algorithms/detail/sections/sectionalize.hpp
@@ -0,0 +1,97 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP
+
+#include <cstddef>
+#include <vector>
+
+#include <boost/concept/requires.hpp>
+#include <boost/range.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/detail/sections/sectionalize.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace sectionalize
+{
+
+
+template <typename MultiGeometry, typename Sections, std::size_t DimensionCount, typename Policy>
+struct sectionalize_multi
+{
+ static inline void apply(MultiGeometry const& multi, Sections& sections, ring_identifier ring_id)
+ {
+ ring_id.multi_index = 0;
+ for (typename boost::range_iterator<MultiGeometry const>::type
+ it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it, ++ring_id.multi_index)
+ {
+ Policy::apply(*it, sections, ring_id);
+ }
+ }
+};
+
+
+}} // namespace detail::sectionalize
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename MultiPolygon,
+ bool Reverse,
+ typename Sections,
+ std::size_t DimensionCount,
+ std::size_t MaxCount
+>
+struct sectionalize<multi_polygon_tag, MultiPolygon, Reverse, Sections, DimensionCount, MaxCount>
+ : detail::sectionalize::sectionalize_multi
+ <
+ MultiPolygon,
+ Sections,
+ DimensionCount,
+ detail::sectionalize::sectionalize_polygon
+ <
+ typename boost::range_value<MultiPolygon>::type,
+ Reverse,
+ Sections,
+ DimensionCount,
+ MaxCount
+ >
+ >
+
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DETAIL_SECTIONS_SECTIONALIZE_HPP
diff --git a/boost/geometry/multi/algorithms/disjoint.hpp b/boost/geometry/multi/algorithms/disjoint.hpp
new file mode 100644
index 000000000..c01e520f5
--- /dev/null
+++ b/boost/geometry/multi/algorithms/disjoint.hpp
@@ -0,0 +1,44 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2012 Mateusz Loskot, London, UK.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DISJOINT_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DISJOINT_HPP
+
+
+#include <boost/geometry/algorithms/disjoint.hpp>
+#include <boost/geometry/multi/algorithms/covered_by.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Point, typename MultiPolygon>
+struct disjoint<Point, MultiPolygon, 2, point_tag, multi_polygon_tag, false>
+ : detail::disjoint::reverse_covered_by<Point, MultiPolygon>
+{};
+
+} // namespace dispatch
+
+
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DISJOINT_HPP
diff --git a/boost/geometry/multi/algorithms/distance.hpp b/boost/geometry/multi/algorithms/distance.hpp
new file mode 100644
index 000000000..32b41fcef
--- /dev/null
+++ b/boost/geometry/multi/algorithms/distance.hpp
@@ -0,0 +1,158 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_DISTANCE_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_DISTANCE_HPP
+
+
+#include <boost/numeric/conversion/bounds.hpp>
+#include <boost/range.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/core/geometry_id.hpp>
+#include <boost/geometry/multi/core/point_type.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/distance.hpp>
+#include <boost/geometry/multi/algorithms/num_points.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace distance
+{
+
+
+template<typename Geometry, typename MultiGeometry, typename Strategy>
+struct distance_single_to_multi
+ : private dispatch::distance
+ <
+ Geometry,
+ typename range_value<MultiGeometry>::type,
+ Strategy
+ >
+{
+ typedef typename strategy::distance::services::return_type<Strategy>::type return_type;
+
+ static inline return_type apply(Geometry const& geometry,
+ MultiGeometry const& multi,
+ Strategy const& strategy)
+ {
+ return_type mindist = return_type();
+ bool first = true;
+
+ for(typename range_iterator<MultiGeometry const>::type it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it, first = false)
+ {
+ return_type dist = dispatch::distance
+ <
+ Geometry,
+ typename range_value<MultiGeometry>::type,
+ Strategy
+ >::apply(geometry, *it, strategy);
+
+ if (first || dist < mindist)
+ {
+ mindist = dist;
+ }
+ }
+
+ return mindist;
+ }
+};
+
+template<typename Multi1, typename Multi2, typename Strategy>
+struct distance_multi_to_multi
+ : private distance_single_to_multi
+ <
+ typename range_value<Multi1>::type,
+ Multi2,
+ Strategy
+ >
+{
+ typedef typename strategy::distance::services::return_type<Strategy>::type return_type;
+
+ static inline return_type apply(Multi1 const& multi1,
+ Multi2 const& multi2, Strategy const& strategy)
+ {
+ return_type mindist = return_type();
+ bool first = true;
+
+ for(typename range_iterator<Multi1 const>::type it = boost::begin(multi1);
+ it != boost::end(multi1);
+ ++it, first = false)
+ {
+ return_type dist = distance_single_to_multi
+ <
+ typename range_value<Multi1>::type,
+ Multi2,
+ Strategy
+ >::apply(*it, multi2, strategy);
+ if (first || dist < mindist)
+ {
+ mindist = dist;
+ }
+ }
+
+ return mindist;
+ }
+};
+
+
+}} // namespace detail::distance
+#endif
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename G1,
+ typename G2,
+ typename Strategy,
+ typename SingleGeometryTag
+>
+struct distance
+<
+ G1, G2, Strategy,
+ SingleGeometryTag, multi_tag, strategy_tag_distance_point_point,
+ false
+>
+ : detail::distance::distance_single_to_multi<G1, G2, Strategy>
+{};
+
+template <typename G1, typename G2, typename Strategy>
+struct distance
+<
+ G1, G2, Strategy,
+ multi_tag, multi_tag, strategy_tag_distance_point_point,
+ false
+>
+ : detail::distance::distance_multi_to_multi<G1, G2, Strategy>
+{};
+
+} // namespace dispatch
+#endif
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_DISTANCE_HPP
diff --git a/boost/geometry/multi/algorithms/envelope.hpp b/boost/geometry/multi/algorithms/envelope.hpp
new file mode 100644
index 000000000..b70aab41e
--- /dev/null
+++ b/boost/geometry/multi/algorithms/envelope.hpp
@@ -0,0 +1,107 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_ENVELOPE_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_ENVELOPE_HPP
+
+#include <vector>
+
+#include <boost/range/metafunctions.hpp>
+
+
+#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/algorithms/envelope.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/core/point_type.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+
+namespace detail { namespace envelope
+{
+
+
+struct envelope_multi_linestring
+{
+ template<typename MultiLinestring, typename Box>
+ static inline void apply(MultiLinestring const& mp, Box& mbr)
+ {
+ assign_inverse(mbr);
+ for (typename boost::range_iterator<MultiLinestring const>::type
+ it = mp.begin();
+ it != mp.end();
+ ++it)
+ {
+ envelope_range_additional(*it, mbr);
+ }
+ }
+};
+
+
+// version for multi_polygon: outer ring's of all polygons
+struct envelope_multi_polygon
+{
+ template<typename MultiPolygon, typename Box>
+ 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>
+struct envelope<Multi, multi_point_tag>
+ : detail::envelope::envelope_range
+{};
+
+template <typename Multi>
+struct envelope<Multi, multi_linestring_tag>
+ : detail::envelope::envelope_multi_linestring
+{};
+
+
+template <typename Multi>
+struct envelope<Multi, multi_polygon_tag>
+ : detail::envelope::envelope_multi_polygon
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_ENVELOPE_HPP
diff --git a/boost/geometry/multi/algorithms/equals.hpp b/boost/geometry/multi/algorithms/equals.hpp
new file mode 100644
index 000000000..54cd07504
--- /dev/null
+++ b/boost/geometry/multi/algorithms/equals.hpp
@@ -0,0 +1,65 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_EQUALS_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_EQUALS_HPP
+
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/core/geometry_id.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/equals.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename MultiPolygon1, typename MultiPolygon2, bool Reverse>
+struct equals
+ <
+ MultiPolygon1, MultiPolygon2,
+ multi_polygon_tag, multi_polygon_tag,
+ 2,
+ Reverse
+ >
+ : detail::equals::equals_by_collection<detail::equals::area_check>
+{};
+
+
+template <typename Polygon, typename MultiPolygon, bool Reverse>
+struct equals
+ <
+ Polygon, MultiPolygon,
+ polygon_tag, multi_polygon_tag,
+ 2,
+ Reverse
+ >
+ : detail::equals::equals_by_collection<detail::equals::area_check>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_EQUALS_HPP
+
diff --git a/boost/geometry/multi/algorithms/for_each.hpp b/boost/geometry/multi/algorithms/for_each.hpp
new file mode 100644
index 000000000..9712b9c45
--- /dev/null
+++ b/boost/geometry/multi/algorithms/for_each.hpp
@@ -0,0 +1,101 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_FOR_EACH_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_FOR_EACH_HPP
+
+
+#include <boost/range.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/core/point_type.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+#include <boost/geometry/algorithms/for_each.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace for_each
+{
+
+// Implementation of multi, for both point and segment,
+// just calling the single version.
+template <typename Policy>
+struct for_each_multi
+{
+ template <typename MultiGeometry, typename Functor>
+ static inline void apply(MultiGeometry& multi, Functor& f)
+ {
+ for(BOOST_AUTO_TPL(it, boost::begin(multi)); it != boost::end(multi); ++it)
+ {
+ Policy::apply(*it, f);
+ }
+ }
+};
+
+
+}} // namespace detail::for_each
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename MultiGeometry>
+struct for_each_point<MultiGeometry, multi_tag>
+ : detail::for_each::for_each_multi
+ <
+ // Specify the dispatch of the single-version as policy
+ for_each_point
+ <
+ typename add_const_if_c
+ <
+ is_const<MultiGeometry>::value,
+ typename boost::range_value<MultiGeometry>::type
+ >::type
+ >
+ >
+{};
+
+
+template <typename MultiGeometry>
+struct for_each_segment<MultiGeometry, multi_tag>
+ : detail::for_each::for_each_multi
+ <
+ // Specify the dispatch of the single-version as policy
+ for_each_segment
+ <
+ typename add_const_if_c
+ <
+ is_const<MultiGeometry>::value,
+ typename boost::range_value<MultiGeometry>::type
+ >::type
+ >
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_FOR_EACH_HPP
diff --git a/boost/geometry/multi/algorithms/intersection.hpp b/boost/geometry/multi/algorithms/intersection.hpp
new file mode 100644
index 000000000..ddb9aed81
--- /dev/null
+++ b/boost/geometry/multi/algorithms/intersection.hpp
@@ -0,0 +1,402 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_INTERSECTION_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_INTERSECTION_HPP
+
+
+#include <boost/geometry/multi/core/closure.hpp>
+#include <boost/geometry/multi/core/geometry_id.hpp>
+#include <boost/geometry/multi/core/is_areal.hpp>
+#include <boost/geometry/multi/core/point_order.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+#include <boost/geometry/multi/algorithms/covered_by.hpp>
+#include <boost/geometry/multi/algorithms/envelope.hpp>
+#include <boost/geometry/multi/algorithms/num_points.hpp>
+#include <boost/geometry/multi/algorithms/detail/overlay/get_ring.hpp>
+#include <boost/geometry/multi/algorithms/detail/overlay/get_turns.hpp>
+#include <boost/geometry/multi/algorithms/detail/overlay/copy_segments.hpp>
+#include <boost/geometry/multi/algorithms/detail/overlay/copy_segment_point.hpp>
+#include <boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp>
+#include <boost/geometry/multi/algorithms/detail/sections/range_by_section.hpp>
+#include <boost/geometry/multi/algorithms/detail/sections/sectionalize.hpp>
+
+#include <boost/geometry/algorithms/intersection.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersection
+{
+
+
+template <typename PointOut>
+struct intersection_multi_linestring_multi_linestring_point
+{
+ template
+ <
+ typename MultiLinestring1, typename MultiLinestring2,
+ typename OutputIterator, typename Strategy
+ >
+ static inline OutputIterator apply(MultiLinestring1 const& ml1,
+ MultiLinestring2 const& ml2, OutputIterator out,
+ Strategy const& strategy)
+ {
+ // Note, this loop is quadratic w.r.t. number of linestrings per input.
+ // Future Enhancement: first do the sections of each, then intersect.
+ for (typename boost::range_iterator
+ <
+ MultiLinestring1 const
+ >::type it1 = boost::begin(ml1);
+ it1 != boost::end(ml1);
+ ++it1)
+ {
+ for (typename boost::range_iterator
+ <
+ MultiLinestring2 const
+ >::type it2 = boost::begin(ml2);
+ it2 != boost::end(ml2);
+ ++it2)
+ {
+ out = intersection_linestring_linestring_point<PointOut>
+ ::apply(*it1, *it2, out, strategy);
+ }
+ }
+
+ return out;
+ }
+};
+
+
+template <typename PointOut>
+struct intersection_linestring_multi_linestring_point
+{
+ template
+ <
+ typename Linestring, typename MultiLinestring,
+ typename OutputIterator, typename Strategy
+ >
+ static inline OutputIterator apply(Linestring const& linestring,
+ MultiLinestring const& ml, OutputIterator out,
+ Strategy const& strategy)
+ {
+ for (typename boost::range_iterator
+ <
+ MultiLinestring const
+ >::type it = boost::begin(ml);
+ it != boost::end(ml);
+ ++it)
+ {
+ out = intersection_linestring_linestring_point<PointOut>
+ ::apply(linestring, *it, out, strategy);
+ }
+
+ return out;
+ }
+};
+
+
+// This loop is quite similar to the loop above, but beacuse the iterator
+// is second (above) or first (below) argument, it is not trivial to merge them.
+template
+<
+ bool ReverseAreal,
+ typename LineStringOut,
+ overlay_type OverlayType
+>
+struct intersection_of_multi_linestring_with_areal
+{
+ template
+ <
+ typename MultiLinestring, typename Areal,
+ typename OutputIterator, typename Strategy
+ >
+ static inline OutputIterator apply(MultiLinestring const& ml, Areal const& areal,
+ OutputIterator out,
+ Strategy const& strategy)
+ {
+ for (typename boost::range_iterator
+ <
+ MultiLinestring const
+ >::type it = boost::begin(ml);
+ it != boost::end(ml);
+ ++it)
+ {
+ out = intersection_of_linestring_with_areal
+ <
+ ReverseAreal, LineStringOut, OverlayType
+ >::apply(*it, areal, out, strategy);
+ }
+
+ return out;
+
+ }
+};
+
+// This one calls the one above with reversed arguments
+template
+<
+ bool ReverseAreal,
+ typename LineStringOut,
+ overlay_type OverlayType
+>
+struct intersection_of_areal_with_multi_linestring
+{
+ template
+ <
+ typename Areal, typename MultiLinestring,
+ typename OutputIterator, typename Strategy
+ >
+ static inline OutputIterator apply(Areal const& areal, MultiLinestring const& ml,
+ OutputIterator out,
+ Strategy const& strategy)
+ {
+ return intersection_of_multi_linestring_with_areal
+ <
+ ReverseAreal, LineStringOut, OverlayType
+ >::apply(ml, areal, out, strategy);
+ }
+};
+
+
+
+template <typename LinestringOut>
+struct clip_multi_linestring
+{
+ template
+ <
+ typename MultiLinestring, typename Box,
+ typename OutputIterator, typename Strategy
+ >
+ static inline OutputIterator apply(MultiLinestring const& multi_linestring,
+ Box const& box, OutputIterator out, Strategy const& )
+ {
+ typedef typename point_type<LinestringOut>::type point_type;
+ strategy::intersection::liang_barsky<Box, point_type> lb_strategy;
+ for (typename boost::range_iterator<MultiLinestring const>::type it
+ = boost::begin(multi_linestring);
+ it != boost::end(multi_linestring); ++it)
+ {
+ out = detail::intersection::clip_range_with_box
+ <LinestringOut>(box, *it, out, lb_strategy);
+ }
+ return out;
+ }
+};
+
+
+}} // namespace detail::intersection
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+// Linear
+template
+<
+ typename MultiLinestring1, typename MultiLinestring2,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ bool Reverse1, bool Reverse2, bool ReverseOut
+>
+struct intersection_insert
+ <
+ MultiLinestring1, MultiLinestring2,
+ GeometryOut,
+ OverlayType,
+ Reverse1, Reverse2, ReverseOut,
+ multi_linestring_tag, multi_linestring_tag, point_tag,
+ false, false, false
+ > : detail::intersection::intersection_multi_linestring_multi_linestring_point
+ <
+ GeometryOut
+ >
+{};
+
+
+template
+<
+ typename Linestring, typename MultiLinestring,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ bool Reverse1, bool Reverse2, bool ReverseOut
+>
+struct intersection_insert
+ <
+ Linestring, MultiLinestring,
+ GeometryOut,
+ OverlayType,
+ Reverse1, Reverse2, ReverseOut,
+ linestring_tag, multi_linestring_tag, point_tag,
+ false, false, false
+ > : detail::intersection::intersection_linestring_multi_linestring_point
+ <
+ GeometryOut
+ >
+{};
+
+
+template
+<
+ typename MultiLinestring, typename Box,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ bool Reverse1, bool Reverse2, bool ReverseOut
+>
+struct intersection_insert
+ <
+ MultiLinestring, Box,
+ GeometryOut,
+ OverlayType,
+ Reverse1, Reverse2, ReverseOut,
+ multi_linestring_tag, box_tag, linestring_tag,
+ false, true, false
+ > : detail::intersection::clip_multi_linestring
+ <
+ GeometryOut
+ >
+{};
+
+
+template
+<
+ typename Linestring, typename MultiPolygon,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ bool ReverseLinestring, bool ReverseMultiPolygon, bool ReverseOut
+>
+struct intersection_insert
+ <
+ Linestring, MultiPolygon,
+ GeometryOut,
+ OverlayType,
+ ReverseLinestring, ReverseMultiPolygon, ReverseOut,
+ linestring_tag, multi_polygon_tag, linestring_tag,
+ false, true, false
+ > : detail::intersection::intersection_of_linestring_with_areal
+ <
+ ReverseMultiPolygon,
+ GeometryOut,
+ OverlayType
+ >
+{};
+
+
+// Derives from areal/mls because runtime arguments are in that order.
+// areal/mls reverses it itself to mls/areal
+template
+<
+ typename Polygon, typename MultiLinestring,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ bool ReversePolygon, bool ReverseMultiLinestring, bool ReverseOut
+>
+struct intersection_insert
+ <
+ Polygon, MultiLinestring,
+ GeometryOut,
+ OverlayType,
+ ReversePolygon, ReverseMultiLinestring, ReverseOut,
+ polygon_tag, multi_linestring_tag, linestring_tag,
+ true, false, false
+ > : detail::intersection::intersection_of_areal_with_multi_linestring
+ <
+ ReversePolygon,
+ GeometryOut,
+ OverlayType
+ >
+{};
+
+
+template
+<
+ typename MultiLinestring, typename Ring,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ bool ReverseMultiLinestring, bool ReverseRing, bool ReverseOut
+>
+struct intersection_insert
+ <
+ MultiLinestring, Ring,
+ GeometryOut,
+ OverlayType,
+ ReverseMultiLinestring, ReverseRing, ReverseOut,
+ multi_linestring_tag, ring_tag, linestring_tag,
+ false, true, false
+ > : detail::intersection::intersection_of_multi_linestring_with_areal
+ <
+ ReverseRing,
+ GeometryOut,
+ OverlayType
+ >
+{};
+
+template
+<
+ typename MultiLinestring, typename Polygon,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ bool ReverseMultiLinestring, bool ReverseRing, bool ReverseOut
+>
+struct intersection_insert
+ <
+ MultiLinestring, Polygon,
+ GeometryOut,
+ OverlayType,
+ ReverseMultiLinestring, ReverseRing, ReverseOut,
+ multi_linestring_tag, polygon_tag, linestring_tag,
+ false, true, false
+ > : detail::intersection::intersection_of_multi_linestring_with_areal
+ <
+ ReverseRing,
+ GeometryOut,
+ OverlayType
+ >
+{};
+
+
+
+template
+<
+ typename MultiLinestring, typename MultiPolygon,
+ typename GeometryOut,
+ overlay_type OverlayType,
+ bool ReverseMultiLinestring, bool ReverseMultiPolygon, bool ReverseOut
+>
+struct intersection_insert
+ <
+ MultiLinestring, MultiPolygon,
+ GeometryOut,
+ OverlayType,
+ ReverseMultiLinestring, ReverseMultiPolygon, ReverseOut,
+ multi_linestring_tag, multi_polygon_tag, linestring_tag,
+ false, true, false
+ > : detail::intersection::intersection_of_multi_linestring_with_areal
+ <
+ ReverseMultiPolygon,
+ GeometryOut,
+ OverlayType
+ >
+{};
+
+
+} // namespace dispatch
+#endif
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_INTERSECTION_HPP
+
diff --git a/boost/geometry/multi/algorithms/length.hpp b/boost/geometry/multi/algorithms/length.hpp
new file mode 100644
index 000000000..e18cbe3d9
--- /dev/null
+++ b/boost/geometry/multi/algorithms/length.hpp
@@ -0,0 +1,62 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_LENGTH_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_LENGTH_HPP
+
+
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/length.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+#include <boost/geometry/multi/algorithms/detail/multi_sum.hpp>
+#include <boost/geometry/multi/algorithms/num_points.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename MultiLinestring>
+struct length<MultiLinestring, multi_linestring_tag> : detail::multi_sum
+{
+ template <typename Strategy>
+ static inline typename default_length_result<MultiLinestring>::type
+ apply(MultiLinestring const& multi, Strategy const& strategy)
+ {
+ return multi_sum::apply
+ <
+ typename default_length_result<MultiLinestring>::type,
+ detail::length::range_length
+ <
+ typename boost::range_value<MultiLinestring>::type,
+ closed // no need to close it explicitly
+ >
+ >(multi, strategy);
+
+ }
+};
+
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_LENGTH_HPP
diff --git a/boost/geometry/multi/algorithms/num_geometries.hpp b/boost/geometry/multi/algorithms/num_geometries.hpp
new file mode 100644
index 000000000..a102d08f2
--- /dev/null
+++ b/boost/geometry/multi/algorithms/num_geometries.hpp
@@ -0,0 +1,53 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_GEOMETRIES_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_GEOMETRIES_HPP
+
+
+#include <cstddef>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/num_geometries.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename MultiGeometry>
+struct num_geometries<MultiGeometry, multi_tag>
+{
+ static inline std::size_t apply(MultiGeometry const& multi_geometry)
+ {
+ return boost::size(multi_geometry);
+ }
+};
+
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_GEOMETRIES_HPP
diff --git a/boost/geometry/multi/algorithms/num_interior_rings.hpp b/boost/geometry/multi/algorithms/num_interior_rings.hpp
new file mode 100644
index 000000000..e43b31d16
--- /dev/null
+++ b/boost/geometry/multi/algorithms/num_interior_rings.hpp
@@ -0,0 +1,62 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_INTERIOR_RINGS_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_INTERIOR_RINGS_HPP
+
+#include <cstddef>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+#include <boost/geometry/algorithms/num_interior_rings.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename MultiPolygon>
+struct num_interior_rings<MultiPolygon, multi_polygon_tag>
+{
+ static inline std::size_t apply(MultiPolygon const& multi_polygon)
+ {
+ std::size_t n = 0;
+ for (typename boost::range_iterator<MultiPolygon const>::type
+ it = boost::begin(multi_polygon);
+ it != boost::end(multi_polygon);
+ ++it)
+ {
+ n += geometry::num_interior_rings(*it);
+ }
+ return n;
+ }
+
+};
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_INTERIOR_RINGS_HPP
diff --git a/boost/geometry/multi/algorithms/num_points.hpp b/boost/geometry/multi/algorithms/num_points.hpp
new file mode 100644
index 000000000..294c08603
--- /dev/null
+++ b/boost/geometry/multi/algorithms/num_points.hpp
@@ -0,0 +1,78 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_POINTS_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_POINTS_HPP
+
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/num_points.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace num_points
+{
+
+
+struct multi_count
+{
+ template <typename MultiGeometry>
+ static inline size_t apply(MultiGeometry const& geometry, bool add_for_open)
+ {
+ typedef typename boost::range_value<MultiGeometry>::type geometry_type;
+ typedef typename boost::range_iterator
+ <
+ MultiGeometry const
+ >::type iterator_type;
+
+ std::size_t n = 0;
+ for (iterator_type it = boost::begin(geometry);
+ it != boost::end(geometry);
+ ++it)
+ {
+ n += dispatch::num_points<geometry_type>::apply(*it, add_for_open);
+ }
+ return n;
+ }
+};
+
+
+}} // namespace detail::num_points
+#endif
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Geometry>
+struct num_points<Geometry, multi_tag>
+ : detail::num_points::multi_count {};
+
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_NUM_POINTS_HPP
diff --git a/boost/geometry/multi/algorithms/perimeter.hpp b/boost/geometry/multi/algorithms/perimeter.hpp
new file mode 100644
index 000000000..5b37525b8
--- /dev/null
+++ b/boost/geometry/multi/algorithms/perimeter.hpp
@@ -0,0 +1,56 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_PERIMETER_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_PERIMETER_HPP
+
+
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/perimeter.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+#include <boost/geometry/multi/algorithms/detail/multi_sum.hpp>
+#include <boost/geometry/multi/algorithms/num_points.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+template <typename MultiPolygon>
+struct perimeter<MultiPolygon, multi_polygon_tag> : detail::multi_sum
+{
+ template <typename Strategy>
+ static inline typename default_length_result<MultiPolygon>::type
+ apply(MultiPolygon const& multi, Strategy const& strategy)
+ {
+ return multi_sum::apply
+ <
+ typename default_length_result<MultiPolygon>::type,
+ perimeter<typename boost::range_value<MultiPolygon>::type>
+ >(multi, strategy);
+ }
+};
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_PERIMETER_HPP
diff --git a/boost/geometry/multi/algorithms/reverse.hpp b/boost/geometry/multi/algorithms/reverse.hpp
new file mode 100644
index 000000000..7a4938ef8
--- /dev/null
+++ b/boost/geometry/multi/algorithms/reverse.hpp
@@ -0,0 +1,63 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_REVERSE_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_REVERSE_HPP
+
+
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/algorithms/reverse.hpp>
+#include <boost/geometry/multi/algorithms/detail/modify.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Geometry>
+struct reverse<Geometry, multi_linestring_tag>
+ : detail::multi_modify
+ <
+ Geometry,
+ detail::reverse::range_reverse
+ >
+{};
+
+
+template <typename Geometry>
+struct reverse<Geometry, multi_polygon_tag>
+ : detail::multi_modify
+ <
+ Geometry,
+ detail::reverse::polygon_reverse
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_REVERSE_HPP
diff --git a/boost/geometry/multi/algorithms/simplify.hpp b/boost/geometry/multi/algorithms/simplify.hpp
new file mode 100644
index 000000000..2c7461b66
--- /dev/null
+++ b/boost/geometry/multi/algorithms/simplify.hpp
@@ -0,0 +1,92 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_SIMPLIFY_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_SIMPLIFY_HPP
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/mutable_range.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+#include <boost/geometry/multi/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/simplify.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace simplify
+{
+
+template<typename Policy>
+struct simplify_multi
+{
+ template <typename MultiGeometry, typename Strategy>
+ static inline void apply(MultiGeometry const& multi, MultiGeometry& out,
+ double max_distance, Strategy const& strategy)
+ {
+ traits::resize<MultiGeometry>::apply(out, boost::size(multi));
+
+ typename boost::range_iterator<MultiGeometry>::type it_out
+ = boost::begin(out);
+ for (typename boost::range_iterator<MultiGeometry const>::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>
+struct simplify<MultiPoint, multi_point_tag>
+ : detail::simplify::simplify_copy
+{};
+
+
+template <typename MultiLinestring>
+struct simplify<MultiLinestring, multi_linestring_tag>
+ : detail::simplify::simplify_multi<detail::simplify::simplify_range<2> >
+{};
+
+
+template <typename MultiPolygon>
+struct simplify<MultiPolygon, multi_polygon_tag>
+ : detail::simplify::simplify_multi<detail::simplify::simplify_polygon>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_SIMPLIFY_HPP
diff --git a/boost/geometry/multi/algorithms/transform.hpp b/boost/geometry/multi/algorithms/transform.hpp
new file mode 100644
index 000000000..13c53e615
--- /dev/null
+++ b/boost/geometry/multi/algorithms/transform.hpp
@@ -0,0 +1,91 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_TRANSFORM_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_TRANSFORM_HPP
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/mutable_range.hpp>
+#include <boost/geometry/algorithms/transform.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace transform
+{
+
+/*!
+ \brief Is able to transform any multi-geometry, calling the single-version as policy
+*/
+template <typename Policy>
+struct transform_multi
+{
+ template <typename Multi1, typename Multi2, typename S>
+ static inline bool apply(Multi1 const& multi1, Multi2& multi2, S const& strategy)
+ {
+ traits::resize<Multi2>::apply(multi2, boost::size(multi1));
+
+ typename boost::range_iterator<Multi1 const>::type it1
+ = boost::begin(multi1);
+ typename boost::range_iterator<Multi2>::type it2
+ = boost::begin(multi2);
+
+ for (; it1 != boost::end(multi1); ++it1, ++it2)
+ {
+ if (! Policy::apply(*it1, *it2, strategy))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+};
+
+
+}} // namespace detail::transform
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Multi1, typename Multi2>
+struct transform
+ <
+ Multi1, Multi2,
+ multi_tag, multi_tag
+ >
+ : detail::transform::transform_multi
+ <
+ transform
+ <
+ typename boost::range_value<Multi1>::type,
+ typename boost::range_value<Multi2>::type
+ >
+ >
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_TRANSFORM_HPP
diff --git a/boost/geometry/multi/algorithms/unique.hpp b/boost/geometry/multi/algorithms/unique.hpp
new file mode 100644
index 000000000..64c56aafb
--- /dev/null
+++ b/boost/geometry/multi/algorithms/unique.hpp
@@ -0,0 +1,86 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_UNIQUE_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_UNIQUE_HPP
+
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/unique.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace unique
+{
+
+
+template <typename Policy>
+struct multi_unique
+{
+ template <typename MultiGeometry, typename ComparePolicy>
+ static inline void apply(MultiGeometry& multi, ComparePolicy const& compare)
+ {
+ for (typename boost::range_iterator<MultiGeometry>::type
+ it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ Policy::apply(*it, compare);
+ }
+ }
+};
+
+
+}} // namespace detail::unique
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+// For points, unique is not applicable and does nothing
+// (Note that it is not "spatially unique" but that it removes duplicate coordinates,
+// like std::unique does). Spatially unique is "dissolve" which can (or will be)
+// possible for multi-points as well, removing points at the same location.
+
+
+template <typename MultiLineString>
+struct unique<MultiLineString, multi_linestring_tag>
+ : detail::unique::multi_unique<detail::unique::range_unique>
+{};
+
+
+template <typename MultiPolygon>
+struct unique<MultiPolygon, multi_polygon_tag>
+ : detail::unique::multi_unique<detail::unique::polygon_unique>
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_UNIQUE_HPP
diff --git a/boost/geometry/multi/algorithms/within.hpp b/boost/geometry/multi/algorithms/within.hpp
new file mode 100644
index 000000000..4094dcc2d
--- /dev/null
+++ b/boost/geometry/multi/algorithms/within.hpp
@@ -0,0 +1,105 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_ALGORITHMS_WITHIN_HPP
+#define BOOST_GEOMETRY_MULTI_ALGORITHMS_WITHIN_HPP
+
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/algorithms/within.hpp>
+#include <boost/geometry/multi/core/closure.hpp>
+#include <boost/geometry/multi/core/point_order.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace within
+{
+
+
+template
+<
+ typename Geometry,
+ typename MultiGeometry,
+ typename Strategy,
+ typename Policy
+>
+struct geometry_multi_within_code
+{
+ static inline int apply(Geometry const& geometry,
+ MultiGeometry const& multi,
+ Strategy const& strategy)
+ {
+ for (typename boost::range_iterator<MultiGeometry const>::type it
+ = boost::begin(multi);
+ it != boost::end(multi);
+ ++it)
+ {
+ // Geometry coding on multi: 1 (within) if within one of them;
+ // 0 (touch) if on border of one of them
+ int const code = Policy::apply(geometry, *it, strategy);
+ if (code != -1)
+ {
+ return code;
+ }
+ }
+ return -1;
+ }
+};
+
+
+}} // namespace detail::within
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Point, typename MultiPolygon>
+struct within<Point, MultiPolygon, point_tag, multi_polygon_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Point const& point,
+ MultiPolygon const& multi_polygon, Strategy const& strategy)
+ {
+ return detail::within::geometry_multi_within_code
+ <
+ Point,
+ MultiPolygon,
+ Strategy,
+ detail::within::point_in_polygon
+ <
+ Point,
+ typename boost::range_value<MultiPolygon>::type,
+ order_as_direction
+ <
+ geometry::point_order<MultiPolygon>::value
+ >::value,
+ geometry::closure<MultiPolygon>::value,
+ Strategy
+ >
+ >::apply(point, multi_polygon, strategy) == 1;
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_ALGORITHMS_WITHIN_HPP
diff --git a/boost/geometry/multi/core/closure.hpp b/boost/geometry/multi/core/closure.hpp
new file mode 100644
index 000000000..3964db256
--- /dev/null
+++ b/boost/geometry/multi/core/closure.hpp
@@ -0,0 +1,58 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_CORE_CLOSURE_HPP
+#define BOOST_GEOMETRY_MULTI_CORE_CLOSURE_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/range.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename Multi>
+struct closure<multi_point_tag, Multi> : public core_detail::closure::closed {};
+
+template <typename Multi>
+struct closure<multi_linestring_tag, Multi> : public core_detail::closure::closed {};
+
+// Specialization for polygon: the closure is the closure of its rings
+template <typename MultiPolygon>
+struct closure<multi_polygon_tag, MultiPolygon>
+{
+ static const closure_selector value = core_dispatch::closure
+ <
+ polygon_tag,
+ typename boost::range_value<MultiPolygon>::type
+ >::value ;
+};
+
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_CORE_CLOSURE_HPP
diff --git a/boost/geometry/multi/core/geometry_id.hpp b/boost/geometry/multi/core/geometry_id.hpp
new file mode 100644
index 000000000..9d69cb20d
--- /dev/null
+++ b/boost/geometry/multi/core/geometry_id.hpp
@@ -0,0 +1,56 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_CORE_GEOMETRY_ID_HPP
+#define BOOST_GEOMETRY_MULTI_CORE_GEOMETRY_ID_HPP
+
+
+#include <boost/mpl/int.hpp>
+#include <boost/type_traits.hpp>
+
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/geometry_id.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <>
+struct geometry_id<multi_point_tag> : boost::mpl::int_<4> {};
+
+
+template <>
+struct geometry_id<multi_linestring_tag> : boost::mpl::int_<5> {};
+
+
+template <>
+struct geometry_id<multi_polygon_tag> : boost::mpl::int_<6> {};
+
+
+} // namespace core_dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_CORE_GEOMETRY_ID_HPP
diff --git a/boost/geometry/multi/core/interior_rings.hpp b/boost/geometry/multi/core/interior_rings.hpp
new file mode 100644
index 000000000..5a200d486
--- /dev/null
+++ b/boost/geometry/multi/core/interior_rings.hpp
@@ -0,0 +1,55 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_CORE_INTERIOR_RINGS_HPP
+#define BOOST_GEOMETRY_MULTI_CORE_INTERIOR_RINGS_HPP
+
+
+#include <cstddef>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+
+template <typename MultiPolygon>
+struct interior_type<multi_polygon_tag, MultiPolygon>
+{
+ typedef typename core_dispatch::interior_type
+ <
+ polygon_tag,
+ typename boost::range_value<MultiPolygon>::type
+ >::type type;
+};
+
+
+} // namespace core_dispatch
+#endif
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_CORE_INTERIOR_RINGS_HPP
diff --git a/boost/geometry/multi/core/is_areal.hpp b/boost/geometry/multi/core/is_areal.hpp
new file mode 100644
index 000000000..ad8daeb49
--- /dev/null
+++ b/boost/geometry/multi/core/is_areal.hpp
@@ -0,0 +1,43 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_CORE_IS_AREAL_HPP
+#define BOOST_GEOMETRY_MULTI_CORE_IS_AREAL_HPP
+
+
+#include <boost/type_traits.hpp>
+
+
+#include <boost/geometry/core/is_areal.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <> struct is_areal<multi_polygon_tag> : boost::true_type {};
+
+} // namespace core_dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_CORE_IS_AREAL_HPP
diff --git a/boost/geometry/multi/core/point_order.hpp b/boost/geometry/multi/core/point_order.hpp
new file mode 100644
index 000000000..6b08468e8
--- /dev/null
+++ b/boost/geometry/multi/core/point_order.hpp
@@ -0,0 +1,57 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_CORE_POINT_ORDER_HPP
+#define BOOST_GEOMETRY_MULTI_CORE_POINT_ORDER_HPP
+
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/point_order.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename Multi>
+struct point_order<multi_point_tag, Multi>
+ : public detail::point_order::clockwise {};
+
+template <typename Multi>
+struct point_order<multi_linestring_tag, Multi>
+ : public detail::point_order::clockwise {};
+
+
+// Specialization for multi_polygon: the order is the order of its polygons
+template <typename MultiPolygon>
+struct point_order<multi_polygon_tag, MultiPolygon>
+{
+ static const order_selector value = core_dispatch::point_order
+ <
+ polygon_tag,
+ typename boost::range_value<MultiPolygon>::type
+ >::value ;
+};
+
+} // namespace core_dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_CORE_POINT_ORDER_HPP
diff --git a/boost/geometry/multi/core/point_type.hpp b/boost/geometry/multi/core/point_type.hpp
new file mode 100644
index 000000000..3c77e973b
--- /dev/null
+++ b/boost/geometry/multi/core/point_type.hpp
@@ -0,0 +1,64 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_CORE_POINT_TYPE_HPP
+#define BOOST_GEOMETRY_MULTI_CORE_POINT_TYPE_HPP
+
+
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename MultiPoint>
+struct point_type<multi_point_tag, MultiPoint>
+{
+ typedef typename boost::range_value<MultiPoint>::type type;
+};
+
+
+template <typename MultiLinestring>
+struct point_type<multi_linestring_tag, MultiLinestring>
+{
+ typedef typename point_type<linestring_tag,
+ typename boost::range_value<MultiLinestring>::type>::type type;
+};
+
+
+
+template <typename MultiPolygon>
+struct point_type<multi_polygon_tag, MultiPolygon>
+{
+ typedef typename point_type<polygon_tag,
+ typename boost::range_value<MultiPolygon>::type>::type type;
+};
+
+
+}
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_CORE_POINT_TYPE_HPP
diff --git a/boost/geometry/multi/core/ring_type.hpp b/boost/geometry/multi/core/ring_type.hpp
new file mode 100644
index 000000000..faafaed02
--- /dev/null
+++ b/boost/geometry/multi/core/ring_type.hpp
@@ -0,0 +1,66 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_CORE_RING_TYPE_HPP
+#define BOOST_GEOMETRY_MULTI_CORE_RING_TYPE_HPP
+
+
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <typename MultiPolygon>
+struct ring_return_type<multi_polygon_tag, MultiPolygon>
+{
+ typedef typename ring_return_type
+ <
+ polygon_tag,
+ typename mpl::if_
+ <
+ boost::is_const<MultiPolygon>,
+ typename boost::range_value<MultiPolygon>::type const,
+ typename boost::range_value<MultiPolygon>::type
+ >::type
+ >::type type;
+};
+
+
+template <typename MultiPolygon>
+struct ring_type<multi_polygon_tag, MultiPolygon>
+{
+ typedef typename boost::remove_reference
+ <
+ typename ring_return_type<multi_polygon_tag, MultiPolygon>::type
+ >::type type;
+};
+
+
+} // namespace core_dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_CORE_RING_TYPE_HPP
diff --git a/boost/geometry/multi/core/tags.hpp b/boost/geometry/multi/core/tags.hpp
new file mode 100644
index 000000000..dcfca65b2
--- /dev/null
+++ b/boost/geometry/multi/core/tags.hpp
@@ -0,0 +1,71 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_CORE_TAGS_HPP
+#define BOOST_GEOMETRY_MULTI_CORE_TAGS_HPP
+
+#include <boost/geometry/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+/// OGC Multi point identifying tag
+struct multi_point_tag : multi_tag, pointlike_tag {};
+
+/// OGC Multi linestring identifying tag
+struct multi_linestring_tag : multi_tag, linear_tag {};
+
+/// OGC Multi polygon identifying tag
+struct multi_polygon_tag : multi_tag, polygonal_tag {};
+
+/// OGC Geometry Collection identifying tag
+struct geometry_collection_tag : multi_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_of
+{};
+
+#ifndef DOXYGEN_NO_DETAIL
+
+template <>
+struct single_tag_of<multi_point_tag>
+{
+ typedef point_tag type;
+};
+
+template <>
+struct single_tag_of<multi_linestring_tag>
+{
+ typedef linestring_tag type;
+};
+
+template <>
+struct single_tag_of<multi_polygon_tag>
+{
+ typedef polygon_tag type;
+};
+
+#endif
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_CORE_TAGS_HPP
diff --git a/boost/geometry/multi/core/topological_dimension.hpp b/boost/geometry/multi/core/topological_dimension.hpp
new file mode 100644
index 000000000..55118f1c7
--- /dev/null
+++ b/boost/geometry/multi/core/topological_dimension.hpp
@@ -0,0 +1,52 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_TOPOLOGICAL_DIMENSION_HPP
+#define BOOST_GEOMETRY_MULTI_TOPOLOGICAL_DIMENSION_HPP
+
+
+#include <boost/mpl/int.hpp>
+
+
+#include <boost/geometry/core/topological_dimension.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace core_dispatch
+{
+
+template <>
+struct top_dim<multi_point_tag> : boost::mpl::int_<0> {};
+
+
+template <>
+struct top_dim<multi_linestring_tag> : boost::mpl::int_<1> {};
+
+
+template <>
+struct top_dim<multi_polygon_tag> : boost::mpl::int_<2> {};
+
+
+} // namespace core_dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif
diff --git a/boost/geometry/multi/geometries/concepts/check.hpp b/boost/geometry/multi/geometries/concepts/check.hpp
new file mode 100644
index 000000000..61afc913c
--- /dev/null
+++ b/boost/geometry/multi/geometries/concepts/check.hpp
@@ -0,0 +1,83 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_CHECK_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_CHECK_HPP
+
+
+
+#include <boost/type_traits/is_const.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/multi/geometries/concepts/multi_point_concept.hpp>
+#include <boost/geometry/multi/geometries/concepts/multi_linestring_concept.hpp>
+#include <boost/geometry/multi/geometries/concepts/multi_polygon_concept.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Geometry>
+struct check<Geometry, multi_point_tag, true>
+ : detail::concept_check::check<concept::ConstMultiPoint<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<Geometry, multi_point_tag, false>
+ : detail::concept_check::check<concept::MultiPoint<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<Geometry, multi_linestring_tag, true>
+ : detail::concept_check::check<concept::ConstMultiLinestring<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<Geometry, multi_linestring_tag, false>
+ : detail::concept_check::check<concept::MultiLinestring<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<Geometry, multi_polygon_tag, true>
+ : detail::concept_check::check<concept::ConstMultiPolygon<Geometry> >
+{};
+
+
+template <typename Geometry>
+struct check<Geometry, multi_polygon_tag, false>
+ : detail::concept_check::check<concept::MultiPolygon<Geometry> >
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_CHECK_HPP
diff --git a/boost/geometry/multi/geometries/concepts/multi_linestring_concept.hpp b/boost/geometry/multi/geometries/concepts/multi_linestring_concept.hpp
new file mode 100644
index 000000000..b0519f07e
--- /dev/null
+++ b/boost/geometry/multi/geometries/concepts/multi_linestring_concept.hpp
@@ -0,0 +1,86 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_LINESTRING_CONCEPT_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_LINESTRING_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <boost/geometry/geometries/concepts/linestring_concept.hpp>
+
+
+namespace boost { namespace geometry { namespace concept
+{
+
+
+/*!
+\brief multi-linestring concept
+\ingroup concepts
+\par Formal definition:
+The multi linestring concept is defined as following:
+- there must be a specialization of traits::tag defining multi_linestring_tag as
+ type
+- it must behave like a Boost.Range
+- its range value must fulfil the Linestring concept
+
+*/
+template <typename Geometry>
+class MultiLinestring
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type linestring_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Linestring<linestring_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(MultiLinestring)
+ {
+ }
+#endif
+};
+
+
+/*!
+\brief concept for multi-linestring (const version)
+\ingroup const_concepts
+*/
+template <typename Geometry>
+class ConstMultiLinestring
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type linestring_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstLinestring<linestring_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstMultiLinestring)
+ {
+ }
+#endif
+};
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_LINESTRING_CONCEPT_HPP
diff --git a/boost/geometry/multi/geometries/concepts/multi_point_concept.hpp b/boost/geometry/multi/geometries/concepts/multi_point_concept.hpp
new file mode 100644
index 000000000..f5942df07
--- /dev/null
+++ b/boost/geometry/multi/geometries/concepts/multi_point_concept.hpp
@@ -0,0 +1,85 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POINT_CONCEPT_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POINT_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+#include <boost/range/metafunctions.hpp>
+
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+
+namespace boost { namespace geometry { namespace concept
+{
+
+
+/*!
+\brief MultiPoint concept
+\ingroup concepts
+\par Formal definition:
+The multi point concept is defined as following:
+- there must be a specialization of traits::tag defining multi_point_tag as type
+- it must behave like a Boost.Range
+- its range value must fulfil the Point concept
+
+*/
+template <typename Geometry>
+class MultiPoint
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Point<point_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(MultiPoint)
+ {
+ }
+#endif
+};
+
+
+/*!
+\brief concept for multi-point (const version)
+\ingroup const_concepts
+*/
+template <typename Geometry>
+class ConstMultiPoint
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type point_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<point_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstMultiPoint)
+ {
+ }
+#endif
+};
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POINT_CONCEPT_HPP
diff --git a/boost/geometry/multi/geometries/concepts/multi_polygon_concept.hpp b/boost/geometry/multi/geometries/concepts/multi_polygon_concept.hpp
new file mode 100644
index 000000000..ca730d4f6
--- /dev/null
+++ b/boost/geometry/multi/geometries/concepts/multi_polygon_concept.hpp
@@ -0,0 +1,86 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POLYGON_CONCEPT_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POLYGON_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/range/concepts.hpp>
+#include <boost/range/metafunctions.hpp>
+
+#include <boost/geometry/geometries/concepts/polygon_concept.hpp>
+
+
+namespace boost { namespace geometry { namespace concept
+{
+
+
+/*!
+\brief multi-polygon concept
+\ingroup concepts
+\par Formal definition:
+The multi polygon concept is defined as following:
+- there must be a specialization of traits::tag defining multi_polygon_tag
+ as type
+- it must behave like a Boost.Range
+- its range value must fulfil the Polygon concept
+
+*/
+template <typename Geometry>
+class MultiPolygon
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type polygon_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::Polygon<polygon_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(MultiPolygon)
+ {
+ }
+#endif
+};
+
+
+/*!
+\brief concept for multi-polygon (const version)
+\ingroup const_concepts
+*/
+template <typename Geometry>
+class ConstMultiPolygon
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+ typedef typename boost::range_value<Geometry>::type polygon_type;
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstPolygon<polygon_type>) );
+ BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept<Geometry>) );
+
+
+public :
+
+ BOOST_CONCEPT_USAGE(ConstMultiPolygon)
+ {
+ }
+#endif
+};
+
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_CONCEPTS_MULTI_POLYGON_CONCEPT_HPP
diff --git a/boost/geometry/multi/geometries/multi_geometries.hpp b/boost/geometry/multi/geometries/multi_geometries.hpp
new file mode 100644
index 000000000..90cf85a0f
--- /dev/null
+++ b/boost/geometry/multi/geometries/multi_geometries.hpp
@@ -0,0 +1,21 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_GEOMETRIES_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_GEOMETRIES_HPP
+
+#include <boost/geometry/multi/geometries/multi_point.hpp>
+#include <boost/geometry/multi/geometries/multi_linestring.hpp>
+#include <boost/geometry/multi/geometries/multi_polygon.hpp>
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_GEOMETRIES_HPP
diff --git a/boost/geometry/multi/geometries/multi_linestring.hpp b/boost/geometry/multi/geometries/multi_linestring.hpp
new file mode 100644
index 000000000..67d4da06b
--- /dev/null
+++ b/boost/geometry/multi/geometries/multi_linestring.hpp
@@ -0,0 +1,80 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_LINESTRING_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_LINESTRING_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/requires.hpp>
+
+#include <boost/geometry/geometries/concepts/linestring_concept.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+namespace model
+{
+
+/*!
+\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
+
+\qbk{before.synopsis,
+[heading Model of]
+[link geometry.reference.concepts.concept_multi_linestring MultiLineString Concept]
+}
+*/
+template
+<
+ typename LineString,
+ template<typename, typename> class Container = std::vector,
+ template<typename> class Allocator = std::allocator
+>
+class multi_linestring : public Container<LineString, Allocator<LineString> >
+{
+ BOOST_CONCEPT_ASSERT( (concept::Linestring<LineString>) );
+};
+
+
+} // namespace model
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename LineString,
+ template<typename, typename> class Container,
+ template<typename> class Allocator
+>
+struct tag< model::multi_linestring<LineString, Container, Allocator> >
+{
+ typedef multi_linestring_tag type;
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_LINESTRING_HPP
diff --git a/boost/geometry/multi/geometries/multi_point.hpp b/boost/geometry/multi/geometries/multi_point.hpp
new file mode 100644
index 000000000..002d8f8a4
--- /dev/null
+++ b/boost/geometry/multi/geometries/multi_point.hpp
@@ -0,0 +1,94 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POINT_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POINT_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/requires.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace model
+{
+
+
+/*!
+\brief multi_point, a collection of points
+\ingroup geometries
+\tparam Point \tparam_point
+\tparam Container \tparam_container
+\tparam Allocator \tparam_allocator
+\details Multipoint can be used to group points belonging to each other,
+ e.g. a constellation, or the result set of an intersection
+\qbk{before.synopsis,
+[heading Model of]
+[link geometry.reference.concepts.concept_multi_point MultiPoint Concept]
+}
+*/
+template
+<
+ typename Point,
+ template<typename, typename> class Container = std::vector,
+ template<typename> class Allocator = std::allocator
+>
+class multi_point : public Container<Point, Allocator<Point> >
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+ typedef Container<Point, Allocator<Point> > base_type;
+
+public :
+ /// \constructor_default{multi_point}
+ inline multi_point()
+ : base_type()
+ {}
+
+ /// \constructor_begin_end{multi_point}
+ template <typename Iterator>
+ inline multi_point(Iterator begin, Iterator end)
+ : base_type(begin, end)
+ {}
+};
+
+} // namespace model
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename Point,
+ template<typename, typename> class Container,
+ template<typename> class Allocator
+>
+struct tag< model::multi_point<Point, Container, Allocator> >
+{
+ typedef multi_point_tag type;
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POINT_HPP
diff --git a/boost/geometry/multi/geometries/multi_polygon.hpp b/boost/geometry/multi/geometries/multi_polygon.hpp
new file mode 100644
index 000000000..af8d04287
--- /dev/null
+++ b/boost/geometry/multi/geometries/multi_polygon.hpp
@@ -0,0 +1,78 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POLYGON_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POLYGON_HPP
+
+#include <memory>
+#include <vector>
+
+#include <boost/concept/requires.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+#include <boost/geometry/geometries/concepts/polygon_concept.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace model
+{
+
+/*!
+\brief multi_polygon, a collection of polygons
+\details Multi-polygon can be used to group polygons belonging to each other,
+ e.g. Hawaii
+\ingroup geometries
+
+\qbk{before.synopsis,
+[heading Model of]
+[link geometry.reference.concepts.concept_multi_polygon MultiPolygon Concept]
+}
+*/
+template
+<
+ typename Polygon,
+ template<typename, typename> class Container = std::vector,
+ template<typename> class Allocator = std::allocator
+>
+class multi_polygon : public Container<Polygon, Allocator<Polygon> >
+{
+ BOOST_CONCEPT_ASSERT( (concept::Polygon<Polygon>) );
+};
+
+
+} // namespace model
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template
+<
+ typename Polygon,
+ template<typename, typename> class Container,
+ template<typename> class Allocator
+>
+struct tag< model::multi_polygon<Polygon, Container, Allocator> >
+{
+ typedef multi_polygon_tag type;
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_MULTI_POLYGON_HPP
diff --git a/boost/geometry/multi/geometries/register/multi_linestring.hpp b/boost/geometry/multi/geometries/register/multi_linestring.hpp
new file mode 100644
index 000000000..5ececdb8e
--- /dev/null
+++ b/boost/geometry/multi/geometries/register/multi_linestring.hpp
@@ -0,0 +1,59 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_LINESTRING_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_LINESTRING_HPP
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+/*!
+\brief \brief_macro{multi_linestring}
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_MULTI_LINESTRING, multi_linestring} The
+ multi_linestring may contain template parameters, which must be specified then.
+\param MultiLineString \param_macro_type{multi_linestring}
+
+\qbk{
+[heading Example]
+[register_multi_linestring]
+[register_multi_linestring_output]
+}
+*/
+#define BOOST_GEOMETRY_REGISTER_MULTI_LINESTRING(MultiLineString) \
+namespace boost { namespace geometry { namespace traits { \
+ template<> struct tag<MultiLineString> { typedef multi_linestring_tag type; }; \
+}}}
+
+
+/*!
+\brief \brief_macro{templated multi_linestring}
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_MULTI_LINESTRING_TEMPLATED, templated multi_linestring}
+ \details_macro_templated{multi_linestring, linestring}
+\param MultiLineString \param_macro_type{multi_linestring (without template parameters)}
+
+\qbk{
+[heading Example]
+[register_multi_linestring_templated]
+[register_multi_linestring_templated_output]
+}
+*/
+#define BOOST_GEOMETRY_REGISTER_MULTI_LINESTRING_TEMPLATED(MultiLineString) \
+namespace boost { namespace geometry { namespace traits { \
+ template<typename LineString> struct tag< MultiLineString<LineString> > { typedef multi_linestring_tag type; }; \
+}}}
+
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_LINESTRING_HPP
diff --git a/boost/geometry/multi/geometries/register/multi_point.hpp b/boost/geometry/multi/geometries/register/multi_point.hpp
new file mode 100644
index 000000000..813f54733
--- /dev/null
+++ b/boost/geometry/multi/geometries/register/multi_point.hpp
@@ -0,0 +1,59 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_POINT_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_POINT_HPP
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+/*!
+\brief \brief_macro{multi_point}
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_MULTI_POINT, multi_point} The
+ multi_point may contain template parameters, which must be specified then.
+\param MultiPoint \param_macro_type{multi_point}
+
+\qbk{
+[heading Example]
+[register_multi_point]
+[register_multi_point_output]
+}
+*/
+#define BOOST_GEOMETRY_REGISTER_MULTI_POINT(MultiPoint) \
+namespace boost { namespace geometry { namespace traits { \
+ template<> struct tag<MultiPoint> { typedef multi_point_tag type; }; \
+}}}
+
+
+/*!
+\brief \brief_macro{templated multi_point}
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_MULTI_POINT_TEMPLATED, templated multi_point}
+ \details_macro_templated{multi_point, point}
+\param MultiPoint \param_macro_type{multi_point (without template parameters)}
+
+\qbk{
+[heading Example]
+[register_multi_point_templated]
+[register_multi_point_templated_output]
+}
+*/
+#define BOOST_GEOMETRY_REGISTER_MULTI_POINT_TEMPLATED(MultiPoint) \
+namespace boost { namespace geometry { namespace traits { \
+ template<typename Point> struct tag< MultiPoint<Point> > { typedef multi_point_tag type; }; \
+}}}
+
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_POINT_HPP
diff --git a/boost/geometry/multi/geometries/register/multi_polygon.hpp b/boost/geometry/multi/geometries/register/multi_polygon.hpp
new file mode 100644
index 000000000..801b98cf2
--- /dev/null
+++ b/boost/geometry/multi/geometries/register/multi_polygon.hpp
@@ -0,0 +1,59 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_POLYGON_HPP
+#define BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_POLYGON_HPP
+
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+
+/*!
+\brief \brief_macro{multi_polygon}
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_MULTI_POLYGON, multi_polygon} The
+ multi_polygon may contain template parameters, which must be specified then.
+\param MultiPolygon \param_macro_type{multi_polygon}
+
+\qbk{
+[heading Example]
+[register_multi_polygon]
+[register_multi_polygon_output]
+}
+*/
+#define BOOST_GEOMETRY_REGISTER_MULTI_POLYGON(MultiPolygon) \
+namespace boost { namespace geometry { namespace traits { \
+ template<> struct tag<MultiPolygon> { typedef multi_polygon_tag type; }; \
+}}}
+
+
+/*!
+\brief \brief_macro{templated multi_polygon}
+\ingroup register
+\details \details_macro{BOOST_GEOMETRY_REGISTER_MULTI_POLYGON_TEMPLATED, templated multi_polygon}
+ \details_macro_templated{multi_polygon, polygon}
+\param MultiPolygon \param_macro_type{multi_polygon (without template parameters)}
+
+\qbk{
+[heading Example]
+[register_multi_polygon_templated]
+[register_multi_polygon_templated_output]
+}
+*/
+#define BOOST_GEOMETRY_REGISTER_MULTI_POLYGON_TEMPLATED(MultiPolygon) \
+namespace boost { namespace geometry { namespace traits { \
+ template<typename Polygon> struct tag< MultiPolygon<Polygon> > { typedef multi_polygon_tag type; }; \
+}}}
+
+
+#endif // BOOST_GEOMETRY_MULTI_GEOMETRIES_REGISTER_MULTI_POLYGON_HPP
diff --git a/boost/geometry/multi/io/dsv/write.hpp b/boost/geometry/multi/io/dsv/write.hpp
new file mode 100644
index 000000000..1a054659a
--- /dev/null
+++ b/boost/geometry/multi/io/dsv/write.hpp
@@ -0,0 +1,86 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_IO_DSV_WRITE_HPP
+#define BOOST_GEOMETRY_MULTI_IO_DSV_WRITE_HPP
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+
+#include <boost/geometry/io/dsv/write.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace dsv
+{
+
+template <typename MultiGeometry>
+struct dsv_multi
+{
+ typedef dispatch::dsv
+ <
+ typename single_tag_of
+ <
+ typename tag<MultiGeometry>::type
+ >::type,
+ typename boost::range_value<MultiGeometry>::type
+ > dispatch_one;
+
+ typedef typename boost::range_iterator
+ <
+ MultiGeometry const
+ >::type iterator;
+
+
+ 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;
+
+ bool first = true;
+ for(iterator it = boost::begin(multi);
+ it != boost::end(multi);
+ ++it, first = false)
+ {
+ os << (first ? "" : settings.list_separator);
+ dispatch_one::apply(os, *it, settings);
+ }
+ os << settings.list_close;
+ }
+};
+
+}} // namespace detail::dsv
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Geometry>
+struct dsv<multi_tag, Geometry>
+ : detail::dsv::dsv_multi<Geometry>
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_IO_DSV_WRITE_HPP
diff --git a/boost/geometry/multi/io/wkt/detail/prefix.hpp b/boost/geometry/multi/io/wkt/detail/prefix.hpp
new file mode 100644
index 000000000..37b07979b
--- /dev/null
+++ b/boost/geometry/multi/io/wkt/detail/prefix.hpp
@@ -0,0 +1,51 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP
+#define BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP
+
+#include <boost/geometry/multi/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace wkt
+{
+
+struct prefix_null
+{
+ static inline const char* apply() { return ""; }
+};
+
+struct prefix_multipoint
+{
+ static inline const char* apply() { return "MULTIPOINT"; }
+};
+
+struct prefix_multilinestring
+{
+ static inline const char* apply() { return "MULTILINESTRING"; }
+};
+
+struct prefix_multipolygon
+{
+ static inline const char* apply() { return "MULTIPOLYGON"; }
+};
+
+}} // namespace wkt::impl
+#endif
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP
diff --git a/boost/geometry/multi/io/wkt/read.hpp b/boost/geometry/multi/io/wkt/read.hpp
new file mode 100644
index 000000000..2bfa830cf
--- /dev/null
+++ b/boost/geometry/multi/io/wkt/read.hpp
@@ -0,0 +1,168 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_IO_WKT_READ_MULTI_HPP
+#define BOOST_GEOMETRY_MULTI_IO_WKT_READ_MULTI_HPP
+
+#include <string>
+
+#include <boost/geometry/core/mutable_range.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/core/point_type.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+#include <boost/geometry/multi/io/wkt/detail/prefix.hpp>
+#include <boost/geometry/io/wkt/read.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace detail { namespace wkt
+{
+
+template <typename MultiGeometry, template<typename> class Parser, typename PrefixPolicy>
+struct multi_parser
+{
+ static inline void apply(std::string const& wkt, MultiGeometry& geometry)
+ {
+ traits::clear<MultiGeometry>::apply(geometry);
+
+ 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 != ")")
+ {
+ traits::resize<MultiGeometry>::apply(geometry, boost::size(geometry) + 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);
+ }
+
+ check_end(it, tokens.end(), wkt);
+ }
+};
+
+template <typename P>
+struct noparenthesis_point_parser
+{
+ static inline void apply(tokenizer::iterator& it, tokenizer::iterator end,
+ std::string const& wkt, P& point)
+ {
+ parsing_assigner<P, 0, dimension<P>::value>::apply(it, end, point, wkt);
+ }
+};
+
+template <typename MultiGeometry, typename PrefixPolicy>
+struct multi_point_parser
+{
+ static inline void apply(std::string const& wkt, MultiGeometry& geometry)
+ {
+ traits::clear<MultiGeometry>::apply(geometry);
+
+ 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);
+
+ // If first point definition starts with "(" then parse points as (x y)
+ // otherwise as "x y"
+ bool using_brackets = (it != tokens.end() && *it == "(");
+
+ while(it != tokens.end() && *it != ")")
+ {
+ traits::resize<MultiGeometry>::apply(geometry, boost::size(geometry) + 1);
+
+ if (using_brackets)
+ {
+ point_parser
+ <
+ typename boost::range_value<MultiGeometry>::type
+ >::apply(it, tokens.end(), wkt, geometry.back());
+ }
+ else
+ {
+ noparenthesis_point_parser
+ <
+ typename boost::range_value<MultiGeometry>::type
+ >::apply(it, tokens.end(), wkt, geometry.back());
+ }
+
+ if (it != tokens.end() && *it == ",")
+ {
+ // Skip "," after point is parsed
+ ++it;
+ }
+ }
+
+ handle_close_parenthesis(it, tokens.end(), wkt);
+ }
+
+ check_end(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_point_parser
+ <
+ MultiGeometry,
+ detail::wkt::prefix_multipoint
+ >
+{};
+
+template <typename MultiGeometry>
+struct read_wkt<multi_linestring_tag, MultiGeometry>
+ : detail::wkt::multi_parser
+ <
+ MultiGeometry,
+ detail::wkt::linestring_parser,
+ detail::wkt::prefix_multilinestring
+ >
+{};
+
+template <typename MultiGeometry>
+struct read_wkt<multi_polygon_tag, MultiGeometry>
+ : detail::wkt::multi_parser
+ <
+ MultiGeometry,
+ detail::wkt::polygon_parser,
+ detail::wkt::prefix_multipolygon
+ >
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_IO_WKT_READ_MULTI_HPP
diff --git a/boost/geometry/multi/io/wkt/wkt.hpp b/boost/geometry/multi/io/wkt/wkt.hpp
new file mode 100644
index 000000000..55f1713d4
--- /dev/null
+++ b/boost/geometry/multi/io/wkt/wkt.hpp
@@ -0,0 +1,20 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_IO_WKT_WKT_HPP
+#define BOOST_GEOMETRY_MULTI_IO_WKT_WKT_HPP
+
+#include <boost/geometry/multi/io/wkt/read.hpp>
+#include <boost/geometry/multi/io/wkt/write.hpp>
+
+#endif // BOOST_GEOMETRY_MULTI_IO_WKT_WKT_HPP
diff --git a/boost/geometry/multi/io/wkt/write.hpp b/boost/geometry/multi/io/wkt/write.hpp
new file mode 100644
index 000000000..47087e944
--- /dev/null
+++ b/boost/geometry/multi/io/wkt/write.hpp
@@ -0,0 +1,109 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_IO_WKT_WRITE_HPP
+#define BOOST_GEOMETRY_MULTI_IO_WKT_WRITE_HPP
+
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+#include <boost/geometry/multi/io/wkt/detail/prefix.hpp>
+#include <boost/geometry/io/wkt/write.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace wkt
+{
+
+template <typename Multi, typename StreamPolicy, typename PrefixPolicy>
+struct wkt_multi
+{
+ template <typename Char, typename Traits>
+ static inline void apply(std::basic_ostream<Char, Traits>& os,
+ Multi const& geometry)
+ {
+ os << PrefixPolicy::apply();
+ // TODO: check EMPTY here
+ os << "(";
+
+ for (typename boost::range_iterator<Multi const>::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, multi_point_tag>
+ : 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, multi_linestring_tag>
+ : 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, multi_polygon_tag>
+ : detail::wkt::wkt_multi
+ <
+ Multi,
+ detail::wkt::wkt_poly
+ <
+ typename boost::range_value<Multi>::type,
+ detail::wkt::prefix_null
+ >,
+ detail::wkt::prefix_multipolygon
+ >
+{};
+
+} // namespace dispatch
+#endif
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_IO_WKT_WRITE_HPP
diff --git a/boost/geometry/multi/multi.hpp b/boost/geometry/multi/multi.hpp
new file mode 100644
index 000000000..df10392cb
--- /dev/null
+++ b/boost/geometry/multi/multi.hpp
@@ -0,0 +1,78 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_HPP
+#define BOOST_GEOMETRY_MULTI_HPP
+
+
+#include <boost/geometry/multi/core/closure.hpp>
+#include <boost/geometry/multi/core/geometry_id.hpp>
+#include <boost/geometry/multi/core/interior_rings.hpp>
+#include <boost/geometry/multi/core/is_areal.hpp>
+#include <boost/geometry/multi/core/point_order.hpp>
+#include <boost/geometry/multi/core/point_type.hpp>
+#include <boost/geometry/multi/core/ring_type.hpp>
+#include <boost/geometry/multi/core/tags.hpp>
+#include <boost/geometry/multi/core/topological_dimension.hpp>
+
+#include <boost/geometry/multi/algorithms/append.hpp>
+#include <boost/geometry/multi/algorithms/area.hpp>
+#include <boost/geometry/multi/algorithms/centroid.hpp>
+#include <boost/geometry/multi/algorithms/clear.hpp>
+#include <boost/geometry/multi/algorithms/convert.hpp>
+#include <boost/geometry/multi/algorithms/correct.hpp>
+#include <boost/geometry/multi/algorithms/covered_by.hpp>
+#include <boost/geometry/multi/algorithms/disjoint.hpp>
+#include <boost/geometry/multi/algorithms/distance.hpp>
+#include <boost/geometry/multi/algorithms/envelope.hpp>
+#include <boost/geometry/multi/algorithms/equals.hpp>
+#include <boost/geometry/multi/algorithms/for_each.hpp>
+#include <boost/geometry/multi/algorithms/intersection.hpp>
+#include <boost/geometry/multi/algorithms/length.hpp>
+#include <boost/geometry/multi/algorithms/num_geometries.hpp>
+#include <boost/geometry/multi/algorithms/num_interior_rings.hpp>
+#include <boost/geometry/multi/algorithms/num_points.hpp>
+#include <boost/geometry/multi/algorithms/perimeter.hpp>
+#include <boost/geometry/multi/algorithms/reverse.hpp>
+#include <boost/geometry/multi/algorithms/simplify.hpp>
+#include <boost/geometry/multi/algorithms/transform.hpp>
+#include <boost/geometry/multi/algorithms/unique.hpp>
+#include <boost/geometry/multi/algorithms/within.hpp>
+
+#include <boost/geometry/multi/algorithms/detail/for_each_range.hpp>
+#include <boost/geometry/multi/algorithms/detail/modify_with_predicate.hpp>
+#include <boost/geometry/multi/algorithms/detail/multi_sum.hpp>
+
+#include <boost/geometry/multi/algorithms/detail/sections/range_by_section.hpp>
+#include <boost/geometry/multi/algorithms/detail/sections/sectionalize.hpp>
+
+#include <boost/geometry/multi/algorithms/detail/overlay/copy_segment_point.hpp>
+#include <boost/geometry/multi/algorithms/detail/overlay/copy_segments.hpp>
+#include <boost/geometry/multi/algorithms/detail/overlay/get_ring.hpp>
+#include <boost/geometry/multi/algorithms/detail/overlay/get_turns.hpp>
+#include <boost/geometry/multi/algorithms/detail/overlay/select_rings.hpp>
+#include <boost/geometry/multi/algorithms/detail/overlay/self_turn_points.hpp>
+
+#include <boost/geometry/multi/geometries/concepts/check.hpp>
+#include <boost/geometry/multi/geometries/concepts/multi_point_concept.hpp>
+#include <boost/geometry/multi/geometries/concepts/multi_linestring_concept.hpp>
+#include <boost/geometry/multi/geometries/concepts/multi_polygon_concept.hpp>
+
+#include <boost/geometry/multi/views/detail/range_type.hpp>
+#include <boost/geometry/multi/strategies/cartesian/centroid_average.hpp>
+
+#include <boost/geometry/multi/io/dsv/write.hpp>
+#include <boost/geometry/multi/io/wkt/wkt.hpp>
+
+
+#endif // BOOST_GEOMETRY_MULTI_HPP
diff --git a/boost/geometry/multi/strategies/cartesian/centroid_average.hpp b/boost/geometry/multi/strategies/cartesian/centroid_average.hpp
new file mode 100644
index 000000000..f28daf20b
--- /dev/null
+++ b/boost/geometry/multi/strategies/cartesian/centroid_average.hpp
@@ -0,0 +1,116 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP
+#define BOOST_GEOMETRY_MULTI_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP
+
+
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/strategies/centroid.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace centroid
+{
+
+
+/*!
+\brief Centroid calculation taking average of points
+\ingroup strategies
+*/
+template
+<
+ typename PointCentroid,
+ typename Point = PointCentroid
+>
+class average
+{
+private :
+
+ /*! subclass to keep state */
+ class sum
+ {
+ friend class 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);
+ }
+
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+namespace services
+{
+
+template <typename Point, std::size_t DimensionCount, typename Geometry>
+struct default_strategy
+<
+ cartesian_tag,
+ pointlike_tag,
+ DimensionCount,
+ Point,
+ Geometry
+>
+{
+ typedef average
+ <
+ Point,
+ typename point_type<Geometry>::type
+ > type;
+};
+
+} // namespace services
+
+#endif
+
+
+}} // namespace strategy::centroid
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_MULTI_STRATEGIES_CARTESIAN_CENTROID_AVERAGE_HPP
diff --git a/boost/geometry/multi/views/detail/range_type.hpp b/boost/geometry/multi/views/detail/range_type.hpp
new file mode 100644
index 000000000..172feb251
--- /dev/null
+++ b/boost/geometry/multi/views/detail/range_type.hpp
@@ -0,0 +1,62 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_MULTI_VIEWS_DETAIL_RANGE_TYPE_HPP
+#define BOOST_GEOMETRY_MULTI_VIEWS_DETAIL_RANGE_TYPE_HPP
+
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/views/detail/range_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// multi-point acts itself as a range
+template <typename Geometry>
+struct range_type<multi_point_tag, Geometry>
+{
+ typedef Geometry type;
+};
+
+
+template <typename Geometry>
+struct range_type<multi_linestring_tag, Geometry>
+{
+ typedef typename boost::range_value<Geometry>::type type;
+};
+
+
+template <typename Geometry>
+struct range_type<multi_polygon_tag, Geometry>
+{
+ // Call its single-version
+ typedef typename geometry::detail::range_type
+ <
+ typename boost::range_value<Geometry>::type
+ >::type type;
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_MULTI_VIEWS_DETAIL_RANGE_TYPE_HPP
diff --git a/boost/geometry/policies/compare.hpp b/boost/geometry/policies/compare.hpp
new file mode 100644
index 000000000..2e952d3e1
--- /dev/null
+++ b/boost/geometry/policies/compare.hpp
@@ -0,0 +1,242 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_POLICIES_COMPARE_HPP
+#define BOOST_GEOMETRY_POLICIES_COMPARE_HPP
+
+
+#include <cstddef>
+
+#include <boost/geometry/strategies/compare.hpp>
+#include <boost/geometry/util/math.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace compare
+{
+
+
+template
+<
+ int Direction,
+ typename Point,
+ typename Strategy,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct compare_loop
+{
+ typedef typename strategy::compare::detail::select_strategy
+ <
+ Strategy, Direction, Point, Dimension
+ >::type compare_type;
+
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+
+ static inline bool apply(Point const& left, Point const& right)
+ {
+ coordinate_type const& cleft = geometry::get<Dimension>(left);
+ coordinate_type const& cright = geometry::get<Dimension>(right);
+
+ if (geometry::math::equals(cleft, cright))
+ {
+ return compare_loop
+ <
+ Direction, Point, Strategy,
+ Dimension + 1, DimensionCount
+ >::apply(left, right);
+ }
+ else
+ {
+ compare_type compare;
+ return compare(cleft, cright);
+ }
+ }
+};
+
+template
+<
+ int Direction,
+ typename Point,
+ typename Strategy,
+ std::size_t DimensionCount
+>
+struct compare_loop<Direction, Point, Strategy, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Point const&, Point const&)
+ {
+ // On coming here, points are equal. Return true if
+ // direction = 0 (equal), false if -1/1 (greater/less)
+ return Direction == 0;
+ }
+};
+
+
+template <int Direction, typename Point, typename Strategy>
+struct compare_in_all_dimensions
+{
+ inline bool operator()(Point const& left, Point const& right) const
+ {
+ return detail::compare::compare_loop
+ <
+ Direction, Point, Strategy,
+ 0, geometry::dimension<Point>::type::value
+ >::apply(left, right);
+ }
+};
+
+
+template <typename Point, typename Strategy, std::size_t Dimension>
+class compare_in_one_dimension
+{
+ Strategy compare;
+
+public :
+ inline bool operator()(Point const& left, Point const& right) const
+ {
+ typedef typename geometry::coordinate_type<Point>::type coordinate_type;
+
+ coordinate_type const& cleft = get<Dimension>(left);
+ coordinate_type const& cright = get<Dimension>(right);
+ return compare(cleft, cright);
+ }
+};
+
+}} // namespace detail::compare
+
+#endif
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ int Direction,
+ typename Point,
+ typename Strategy,
+ int Dimension
+>
+struct compare_geometries
+ : detail::compare::compare_in_one_dimension
+ <
+ Point,
+ typename strategy::compare::detail::select_strategy
+ <
+ Strategy, Direction, Point, Dimension
+ >::type,
+ Dimension
+ >
+{};
+
+
+// Specialization with -1: compare in all dimensions
+template <int Direction, typename Point, typename Strategy>
+struct compare_geometries<Direction, Point, Strategy, -1>
+ : detail::compare::compare_in_all_dimensions<Direction, Point, Strategy>
+{};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+/*!
+\brief Less functor, to sort points in ascending order.
+\ingroup compare
+\details This functor compares points and orders them on x,
+ then on y, then on z coordinate.
+\tparam Geometry the geometry
+\tparam Dimension the dimension to sort on, defaults to -1,
+ indicating ALL dimensions. That's to say, first on x,
+ on equal x-es then on y, etc.
+ If a dimension is specified, only that dimension is considered
+\tparam Strategy underlying coordinate comparing functor,
+ defaults to the default comparison strategies
+ related to the point coordinate system. If specified, the specified
+ strategy is used. This can e.g. be std::less<double>.
+*/
+template
+<
+ typename Point,
+ int Dimension = -1,
+ typename Strategy = strategy::compare::default_strategy
+>
+struct less
+ : dispatch::compare_geometries
+ <
+ 1, // indicates ascending
+ Point,
+ Strategy,
+ Dimension
+ >
+{
+ typedef Point first_argument_type;
+ typedef Point second_argument_type;
+ typedef bool result_type;
+};
+
+
+/*!
+\brief Greater functor
+\ingroup compare
+\details Can be used to sort points in reverse order
+\see Less functor
+*/
+template
+<
+ typename Point,
+ int Dimension = -1,
+ typename Strategy = strategy::compare::default_strategy
+>
+struct greater
+ : dispatch::compare_geometries
+ <
+ -1, // indicates descending
+ Point,
+ Strategy,
+ Dimension
+ >
+{};
+
+
+/*!
+\brief Equal To functor, to compare if points are equal
+\ingroup compare
+\tparam Geometry the geometry
+\tparam Dimension the dimension to compare on, defaults to -1,
+ indicating ALL dimensions.
+ If a dimension is specified, only that dimension is considered
+\tparam Strategy underlying coordinate comparing functor
+*/
+template
+<
+ typename Point,
+ int Dimension = -1,
+ typename Strategy = strategy::compare::default_strategy
+>
+struct equal_to
+ : dispatch::compare_geometries
+ <
+ 0,
+ Point,
+ Strategy,
+ Dimension
+ >
+{};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_POLICIES_COMPARE_HPP
diff --git a/boost/geometry/policies/relate/de9im.hpp b/boost/geometry/policies/relate/de9im.hpp
new file mode 100644
index 000000000..766d80b22
--- /dev/null
+++ b/boost/geometry/policies/relate/de9im.hpp
@@ -0,0 +1,177 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DE9IM_HPP
+#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DE9IM_HPP
+
+
+#include <boost/geometry/strategies/intersection_result.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace policies { namespace relate
+{
+
+
+template <typename S1, typename S2>
+struct segments_de9im
+{
+ typedef de9im_segment return_type;
+ typedef S1 segment_type1;
+ typedef S2 segment_type2;
+ typedef typename select_coordinate_type<S1, S2>::type coordinate_type;
+
+ static inline return_type rays_intersect(bool on_segment,
+ double ra, double rb,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ coordinate_type const& dx2, coordinate_type const& dy2,
+ coordinate_type const& wx, coordinate_type const& wy,
+ S1 const& s1, S2 const& s2)
+ {
+ if(on_segment)
+ {
+ // 0 <= ra <= 1 and 0 <= rb <= 1
+ // Now check if one of them is 0 or 1, these are "touch" cases
+ bool a = math::equals(ra, 0.0) || math::equals(ra, 1.0);
+ bool b = math::equals(rb, 0.0) || math::equals(rb, 1.0);
+ if (a && b)
+ {
+ // Touch boundary/boundary: i-i == -1, i-b == -1, b-b == 0
+ // Opposite: if both are equal they touch in opposite direction
+ return de9im_segment(ra,rb,
+ -1, -1, 1,
+ -1, 0, 0,
+ 1, 0, 2, false, math::equals(ra,rb));
+ }
+ else if (a || b)
+ {
+ // Touch boundary/interior: i-i == -1, i-b == -1 or 0, b-b == -1
+ int A = a ? 0 : -1;
+ int B = b ? 0 : -1;
+ return de9im_segment(ra,rb,
+ -1, B, 1,
+ A, -1, 0,
+ 1, 0, 2);
+ }
+
+ // Intersects: i-i == 0, i-b == -1, i-e == 1
+ return de9im_segment(ra,rb,
+ 0, -1, 1,
+ -1, -1, 0,
+ 1, 0, 2);
+ }
+
+ // Not on segment, disjoint
+ return de9im_segment(ra,rb,
+ -1, -1, 1,
+ -1, -1, 0,
+ 1, 0, 2);
+ }
+
+ static inline return_type collinear_touch(coordinate_type const& x,
+ coordinate_type const& y, bool opposite, char)
+ {
+ return de9im_segment(0,0,
+ -1, -1, 1,
+ -1, 0, 0,
+ 1, 0, 2,
+ true, opposite);
+ }
+
+ template <typename S>
+ static inline return_type collinear_interior_boundary_intersect(S const& s,
+ bool a_within_b, bool opposite)
+ {
+ return a_within_b
+ ? de9im_segment(0,0,
+ 1, -1, -1,
+ 0, 0, -1,
+ 1, 0, 2,
+ true, opposite)
+ : de9im_segment(0,0,
+ 1, 0, 1,
+ -1, 0, 0,
+ -1, -1, 2,
+ true, opposite);
+ }
+
+
+
+ static inline return_type collinear_a_in_b(S1 const& s, bool opposite)
+ {
+ return de9im_segment(0,0,
+ 1, -1, -1,
+ 0, -1, -1,
+ 1, 0, 2,
+ true, opposite);
+ }
+ static inline return_type collinear_b_in_a(S2 const& s, bool opposite)
+ {
+ return de9im_segment(0,0,
+ 1, 0, 1,
+ -1, -1, 0,
+ -1, -1, 2,
+ true, opposite);
+ }
+
+ static inline return_type collinear_overlaps(
+ coordinate_type const& x1, coordinate_type const& y1,
+ coordinate_type const& x2, coordinate_type const& y2, bool opposite)
+ {
+ return de9im_segment(0,0,
+ 1, 0, 1,
+ 0, -1, 0,
+ 1, 0, 2,
+ true, opposite);
+ }
+
+ static inline return_type segment_equal(S1 const& s, bool opposite)
+ {
+ return de9im_segment(0,0,
+ 1, -1, -1,
+ -1, 0, -1,
+ -1, -1, 2,
+ true, opposite);
+ }
+
+ static inline return_type degenerate(S1 const& segment, bool a_degenerate)
+ {
+ return a_degenerate
+ ? de9im_segment(0,0,
+ 0, -1, -1,
+ -1, -1, -1,
+ 1, 0, 2,
+ false, false, false, true)
+ : de9im_segment(0,0,
+ 0, -1, 1,
+ -1, -1, 0,
+ -1, -1, 2,
+ false, false, false, true);
+ }
+
+ static inline return_type collinear_disjoint()
+ {
+ return de9im_segment(0,0,
+ -1, -1, 1,
+ -1, -1, 0,
+ 1, 0, 2,
+ true);
+ }
+
+};
+
+
+}} // namespace policies::relate
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DE9IM_HPP
diff --git a/boost/geometry/policies/relate/direction.hpp b/boost/geometry/policies/relate/direction.hpp
new file mode 100644
index 000000000..62859f33b
--- /dev/null
+++ b/boost/geometry/policies/relate/direction.hpp
@@ -0,0 +1,362 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP
+#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP
+
+
+#include <cstddef>
+#include <string>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/geometry/arithmetic/determinant.hpp>
+#include <boost/geometry/strategies/side_info.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace policies { namespace relate
+{
+
+struct direction_type
+{
+ // NOTE: "char" will be replaced by enum in future version
+
+ inline direction_type(side_info const& s, char h,
+ int ha, int hb,
+ int da = 0, int db = 0,
+ bool op = false)
+ : how(h)
+ , opposite(op)
+ , how_a(ha)
+ , how_b(hb)
+ , dir_a(da)
+ , dir_b(db)
+ , sides(s)
+ {
+ arrival[0] = ha;
+ arrival[1] = hb;
+ }
+
+ inline direction_type(char h, bool op, int ha = 0, int hb = 0)
+ : how(h)
+ , opposite(op)
+ , how_a(ha)
+ , how_b(hb)
+ , dir_a(0)
+ , dir_b(0)
+ {
+ arrival[0] = ha;
+ arrival[1] = hb;
+ }
+
+
+ // TODO: replace this
+ // NOTE: "char" will be replaced by enum in future version
+ // "How" is the intersection formed?
+ char how;
+
+ // Is it opposite (for collinear/equal cases)
+ bool opposite;
+
+ // Information on how A arrives at intersection, how B arrives at intersection
+ // 1: arrives at intersection
+ // -1: starts from intersection
+ int how_a;
+ int how_b;
+
+ // Direction: how is A positioned from B
+ // 1: points left, seen from IP
+ // -1: points right, seen from IP
+ // In case of intersection: B's TO direction
+ // In case that B's TO direction is at A: B's from direction
+ // In collinear cases: it is 0
+ int dir_a; // Direction of A-s TO from IP
+ int dir_b; // Direction of B-s TO from IP
+
+ // New information
+ side_info sides;
+ int arrival[2]; // 1=arrival, -1departure, 0=neutral; == how_a//how_b
+
+
+ // About arrival[0] (== arrival of a2 w.r.t. b) for COLLINEAR cases
+ // Arrival 1: a1--------->a2 (a arrives within b)
+ // b1----->b2
+
+ // Arrival 1: (a in b)
+ //
+
+
+ // Arrival -1: a1--------->a2 (a does not arrive within b)
+ // b1----->b2
+
+ // Arrival -1: (b in a) a_1-------------a_2
+ // b_1---b_2
+
+ // Arrival 0: a1------->a2 (a arrives at TO-border of b)
+ // b1--->b2
+
+};
+
+
+template <typename S1, typename S2, typename CalculationType = void>
+struct segments_direction
+{
+ typedef direction_type return_type;
+ typedef S1 segment_type1;
+ typedef S2 segment_type2;
+ typedef typename select_calculation_type
+ <
+ S1, S2, CalculationType
+ >::type coordinate_type;
+
+ // Get the same type, but at least a double
+ typedef typename select_most_precise<coordinate_type, double>::type rtype;
+
+
+ template <typename R>
+ static inline return_type segments_intersect(side_info const& sides,
+ R const&,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ coordinate_type const& dx2, coordinate_type const& dy2,
+ S1 const& s1, S2 const& s2)
+ {
+ bool const ra0 = sides.get<0,0>() == 0;
+ bool const ra1 = sides.get<0,1>() == 0;
+ bool const rb0 = sides.get<1,0>() == 0;
+ bool const rb1 = sides.get<1,1>() == 0;
+
+ return
+ // opposite and same starting point (FROM)
+ ra0 && rb0 ? calculate_side<1>(sides, dx1, dy1, s1, s2, 'f', -1, -1)
+
+ // opposite and point to each other (TO)
+ : ra1 && rb1 ? calculate_side<0>(sides, dx1, dy1, s1, s2, 't', 1, 1)
+
+ // not opposite, forming an angle, first a then b,
+ // directed either both left, or both right
+ // Check side of B2 from A. This is not calculated before
+ : ra1 && rb0 ? angle<1>(sides, dx1, dy1, s1, s2, 'a', 1, -1)
+
+ // not opposite, forming a angle, first b then a,
+ // directed either both left, or both right
+ : ra0 && rb1 ? angle<0>(sides, dx1, dy1, s1, s2, 'a', -1, 1)
+
+ // b starts from interior of a
+ : rb0 ? starts_from_middle(sides, dx1, dy1, s1, s2, 'B', 0, -1)
+
+ // a starts from interior of b (#39)
+ : ra0 ? starts_from_middle(sides, dx1, dy1, s1, s2, 'A', -1, 0)
+
+ // b ends at interior of a, calculate direction of A from IP
+ : rb1 ? b_ends_at_middle(sides, dx2, dy2, s1, s2)
+
+ // a ends at interior of b
+ : ra1 ? a_ends_at_middle(sides, dx1, dy1, s1, s2)
+
+ // normal intersection
+ : calculate_side<1>(sides, dx1, dy1, s1, s2, 'i', -1, -1)
+ ;
+ }
+
+ static inline return_type collinear_touch(
+ coordinate_type const& ,
+ coordinate_type const& , int arrival_a, int arrival_b)
+ {
+ // Though this is 'collinear', we handle it as To/From/Angle because it is the same.
+ // It only does NOT have a direction.
+ side_info sides;
+ //int const arrive = how == 'T' ? 1 : -1;
+ bool opposite = arrival_a == arrival_b;
+ return
+ ! opposite
+ ? return_type(sides, 'a', arrival_a, arrival_b)
+ : return_type(sides, arrival_a == 0 ? 't' : 'f', arrival_a, arrival_b, 0, 0, true);
+ }
+
+ template <typename S>
+ static inline return_type collinear_interior_boundary_intersect(S const& , bool,
+ int arrival_a, int arrival_b, bool opposite)
+ {
+ return_type r('c', opposite);
+ r.arrival[0] = arrival_a;
+ r.arrival[1] = arrival_b;
+ return r;
+ }
+
+ static inline return_type collinear_a_in_b(S1 const& , bool opposite)
+ {
+ return_type r('c', opposite);
+ r.arrival[0] = 1;
+ r.arrival[1] = -1;
+ return r;
+ }
+ static inline return_type collinear_b_in_a(S2 const& , bool opposite)
+ {
+ return_type r('c', opposite);
+ r.arrival[0] = -1;
+ r.arrival[1] = 1;
+ return r;
+ }
+
+ static inline return_type collinear_overlaps(
+ coordinate_type const& , coordinate_type const& ,
+ coordinate_type const& , coordinate_type const& ,
+ int arrival_a, int arrival_b, bool opposite)
+ {
+ return_type r('c', opposite);
+ r.arrival[0] = arrival_a;
+ r.arrival[1] = arrival_b;
+ return r;
+ }
+
+ static inline return_type segment_equal(S1 const& , bool opposite)
+ {
+ return return_type('e', opposite);
+ }
+
+ static inline return_type degenerate(S1 const& , bool)
+ {
+ return return_type('0', false);
+ }
+
+ static inline return_type disjoint()
+ {
+ return return_type('d', false);
+ }
+
+ static inline return_type collinear_disjoint()
+ {
+ return return_type('d', false);
+ }
+
+ static inline return_type error(std::string const&)
+ {
+ // Return "E" to denote error
+ // This will throw an error in get_turn_info
+ // TODO: change to enum or similar
+ return return_type('E', false);
+ }
+
+private :
+
+ static inline bool is_left
+ (
+ coordinate_type const& ux,
+ coordinate_type const& uy,
+ coordinate_type const& vx,
+ coordinate_type const& vy
+ )
+ {
+ // This is a "side calculation" as in the strategies, but here terms are precalculated
+ // We might merge this with side, offering a pre-calculated term (in fact already done using cross-product)
+ // Waiting for implementing spherical...
+
+ rtype const zero = rtype();
+ return geometry::detail::determinant<rtype>(ux, uy, vx, vy) > zero;
+ }
+
+ template <std::size_t I>
+ static inline return_type calculate_side(side_info const& sides,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ S1 const& s1, S2 const& s2,
+ char how, int how_a, int how_b)
+ {
+ coordinate_type dpx = get<I, 0>(s2) - get<0, 0>(s1);
+ coordinate_type dpy = get<I, 1>(s2) - get<0, 1>(s1);
+
+ return is_left(dx1, dy1, dpx, dpy)
+ ? return_type(sides, how, how_a, how_b, -1, 1)
+ : return_type(sides, how, how_a, how_b, 1, -1);
+ }
+
+ template <std::size_t I>
+ static inline return_type angle(side_info const& sides,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ S1 const& s1, S2 const& s2,
+ char how, int how_a, int how_b)
+ {
+ coordinate_type dpx = get<I, 0>(s2) - get<0, 0>(s1);
+ coordinate_type dpy = get<I, 1>(s2) - get<0, 1>(s1);
+
+ return is_left(dx1, dy1, dpx, dpy)
+ ? return_type(sides, how, how_a, how_b, 1, 1)
+ : return_type(sides, how, how_a, how_b, -1, -1);
+ }
+
+
+ static inline return_type starts_from_middle(side_info const& sides,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ S1 const& s1, S2 const& s2,
+ char which,
+ int how_a, int how_b)
+ {
+ // Calculate ARROW of b segment w.r.t. s1
+ coordinate_type dpx = get<1, 0>(s2) - get<0, 0>(s1);
+ coordinate_type dpy = get<1, 1>(s2) - get<0, 1>(s1);
+
+ int dir = is_left(dx1, dy1, dpx, dpy) ? 1 : -1;
+
+ // From other perspective, then reverse
+ bool const is_a = which == 'A';
+ if (is_a)
+ {
+ dir = -dir;
+ }
+
+ return return_type(sides, 's',
+ how_a,
+ how_b,
+ is_a ? dir : -dir,
+ ! is_a ? dir : -dir);
+ }
+
+
+
+ // To be harmonized
+ static inline return_type a_ends_at_middle(side_info const& sides,
+ coordinate_type const& dx, coordinate_type const& dy,
+ S1 const& s1, S2 const& s2)
+ {
+ coordinate_type dpx = get<1, 0>(s2) - get<0, 0>(s1);
+ coordinate_type dpy = get<1, 1>(s2) - get<0, 1>(s1);
+
+ // Ending at the middle, one ARRIVES, the other one is NEUTRAL
+ // (because it both "arrives" and "departs" there
+ return is_left(dx, dy, dpx, dpy)
+ ? return_type(sides, 'm', 1, 0, 1, 1)
+ : return_type(sides, 'm', 1, 0, -1, -1);
+ }
+
+
+ static inline return_type b_ends_at_middle(side_info const& sides,
+ coordinate_type const& dx, coordinate_type const& dy,
+ S1 const& s1, S2 const& s2)
+ {
+ coordinate_type dpx = get<1, 0>(s1) - get<0, 0>(s2);
+ coordinate_type dpy = get<1, 1>(s1) - get<0, 1>(s2);
+
+ return is_left(dx, dy, dpx, dpy)
+ ? return_type(sides, 'm', 0, 1, 1, 1)
+ : return_type(sides, 'm', 0, 1, -1, -1);
+ }
+
+};
+
+}} // namespace policies::relate
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_DIRECTION_HPP
diff --git a/boost/geometry/policies/relate/intersection_points.hpp b/boost/geometry/policies/relate/intersection_points.hpp
new file mode 100644
index 000000000..ff8ec1949
--- /dev/null
+++ b/boost/geometry/policies/relate/intersection_points.hpp
@@ -0,0 +1,165 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
+#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
+
+
+#include <algorithm>
+#include <string>
+
+#include <boost/concept_check.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/arithmetic/determinant.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/strategies/side_info.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace policies { namespace relate
+{
+
+
+template <typename S1, typename S2, typename ReturnType, typename CalculationType = void>
+struct segments_intersection_points
+{
+ typedef ReturnType return_type;
+ typedef S1 segment_type1;
+ typedef S2 segment_type2;
+
+ typedef typename select_calculation_type
+ <
+ S1, S2, CalculationType
+ >::type coordinate_type;
+
+ template <typename R>
+ static inline return_type segments_intersect(side_info const&,
+ R const& r,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ coordinate_type const& , coordinate_type const& ,
+ S1 const& s1, S2 const& )
+ {
+ typedef typename geometry::coordinate_type
+ <
+ typename return_type::point_type
+ >::type return_coordinate_type;
+
+ coordinate_type const s1x = get<0, 0>(s1);
+ coordinate_type const s1y = get<0, 1>(s1);
+
+ return_type result;
+ result.count = 1;
+ set<0>(result.intersections[0],
+ boost::numeric_cast<return_coordinate_type>(R(s1x) + r * R(dx1)));
+ set<1>(result.intersections[0],
+ boost::numeric_cast<return_coordinate_type>(R(s1y) + r * R(dy1)));
+
+ return result;
+ }
+
+ static inline return_type collinear_touch(coordinate_type const& x,
+ coordinate_type const& y, int, int)
+ {
+ return_type result;
+ result.count = 1;
+ set<0>(result.intersections[0], x);
+ set<1>(result.intersections[0], y);
+ return result;
+ }
+
+ template <typename S>
+ static inline return_type collinear_inside(S const& s, int index1 = 0, int index2 = 1)
+ {
+ return_type result;
+ result.count = 2;
+ set<0>(result.intersections[index1], get<0, 0>(s));
+ set<1>(result.intersections[index1], get<0, 1>(s));
+ set<0>(result.intersections[index2], get<1, 0>(s));
+ set<1>(result.intersections[index2], get<1, 1>(s));
+ return result;
+ }
+
+ template <typename S>
+ static inline return_type collinear_interior_boundary_intersect(S const& s, bool a_in_b,
+ int, int, bool opposite)
+ {
+ int index1 = opposite && ! a_in_b ? 1 : 0;
+ return collinear_inside(s, index1, 1 - index1);
+ }
+
+ static inline return_type collinear_a_in_b(S1 const& s, bool)
+ {
+ return collinear_inside(s);
+ }
+ static inline return_type collinear_b_in_a(S2 const& s, bool opposite)
+ {
+ int index1 = opposite ? 1 : 0;
+ return collinear_inside(s, index1, 1 - index1);
+ }
+
+ static inline return_type collinear_overlaps(
+ coordinate_type const& x1, coordinate_type const& y1,
+ coordinate_type const& x2, coordinate_type const& y2,
+ int, int, bool)
+ {
+ return_type result;
+ result.count = 2;
+ set<0>(result.intersections[0], x1);
+ set<1>(result.intersections[0], y1);
+ set<0>(result.intersections[1], x2);
+ set<1>(result.intersections[1], y2);
+ return result;
+ }
+
+ static inline return_type segment_equal(S1 const& s, bool)
+ {
+ return_type result;
+ result.count = 2;
+ // TODO: order of IP's
+ set<0>(result.intersections[0], get<0, 0>(s));
+ set<1>(result.intersections[0], get<0, 1>(s));
+ set<0>(result.intersections[1], get<1, 0>(s));
+ set<1>(result.intersections[1], get<1, 1>(s));
+ return result;
+ }
+
+ static inline return_type disjoint()
+ {
+ return return_type();
+ }
+ static inline return_type error(std::string const&)
+ {
+ return return_type();
+ }
+
+ static inline return_type collinear_disjoint()
+ {
+ return return_type();
+ }
+
+ static inline return_type degenerate(S1 const& s, bool)
+ {
+ return_type result;
+ result.count = 1;
+ set<0>(result.intersections[0], get<0, 0>(s));
+ set<1>(result.intersections[0], get<0, 1>(s));
+ return result;
+ }
+};
+
+
+}} // namespace policies::relate
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_INTERSECTION_POINTS_HPP
diff --git a/boost/geometry/policies/relate/tupled.hpp b/boost/geometry/policies/relate/tupled.hpp
new file mode 100644
index 000000000..e78ccfbc1
--- /dev/null
+++ b/boost/geometry/policies/relate/tupled.hpp
@@ -0,0 +1,175 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_TUPLED_HPP
+#define BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_TUPLED_HPP
+
+
+#include <string>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/geometry/strategies/side_info.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace policies { namespace relate
+{
+
+
+// "tupled" to return intersection results together.
+// Now with two, with some meta-programming and derivations it can also be three (or more)
+template <typename Policy1, typename Policy2, typename CalculationType = void>
+struct segments_tupled
+{
+ typedef boost::tuple
+ <
+ typename Policy1::return_type,
+ typename Policy2::return_type
+ > return_type;
+
+ // Take segments of first policy, they should be equal
+ typedef typename Policy1::segment_type1 segment_type1;
+ typedef typename Policy1::segment_type2 segment_type2;
+
+ typedef typename select_calculation_type
+ <
+ segment_type1,
+ segment_type2,
+ CalculationType
+ >::type coordinate_type;
+
+ // Get the same type, but at least a double
+ typedef typename select_most_precise<coordinate_type, double>::type rtype;
+
+ template <typename R>
+ static inline return_type segments_intersect(side_info const& sides,
+ R const& r,
+ coordinate_type const& dx1, coordinate_type const& dy1,
+ coordinate_type const& dx2, coordinate_type const& dy2,
+ segment_type1 const& s1, segment_type2 const& s2)
+ {
+ return boost::make_tuple
+ (
+ Policy1::segments_intersect(sides, r,
+ dx1, dy1, dx2, dy2, s1, s2),
+ Policy2::segments_intersect(sides, r,
+ dx1, dy1, dx2, dy2, s1, s2)
+ );
+ }
+
+ static inline return_type collinear_touch(coordinate_type const& x,
+ coordinate_type const& y, int arrival_a, int arrival_b)
+ {
+ return boost::make_tuple
+ (
+ Policy1::collinear_touch(x, y, arrival_a, arrival_b),
+ Policy2::collinear_touch(x, y, arrival_a, arrival_b)
+ );
+ }
+
+ template <typename S>
+ static inline return_type collinear_interior_boundary_intersect(S const& segment,
+ bool a_within_b,
+ int arrival_a, int arrival_b, bool opposite)
+ {
+ return boost::make_tuple
+ (
+ Policy1::collinear_interior_boundary_intersect(segment, a_within_b, arrival_a, arrival_b, opposite),
+ Policy2::collinear_interior_boundary_intersect(segment, a_within_b, arrival_a, arrival_b, opposite)
+ );
+ }
+
+ static inline return_type collinear_a_in_b(segment_type1 const& segment,
+ bool opposite)
+ {
+ return boost::make_tuple
+ (
+ Policy1::collinear_a_in_b(segment, opposite),
+ Policy2::collinear_a_in_b(segment, opposite)
+ );
+ }
+ static inline return_type collinear_b_in_a(segment_type2 const& segment,
+ bool opposite)
+ {
+ return boost::make_tuple
+ (
+ Policy1::collinear_b_in_a(segment, opposite),
+ Policy2::collinear_b_in_a(segment, opposite)
+ );
+ }
+
+
+ static inline return_type collinear_overlaps(
+ coordinate_type const& x1, coordinate_type const& y1,
+ coordinate_type const& x2, coordinate_type const& y2,
+ int arrival_a, int arrival_b, bool opposite)
+ {
+ return boost::make_tuple
+ (
+ Policy1::collinear_overlaps(x1, y1, x2, y2, arrival_a, arrival_b, opposite),
+ Policy2::collinear_overlaps(x1, y1, x2, y2, arrival_a, arrival_b, opposite)
+ );
+ }
+
+ static inline return_type segment_equal(segment_type1 const& s,
+ bool opposite)
+ {
+ return boost::make_tuple
+ (
+ Policy1::segment_equal(s, opposite),
+ Policy2::segment_equal(s, opposite)
+ );
+ }
+
+ static inline return_type degenerate(segment_type1 const& segment,
+ bool a_degenerate)
+ {
+ return boost::make_tuple
+ (
+ Policy1::degenerate(segment, a_degenerate),
+ Policy2::degenerate(segment, a_degenerate)
+ );
+ }
+
+ static inline return_type disjoint()
+ {
+ return boost::make_tuple
+ (
+ Policy1::disjoint(),
+ Policy2::disjoint()
+ );
+ }
+
+ static inline return_type error(std::string const& msg)
+ {
+ return boost::make_tuple
+ (
+ Policy1::error(msg),
+ Policy2::error(msg)
+ );
+ }
+
+ static inline return_type collinear_disjoint()
+ {
+ return boost::make_tuple
+ (
+ Policy1::collinear_disjoint(),
+ Policy2::collinear_disjoint()
+ );
+ }
+
+};
+
+}} // namespace policies::relate
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_GEOMETRY_POLICIES_RELATE_TUPLED_HPP
diff --git a/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp b/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp
new file mode 100644
index 000000000..747c14075
--- /dev/null
+++ b/boost/geometry/strategies/agnostic/hull_graham_andrew.hpp
@@ -0,0 +1,384 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP
+#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP
+
+
+#include <cstddef>
+#include <algorithm>
+#include <vector>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/strategies/convex_hull.hpp>
+
+#include <boost/geometry/views/detail/range_type.hpp>
+
+#include <boost/geometry/policies/compare.hpp>
+
+#include <boost/geometry/algorithms/detail/for_each_range.hpp>
+#include <boost/geometry/views/reversible_view.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace convex_hull
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template
+<
+ typename InputRange,
+ typename RangeIterator,
+ typename StrategyLess,
+ typename StrategyGreater
+>
+struct get_extremes
+{
+ typedef typename point_type<InputRange>::type point_type;
+
+ point_type left, right;
+
+ bool first;
+
+ StrategyLess less;
+ StrategyGreater greater;
+
+ inline get_extremes()
+ : first(true)
+ {}
+
+ inline void apply(InputRange const& range)
+ {
+ if (boost::size(range) == 0)
+ {
+ return;
+ }
+
+ // 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)
+ {
+ // First time, assign left/right
+ left = *left_it;
+ right = *right_it;
+ first = false;
+ }
+ else
+ {
+ // Next time, check if this range was left/right from
+ // the extremes already collected
+ if (less(*left_it, left))
+ {
+ left = *left_it;
+ }
+
+ if (greater(*right_it, right))
+ {
+ right = *right_it;
+ }
+ }
+ }
+};
+
+
+template
+<
+ typename InputRange,
+ typename RangeIterator,
+ typename Container,
+ typename SideStrategy
+>
+struct assign_range
+{
+ Container lower_points, upper_points;
+
+ typedef typename point_type<InputRange>::type point_type;
+
+ point_type const& most_left;
+ point_type const& most_right;
+
+ inline assign_range(point_type const& left, point_type const& right)
+ : most_left(left)
+ , most_right(right)
+ {}
+
+ inline void apply(InputRange const& range)
+ {
+ typedef SideStrategy side;
+
+ // Put points in one of the two output sequences
+ for (RangeIterator it = boost::begin(range);
+ it != boost::end(range);
+ ++it)
+ {
+ // check if it is lying most_left or most_right from the line
+
+ int dir = side::apply(most_left, most_right, *it);
+ switch(dir)
+ {
+ case 1 : // left side
+ upper_points.push_back(*it);
+ break;
+ case -1 : // right side
+ lower_points.push_back(*it);
+ break;
+
+ // 0: on line most_left-most_right,
+ // or most_left, or most_right,
+ // -> all never part of hull
+ }
+ }
+ }
+};
+
+template <typename Range>
+static inline void sort(Range& range)
+{
+ typedef typename boost::range_value<Range>::type point_type;
+ typedef geometry::less<point_type> comparator;
+
+ std::sort(boost::begin(range), boost::end(range), comparator());
+}
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+\brief Graham scan strategy to calculate convex hull
+\ingroup strategies
+\note Completely reworked version inspired on the sources listed below
+\see http://www.ddj.com/architect/201806315
+\see http://marknelson.us/2007/08/22/convex
+ */
+template <typename InputGeometry, typename OutputPoint>
+class graham_andrew
+{
+public :
+ typedef OutputPoint point_type;
+ typedef InputGeometry geometry_type;
+
+private:
+
+ typedef typename cs_tag<point_type>::type cs_tag;
+
+ typedef typename std::vector<point_type> container_type;
+ typedef typename std::vector<point_type>::const_iterator iterator;
+ typedef typename std::vector<point_type>::const_reverse_iterator rev_iterator;
+
+
+ class partitions
+ {
+ friend class graham_andrew;
+
+ container_type m_lower_hull;
+ container_type m_upper_hull;
+ container_type m_copied_input;
+ };
+
+
+public:
+ typedef partitions state_type;
+
+
+ inline void apply(InputGeometry const& geometry, partitions& state) const
+ {
+ // First pass.
+ // Get min/max (in most cases left / right) points
+ // This makes use of the geometry::less/greater predicates
+
+ // For the left boundary it is important that multiple points
+ // are sorted from bottom to top. Therefore the less predicate
+ // does not take the x-only template parameter (this fixes ticket #6019.
+ // For the right boundary it is not necessary (though also not harmful),
+ // because points are sorted from bottom to top in a later stage.
+ // For symmetry and to get often more balanced lower/upper halves
+ // we keep it.
+
+ typedef typename geometry::detail::range_type<InputGeometry>::type range_type;
+
+ typedef typename boost::range_iterator
+ <
+ range_type const
+ >::type range_iterator;
+
+ detail::get_extremes
+ <
+ range_type,
+ range_iterator,
+ geometry::less<point_type>,
+ geometry::greater<point_type>
+ > extremes;
+ geometry::detail::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::services::default_strategy<cs_tag>::type
+ > assigner(extremes.left, extremes.right);
+
+ geometry::detail::for_each_range(geometry, assigner);
+
+
+ // Sort both collections, first on x(, then on y)
+ detail::sort(assigner.lower_points);
+ detail::sort(assigner.upper_points);
+
+ //std::cout << boost::size(assigner.lower_points) << std::endl;
+ //std::cout << boost::size(assigner.upper_points) << std::endl;
+
+ // And decide which point should be in the final hull
+ build_half_hull<-1>(assigner.lower_points, state.m_lower_hull,
+ extremes.left, extremes.right);
+ build_half_hull<1>(assigner.upper_points, state.m_upper_hull,
+ extremes.left, extremes.right);
+ }
+
+
+ template <typename OutputIterator>
+ inline void result(partitions const& state,
+ OutputIterator out, bool clockwise) const
+ {
+ if (clockwise)
+ {
+ output_range<iterate_forward>(state.m_upper_hull, out, false);
+ output_range<iterate_reverse>(state.m_lower_hull, out, true);
+ }
+ else
+ {
+ output_range<iterate_forward>(state.m_lower_hull, out, false);
+ output_range<iterate_reverse>(state.m_upper_hull, out, true);
+ }
+ }
+
+
+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::services::default_strategy<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 <iterate_direction Direction, typename OutputIterator>
+ static inline void output_range(container_type const& range,
+ OutputIterator out, bool skip_first)
+ {
+ typedef typename reversible_view<container_type const, Direction>::type view_type;
+ view_type view(range);
+ bool first = true;
+ for (typename boost::range_iterator<view_type const>::type it = boost::begin(view);
+ it != boost::end(view); ++it)
+ {
+ if (first && skip_first)
+ {
+ first = false;
+ }
+ else
+ {
+ *out = *it;
+ ++out;
+ }
+ }
+ }
+
+};
+
+}} // namespace strategy::convex_hull
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename InputGeometry, typename OutputPoint>
+struct strategy_convex_hull<InputGeometry, OutputPoint, cartesian_tag>
+{
+ typedef strategy::convex_hull::graham_andrew<InputGeometry, OutputPoint> type;
+};
+#endif
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_CONVEX_GRAHAM_ANDREW_HPP
diff --git a/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp b/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp
new file mode 100644
index 000000000..1398ddb68
--- /dev/null
+++ b/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp
@@ -0,0 +1,151 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_POINT_IN_BOX_BY_SIDE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_POINT_IN_BOX_BY_SIDE_HPP
+
+#include <boost/array.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/strategies/covered_by.hpp>
+#include <boost/geometry/strategies/within.hpp>
+
+
+namespace boost { namespace geometry { namespace strategy
+{
+
+namespace within
+{
+
+struct decide_within
+{
+ static inline bool apply(int side, bool& result)
+ {
+ if (side != 1)
+ {
+ result = false;
+ return false;
+ }
+ return true; // continue
+ }
+};
+
+struct decide_covered_by
+{
+ static inline bool apply(int side, bool& result)
+ {
+ if (side != 1)
+ {
+ result = side >= 0;
+ return false;
+ }
+ return true; // continue
+ }
+};
+
+
+template <typename Point, typename Box, typename Decide = decide_within>
+struct point_in_box_by_side
+{
+ typedef typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<Box>::type
+ >::type side_strategy_type;
+
+ static inline bool apply(Point const& point, Box const& box)
+ {
+ // Create (counterclockwise) array of points, the fifth one closes it
+ // Every point should be on the LEFT side (=1), or ON the border (=0),
+ // So >= 1 or >= 0
+ boost::array<typename point_type<Box>::type, 5> bp;
+ geometry::detail::assign_box_corners_oriented<true>(box, bp);
+ bp[4] = bp[0];
+
+ bool result = true;
+ side_strategy_type strategy;
+ boost::ignore_unused_variable_warning(strategy);
+
+ for (int i = 1; i < 5; i++)
+ {
+ int const side = strategy.apply(point, bp[i - 1], bp[i]);
+ if (! Decide::apply(side, result))
+ {
+ return result;
+ }
+ }
+
+ return result;
+ }
+};
+
+
+} // namespace within
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+namespace within { namespace services
+{
+
+template <typename Point, typename Box>
+struct default_strategy
+ <
+ point_tag, box_tag,
+ point_tag, areal_tag,
+ spherical_tag, spherical_tag,
+ Point, Box
+ >
+{
+ typedef within::point_in_box_by_side
+ <
+ Point, Box, within::decide_within
+ > type;
+};
+
+
+
+}} // namespace within::services
+
+
+namespace covered_by { namespace services
+{
+
+
+template <typename Point, typename Box>
+struct default_strategy
+ <
+ point_tag, box_tag,
+ point_tag, areal_tag,
+ spherical_tag, spherical_tag,
+ Point, Box
+ >
+{
+ typedef within::point_in_box_by_side
+ <
+ Point, Box, within::decide_covered_by
+ > type;
+};
+
+
+}} // namespace covered_by::services
+
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}}} // namespace boost::geometry::strategy
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_AGNOSTIC_POINT_IN_BOX_BY_SIDE_HPP
diff --git a/boost/geometry/strategies/agnostic/point_in_poly_oriented_winding.hpp b/boost/geometry/strategies/agnostic/point_in_poly_oriented_winding.hpp
new file mode 100644
index 000000000..423948fff
--- /dev/null
+++ b/boost/geometry/strategies/agnostic/point_in_poly_oriented_winding.hpp
@@ -0,0 +1,208 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_ORIENTED_WINDING_HPP
+#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_ORIENTED_WINDING_HPP
+
+
+#include <boost/geometry/core/point_order.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+#include <boost/geometry/strategies/side.hpp>
+#include <boost/geometry/strategies/within.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace within
+{
+
+/*!
+\brief Within detection using winding rule, but checking if enclosing ring is
+ counter clockwise and, if so, reverses the result
+\ingroup strategies
+\tparam Point \tparam_point
+\tparam Reverse True if parameter should be reversed
+\tparam PointOfSegment \tparam_segment_point
+\tparam CalculationType \tparam_calculation
+\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
+
+\qbk{
+[heading See also]
+[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]
+}
+ */
+template
+<
+ bool Reverse,
+ typename Point,
+ typename PointOfSegment = Point,
+ typename CalculationType = void
+>
+class oriented_winding
+{
+ typedef typename select_calculation_type
+ <
+ Point,
+ PointOfSegment,
+ CalculationType
+ >::type calculation_type;
+
+
+ typedef typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<Point>::type
+ >::type strategy_side_type;
+
+
+ /*! subclass to keep state */
+ class counter
+ {
+ int m_count;
+ bool m_touches;
+ calculation_type m_sum_area;
+
+ inline int code() const
+ {
+ return m_touches ? 0 : m_count == 0 ? -1 : 1;
+ }
+ inline int clockwise_oriented_code() const
+ {
+ return (m_sum_area > 0) ? code() : -code();
+ }
+ inline int oriented_code() const
+ {
+ return Reverse
+ ? -clockwise_oriented_code()
+ : clockwise_oriented_code();
+ }
+
+ public :
+ friend class oriented_winding;
+
+ inline counter()
+ : m_count(0)
+ , m_touches(false)
+ , m_sum_area(0)
+ {}
+
+ inline void add_to_area(calculation_type triangle)
+ {
+ m_sum_area += triangle;
+ }
+
+ };
+
+
+ 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.m_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)
+ {
+ state.add_to_area(get<0>(s2) * get<1>(s1) - get<0>(s1) * get<1>(s2));
+
+ 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.m_touches = true;
+ state.m_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.m_count += count;
+ }
+ }
+ return ! state.m_touches;
+ }
+
+ static inline int result(counter const& state)
+ {
+ return state.oriented_code();
+ }
+};
+
+
+}} // namespace strategy::within
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_ORIENTED_WINDING_HPP
diff --git a/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp b/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
new file mode 100644
index 000000000..69188650d
--- /dev/null
+++ b/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
@@ -0,0 +1,232 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
+#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
+
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+#include <boost/geometry/strategies/side.hpp>
+#include <boost/geometry/strategies/covered_by.hpp>
+#include <boost/geometry/strategies/within.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace within
+{
+
+/*!
+\brief Within detection using winding rule
+\ingroup strategies
+\tparam Point \tparam_point
+\tparam PointOfSegment \tparam_segment_point
+\tparam CalculationType \tparam_calculation
+\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
+
+\qbk{
+[heading See also]
+[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]
+}
+ */
+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::services::default_strategy
+ <
+ typename cs_tag<Point>::type
+ >::type strategy_side_type;
+
+
+ /*! subclass to keep state */
+ class counter
+ {
+ int m_count;
+ bool m_touches;
+
+ inline int code() const
+ {
+ return m_touches ? 0 : m_count == 0 ? -1 : 1;
+ }
+
+ public :
+ friend class winding;
+
+ inline counter()
+ : m_count(0)
+ , m_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.m_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.m_touches = true;
+ state.m_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.m_count += count;
+ }
+ }
+ return ! state.m_touches;
+ }
+
+ static inline int result(counter const& state)
+ {
+ return state.code();
+ }
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+// Register using "areal_tag" for ring, polygon, multi-polygon
+template <typename AnyTag, typename Point, typename Geometry>
+struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, cartesian_tag, cartesian_tag, Point, Geometry>
+{
+ typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
+};
+
+template <typename AnyTag, typename Point, typename Geometry>
+struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, spherical_tag, spherical_tag, Point, Geometry>
+{
+ typedef winding<Point, typename geometry::point_type<Geometry>::type> type;
+};
+
+
+} // namespace services
+
+#endif
+
+
+}} // namespace strategy::within
+
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace strategy { namespace covered_by { namespace services
+{
+
+// Register using "areal_tag" for ring, polygon, multi-polygon
+template <typename AnyTag, typename Point, typename Geometry>
+struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, cartesian_tag, cartesian_tag, Point, Geometry>
+{
+ typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
+};
+
+template <typename AnyTag, typename Point, typename Geometry>
+struct default_strategy<point_tag, AnyTag, point_tag, areal_tag, spherical_tag, spherical_tag, Point, Geometry>
+{
+ typedef strategy::within::winding<Point, typename geometry::point_type<Geometry>::type> type;
+};
+
+
+}}} // namespace strategy::covered_by::services
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_POINT_IN_POLY_WINDING_HPP
diff --git a/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp b/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp
new file mode 100644
index 000000000..8825791db
--- /dev/null
+++ b/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp
@@ -0,0 +1,229 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 1995, 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 1995 Maarten Hilferink, Amsterdam, the Netherlands
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP
+#define BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP
+
+
+#include <cstddef>
+#include <vector>
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/strategies/distance.hpp>
+
+
+
+//#define GL_DEBUG_DOUGLAS_PEUCKER
+
+#ifdef GL_DEBUG_DOUGLAS_PEUCKER
+#include <boost/geometry/io/dsv/write.hpp>
+#endif
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace simplify
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+ /*!
+ \brief Small wrapper around a point, with an extra member "included"
+ \details
+ It has a const-reference to the original point (so no copy here)
+ \tparam the enclosed point type
+ */
+ template<typename Point>
+ struct douglas_peucker_point
+ {
+ Point const& p;
+ bool included;
+
+ inline douglas_peucker_point(Point const& ap)
+ : p(ap)
+ , included(false)
+ {}
+
+ // Necessary for proper compilation
+ inline douglas_peucker_point<Point> operator=(douglas_peucker_point<Point> const& )
+ {
+ return douglas_peucker_point<Point>(*this);
+ }
+ };
+}
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+\brief Implements the simplify algorithm.
+\ingroup strategies
+\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
+{
+public :
+
+ // See also ticket 5954 https://svn.boost.org/trac/boost/ticket/5954
+ // Comparable is currently not possible here because it has to be compared to the squared of max_distance, and more.
+ // For now we have to take the real distance.
+ typedef PointDistanceStrategy distance_strategy_type;
+ // typedef typename strategy::distance::services::comparable_type<PointDistanceStrategy>::type distance_strategy_type;
+
+ typedef typename strategy::distance::services::return_type<distance_strategy_type>::type return_type;
+
+private :
+ typedef detail::douglas_peucker_point<Point> dp_point_type;
+ typedef typename std::vector<dp_point_type>::iterator iterator_type;
+
+
+ static inline void consider(iterator_type begin,
+ iterator_type end,
+ return_type const& max_dist, int& n,
+ distance_strategy_type 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 far point, compare to the current segment
+ //geometry::segment<Point const> s(begin->p, last->p);
+ return_type md(-1.0); // any value < 0
+ iterator_type candidate;
+ 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 :
+
+ template <typename Range, typename OutputIterator>
+ static inline OutputIterator apply(Range const& range,
+ OutputIterator out, double max_distance)
+ {
+ distance_strategy_type 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 strategy::distance::services::return_type<distance_strategy_type>::type return_type;
+
+ consider(boost::begin(ref_candidates), boost::end(ref_candidates), max_distance, n, strategy);
+
+ // Copy included elements to the output
+ for(typename std::vector<dp_point_type>::const_iterator it
+ = boost::begin(ref_candidates);
+ it != boost::end(ref_candidates);
+ ++it)
+ {
+ if (it->included)
+ {
+ // copy-coordinates does not work because OutputIterator
+ // does not model Point (??)
+ //geometry::convert(it->p, *out);
+ *out = it->p;
+ out++;
+ }
+ }
+ return out;
+ }
+
+};
+
+}} // namespace strategy::simplify
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGY_AGNOSTIC_SIMPLIFY_DOUGLAS_PEUCKER_HPP
diff --git a/boost/geometry/strategies/area.hpp b/boost/geometry/strategies/area.hpp
new file mode 100644
index 000000000..e192d9b28
--- /dev/null
+++ b/boost/geometry/strategies/area.hpp
@@ -0,0 +1,50 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_AREA_HPP
+#define BOOST_GEOMETRY_STRATEGIES_AREA_HPP
+
+#include <boost/mpl/assert.hpp>
+
+#include <boost/geometry/strategies/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace area { namespace services
+{
+
+/*!
+ \brief Traits class binding a default area strategy to a coordinate system
+ \ingroup area
+ \tparam Tag tag of coordinate system
+ \tparam PointOfSegment point-type
+*/
+template <typename Tag, typename PointOfSegment>
+struct default_strategy
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE
+ , (types<PointOfSegment>)
+ );
+};
+
+
+}}} // namespace strategy::area::services
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_AREA_HPP
diff --git a/boost/geometry/strategies/cartesian/area_surveyor.hpp b/boost/geometry/strategies/cartesian/area_surveyor.hpp
new file mode 100644
index 000000000..74b63532c
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/area_surveyor.hpp
@@ -0,0 +1,134 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP
+
+
+#include <boost/mpl/if.hpp>
+
+#include <boost/geometry/arithmetic/determinant.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace area
+{
+
+/*!
+\brief Area calculation for cartesian points
+\ingroup strategies
+\details Calculates area using the Surveyor's formula, a well-known
+ triangulation algorithm
+\tparam PointOfSegment \tparam_segment_point
+\tparam CalculationType \tparam_calculation
+
+\qbk{
+[heading See also]
+[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
+}
+
+*/
+template
+<
+ typename PointOfSegment,
+ typename CalculationType = void
+>
+class surveyor
+{
+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 surveyor;
+
+ 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;
+ return_type const two = 2;
+ result /= two;
+ 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 += detail::determinant<return_type>(p2, p1);
+ }
+
+ static inline return_type result(summation const& state)
+ {
+ return state.area();
+ }
+
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+ template <typename Point>
+ struct default_strategy<cartesian_tag, Point>
+ {
+ typedef strategy::area::surveyor<Point> type;
+ };
+
+} // namespace services
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::area
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AREA_SURVEYOR_HPP
diff --git a/boost/geometry/strategies/cartesian/box_in_box.hpp b/boost/geometry/strategies/cartesian/box_in_box.hpp
new file mode 100644
index 000000000..7680b8362
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/box_in_box.hpp
@@ -0,0 +1,176 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/strategies/covered_by.hpp>
+#include <boost/geometry/strategies/within.hpp>
+
+
+namespace boost { namespace geometry { namespace strategy
+{
+
+
+namespace within
+{
+
+struct box_within_range
+{
+ template <typename BoxContainedValue, typename BoxContainingValue>
+ static inline bool apply(BoxContainedValue const& bed_min
+ , BoxContainedValue const& bed_max
+ , BoxContainingValue const& bing_min
+ , BoxContainingValue const& bing_max)
+ {
+ return bed_min > bing_min && bed_max < bing_max;
+ }
+};
+
+
+struct box_covered_by_range
+{
+ template <typename BoxContainedValue, typename BoxContainingValue>
+ static inline bool apply(BoxContainedValue const& bed_min
+ , BoxContainedValue const& bed_max
+ , BoxContainingValue const& bing_min
+ , BoxContainingValue const& bing_max)
+ {
+ return bed_min >= bing_min && bed_max <= bing_max;
+ }
+};
+
+
+template
+<
+ typename SubStrategy,
+ typename Box1,
+ typename Box2,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct relate_box_box_loop
+{
+ static inline bool apply(Box1 const& b_contained, Box2 const& b_containing)
+ {
+ assert_dimension_equal<Box1, Box2>();
+
+ if (! SubStrategy::apply(
+ get<min_corner, Dimension>(b_contained),
+ get<max_corner, Dimension>(b_contained),
+ get<min_corner, Dimension>(b_containing),
+ get<max_corner, Dimension>(b_containing)
+ )
+ )
+ {
+ return false;
+ }
+
+ return relate_box_box_loop
+ <
+ SubStrategy,
+ Box1, Box2,
+ Dimension + 1, DimensionCount
+ >::apply(b_contained, b_containing);
+ }
+};
+
+template
+<
+ typename SubStrategy,
+ typename Box1,
+ typename Box2,
+ std::size_t DimensionCount
+>
+struct relate_box_box_loop<SubStrategy, Box1, Box2, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Box1 const& , Box2 const& )
+ {
+ return true;
+ }
+};
+
+template
+<
+ typename Box1,
+ typename Box2,
+ typename SubStrategy = box_within_range
+>
+struct box_in_box
+{
+ static inline bool apply(Box1 const& box1, Box2 const& box2)
+ {
+ return relate_box_box_loop
+ <
+ SubStrategy,
+ Box1, Box2, 0, dimension<Box1>::type::value
+ >::apply(box1, box2);
+ }
+};
+
+
+} // namespace within
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+namespace within { namespace services
+{
+
+template <typename BoxContained, typename BoxContaining>
+struct default_strategy
+ <
+ box_tag, box_tag,
+ box_tag, areal_tag,
+ cartesian_tag, cartesian_tag,
+ BoxContained, BoxContaining
+ >
+{
+ typedef within::box_in_box<BoxContained, BoxContaining> type;
+};
+
+
+}} // namespace within::services
+
+namespace covered_by { namespace services
+{
+
+template <typename BoxContained, typename BoxContaining>
+struct default_strategy
+ <
+ box_tag, box_tag,
+ box_tag, areal_tag,
+ cartesian_tag, cartesian_tag,
+ BoxContained, BoxContaining
+ >
+{
+ typedef within::box_in_box
+ <
+ BoxContained, BoxContaining,
+ within::box_covered_by_range
+ > type;
+};
+
+}} // namespace covered_by::services
+
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}}} // namespace boost::geometry::strategy
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BOX_IN_BOX_HPP
diff --git a/boost/geometry/strategies/cartesian/cart_intersect.hpp b/boost/geometry/strategies/cartesian/cart_intersect.hpp
new file mode 100644
index 000000000..678e9d7c2
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/cart_intersect.hpp
@@ -0,0 +1,754 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP
+
+#include <algorithm>
+
+#include <boost/geometry/core/exception.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/geometries/concepts/segment_concept.hpp>
+
+#include <boost/geometry/arithmetic/determinant.hpp>
+#include <boost/geometry/algorithms/detail/assign_values.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+// Temporary / will be Strategy as template parameter
+#include <boost/geometry/strategies/side.hpp>
+#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
+
+#include <boost/geometry/strategies/side_info.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace intersection
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <std::size_t Dimension, typename Segment, typename T>
+static inline void segment_arrange(Segment const& s, T& s_1, T& s_2, bool& swapped)
+{
+ s_1 = get<0, Dimension>(s);
+ s_2 = get<1, Dimension>(s);
+ if (s_1 > s_2)
+ {
+ std::swap(s_1, s_2);
+ swapped = true;
+ }
+}
+
+template <std::size_t Index, typename Segment>
+inline typename geometry::point_type<Segment>::type get_from_index(
+ Segment const& segment)
+{
+ typedef typename geometry::point_type<Segment>::type point_type;
+ point_type point;
+ geometry::detail::assign::assign_point_from_index
+ <
+ Segment, point_type, Index, 0, dimension<Segment>::type::value
+ >::apply(segment, point);
+ return point;
+}
+
+}
+#endif
+
+/***
+template <typename T>
+inline std::string rdebug(T const& value)
+{
+ if (math::equals(value, 0)) return "'0'";
+ if (math::equals(value, 1)) return "'1'";
+ if (value < 0) return "<0";
+ if (value > 1) return ">1";
+ return "<0..1>";
+}
+***/
+
+/*!
+ \see http://mathworld.wolfram.com/Line-LineIntersection.html
+ */
+template <typename Policy, typename CalculationType = void>
+struct relate_cartesian_segments
+{
+ typedef typename Policy::return_type return_type;
+ typedef typename Policy::segment_type1 segment_type1;
+ typedef typename Policy::segment_type2 segment_type2;
+
+ //typedef typename point_type<segment_type1>::type point_type;
+ //BOOST_CONCEPT_ASSERT( (concept::Point<point_type>) );
+
+ BOOST_CONCEPT_ASSERT( (concept::ConstSegment<segment_type1>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstSegment<segment_type2>) );
+
+ typedef typename select_calculation_type
+ <segment_type1, segment_type2, CalculationType>::type coordinate_type;
+
+ /// Relate segments a and b
+ static inline return_type apply(segment_type1 const& a, segment_type2 const& b)
+ {
+ coordinate_type const dx_a = get<1, 0>(a) - get<0, 0>(a); // distance in x-dir
+ coordinate_type const dx_b = get<1, 0>(b) - get<0, 0>(b);
+ coordinate_type const dy_a = get<1, 1>(a) - get<0, 1>(a); // distance in y-dir
+ coordinate_type const dy_b = get<1, 1>(b) - get<0, 1>(b);
+ return apply(a, b, dx_a, dy_a, dx_b, dy_b);
+ }
+
+
+ // Relate segments a and b using precalculated differences.
+ // This can save two or four subtractions in many cases
+ static inline return_type apply(segment_type1 const& a, segment_type2 const& b,
+ coordinate_type const& dx_a, coordinate_type const& dy_a,
+ coordinate_type const& dx_b, coordinate_type const& dy_b)
+ {
+ typedef side::side_by_triangle<coordinate_type> side;
+ side_info sides;
+
+ coordinate_type const zero = 0;
+ bool const a_is_point = math::equals(dx_a, zero) && math::equals(dy_a, zero);
+ bool const b_is_point = math::equals(dx_b, zero) && math::equals(dy_b, zero);
+
+ if(a_is_point && b_is_point)
+ {
+ if(math::equals(get<1,0>(a), get<1,0>(b)) && math::equals(get<1,1>(a), get<1,1>(b)))
+ {
+ Policy::degenerate(a, true);
+ }
+ else
+ {
+ return Policy::disjoint();
+ }
+ }
+
+ bool collinear_use_first = math::abs(dx_a) + math::abs(dx_b) >= math::abs(dy_a) + math::abs(dy_b);
+
+ sides.set<0>
+ (
+ side::apply(detail::get_from_index<0>(b)
+ , detail::get_from_index<1>(b)
+ , detail::get_from_index<0>(a)),
+ side::apply(detail::get_from_index<0>(b)
+ , detail::get_from_index<1>(b)
+ , detail::get_from_index<1>(a))
+ );
+ sides.set<1>
+ (
+ side::apply(detail::get_from_index<0>(a)
+ , detail::get_from_index<1>(a)
+ , detail::get_from_index<0>(b)),
+ side::apply(detail::get_from_index<0>(a)
+ , detail::get_from_index<1>(a)
+ , detail::get_from_index<1>(b))
+ );
+
+ bool collinear = sides.collinear();
+
+ robustness_verify_collinear(a, b, a_is_point, b_is_point, sides, collinear);
+ robustness_verify_meeting(a, b, sides, collinear, collinear_use_first);
+
+ if (sides.same<0>() || sides.same<1>())
+ {
+ // Both points are at same side of other segment, we can leave
+ if (robustness_verify_same_side(a, b, sides))
+ {
+ return Policy::disjoint();
+ }
+ }
+
+ // Degenerate cases: segments of single point, lying on other segment, non disjoint
+ if (a_is_point)
+ {
+ return Policy::degenerate(a, true);
+ }
+ if (b_is_point)
+ {
+ return Policy::degenerate(b, false);
+ }
+
+ typedef typename select_most_precise
+ <
+ coordinate_type, double
+ >::type promoted_type;
+
+ // r: ratio 0-1 where intersection divides A/B
+ // (only calculated for non-collinear segments)
+ promoted_type r;
+ if (! collinear)
+ {
+ // Calculate determinants - Cramers rule
+ coordinate_type const wx = get<0, 0>(a) - get<0, 0>(b);
+ coordinate_type const wy = get<0, 1>(a) - get<0, 1>(b);
+ coordinate_type const d = geometry::detail::determinant<coordinate_type>(dx_a, dy_a, dx_b, dy_b);
+ coordinate_type const da = geometry::detail::determinant<coordinate_type>(dx_b, dy_b, wx, wy);
+
+ coordinate_type const zero = coordinate_type();
+ if (math::equals(d, zero))
+ {
+ // This is still a collinear case (because of FP imprecision this can occur here)
+ // sides.debug();
+ sides.set<0>(0,0);
+ sides.set<1>(0,0);
+ collinear = true;
+ }
+ else
+ {
+ r = promoted_type(da) / promoted_type(d);
+
+ if (! robustness_verify_r(a, b, r))
+ {
+ return Policy::disjoint();
+ }
+
+ //robustness_handle_meeting(a, b, sides, dx_a, dy_a, wx, wy, d, r);
+
+ if (robustness_verify_disjoint_at_one_collinear(a, b, sides))
+ {
+ return Policy::disjoint();
+ }
+
+ }
+ }
+
+ if(collinear)
+ {
+ if (collinear_use_first)
+ {
+ return relate_collinear<0>(a, b);
+ }
+ else
+ {
+ // Y direction contains larger segments (maybe dx is zero)
+ return relate_collinear<1>(a, b);
+ }
+ }
+
+ return Policy::segments_intersect(sides, r,
+ dx_a, dy_a, dx_b, dy_b,
+ a, b);
+ }
+
+private :
+
+
+ // Ratio should lie between 0 and 1
+ // Also these three conditions might be of FP imprecision, the segments were actually (nearly) collinear
+ template <typename T>
+ static inline bool robustness_verify_r(
+ segment_type1 const& a, segment_type2 const& b,
+ T& r)
+ {
+ T const zero = 0;
+ T const one = 1;
+ if (r < zero || r > one)
+ {
+ if (verify_disjoint<0>(a, b) || verify_disjoint<1>(a, b))
+ {
+ // Can still be disjoint (even if not one is left or right from another)
+ // This is e.g. in case #snake4 of buffer test.
+ return false;
+ }
+
+ //std::cout << "ROBUSTNESS: correction of r " << r << std::endl;
+ // sides.debug();
+
+ // ROBUSTNESS: the r value can in epsilon-cases much larger than 1, while (with perfect arithmetic)
+ // it should be one. It can be 1.14 or even 1.98049 or 2 (while still intersecting)
+
+ // If segments are crossing (we can see that with the sides)
+ // and one is inside the other, there must be an intersection point.
+ // We correct for that.
+ // This is (only) in case #ggl_list_20110820_christophe in unit tests
+
+ // If segments are touching (two sides zero), of course they should intersect
+ // This is (only) in case #buffer_rt_i in the unit tests)
+
+ // If one touches in the middle, they also should intersect (#buffer_rt_j)
+
+ // Note that even for ttmath r is occasionally > 1, e.g. 1.0000000000000000000000036191231203575
+
+ if (r > one)
+ {
+ r = one;
+ }
+ else if (r < zero)
+ {
+ r = zero;
+ }
+ }
+ return true;
+ }
+
+ static inline void robustness_verify_collinear(
+ segment_type1 const& , segment_type2 const& ,
+ bool a_is_point, bool b_is_point,
+ side_info& sides,
+ bool& collinear)
+ {
+ if ((sides.zero<0>() && ! b_is_point && ! sides.zero<1>()) || (sides.zero<1>() && ! a_is_point && ! sides.zero<0>()))
+ {
+ // If one of the segments is collinear, the other must be as well.
+ // So handle it as collinear.
+ // (In float/double epsilon margins it can easily occur that one or two of them are -1/1)
+ // sides.debug();
+ sides.set<0>(0,0);
+ sides.set<1>(0,0);
+ collinear = true;
+ }
+ }
+
+ static inline void robustness_verify_meeting(
+ segment_type1 const& a, segment_type2 const& b,
+ side_info& sides,
+ bool& collinear, bool& collinear_use_first)
+ {
+ if (sides.meeting())
+ {
+ // If two segments meet each other at their segment-points, two sides are zero,
+ // the other two are not (unless collinear but we don't mean those here).
+ // However, in near-epsilon ranges it can happen that two sides are zero
+ // but they do not meet at their segment-points.
+ // In that case they are nearly collinear and handled as such.
+ if (! point_equals
+ (
+ select(sides.zero_index<0>(), a),
+ select(sides.zero_index<1>(), b)
+ )
+ )
+ {
+ sides.set<0>(0,0);
+ sides.set<1>(0,0);
+ collinear = true;
+
+ if (collinear_use_first && analyse_equal<0>(a, b))
+ {
+ collinear_use_first = false;
+ }
+ else if (! collinear_use_first && analyse_equal<1>(a, b))
+ {
+ collinear_use_first = true;
+ }
+
+ }
+ }
+ }
+
+ // Verifies and if necessary correct missed touch because of robustness
+ // This is the case at multi_polygon_buffer unittest #rt_m
+ static inline bool robustness_verify_same_side(
+ segment_type1 const& a, segment_type2 const& b,
+ side_info& sides)
+ {
+ int corrected = 0;
+ if (sides.one_touching<0>())
+ {
+ if (point_equals(
+ select(sides.zero_index<0>(), a),
+ select(0, b)
+ ))
+ {
+ sides.correct_to_zero<1, 0>();
+ corrected = 1;
+ }
+ if (point_equals
+ (
+ select(sides.zero_index<0>(), a),
+ select(1, b)
+ ))
+ {
+ sides.correct_to_zero<1, 1>();
+ corrected = 2;
+ }
+ }
+ else if (sides.one_touching<1>())
+ {
+ if (point_equals(
+ select(sides.zero_index<1>(), b),
+ select(0, a)
+ ))
+ {
+ sides.correct_to_zero<0, 0>();
+ corrected = 3;
+ }
+ if (point_equals
+ (
+ select(sides.zero_index<1>(), b),
+ select(1, a)
+ ))
+ {
+ sides.correct_to_zero<0, 1>();
+ corrected = 4;
+ }
+ }
+
+ return corrected == 0;
+ }
+
+ static inline bool robustness_verify_disjoint_at_one_collinear(
+ segment_type1 const& a, segment_type2 const& b,
+ side_info const& sides)
+ {
+ if (sides.one_of_all_zero())
+ {
+ if (verify_disjoint<0>(a, b) || verify_disjoint<1>(a, b))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+/*
+ // If r is one, or zero, segments should meet and their endpoints.
+ // Robustness issue: check if this is really the case.
+ // It turns out to be no problem, see buffer test #rt_s1 (and there are many cases generated)
+ // It generates an "ends in the middle" situation which is correct.
+ template <typename T, typename R>
+ static inline void robustness_handle_meeting(segment_type1 const& a, segment_type2 const& b,
+ side_info& sides,
+ T const& dx_a, T const& dy_a, T const& wx, T const& wy,
+ T const& d, R const& r)
+ {
+ return;
+
+ T const db = geometry::detail::determinant<T>(dx_a, dy_a, wx, wy);
+
+ R const zero = 0;
+ R const one = 1;
+ if (math::equals(r, zero) || math::equals(r, one))
+ {
+ R rb = db / d;
+ if (rb <= 0 || rb >= 1 || math::equals(rb, 0) || math::equals(rb, 1))
+ {
+ if (sides.one_zero<0>() && ! sides.one_zero<1>()) // or vice versa
+ {
+#if defined(BOOST_GEOMETRY_COUNT_INTERSECTION_EQUAL)
+ extern int g_count_intersection_equal;
+ g_count_intersection_equal++;
+#endif
+ sides.debug();
+ std::cout << "E r=" << r << " r.b=" << rb << " ";
+ }
+ }
+ }
+ }
+*/
+ template <std::size_t Dimension>
+ static inline bool verify_disjoint(segment_type1 const& a,
+ segment_type2 const& b)
+ {
+ coordinate_type a_1, a_2, b_1, b_2;
+ bool a_swapped = false, b_swapped = false;
+ detail::segment_arrange<Dimension>(a, a_1, a_2, a_swapped);
+ detail::segment_arrange<Dimension>(b, b_1, b_2, b_swapped);
+ return math::smaller(a_2, b_1) || math::larger(a_1, b_2);
+ }
+
+ template <typename Segment>
+ static inline typename point_type<Segment>::type select(int index, Segment const& segment)
+ {
+ return index == 0
+ ? detail::get_from_index<0>(segment)
+ : detail::get_from_index<1>(segment)
+ ;
+ }
+
+ // We cannot use geometry::equals here. Besides that this will be changed
+ // to compare segment-coordinate-values directly (not necessary to retrieve point first)
+ template <typename Point1, typename Point2>
+ static inline bool point_equals(Point1 const& point1, Point2 const& point2)
+ {
+ return math::equals(get<0>(point1), get<0>(point2))
+ && math::equals(get<1>(point1), get<1>(point2))
+ ;
+ }
+
+ // We cannot use geometry::equals here. Besides that this will be changed
+ // to compare segment-coordinate-values directly (not necessary to retrieve point first)
+ template <typename Point1, typename Point2>
+ static inline bool point_equality(Point1 const& point1, Point2 const& point2,
+ bool& equals_0, bool& equals_1)
+ {
+ equals_0 = math::equals(get<0>(point1), get<0>(point2));
+ equals_1 = math::equals(get<1>(point1), get<1>(point2));
+ return equals_0 && equals_1;
+ }
+
+ template <std::size_t Dimension>
+ static inline bool analyse_equal(segment_type1 const& a, segment_type2 const& b)
+ {
+ coordinate_type const a_1 = geometry::get<0, Dimension>(a);
+ coordinate_type const a_2 = geometry::get<1, Dimension>(a);
+ coordinate_type const b_1 = geometry::get<0, Dimension>(b);
+ coordinate_type const b_2 = geometry::get<1, Dimension>(b);
+ return math::equals(a_1, b_1)
+ || math::equals(a_2, b_1)
+ || math::equals(a_1, b_2)
+ || math::equals(a_2, b_2)
+ ;
+ }
+
+ template <std::size_t Dimension>
+ static inline return_type relate_collinear(segment_type1 const& a,
+ segment_type2 const& b)
+ {
+ coordinate_type a_1, a_2, b_1, b_2;
+ bool a_swapped = false, b_swapped = false;
+ detail::segment_arrange<Dimension>(a, a_1, a_2, a_swapped);
+ detail::segment_arrange<Dimension>(b, b_1, b_2, b_swapped);
+ if (math::smaller(a_2, b_1) || math::larger(a_1, b_2))
+ //if (a_2 < b_1 || a_1 > b_2)
+ {
+ return Policy::disjoint();
+ }
+ return relate_collinear(a, b, a_1, a_2, b_1, b_2, a_swapped, b_swapped);
+ }
+
+ /// Relate segments known collinear
+ static inline return_type relate_collinear(segment_type1 const& a
+ , segment_type2 const& b
+ , coordinate_type a_1, coordinate_type a_2
+ , coordinate_type b_1, coordinate_type b_2
+ , bool a_swapped, bool b_swapped)
+ {
+ // All ca. 150 lines are about collinear rays
+ // The intersections, if any, are always boundary points of the segments. No need to calculate anything.
+ // However we want to find out HOW they intersect, there are many cases.
+ // Most sources only provide the intersection (above) or that there is a collinearity (but not the points)
+ // or some spare sources give the intersection points (calculated) but not how they align.
+ // This source tries to give everything and still be efficient.
+ // It is therefore (and because of the extensive clarification comments) rather long...
+
+ // \see http://mpa.itc.it/radim/g50history/CMP/4.2.1-CERL-beta-libes/file475.txt
+ // \see http://docs.codehaus.org/display/GEOTDOC/Point+Set+Theory+and+the+DE-9IM+Matrix
+ // \see http://mathworld.wolfram.com/Line-LineIntersection.html
+
+ // Because of collinearity the case is now one-dimensional and can be checked using intervals
+ // This function is called either horizontally or vertically
+ // We get then two intervals:
+ // a_1-------------a_2 where a_1 < a_2
+ // b_1-------------b_2 where b_1 < b_2
+ // In all figures below a_1/a_2 denotes arranged intervals, a1-a2 or a2-a1 are still unarranged
+
+ // Handle "equal", in polygon neighbourhood comparisons a common case
+
+ bool const opposite = a_swapped ^ b_swapped;
+ bool const both_swapped = a_swapped && b_swapped;
+
+ // Check if segments are equal or opposite equal...
+ bool const swapped_a1_eq_b1 = math::equals(a_1, b_1);
+ bool const swapped_a2_eq_b2 = math::equals(a_2, b_2);
+
+ if (swapped_a1_eq_b1 && swapped_a2_eq_b2)
+ {
+ return Policy::segment_equal(a, opposite);
+ }
+
+ bool const swapped_a2_eq_b1 = math::equals(a_2, b_1);
+ bool const swapped_a1_eq_b2 = math::equals(a_1, b_2);
+
+ bool const a1_eq_b1 = both_swapped ? swapped_a2_eq_b2 : a_swapped ? swapped_a2_eq_b1 : b_swapped ? swapped_a1_eq_b2 : swapped_a1_eq_b1;
+ bool const a2_eq_b2 = both_swapped ? swapped_a1_eq_b1 : a_swapped ? swapped_a1_eq_b2 : b_swapped ? swapped_a2_eq_b1 : swapped_a2_eq_b2;
+
+ bool const a1_eq_b2 = both_swapped ? swapped_a2_eq_b1 : a_swapped ? swapped_a2_eq_b2 : b_swapped ? swapped_a1_eq_b1 : swapped_a1_eq_b2;
+ bool const a2_eq_b1 = both_swapped ? swapped_a1_eq_b2 : a_swapped ? swapped_a1_eq_b1 : b_swapped ? swapped_a2_eq_b2 : swapped_a2_eq_b1;
+
+
+
+
+ // The rest below will return one or two intersections.
+ // The delegated class can decide which is the intersection point, or two, build the Intersection Matrix (IM)
+ // For IM it is important to know which relates to which. So this information is given,
+ // without performance penalties to intersection calculation
+
+ bool const has_common_points = swapped_a1_eq_b1 || swapped_a1_eq_b2 || swapped_a2_eq_b1 || swapped_a2_eq_b2;
+
+
+ // "Touch" -> one intersection point -> one but not two common points
+ // --------> A (or B)
+ // <---------- B (or A)
+ // a_2==b_1 (b_2==a_1 or a_2==b1)
+
+ // The check a_2/b_1 is necessary because it excludes cases like
+ // ------->
+ // --->
+ // ... which are handled lateron
+
+ // Corresponds to 4 cases, of which the equal points are determined above
+ // #1: a1---->a2 b1--->b2 (a arrives at b's border)
+ // #2: a2<----a1 b2<---b1 (b arrives at a's border)
+ // #3: a1---->a2 b2<---b1 (both arrive at each others border)
+ // #4: a2<----a1 b1--->b2 (no arrival at all)
+ // Where the arranged forms have two forms:
+ // a_1-----a_2/b_1-------b_2 or reverse (B left of A)
+ if ((swapped_a2_eq_b1 || swapped_a1_eq_b2) && ! swapped_a1_eq_b1 && ! swapped_a2_eq_b2)
+ {
+ if (a2_eq_b1) return Policy::collinear_touch(get<1, 0>(a), get<1, 1>(a), 0, -1);
+ if (a1_eq_b2) return Policy::collinear_touch(get<0, 0>(a), get<0, 1>(a), -1, 0);
+ if (a2_eq_b2) return Policy::collinear_touch(get<1, 0>(a), get<1, 1>(a), 0, 0);
+ if (a1_eq_b1) return Policy::collinear_touch(get<0, 0>(a), get<0, 1>(a), -1, -1);
+ }
+
+
+ // "Touch/within" -> there are common points and also an intersection of interiors:
+ // Corresponds to many cases:
+ // #1a: a1------->a2 #1b: a1-->a2
+ // b1--->b2 b1------->b2
+ // #2a: a2<-------a1 #2b: a2<--a1
+ // b1--->b2 b1------->b2
+ // #3a: a1------->a2 #3b: a1-->a2
+ // b2<---b1 b2<-------b1
+ // #4a: a2<-------a1 #4b: a2<--a1
+ // b2<---b1 b2<-------b1
+
+ // Note: next cases are similar and handled by the code
+ // #4c: a1--->a2
+ // b1-------->b2
+ // #4d: a1-------->a2
+ // b1-->b2
+
+ // For case 1-4: a_1 < (b_1 or b_2) < a_2, two intersections are equal to segment B
+ // For case 5-8: b_1 < (a_1 or a_2) < b_2, two intersections are equal to segment A
+ if (has_common_points)
+ {
+ // Either A is in B, or B is in A, or (in case of robustness/equals)
+ // both are true, see below
+ bool a_in_b = (b_1 < a_1 && a_1 < b_2) || (b_1 < a_2 && a_2 < b_2);
+ bool b_in_a = (a_1 < b_1 && b_1 < a_2) || (a_1 < b_2 && b_2 < a_2);
+
+ if (a_in_b && b_in_a)
+ {
+ // testcase "ggl_list_20110306_javier"
+ // In robustness it can occur that a point of A is inside B AND a point of B is inside A,
+ // still while has_common_points is true (so one point equals the other).
+ // If that is the case we select on length.
+ coordinate_type const length_a = geometry::math::abs(a_1 - a_2);
+ coordinate_type const length_b = geometry::math::abs(b_1 - b_2);
+ if (length_a > length_b)
+ {
+ a_in_b = false;
+ }
+ else
+ {
+ b_in_a = false;
+ }
+ }
+
+ int const arrival_a = a_in_b ? 1 : -1;
+ if (a2_eq_b2) return Policy::collinear_interior_boundary_intersect(a_in_b ? a : b, a_in_b, 0, 0, false);
+ if (a1_eq_b2) return Policy::collinear_interior_boundary_intersect(a_in_b ? a : b, a_in_b, arrival_a, 0, true);
+ if (a2_eq_b1) return Policy::collinear_interior_boundary_intersect(a_in_b ? a : b, a_in_b, 0, -arrival_a, true);
+ if (a1_eq_b1) return Policy::collinear_interior_boundary_intersect(a_in_b ? a : b, a_in_b, arrival_a, -arrival_a, false);
+ }
+
+
+
+ // "Inside", a completely within b or b completely within a
+ // 2 cases:
+ // case 1:
+ // a_1---a_2 -> take A's points as intersection points
+ // b_1------------b_2
+ // case 2:
+ // a_1------------a_2
+ // b_1---b_2 -> take B's points
+ if (a_1 > b_1 && a_2 < b_2)
+ {
+ // A within B
+ return Policy::collinear_a_in_b(a, opposite);
+ }
+ if (b_1 > a_1 && b_2 < a_2)
+ {
+ // B within A
+ return Policy::collinear_b_in_a(b, opposite);
+ }
+
+
+ /*
+
+ Now that all cases with equal,touch,inside,disjoint,
+ degenerate are handled the only thing left is an overlap
+
+ Either a1 is between b1,b2
+ or a2 is between b1,b2 (a2 arrives)
+
+ Next table gives an overview.
+ The IP's are ordered following the line A1->A2
+
+ | |
+ | a_2 in between | a_1 in between
+ | |
+ -----+---------------------------------+--------------------------
+ | a1--------->a2 | a1--------->a2
+ | b1----->b2 | b1----->b2
+ | (b1,a2), a arrives | (a1,b2), b arrives
+ | |
+ -----+---------------------------------+--------------------------
+ a sw.| a2<---------a1* | a2<---------a1*
+ | b1----->b2 | b1----->b2
+ | (a1,b1), no arrival | (b2,a2), a and b arrive
+ | |
+ -----+---------------------------------+--------------------------
+ | a1--------->a2 | a1--------->a2
+ b sw.| b2<-----b1 | b2<-----b1
+ | (b2,a2), a and b arrive | (a1,b1), no arrival
+ | |
+ -----+---------------------------------+--------------------------
+ a sw.| a2<---------a1* | a2<---------a1*
+ b sw.| b2<-----b1 | b2<-----b1
+ | (a1,b2), b arrives | (b1,a2), a arrives
+ | |
+ -----+---------------------------------+--------------------------
+ * Note that a_1 < a_2, and a1 <> a_1; if a is swapped,
+ the picture might seem wrong but it (supposed to be) is right.
+ */
+
+ if (b_1 < a_2 && a_2 < b_2)
+ {
+ // Left column, from bottom to top
+ return
+ both_swapped ? Policy::collinear_overlaps(get<0, 0>(a), get<0, 1>(a), get<1, 0>(b), get<1, 1>(b), -1, 1, opposite)
+ : b_swapped ? Policy::collinear_overlaps(get<1, 0>(b), get<1, 1>(b), get<1, 0>(a), get<1, 1>(a), 1, 1, opposite)
+ : a_swapped ? Policy::collinear_overlaps(get<0, 0>(a), get<0, 1>(a), get<0, 0>(b), get<0, 1>(b), -1, -1, opposite)
+ : Policy::collinear_overlaps(get<0, 0>(b), get<0, 1>(b), get<1, 0>(a), get<1, 1>(a), 1, -1, opposite)
+ ;
+ }
+ if (b_1 < a_1 && a_1 < b_2)
+ {
+ // Right column, from bottom to top
+ return
+ both_swapped ? Policy::collinear_overlaps(get<0, 0>(b), get<0, 1>(b), get<1, 0>(a), get<1, 1>(a), 1, -1, opposite)
+ : b_swapped ? Policy::collinear_overlaps(get<0, 0>(a), get<0, 1>(a), get<0, 0>(b), get<0, 1>(b), -1, -1, opposite)
+ : a_swapped ? Policy::collinear_overlaps(get<1, 0>(b), get<1, 1>(b), get<1, 0>(a), get<1, 1>(a), 1, 1, opposite)
+ : Policy::collinear_overlaps(get<0, 0>(a), get<0, 1>(a), get<1, 0>(b), get<1, 1>(b), -1, 1, opposite)
+ ;
+ }
+ // Nothing should goes through. If any we have made an error
+ // std::cout << "Robustness issue, non-logical behaviour" << std::endl;
+ return Policy::error("Robustness issue, non-logical behaviour");
+ }
+};
+
+
+}} // namespace strategy::intersection
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_INTERSECTION_HPP
diff --git a/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp b/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp
new file mode 100644
index 000000000..8b42715e0
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp
@@ -0,0 +1,242 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/arithmetic/determinant.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/strategies/centroid.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+// Note: when calling the namespace "centroid", it sometimes,
+// somehow, in gcc, gives compilation problems (confusion with function centroid).
+
+namespace strategy { namespace centroid
+{
+
+
+
+/*!
+\brief Centroid calculation using algorith Bashein / Detmer
+\ingroup strategies
+\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
+
+\qbk{
+[heading See also]
+[link geometry.reference.algorithms.centroid.centroid_3_with_strategy centroid (with strategy)]
+}
+
+ */
+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;
+ }
+ };
+
+public :
+ typedef sums state_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 = geometry::detail::determinant<calculation_type>(p1, p2);
+ 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)
+ {
+ calculation_type const zero = calculation_type();
+ if (state.count > 0 && ! math::equals(state.sum_a2, zero))
+ {
+ calculation_type const v3 = 3;
+ calculation_type const a3 = v3 * state.sum_a2;
+
+ typedef typename geometry::coordinate_type
+ <
+ Point
+ >::type coordinate_type;
+
+ set<0>(centroid,
+ boost::numeric_cast<coordinate_type>(state.sum_x / a3));
+ set<1>(centroid,
+ boost::numeric_cast<coordinate_type>(state.sum_y / a3));
+ return true;
+ }
+
+ return false;
+ }
+
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+// Register this strategy for rings and (multi)polygons, in two dimensions
+template <typename Point, typename Geometry>
+struct default_strategy<cartesian_tag, areal_tag, 2, Point, Geometry>
+{
+ typedef bashein_detmer
+ <
+ Point,
+ typename point_type<Geometry>::type
+ > type;
+};
+
+
+} // namespace services
+
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::centroid
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_BASHEIN_DETMER_HPP
diff --git a/boost/geometry/strategies/cartesian/centroid_weighted_length.hpp b/boost/geometry/strategies/cartesian/centroid_weighted_length.hpp
new file mode 100644
index 000000000..48feae51d
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/centroid_weighted_length.hpp
@@ -0,0 +1,144 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+// Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP
+
+#include <boost/geometry/algorithms/distance.hpp>
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+#include <boost/geometry/strategies/centroid.hpp>
+#include <boost/geometry/strategies/default_distance_result.hpp>
+
+// Helper geometry
+#include <boost/geometry/geometries/point.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace centroid
+{
+
+namespace detail
+{
+
+template <typename Type, std::size_t DimensionCount>
+struct weighted_length_sums
+{
+ typedef typename geometry::model::point
+ <
+ Type, DimensionCount,
+ cs::cartesian
+ > work_point;
+
+ Type length;
+ work_point average_sum;
+
+ inline weighted_length_sums()
+ : length(Type())
+ {
+ geometry::assign_zero(average_sum);
+ }
+};
+}
+
+template
+<
+ typename Point,
+ typename PointOfSegment = Point
+>
+class weighted_length
+{
+private :
+ typedef typename select_most_precise
+ <
+ typename default_distance_result<Point>::type,
+ typename default_distance_result<PointOfSegment>::type
+ >::type distance_type;
+
+public :
+ typedef detail::weighted_length_sums
+ <
+ distance_type,
+ geometry::dimension<Point>::type::value
+ > state_type;
+
+ static inline void apply(PointOfSegment const& p1,
+ PointOfSegment const& p2, state_type& state)
+ {
+ distance_type const d = geometry::distance(p1, p2);
+ state.length += d;
+
+ typename state_type::work_point weighted_median;
+ geometry::assign_zero(weighted_median);
+ geometry::add_point(weighted_median, p1);
+ geometry::add_point(weighted_median, p2);
+ geometry::multiply_value(weighted_median, d/2);
+ geometry::add_point(state.average_sum, weighted_median);
+ }
+
+ static inline bool result(state_type const& state, Point& centroid)
+ {
+ distance_type const zero = distance_type();
+ if (! geometry::math::equals(state.length, zero))
+ {
+ assign_zero(centroid);
+ add_point(centroid, state.average_sum);
+ divide_value(centroid, state.length);
+ return true;
+ }
+
+ return false;
+ }
+
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+
+// Register this strategy for linear geometries, in all dimensions
+
+template <std::size_t N, typename Point, typename Geometry>
+struct default_strategy
+<
+ cartesian_tag,
+ linear_tag,
+ N,
+ Point,
+ Geometry
+>
+{
+ typedef weighted_length
+ <
+ Point,
+ typename point_type<Geometry>::type
+ > type;
+};
+
+
+} // namespace services
+
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::centroid
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP
diff --git a/boost/geometry/strategies/cartesian/distance_projected_point.hpp b/boost/geometry/strategies/cartesian/distance_projected_point.hpp
new file mode 100644
index 000000000..9cff4d8af
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/distance_projected_point.hpp
@@ -0,0 +1,320 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/arithmetic/dot_product.hpp>
+
+#include <boost/geometry/strategies/tags.hpp>
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/default_distance_result.hpp>
+#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
+
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+// Helper geometry (projected point on line)
+#include <boost/geometry/geometries/point.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace distance
+{
+
+
+/*!
+\brief Strategy for distance point to segment
+\ingroup strategies
+\details Calculates distance using projected-point method, and (optionally) Pythagoras
+\author Adapted from: http://geometryalgorithms.com/Archive/algorithm_0102/algorithm_0102.htm
+\tparam Point \tparam_point
+\tparam PointOfSegment \tparam_segment_point
+\tparam CalculationType \tparam_calculation
+\tparam Strategy underlying point-point distance strategy
+\par Concepts for Strategy:
+- cartesian_distance operator(Point,Point)
+\note If the Strategy is a "comparable::pythagoras", this strategy
+ automatically is a comparable projected_point strategy (so without sqrt)
+
+\qbk{
+[heading See also]
+[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
+}
+
+*/
+template
+<
+ typename Point,
+ typename PointOfSegment = Point,
+ typename CalculationType = void,
+ typename Strategy = pythagoras<Point, PointOfSegment, CalculationType>
+>
+class projected_point
+{
+public :
+ // The three typedefs below are necessary to calculate distances
+ // from segments defined in integer coordinates.
+
+ // Integer coordinates can still result in FP distances.
+ // There is a division, which must be represented in FP.
+ // So promote.
+ typedef typename promote_floating_point
+ <
+ typename strategy::distance::services::return_type
+ <
+ Strategy
+ >::type
+ >::type calculation_type;
+
+private :
+
+ // A projected point of points in Integer coordinates must be able to be
+ // represented in FP.
+ typedef model::point
+ <
+ calculation_type,
+ dimension<PointOfSegment>::value,
+ typename coordinate_system<PointOfSegment>::type
+ > fp_point_type;
+
+ // For convenience
+ typedef fp_point_type fp_vector_type;
+
+ // We have to use a strategy using FP coordinates (fp-type) which is
+ // not always the same as Strategy (defined as point_strategy_type)
+ // So we create a "similar" one
+ typedef typename strategy::distance::services::similar_type
+ <
+ Strategy,
+ Point,
+ fp_point_type
+ >::type fp_strategy_type;
+
+public :
+
+ inline calculation_type apply(Point const& p,
+ PointOfSegment const& p1, PointOfSegment const& p2) const
+ {
+ assert_dimension_equal<Point, PointOfSegment>();
+
+ /*
+ Algorithm [p1: (x1,y1), p2: (x2,y2), p: (px,py)]
+ VECTOR v(x2 - x1, y2 - y1)
+ VECTOR w(px - x1, py - y1)
+ c1 = w . v
+ c2 = v . v
+ b = c1 / c2
+ RETURN POINT(x1 + b * vx, y1 + b * vy)
+ */
+
+ // v is multiplied below with a (possibly) FP-value, so should be in FP
+ // For consistency we define w also in FP
+ fp_vector_type v, w;
+
+ geometry::convert(p2, v);
+ geometry::convert(p, w);
+ subtract_point(v, p1);
+ subtract_point(w, p1);
+
+ Strategy strategy;
+ boost::ignore_unused_variable_warning(strategy);
+
+ calculation_type const zero = calculation_type();
+ calculation_type const c1 = dot_product(w, v);
+ if (c1 <= zero)
+ {
+ return strategy.apply(p, p1);
+ }
+ calculation_type const c2 = dot_product(v, v);
+ if (c2 <= c1)
+ {
+ return strategy.apply(p, p2);
+ }
+
+ // See above, c1 > 0 AND c2 > c1 so: c2 != 0
+ calculation_type const b = c1 / c2;
+
+ fp_strategy_type fp_strategy
+ = strategy::distance::services::get_similar
+ <
+ Strategy, Point, fp_point_type
+ >::apply(strategy);
+ boost::ignore_unused_variable_warning(fp_strategy);
+
+ fp_point_type projected;
+ geometry::convert(p1, projected);
+ multiply_value(v, b);
+ add_point(projected, v);
+
+ //std::cout << "distance " << dsv(p) << " .. " << dsv(projected) << std::endl;
+
+ return fp_strategy.apply(p, projected);
+ }
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
+struct tag<projected_point<Point, PointOfSegment, CalculationType, Strategy> >
+{
+ typedef strategy_tag_distance_point_segment type;
+};
+
+
+template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
+struct return_type<projected_point<Point, PointOfSegment, CalculationType, Strategy> >
+{
+ typedef typename projected_point<Point, PointOfSegment, CalculationType, Strategy>::calculation_type type;
+};
+
+template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
+struct strategy_point_point<projected_point<Point, PointOfSegment, CalculationType, Strategy> >
+{
+ typedef Strategy type;
+};
+
+
+template
+<
+ typename Point,
+ typename PointOfSegment,
+ typename CalculationType,
+ typename Strategy,
+ typename P1,
+ typename P2
+>
+struct similar_type<projected_point<Point, PointOfSegment, CalculationType, Strategy>, P1, P2>
+{
+ typedef projected_point<P1, P2, CalculationType, Strategy> type;
+};
+
+
+template
+<
+ typename Point,
+ typename PointOfSegment,
+ typename CalculationType,
+ typename Strategy,
+ typename P1,
+ typename P2
+>
+struct get_similar<projected_point<Point, PointOfSegment, CalculationType, Strategy>, P1, P2>
+{
+ static inline typename similar_type
+ <
+ projected_point<Point, PointOfSegment, CalculationType, Strategy>, P1, P2
+ >::type apply(projected_point<Point, PointOfSegment, CalculationType, Strategy> const& )
+ {
+ return projected_point<P1, P2, CalculationType, Strategy>();
+ }
+};
+
+
+template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
+struct comparable_type<projected_point<Point, PointOfSegment, CalculationType, Strategy> >
+{
+ // Define a projected_point strategy with its underlying point-point-strategy
+ // being comparable
+ typedef projected_point
+ <
+ Point,
+ PointOfSegment,
+ CalculationType,
+ typename comparable_type<Strategy>::type
+ > type;
+};
+
+
+template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
+struct get_comparable<projected_point<Point, PointOfSegment, CalculationType, Strategy> >
+{
+ typedef typename comparable_type
+ <
+ projected_point<Point, PointOfSegment, CalculationType, Strategy>
+ >::type comparable_type;
+public :
+ static inline comparable_type apply(projected_point<Point, PointOfSegment, CalculationType, Strategy> const& )
+ {
+ return comparable_type();
+ }
+};
+
+
+template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
+struct result_from_distance<projected_point<Point, PointOfSegment, CalculationType, Strategy> >
+{
+private :
+ typedef typename return_type<projected_point<Point, PointOfSegment, CalculationType, Strategy> >::type return_type;
+public :
+ template <typename T>
+ static inline return_type apply(projected_point<Point, PointOfSegment, CalculationType, Strategy> const& , T const& value)
+ {
+ Strategy s;
+ return result_from_distance<Strategy>::apply(s, value);
+ }
+};
+
+
+// Get default-strategy for point-segment distance calculation
+// while still have the possibility to specify point-point distance strategy (PPS)
+// It is used in algorithms/distance.hpp where users specify PPS for distance
+// of point-to-segment or point-to-linestring.
+// Convenient for geographic coordinate systems especially.
+template <typename Point, typename PointOfSegment, typename Strategy>
+struct default_strategy<segment_tag, Point, PointOfSegment, cartesian_tag, cartesian_tag, Strategy>
+{
+ typedef strategy::distance::projected_point
+ <
+ Point,
+ PointOfSegment,
+ void,
+ typename boost::mpl::if_
+ <
+ boost::is_void<Strategy>,
+ typename default_strategy
+ <
+ point_tag, Point, PointOfSegment,
+ cartesian_tag, cartesian_tag
+ >::type,
+ Strategy
+ >::type
+ > type;
+};
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::distance
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP
diff --git a/boost/geometry/strategies/cartesian/distance_pythagoras.hpp b/boost/geometry/strategies/cartesian/distance_pythagoras.hpp
new file mode 100644
index 000000000..c62cf749e
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/distance_pythagoras.hpp
@@ -0,0 +1,349 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/access.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+
+#include <boost/geometry/util/calculation_type.hpp>
+
+
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace distance
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Point1, typename Point2, size_t I, typename T>
+struct compute_pythagoras
+{
+ static inline T apply(Point1 const& p1, Point2 const& p2)
+ {
+ T const c1 = boost::numeric_cast<T>(get<I-1>(p1));
+ T const c2 = boost::numeric_cast<T>(get<I-1>(p2));
+ T const d = c1 - c2;
+ return d * d + compute_pythagoras<Point1, Point2, I-1, T>::apply(p1, p2);
+ }
+};
+
+template <typename Point1, typename Point2, typename T>
+struct compute_pythagoras<Point1, Point2, 0, T>
+{
+ static inline T apply(Point1 const&, Point2 const&)
+ {
+ return boost::numeric_cast<T>(0);
+ }
+};
+
+}
+#endif // DOXYGEN_NO_DETAIL
+
+
+namespace comparable
+{
+
+/*!
+\brief Strategy to calculate comparable distance between two points
+\ingroup strategies
+\tparam Point1 \tparam_first_point
+\tparam Point2 \tparam_second_point
+\tparam CalculationType \tparam_calculation
+*/
+template
+<
+ typename Point1,
+ typename Point2 = Point1,
+ typename CalculationType = void
+>
+class pythagoras
+{
+public :
+
+ typedef typename util::calculation_type::geometric::binary
+ <
+ Point1,
+ Point2,
+ CalculationType
+ >::type calculation_type;
+
+ static inline calculation_type apply(Point1 const& p1, Point2 const& p2)
+ {
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point1>) );
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
+
+ // Calculate distance using Pythagoras
+ // (Leave comment above for Doxygen)
+
+ assert_dimension_equal<Point1, Point2>();
+
+ return detail::compute_pythagoras
+ <
+ Point1, Point2,
+ dimension<Point1>::value,
+ calculation_type
+ >::apply(p1, p2);
+ }
+};
+
+} // namespace comparable
+
+
+/*!
+\brief Strategy to calculate the distance between two points
+\ingroup strategies
+\tparam Point1 \tparam_first_point
+\tparam Point2 \tparam_second_point
+\tparam CalculationType \tparam_calculation
+
+\qbk{
+[heading Notes]
+[note Can be used for points with two\, three or more dimensions]
+[heading See also]
+[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
+}
+
+*/
+template
+<
+ typename Point1,
+ typename Point2 = Point1,
+ typename CalculationType = void
+>
+class pythagoras
+{
+ typedef comparable::pythagoras<Point1, Point2, CalculationType> comparable_type;
+public :
+ typedef typename util::calculation_type::geometric::binary
+ <
+ Point1,
+ Point2,
+ CalculationType,
+ double,
+ double // promote integer to double
+ >::type calculation_type;
+
+ /*!
+ \brief applies the distance calculation using pythagoras
+ \return the calculated distance (including taking the square root)
+ \param p1 first point
+ \param p2 second point
+ */
+ static inline calculation_type apply(Point1 const& p1, Point2 const& p2)
+ {
+ calculation_type const t = comparable_type::apply(p1, p2);
+ return sqrt(t);
+ }
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct tag<pythagoras<Point1, Point2, CalculationType> >
+{
+ typedef strategy_tag_distance_point_point type;
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct return_type<pythagoras<Point1, Point2, CalculationType> >
+{
+ typedef typename pythagoras<Point1, Point2, CalculationType>::calculation_type type;
+};
+
+
+template
+<
+ typename Point1,
+ typename Point2,
+ typename CalculationType,
+ typename P1,
+ typename P2
+>
+struct similar_type<pythagoras<Point1, Point2, CalculationType>, P1, P2>
+{
+ typedef pythagoras<P1, P2, CalculationType> type;
+};
+
+
+template
+<
+ typename Point1,
+ typename Point2,
+ typename CalculationType,
+ typename P1,
+ typename P2
+>
+struct get_similar<pythagoras<Point1, Point2, CalculationType>, P1, P2>
+{
+ static inline typename similar_type
+ <
+ pythagoras<Point1, Point2, CalculationType>, P1, P2
+ >::type apply(pythagoras<Point1, Point2, CalculationType> const& )
+ {
+ return pythagoras<P1, P2, CalculationType>();
+ }
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct comparable_type<pythagoras<Point1, Point2, CalculationType> >
+{
+ typedef comparable::pythagoras<Point1, Point2, CalculationType> type;
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct get_comparable<pythagoras<Point1, Point2, CalculationType> >
+{
+ typedef comparable::pythagoras<Point1, Point2, CalculationType> comparable_type;
+public :
+ static inline comparable_type apply(pythagoras<Point1, Point2, CalculationType> const& )
+ {
+ return comparable_type();
+ }
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct result_from_distance<pythagoras<Point1, Point2, CalculationType> >
+{
+private :
+ typedef typename return_type<pythagoras<Point1, Point2, CalculationType> >::type return_type;
+public :
+ template <typename T>
+ static inline return_type apply(pythagoras<Point1, Point2, CalculationType> const& , T const& value)
+ {
+ return return_type(value);
+ }
+};
+
+
+// Specializations for comparable::pythagoras
+template <typename Point1, typename Point2, typename CalculationType>
+struct tag<comparable::pythagoras<Point1, Point2, CalculationType> >
+{
+ typedef strategy_tag_distance_point_point type;
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct return_type<comparable::pythagoras<Point1, Point2, CalculationType> >
+{
+ typedef typename comparable::pythagoras<Point1, Point2, CalculationType>::calculation_type type;
+};
+
+
+
+
+template
+<
+ typename Point1,
+ typename Point2,
+ typename CalculationType,
+ typename P1,
+ typename P2
+>
+struct similar_type<comparable::pythagoras<Point1, Point2, CalculationType>, P1, P2>
+{
+ typedef comparable::pythagoras<P1, P2, CalculationType> type;
+};
+
+
+template
+<
+ typename Point1,
+ typename Point2,
+ typename CalculationType,
+ typename P1,
+ typename P2
+>
+struct get_similar<comparable::pythagoras<Point1, Point2, CalculationType>, P1, P2>
+{
+ static inline typename similar_type
+ <
+ comparable::pythagoras<Point1, Point2, CalculationType>, P1, P2
+ >::type apply(comparable::pythagoras<Point1, Point2, CalculationType> const& )
+ {
+ return comparable::pythagoras<P1, P2, CalculationType>();
+ }
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct comparable_type<comparable::pythagoras<Point1, Point2, CalculationType> >
+{
+ typedef comparable::pythagoras<Point1, Point2, CalculationType> type;
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct get_comparable<comparable::pythagoras<Point1, Point2, CalculationType> >
+{
+ typedef comparable::pythagoras<Point1, Point2, CalculationType> comparable_type;
+public :
+ static inline comparable_type apply(comparable::pythagoras<Point1, Point2, CalculationType> const& )
+ {
+ return comparable_type();
+ }
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct result_from_distance<comparable::pythagoras<Point1, Point2, CalculationType> >
+{
+private :
+ typedef typename return_type<comparable::pythagoras<Point1, Point2, CalculationType> >::type return_type;
+public :
+ template <typename T>
+ static inline return_type apply(comparable::pythagoras<Point1, Point2, CalculationType> const& , T const& value)
+ {
+ return_type const v = value;
+ return v * v;
+ }
+};
+
+
+template <typename Point1, typename Point2>
+struct default_strategy<point_tag, Point1, Point2, cartesian_tag, cartesian_tag, void>
+{
+ typedef pythagoras<Point1, Point2> type;
+};
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::distance
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP
diff --git a/boost/geometry/strategies/cartesian/point_in_box.hpp b/boost/geometry/strategies/cartesian/point_in_box.hpp
new file mode 100644
index 000000000..275f7550e
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/point_in_box.hpp
@@ -0,0 +1,172 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP
+
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/strategies/covered_by.hpp>
+#include <boost/geometry/strategies/within.hpp>
+
+
+namespace boost { namespace geometry { namespace strategy
+{
+
+namespace within
+{
+
+
+struct within_range
+{
+ template <typename Value1, typename Value2>
+ static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)
+ {
+ return value > min_value && value < max_value;
+ }
+};
+
+
+struct covered_by_range
+{
+ template <typename Value1, typename Value2>
+ static inline bool apply(Value1 const& value, Value2 const& min_value, Value2 const& max_value)
+ {
+ return value >= min_value && value <= max_value;
+ }
+};
+
+
+template
+<
+ typename SubStrategy,
+ typename Point,
+ typename Box,
+ std::size_t Dimension,
+ std::size_t DimensionCount
+>
+struct relate_point_box_loop
+{
+ static inline bool apply(Point const& point, Box const& box)
+ {
+ if (! SubStrategy::apply(get<Dimension>(point),
+ get<min_corner, Dimension>(box),
+ get<max_corner, Dimension>(box))
+ )
+ {
+ return false;
+ }
+
+ return relate_point_box_loop
+ <
+ SubStrategy,
+ Point, Box,
+ Dimension + 1, DimensionCount
+ >::apply(point, box);
+ }
+};
+
+
+template
+<
+ typename SubStrategy,
+ typename Point,
+ typename Box,
+ std::size_t DimensionCount
+>
+struct relate_point_box_loop<SubStrategy, Point, Box, DimensionCount, DimensionCount>
+{
+ static inline bool apply(Point const& , Box const& )
+ {
+ return true;
+ }
+};
+
+
+template
+<
+ typename Point,
+ typename Box,
+ typename SubStrategy = within_range
+>
+struct point_in_box
+{
+ static inline bool apply(Point const& point, Box const& box)
+ {
+ return relate_point_box_loop
+ <
+ SubStrategy,
+ Point, Box,
+ 0, dimension<Point>::type::value
+ >::apply(point, box);
+ }
+};
+
+
+} // namespace within
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+namespace within { namespace services
+{
+
+template <typename Point, typename Box>
+struct default_strategy
+ <
+ point_tag, box_tag,
+ point_tag, areal_tag,
+ cartesian_tag, cartesian_tag,
+ Point, Box
+ >
+{
+ typedef within::point_in_box<Point, Box> type;
+};
+
+
+}} // namespace within::services
+
+
+namespace covered_by { namespace services
+{
+
+
+template <typename Point, typename Box>
+struct default_strategy
+ <
+ point_tag, box_tag,
+ point_tag, areal_tag,
+ cartesian_tag, cartesian_tag,
+ Point, Box
+ >
+{
+ typedef within::point_in_box
+ <
+ Point, Box,
+ within::covered_by_range
+ > type;
+};
+
+
+}} // namespace covered_by::services
+
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}}} // namespace boost::geometry::strategy
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_BOX_HPP
diff --git a/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp b/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp
new file mode 100644
index 000000000..94da5cc67
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp
@@ -0,0 +1,124 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP
+
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace within
+{
+
+/*!
+\brief Within detection using cross counting,
+\ingroup strategies
+\tparam Point \tparam_point
+\tparam PointOfSegment \tparam_segment_point
+\tparam CalculationType \tparam_calculation
+\see http://tog.acm.org/resources/GraphicsGems/gemsiv/ptpoly_haines/ptinpoly.c
+\note Does NOT work correctly for point ON border
+\qbk{
+[heading See also]
+[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]
+}
+ */
+
+template
+<
+ typename Point,
+ typename PointOfSegment = Point,
+ typename CalculationType = void
+>
+class crossings_multiply
+{
+ typedef typename select_calculation_type
+ <
+ Point,
+ PointOfSegment,
+ CalculationType
+ >::type calculation_type;
+
+ class flags
+ {
+ bool inside_flag;
+ bool first;
+ bool yflag0;
+
+ public :
+
+ friend class crossings_multiply;
+
+ inline flags()
+ : inside_flag(false)
+ , first(true)
+ , yflag0(false)
+ {}
+ };
+
+public :
+
+ typedef Point point_type;
+ typedef PointOfSegment segment_point_type;
+ typedef flags state_type;
+
+ static inline bool apply(Point const& point,
+ PointOfSegment const& seg1, PointOfSegment const& seg2,
+ flags& state)
+ {
+ calculation_type const tx = get<0>(point);
+ calculation_type const ty = get<1>(point);
+ calculation_type const x0 = get<0>(seg1);
+ calculation_type const y0 = get<1>(seg1);
+ calculation_type const x1 = get<0>(seg2);
+ calculation_type const y1 = get<1>(seg2);
+
+ if (state.first)
+ {
+ state.first = false;
+ state.yflag0 = y0 >= ty;
+ }
+
+
+ bool yflag1 = y1 >= ty;
+ if (state.yflag0 != yflag1)
+ {
+ if ( ((y1-ty) * (x0-x1) >= (x1-tx) * (y0-y1)) == yflag1 )
+ {
+ state.inside_flag = ! state.inside_flag;
+ }
+ }
+ state.yflag0 = yflag1;
+ return true;
+ }
+
+ static inline int result(flags const& state)
+ {
+ return state.inside_flag ? 1 : -1;
+ }
+};
+
+
+
+}} // namespace strategy::within
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_CROSSINGS_MULTIPLY_HPP
diff --git a/boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp b/boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp
new file mode 100644
index 000000000..a774d3c52
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp
@@ -0,0 +1,118 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP
+
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace within
+{
+
+/*!
+\brief Within detection using cross counting
+\ingroup strategies
+\tparam Point \tparam_point
+\tparam PointOfSegment \tparam_segment_point
+\tparam CalculationType \tparam_calculation
+\author adapted from Randolph Franklin algorithm
+\author Barend and Maarten, 1995
+\author Revised for templatized library, Barend Gehrels, 2007
+\return true if point is in ring, works for closed rings in both directions
+\note Does NOT work correctly for point ON border
+
+\qbk{
+[heading See also]
+[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]
+}
+ */
+
+template
+<
+ typename Point,
+ typename PointOfSegment = Point,
+ typename CalculationType = void
+>
+class franklin
+{
+ typedef typename select_calculation_type
+ <
+ Point,
+ PointOfSegment,
+ CalculationType
+ >::type calculation_type;
+
+ /*! subclass to keep state */
+ class crossings
+ {
+ bool crosses;
+
+ public :
+
+ friend class franklin;
+ inline crossings()
+ : crosses(false)
+ {}
+ };
+
+public :
+
+ typedef Point point_type;
+ typedef PointOfSegment segment_point_type;
+ typedef crossings state_type;
+
+ static inline bool apply(Point const& point,
+ PointOfSegment const& seg1, PointOfSegment const& seg2,
+ crossings& state)
+ {
+ calculation_type const& px = get<0>(point);
+ calculation_type const& py = get<1>(point);
+ calculation_type const& x1 = get<0>(seg1);
+ calculation_type const& y1 = get<1>(seg1);
+ calculation_type const& x2 = get<0>(seg2);
+ calculation_type const& y2 = get<1>(seg2);
+
+ if (
+ ( (y2 <= py && py < y1) || (y1 <= py && py < y2) )
+ && (px < (x1 - x2) * (py - y2) / (y1 - y2) + x2)
+ )
+ {
+ state.crosses = ! state.crosses;
+ }
+ return true;
+ }
+
+ static inline int result(crossings const& state)
+ {
+ return state.crosses ? 1 : -1;
+ }
+};
+
+
+
+}} // namespace strategy::within
+
+
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_POINT_IN_POLY_FRANKLIN_HPP
diff --git a/boost/geometry/strategies/cartesian/side_by_triangle.hpp b/boost/geometry/strategies/cartesian/side_by_triangle.hpp
new file mode 100644
index 000000000..967090c50
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/side_by_triangle.hpp
@@ -0,0 +1,121 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/arithmetic/determinant.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+#include <boost/geometry/strategies/side.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace side
+{
+
+/*!
+\brief Check at which side of a segment a point lies:
+ left of segment (> 0), right of segment (< 0), on segment (0)
+\ingroup strategies
+\tparam CalculationType \tparam_calculation
+ */
+template <typename CalculationType = void>
+class side_by_triangle
+{
+public :
+
+ // Template member function, because it is not always trivial
+ // or convenient to explicitly mention the typenames in the
+ // strategy-struct itself.
+
+ // Types can be all three different. Therefore it is
+ // not implemented (anymore) as "segment"
+
+ template <typename P1, typename P2, typename P>
+ static inline int apply(P1 const& p1, P2 const& p2, P const& p)
+ {
+ typedef typename boost::mpl::if_c
+ <
+ boost::is_void<CalculationType>::type::value,
+ typename select_most_precise
+ <
+ typename select_most_precise
+ <
+ typename coordinate_type<P1>::type,
+ typename coordinate_type<P2>::type
+ >::type,
+ typename coordinate_type<P>::type
+ >::type,
+ CalculationType
+ >::type coordinate_type;
+
+ coordinate_type const x = get<0>(p);
+ coordinate_type const y = get<1>(p);
+
+ coordinate_type const sx1 = get<0>(p1);
+ coordinate_type const sy1 = get<1>(p1);
+ coordinate_type const sx2 = get<0>(p2);
+ coordinate_type const sy2 = get<1>(p2);
+
+ // Promote float->double, small int->int
+ typedef typename select_most_precise
+ <
+ coordinate_type,
+ double
+ >::type promoted_type;
+
+ promoted_type const dx = sx2 - sx1;
+ promoted_type const dy = sy2 - sy1;
+ promoted_type const dpx = x - sx1;
+ promoted_type const dpy = y - sy1;
+
+ promoted_type const s
+ = geometry::detail::determinant<promoted_type>
+ (
+ dx, dy,
+ dpx, dpy
+ );
+
+ promoted_type const zero = promoted_type();
+ return math::equals(s, zero) ? 0
+ : s > zero ? 1
+ : -1;
+ }
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template <typename CalculationType>
+struct default_strategy<cartesian_tag, CalculationType>
+{
+ typedef side_by_triangle<CalculationType> type;
+};
+
+}
+#endif
+
+}} // namespace strategy::side
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
diff --git a/boost/geometry/strategies/centroid.hpp b/boost/geometry/strategies/centroid.hpp
new file mode 100644
index 000000000..4963e6b40
--- /dev/null
+++ b/boost/geometry/strategies/centroid.hpp
@@ -0,0 +1,72 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CENTROID_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CENTROID_HPP
+
+
+#include <cstddef>
+
+#include <boost/mpl/assert.hpp>
+
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/strategies/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace centroid
+{
+
+struct not_applicable_strategy
+{
+};
+
+
+namespace services
+{
+
+/*!
+ \brief Traits class binding a centroid calculation strategy to a coordinate system
+ \ingroup centroid
+ \tparam CsTag tag of coordinate system, for specialization
+ \tparam GeometryTag tag of geometry, for specialization
+ \tparam Dimension dimension of geometry, for specialization
+ \tparam Point point-type
+ \tparam Geometry
+*/
+template
+<
+ typename CsTag,
+ typename GeometryTag,
+ std::size_t Dimension,
+ typename Point,
+ typename Geometry
+>
+struct default_strategy
+{
+ typedef not_applicable_strategy type;
+};
+
+
+} // namespace services
+
+
+}} // namespace strategy::centroid
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CENTROID_HPP
diff --git a/boost/geometry/strategies/compare.hpp b/boost/geometry/strategies/compare.hpp
new file mode 100644
index 000000000..295831922
--- /dev/null
+++ b/boost/geometry/strategies/compare.hpp
@@ -0,0 +1,172 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_COMPARE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_COMPARE_HPP
+
+#include <cstddef>
+#include <functional>
+
+#include <boost/mpl/if.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+
+#include <boost/geometry/strategies/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Traits class binding a comparing strategy to a coordinate system
+ \ingroup util
+ \tparam Tag tag of coordinate system of point-type
+ \tparam Direction direction to compare on: 1 for less (-> ascending order)
+ and -1 for greater (-> descending order)
+ \tparam Point point-type
+ \tparam CoordinateSystem coordinate sytem of point
+ \tparam Dimension: the dimension to compare on
+*/
+template
+<
+ typename Tag,
+ int Direction,
+ typename Point,
+ typename CoordinateSystem,
+ std::size_t Dimension
+>
+struct strategy_compare
+{
+ typedef strategy::not_implemented type;
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+// For compare we add defaults specializations,
+// because they defaultly redirect to std::less / greater / equal_to
+template
+<
+ typename Tag,
+ typename Point,
+ typename CoordinateSystem,
+ std::size_t Dimension
+>
+struct strategy_compare<Tag, 1, Point, CoordinateSystem, Dimension>
+{
+ typedef std::less<typename coordinate_type<Point>::type> type;
+};
+
+
+template
+<
+ typename Tag,
+ typename Point,
+ typename CoordinateSystem,
+ std::size_t Dimension
+>
+struct strategy_compare<Tag, -1, Point, CoordinateSystem, Dimension>
+{
+ typedef std::greater<typename coordinate_type<Point>::type> type;
+};
+
+
+template
+<
+ typename Tag,
+ typename Point,
+ typename CoordinateSystem,
+ std::size_t Dimension
+>
+struct strategy_compare<Tag, 0, Point, CoordinateSystem, Dimension>
+{
+ typedef std::equal_to<typename coordinate_type<Point>::type> type;
+};
+
+
+#endif
+
+
+namespace strategy { namespace compare
+{
+
+
+/*!
+ \brief Default strategy, indicates the default strategy for comparisons
+ \details The default strategy for comparisons defer in most cases
+ to std::less (for ascending) and std::greater (for descending).
+ However, if a spherical coordinate system is used, and comparison
+ is done on longitude, it will take another strategy handling circular
+*/
+struct default_strategy {};
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Type>
+struct is_default : boost::false_type
+{};
+
+
+template <>
+struct is_default<default_strategy> : boost::true_type
+{};
+
+
+/*!
+ \brief Meta-function to select strategy
+ \details If "default_strategy" is specified, it will take the
+ traits-registered class for the specified coordinate system.
+ If another strategy is explicitly specified, it takes that one.
+*/
+template
+<
+ typename Strategy,
+ int Direction,
+ typename Point,
+ std::size_t Dimension
+>
+struct select_strategy
+{
+ typedef typename
+ boost::mpl::if_
+ <
+ is_default<Strategy>,
+ typename strategy_compare
+ <
+ typename cs_tag<Point>::type,
+ Direction,
+ Point,
+ typename coordinate_system<Point>::type,
+ Dimension
+ >::type,
+ Strategy
+ >::type type;
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace strategy::compare
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_COMPARE_HPP
diff --git a/boost/geometry/strategies/concepts/area_concept.hpp b/boost/geometry/strategies/concepts/area_concept.hpp
new file mode 100644
index 000000000..75821b52a
--- /dev/null
+++ b/boost/geometry/strategies/concepts/area_concept.hpp
@@ -0,0 +1,75 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_AREA_CONCEPT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_AREA_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+
+
+namespace boost { namespace geometry { namespace concept
+{
+
+
+/*!
+ \brief Checks strategy for area
+ \ingroup area
+*/
+template <typename Strategy>
+class AreaStrategy
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ // 1) must define state_type,
+ typedef typename Strategy::state_type state_type;
+
+ // 2) must define return_type,
+ typedef typename Strategy::return_type return_type;
+
+ // 3) must define point_type, of polygon (segments)
+ typedef typename Strategy::segment_point_type spoint_type;
+
+ struct check_methods
+ {
+ static void apply()
+ {
+ Strategy const* str = 0;
+ state_type *st = 0;
+
+ // 4) must implement a method apply with the following signature
+ spoint_type const* sp = 0;
+ str->apply(*sp, *sp, *st);
+
+ // 5) must implement a static method result with the following signature
+ return_type r = str->result(*st);
+
+ boost::ignore_unused_variable_warning(r);
+ boost::ignore_unused_variable_warning(str);
+ }
+ };
+
+public :
+ BOOST_CONCEPT_USAGE(AreaStrategy)
+ {
+ check_methods::apply();
+ }
+
+#endif
+};
+
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_AREA_CONCEPT_HPP
diff --git a/boost/geometry/strategies/concepts/centroid_concept.hpp b/boost/geometry/strategies/concepts/centroid_concept.hpp
new file mode 100644
index 000000000..f493ef681
--- /dev/null
+++ b/boost/geometry/strategies/concepts/centroid_concept.hpp
@@ -0,0 +1,78 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CENTROID_CONCEPT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CENTROID_CONCEPT_HPP
+
+
+
+#include <boost/concept_check.hpp>
+
+
+namespace boost { namespace geometry { namespace concept
+{
+
+
+/*!
+ \brief Checks strategy for centroid
+ \ingroup centroid
+*/
+template <typename Strategy>
+class CentroidStrategy
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ // 1) must define state_type,
+ typedef typename Strategy::state_type state_type;
+
+ // 2) must define point_type,
+ typedef typename Strategy::point_type point_type;
+
+ // 3) must define point_type, of polygon (segments)
+ typedef typename Strategy::segment_point_type spoint_type;
+
+ struct check_methods
+ {
+ static void apply()
+ {
+ Strategy *str = 0;
+ state_type *st = 0;
+
+ // 4) must implement a static method apply,
+ // getting two segment-points
+ spoint_type const* sp = 0;
+ str->apply(*sp, *sp, *st);
+
+ // 5) must implement a static method result
+ // getting the centroid
+ point_type *c = 0;
+ bool r = str->result(*st, *c);
+
+ boost::ignore_unused_variable_warning(str);
+ boost::ignore_unused_variable_warning(r);
+ }
+ };
+
+public :
+ BOOST_CONCEPT_USAGE(CentroidStrategy)
+ {
+ check_methods::apply();
+ }
+#endif
+};
+
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CENTROID_CONCEPT_HPP
diff --git a/boost/geometry/strategies/concepts/convex_hull_concept.hpp b/boost/geometry/strategies/concepts/convex_hull_concept.hpp
new file mode 100644
index 000000000..b31f0caa4
--- /dev/null
+++ b/boost/geometry/strategies/concepts/convex_hull_concept.hpp
@@ -0,0 +1,75 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CONVEX_HULL_CONCEPT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CONVEX_HULL_CONCEPT_HPP
+
+
+#include <vector>
+
+#include <boost/concept_check.hpp>
+
+
+namespace boost { namespace geometry { namespace concept
+{
+
+
+/*!
+ \brief Checks strategy for convex_hull
+ \ingroup convex_hull
+*/
+template <typename Strategy>
+class ConvexHullStrategy
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ // 1) must define state_type
+ typedef typename Strategy::state_type state_type;
+
+ // 2) must define point_type
+ typedef typename Strategy::point_type point_type;
+
+ // 3) must define geometry_type
+ typedef typename Strategy::geometry_type geometry_type;
+
+ struct check_methods
+ {
+ static void apply()
+ {
+ Strategy const* str;
+
+ state_type* st;
+ geometry_type* sp;
+ std::vector<point_type> *v;
+
+ // 4) must implement a method apply, iterating over a range
+ str->apply(*sp, *st);
+
+ // 5) must implement a method result, with an output iterator
+ str->result(*st, std::back_inserter(*v), true);
+ }
+ };
+
+public :
+ BOOST_CONCEPT_USAGE(ConvexHullStrategy)
+ {
+ check_methods::apply();
+ }
+#endif
+};
+
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CONVEX_HULL_CONCEPT_HPP
diff --git a/boost/geometry/strategies/concepts/distance_concept.hpp b/boost/geometry/strategies/concepts/distance_concept.hpp
new file mode 100644
index 000000000..ba347d015
--- /dev/null
+++ b/boost/geometry/strategies/concepts/distance_concept.hpp
@@ -0,0 +1,206 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP
+
+#include <vector>
+#include <iterator>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/geometry/util/parameter_type_of.hpp>
+
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/geometries/segment.hpp>
+
+
+namespace boost { namespace geometry { namespace concept
+{
+
+
+/*!
+ \brief Checks strategy for point-segment-distance
+ \ingroup distance
+*/
+template <typename Strategy>
+struct PointDistanceStrategy
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+private :
+
+ struct checker
+ {
+ template <typename ApplyMethod>
+ static void apply(ApplyMethod const&)
+ {
+ // 1: inspect and define both arguments of apply
+ typedef typename parameter_type_of
+ <
+ ApplyMethod, 0
+ >::type ptype1;
+
+ typedef typename parameter_type_of
+ <
+ ApplyMethod, 1
+ >::type ptype2;
+
+ // 2) check if apply-arguments fulfill point concept
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::ConstPoint<ptype1>)
+ );
+
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::ConstPoint<ptype2>)
+ );
+
+
+ // 3) must define meta-function return_type
+ typedef typename strategy::distance::services::return_type<Strategy>::type rtype;
+
+ // 4) must define meta-function "similar_type"
+ typedef typename strategy::distance::services::similar_type
+ <
+ Strategy, ptype2, ptype1
+ >::type stype;
+
+ // 5) must define meta-function "comparable_type"
+ typedef typename strategy::distance::services::comparable_type
+ <
+ Strategy
+ >::type ctype;
+
+ // 6) must define meta-function "tag"
+ typedef typename strategy::distance::services::tag
+ <
+ Strategy
+ >::type tag;
+
+ // 7) must implement apply with arguments
+ Strategy* str = 0;
+ ptype1 *p1 = 0;
+ ptype2 *p2 = 0;
+ rtype r = str->apply(*p1, *p2);
+
+ // 8) must define (meta)struct "get_similar" with apply
+ stype s = strategy::distance::services::get_similar
+ <
+ Strategy,
+ ptype2, ptype1
+ >::apply(*str);
+
+ // 9) must define (meta)struct "get_comparable" with apply
+ ctype c = strategy::distance::services::get_comparable
+ <
+ Strategy
+ >::apply(*str);
+
+ // 10) must define (meta)struct "result_from_distance" with apply
+ r = strategy::distance::services::result_from_distance
+ <
+ Strategy
+ >::apply(*str, 1.0);
+
+ boost::ignore_unused_variable_warning(str);
+ boost::ignore_unused_variable_warning(s);
+ boost::ignore_unused_variable_warning(c);
+ boost::ignore_unused_variable_warning(r);
+ }
+ };
+
+
+
+public :
+ BOOST_CONCEPT_USAGE(PointDistanceStrategy)
+ {
+ checker::apply(&Strategy::apply);
+ }
+#endif
+};
+
+
+/*!
+ \brief Checks strategy for point-segment-distance
+ \ingroup strategy_concepts
+*/
+template <typename Strategy>
+struct PointSegmentDistanceStrategy
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+private :
+
+ struct checker
+ {
+ template <typename ApplyMethod>
+ static void apply(ApplyMethod const&)
+ {
+ typedef typename parameter_type_of
+ <
+ ApplyMethod, 0
+ >::type ptype;
+
+ typedef typename parameter_type_of
+ <
+ ApplyMethod, 1
+ >::type sptype;
+
+ // 2) check if apply-arguments fulfill point concept
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::ConstPoint<ptype>)
+ );
+
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::ConstPoint<sptype>)
+ );
+
+
+ // 3) must define meta-function return_type
+ typedef typename strategy::distance::services::return_type<Strategy>::type rtype;
+
+ // 4) must define underlying point-distance-strategy
+ typedef typename strategy::distance::services::strategy_point_point<Strategy>::type stype;
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::PointDistanceStrategy<stype>)
+ );
+
+
+ Strategy *str = 0;
+ ptype *p = 0;
+ sptype *sp1 = 0;
+ sptype *sp2 = 0;
+
+ rtype r = str->apply(*p, *sp1, *sp2);
+
+ boost::ignore_unused_variable_warning(str);
+ boost::ignore_unused_variable_warning(r);
+ }
+ };
+
+public :
+ BOOST_CONCEPT_USAGE(PointSegmentDistanceStrategy)
+ {
+ checker::apply(&Strategy::apply);
+ }
+#endif
+};
+
+
+}}} // namespace boost::geometry::concept
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP
diff --git a/boost/geometry/strategies/concepts/segment_intersect_concept.hpp b/boost/geometry/strategies/concepts/segment_intersect_concept.hpp
new file mode 100644
index 000000000..43bcccf37
--- /dev/null
+++ b/boost/geometry/strategies/concepts/segment_intersect_concept.hpp
@@ -0,0 +1,78 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SEGMENT_INTERSECT_CONCEPT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SEGMENT_INTERSECT_CONCEPT_HPP
+
+
+//NOT FINISHED!
+
+#include <boost/concept_check.hpp>
+
+
+namespace boost { namespace geometry { namespace concept
+{
+
+
+/*!
+ \brief Checks strategy for segment intersection
+ \ingroup segment_intersection
+*/
+template <typename Strategy>
+class SegmentIntersectStrategy
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ // 1) must define return_type
+ typedef typename Strategy::return_type return_type;
+
+ // 2) must define point_type (of segment points)
+ //typedef typename Strategy::point_type point_type;
+
+ // 3) must define segment_type 1 and 2 (of segment points)
+ typedef typename Strategy::segment_type1 segment_type1;
+ typedef typename Strategy::segment_type2 segment_type2;
+
+
+ struct check_methods
+ {
+ static void apply()
+ {
+ Strategy const* str;
+
+ return_type* rt;
+ //point_type const* p;
+ segment_type1 const* s1;
+ segment_type2 const* s2;
+
+ // 4) must implement a method apply
+ // having two segments
+ *rt = str->apply(*s1, *s2);
+
+ }
+ };
+
+
+public :
+ BOOST_CONCEPT_USAGE(SegmentIntersectStrategy)
+ {
+ check_methods::apply();
+ }
+#endif
+};
+
+
+
+}}} // namespace boost::geometry::concept
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SEGMENT_INTERSECT_CONCEPT_HPP
diff --git a/boost/geometry/strategies/concepts/simplify_concept.hpp b/boost/geometry/strategies/concepts/simplify_concept.hpp
new file mode 100644
index 000000000..92e5156b5
--- /dev/null
+++ b/boost/geometry/strategies/concepts/simplify_concept.hpp
@@ -0,0 +1,109 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SIMPLIFY_CONCEPT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SIMPLIFY_CONCEPT_HPP
+
+#include <vector>
+#include <iterator>
+
+#include <boost/concept_check.hpp>
+
+#include <boost/geometry/strategies/concepts/distance_concept.hpp>
+
+
+namespace boost { namespace geometry { namespace concept
+{
+
+
+/*!
+ \brief Checks strategy for simplify
+ \ingroup simplify
+*/
+template <typename Strategy>
+struct SimplifyStrategy
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+private :
+
+ // 1) must define distance_strategy_type,
+ // defining point-segment distance strategy (to be checked)
+ typedef typename Strategy::distance_strategy_type ds_type;
+
+
+ struct checker
+ {
+ template <typename ApplyMethod>
+ static void apply(ApplyMethod const&)
+ {
+ namespace ft = boost::function_types;
+ typedef typename ft::parameter_types
+ <
+ ApplyMethod
+ >::type parameter_types;
+
+ typedef typename boost::mpl::if_
+ <
+ ft::is_member_function_pointer<ApplyMethod>,
+ boost::mpl::int_<1>,
+ boost::mpl::int_<0>
+ >::type base_index;
+
+ // 1: inspect and define both arguments of apply
+ typedef typename boost::remove_const
+ <
+ typename boost::remove_reference
+ <
+ typename boost::mpl::at
+ <
+ parameter_types,
+ base_index
+ >::type
+ >::type
+ >::type point_type;
+
+
+
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::PointSegmentDistanceStrategy<ds_type>)
+ );
+
+ Strategy *str = 0;
+ std::vector<point_type> const* v1 = 0;
+ std::vector<point_type> * v2 = 0;
+
+ // 2) must implement method apply with arguments
+ // - Range
+ // - OutputIterator
+ // - floating point value
+ str->apply(*v1, std::back_inserter(*v2), 1.0);
+
+ boost::ignore_unused_variable_warning(str);
+ }
+ };
+
+public :
+ BOOST_CONCEPT_USAGE(SimplifyStrategy)
+ {
+ checker::apply(&ds_type::apply);
+
+ }
+#endif
+};
+
+
+
+}}} // namespace boost::geometry::concept
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SIMPLIFY_CONCEPT_HPP
diff --git a/boost/geometry/strategies/concepts/within_concept.hpp b/boost/geometry/strategies/concepts/within_concept.hpp
new file mode 100644
index 000000000..a9684b98e
--- /dev/null
+++ b/boost/geometry/strategies/concepts/within_concept.hpp
@@ -0,0 +1,291 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP
+
+
+
+#include <boost/concept_check.hpp>
+#include <boost/function_types/result_type.hpp>
+
+#include <boost/geometry/util/parameter_type_of.hpp>
+
+
+namespace boost { namespace geometry { namespace concept
+{
+
+
+/*!
+\brief Checks strategy for within (point-in-polygon)
+\ingroup within
+*/
+template <typename Strategy>
+class WithinStrategyPolygonal
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ // 1) must define state_type
+ typedef typename Strategy::state_type state_type;
+
+ struct checker
+ {
+ template <typename ApplyMethod, typename ResultMethod>
+ static void apply(ApplyMethod const&, ResultMethod const& )
+ {
+ typedef typename parameter_type_of
+ <
+ ApplyMethod, 0
+ >::type point_type;
+ typedef typename parameter_type_of
+ <
+ ApplyMethod, 1
+ >::type segment_point_type;
+
+ // CHECK: apply-arguments should both fulfill point concept
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::ConstPoint<point_type>)
+ );
+
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::ConstPoint<segment_point_type>)
+ );
+
+ // CHECK: return types (result: int, apply: bool)
+ BOOST_MPL_ASSERT_MSG
+ (
+ (boost::is_same
+ <
+ bool, typename boost::function_types::result_type<ApplyMethod>::type
+ >::type::value),
+ WRONG_RETURN_TYPE_OF_APPLY
+ , (bool)
+ );
+ BOOST_MPL_ASSERT_MSG
+ (
+ (boost::is_same
+ <
+ int, typename boost::function_types::result_type<ResultMethod>::type
+ >::type::value),
+ WRONG_RETURN_TYPE_OF_RESULT
+ , (int)
+ );
+
+
+ // CHECK: calling method apply and result
+ Strategy const* str = 0;
+ state_type* st = 0;
+ point_type const* p = 0;
+ segment_point_type const* sp = 0;
+
+ bool b = str->apply(*p, *sp, *sp, *st);
+ int r = str->result(*st);
+
+ boost::ignore_unused_variable_warning(r);
+ boost::ignore_unused_variable_warning(b);
+ boost::ignore_unused_variable_warning(str);
+ }
+ };
+
+
+public :
+ BOOST_CONCEPT_USAGE(WithinStrategyPolygonal)
+ {
+ checker::apply(&Strategy::apply, &Strategy::result);
+ }
+#endif
+};
+
+template <typename Strategy>
+class WithinStrategyPointBox
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ struct checker
+ {
+ template <typename ApplyMethod>
+ static void apply(ApplyMethod const&)
+ {
+ typedef typename parameter_type_of
+ <
+ ApplyMethod, 0
+ >::type point_type;
+ typedef typename parameter_type_of
+ <
+ ApplyMethod, 1
+ >::type box_type;
+
+ // CHECK: apply-arguments should fulfill point/box concept
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::ConstPoint<point_type>)
+ );
+
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::ConstBox<box_type>)
+ );
+
+ // CHECK: return types (apply: bool)
+ BOOST_MPL_ASSERT_MSG
+ (
+ (boost::is_same
+ <
+ bool,
+ typename boost::function_types::result_type<ApplyMethod>::type
+ >::type::value),
+ WRONG_RETURN_TYPE
+ , (bool)
+ );
+
+
+ // CHECK: calling method apply
+ Strategy const* str = 0;
+ point_type const* p = 0;
+ box_type const* bx = 0;
+
+ bool b = str->apply(*p, *bx);
+
+ boost::ignore_unused_variable_warning(b);
+ boost::ignore_unused_variable_warning(str);
+ }
+ };
+
+
+public :
+ BOOST_CONCEPT_USAGE(WithinStrategyPointBox)
+ {
+ checker::apply(&Strategy::apply);
+ }
+#endif
+};
+
+template <typename Strategy>
+class WithinStrategyBoxBox
+{
+#ifndef DOXYGEN_NO_CONCEPT_MEMBERS
+
+ struct checker
+ {
+ template <typename ApplyMethod>
+ static void apply(ApplyMethod const&)
+ {
+ typedef typename parameter_type_of
+ <
+ ApplyMethod, 0
+ >::type box_type1;
+ typedef typename parameter_type_of
+ <
+ ApplyMethod, 1
+ >::type box_type2;
+
+ // CHECK: apply-arguments should both fulfill box concept
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::ConstBox<box_type1>)
+ );
+
+ BOOST_CONCEPT_ASSERT
+ (
+ (concept::ConstBox<box_type2>)
+ );
+
+ // CHECK: return types (apply: bool)
+ BOOST_MPL_ASSERT_MSG
+ (
+ (boost::is_same
+ <
+ bool,
+ typename boost::function_types::result_type<ApplyMethod>::type
+ >::type::value),
+ WRONG_RETURN_TYPE
+ , (bool)
+ );
+
+
+ // CHECK: calling method apply
+ Strategy const* str = 0;
+ box_type1 const* b1 = 0;
+ box_type2 const* b2 = 0;
+
+ bool b = str->apply(*b1, *b2);
+
+ boost::ignore_unused_variable_warning(b);
+ boost::ignore_unused_variable_warning(str);
+ }
+ };
+
+
+public :
+ BOOST_CONCEPT_USAGE(WithinStrategyBoxBox)
+ {
+ checker::apply(&Strategy::apply);
+ }
+#endif
+};
+
+// So now: boost::geometry::concept::within
+namespace within
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename FirstTag, typename SecondTag, typename CastedTag, typename Strategy>
+struct check_within
+{};
+
+
+template <typename AnyTag, typename Strategy>
+struct check_within<point_tag, AnyTag, areal_tag, Strategy>
+{
+ BOOST_CONCEPT_ASSERT( (WithinStrategyPolygonal<Strategy>) );
+};
+
+
+template <typename Strategy>
+struct check_within<point_tag, box_tag, areal_tag, Strategy>
+{
+ BOOST_CONCEPT_ASSERT( (WithinStrategyPointBox<Strategy>) );
+};
+
+template <typename Strategy>
+struct check_within<box_tag, box_tag, areal_tag, Strategy>
+{
+ BOOST_CONCEPT_ASSERT( (WithinStrategyBoxBox<Strategy>) );
+};
+
+
+} // namespace dispatch
+#endif
+
+
+/*!
+\brief Checks, in compile-time, the concept of any within-strategy
+\ingroup concepts
+*/
+template <typename FirstTag, typename SecondTag, typename CastedTag, typename Strategy>
+inline void check()
+{
+ dispatch::check_within<FirstTag, SecondTag, CastedTag, Strategy> c;
+ boost::ignore_unused_variable_warning(c);
+}
+
+
+}}}} // namespace boost::geometry::concept::within
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP
diff --git a/boost/geometry/strategies/convex_hull.hpp b/boost/geometry/strategies/convex_hull.hpp
new file mode 100644
index 000000000..f4edc5ba3
--- /dev/null
+++ b/boost/geometry/strategies/convex_hull.hpp
@@ -0,0 +1,47 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP
+
+#include <boost/geometry/strategies/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+
+
+/*!
+ \brief Traits class binding a convex hull calculation strategy to a coordinate system
+ \ingroup convex_hull
+ \tparam Tag tag of coordinate system
+ \tparam Geometry the geometry type (hull operates internally per hull over geometry)
+ \tparam Point point-type of output points
+*/
+template
+<
+ typename Geometry1,
+ typename Point,
+ typename CsTag = typename cs_tag<Point>::type
+>
+struct strategy_convex_hull
+{
+ typedef strategy::not_implemented type;
+};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_HPP
diff --git a/boost/geometry/strategies/covered_by.hpp b/boost/geometry/strategies/covered_by.hpp
new file mode 100644
index 000000000..a5aae7703
--- /dev/null
+++ b/boost/geometry/strategies/covered_by.hpp
@@ -0,0 +1,72 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_COVERED_BY_HPP
+#define BOOST_GEOMETRY_STRATEGIES_COVERED_BY_HPP
+
+#include <boost/mpl/assert.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace covered_by
+{
+
+
+namespace services
+{
+
+/*!
+\brief Traits class binding a covered_by determination strategy to a coordinate system
+\ingroup covered_by
+\tparam TagContained tag (possibly casted) of point-type
+\tparam TagContained tag (possibly casted) of (possibly) containing type
+\tparam CsTagContained tag of coordinate system of point-type
+\tparam CsTagContaining tag of coordinate system of (possibly) containing type
+\tparam Geometry geometry-type of input (often point, or box)
+\tparam GeometryContaining geometry-type of input (possibly) containing type
+*/
+template
+<
+ typename TagContained,
+ typename TagContaining,
+ typename CastedTagContained,
+ typename CastedTagContaining,
+ typename CsTagContained,
+ typename CsTagContaining,
+ typename GeometryContained,
+ typename GeometryContaining
+>
+struct default_strategy
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THESE_TYPES
+ , (types<GeometryContained, GeometryContaining>)
+ );
+};
+
+
+} // namespace services
+
+
+}} // namespace strategy::covered_by
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_COVERED_BY_HPP
+
diff --git a/boost/geometry/strategies/default_area_result.hpp b/boost/geometry/strategies/default_area_result.hpp
new file mode 100644
index 000000000..8adfa5d6e
--- /dev/null
+++ b/boost/geometry/strategies/default_area_result.hpp
@@ -0,0 +1,51 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_DEFAULT_AREA_RESULT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_AREA_RESULT_HPP
+
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/strategies/area.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+/*!
+\brief Meta-function defining return type of area function, using the default strategy
+\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 default_area_result
+{
+ typedef typename point_type<Geometry>::type point_type;
+ typedef typename strategy::area::services::default_strategy
+ <
+ typename cs_tag<point_type>::type,
+ point_type
+ >::type strategy_type;
+
+ typedef typename strategy_type::return_type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_DEFAULT_AREA_RESULT_HPP
diff --git a/boost/geometry/strategies/default_distance_result.hpp b/boost/geometry/strategies/default_distance_result.hpp
new file mode 100644
index 000000000..ea5f3ff76
--- /dev/null
+++ b/boost/geometry/strategies/default_distance_result.hpp
@@ -0,0 +1,50 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_DEFAULT_DISTANCE_RESULT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_DISTANCE_RESULT_HPP
+
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/strategies/distance.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+/*!
+\brief Meta-function defining return type of distance function
+\ingroup distance
+\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 Geometry1, typename Geometry2 = Geometry1>
+struct default_distance_result
+{
+ typedef typename strategy::distance::services::return_type
+ <
+ typename strategy::distance::services::default_strategy
+ <
+ point_tag,
+ typename point_type<Geometry1>::type,
+ typename point_type<Geometry2>::type
+ >::type
+ >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_DEFAULT_DISTANCE_RESULT_HPP
diff --git a/boost/geometry/strategies/default_length_result.hpp b/boost/geometry/strategies/default_length_result.hpp
new file mode 100644
index 000000000..706941b9e
--- /dev/null
+++ b/boost/geometry/strategies/default_length_result.hpp
@@ -0,0 +1,46 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_DEFAULT_LENGTH_RESULT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_DEFAULT_LENGTH_RESULT_HPP
+
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief Meta-function defining return type of length function
+ \ingroup length
+ \note Length of a line of integer coordinates can be double.
+ So we take at least a double. If Big Number types are used,
+ we take that type.
+
+ */
+template <typename Geometry>
+struct default_length_result
+{
+ typedef typename select_most_precise
+ <
+ typename coordinate_type<Geometry>::type,
+ long double
+ >::type type;
+};
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_DEFAULT_LENGTH_RESULT_HPP
diff --git a/boost/geometry/strategies/distance.hpp b/boost/geometry/strategies/distance.hpp
new file mode 100644
index 000000000..ef9a7ee10
--- /dev/null
+++ b/boost/geometry/strategies/distance.hpp
@@ -0,0 +1,135 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_DISTANCE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_DISTANCE_HPP
+
+
+#include <boost/mpl/assert.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/strategies/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace distance { namespace services
+{
+
+
+template <typename Strategy> struct tag {};
+template <typename Strategy> struct return_type
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_STRATEGY, (types<Strategy>)
+ );
+};
+
+
+/*!
+ \brief Metafunction delivering a similar strategy with other input point types
+*/
+template
+<
+ typename Strategy,
+ typename Point1,
+ typename Point2
+>
+struct similar_type
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_STRATEGY
+ , (types<Strategy, Point1, Point2>)
+ );
+};
+
+template
+<
+ typename Strategy,
+ typename Point1,
+ typename Point2
+>
+struct get_similar
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_STRATEGY
+ , (types<Strategy, Point1, Point2>)
+ );
+};
+
+template <typename Strategy> struct comparable_type
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_STRATEGY, (types<Strategy>)
+ );
+};
+
+template <typename Strategy> struct get_comparable
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_STRATEGY, (types<Strategy>)
+ );
+};
+
+template <typename Strategy> struct result_from_distance {};
+
+
+// For point-segment only:
+template <typename Strategy> struct strategy_point_point {};
+
+
+// Default strategy
+
+
+/*!
+ \brief Traits class binding a default strategy for distance
+ to one (or possibly two) coordinate system(s)
+ \ingroup distance
+ \tparam GeometryTag tag (point/segment) for which this strategy is the default
+ \tparam Point1 first point-type
+ \tparam Point2 second point-type
+ \tparam CsTag1 tag of coordinate system of first point type
+ \tparam CsTag2 tag of coordinate system of second point type
+*/
+template
+<
+ typename GeometryTag,
+ typename Point1,
+ typename Point2 = Point1,
+ typename CsTag1 = typename cs_tag<Point1>::type,
+ typename CsTag2 = typename cs_tag<Point2>::type,
+ typename UnderlyingStrategy = void
+>
+struct default_strategy
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE_COMBINATION
+ , (types<Point1, Point2, CsTag1, CsTag2>)
+ );
+};
+
+
+}}} // namespace strategy::distance::services
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_DISTANCE_HPP
diff --git a/boost/geometry/strategies/intersection.hpp b/boost/geometry/strategies/intersection.hpp
new file mode 100644
index 000000000..fc628c063
--- /dev/null
+++ b/boost/geometry/strategies/intersection.hpp
@@ -0,0 +1,93 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_INTERSECTION_HPP
+#define BOOST_GEOMETRY_STRATEGIES_INTERSECTION_HPP
+
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/geometries/segment.hpp>
+
+#include <boost/geometry/policies/relate/intersection_points.hpp>
+#include <boost/geometry/policies/relate/direction.hpp>
+#include <boost/geometry/policies/relate/tupled.hpp>
+
+#include <boost/geometry/strategies/side.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+#include <boost/geometry/strategies/intersection_result.hpp>
+
+#include <boost/geometry/strategies/cartesian/cart_intersect.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+// The intersection strategy is a "compound strategy",
+// it contains a segment-intersection-strategy
+// and a side-strategy
+/*!
+\tparam CalculationType \tparam_calculation
+*/
+template
+<
+ typename Tag,
+ typename Geometry1,
+ typename Geometry2,
+ typename IntersectionPoint,
+ typename CalculationType = void
+>
+struct strategy_intersection
+{
+private :
+ typedef typename geometry::point_type<Geometry1>::type point1_type;
+ typedef typename geometry::point_type<Geometry2>::type point2_type;
+ typedef typename model::referring_segment<point1_type const> segment1_type;
+ typedef typename model::referring_segment<point2_type const> segment2_type;
+
+ typedef segment_intersection_points
+ <
+ IntersectionPoint
+ > ip_type;
+
+public:
+ typedef strategy::intersection::relate_cartesian_segments
+ <
+ policies::relate::segments_tupled
+ <
+ policies::relate::segments_intersection_points
+ <
+ segment1_type,
+ segment2_type,
+ ip_type,
+ CalculationType
+ > ,
+ policies::relate::segments_direction
+ <
+ segment1_type,
+ segment2_type,
+ CalculationType
+ >,
+ CalculationType
+ >,
+ CalculationType
+ > segment_intersection_strategy_type;
+
+ typedef typename strategy::side::services::default_strategy
+ <
+ Tag,
+ CalculationType
+ >::type side_strategy_type;
+};
+
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_INTERSECTION_HPP
diff --git a/boost/geometry/strategies/intersection_result.hpp b/boost/geometry/strategies/intersection_result.hpp
new file mode 100644
index 000000000..15917a9eb
--- /dev/null
+++ b/boost/geometry/strategies/intersection_result.hpp
@@ -0,0 +1,174 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_INTERSECTION_RESULT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_INTERSECTION_RESULT_HPP
+
+#if defined(HAVE_MATRIX_AS_STRING)
+#include <string>
+#endif
+
+#include <cstddef>
+
+
+namespace boost { namespace geometry
+{
+
+/*!
+ \brief Dimensionally Extended 9 Intersection Matrix
+ \details
+ \ingroup overlay
+ \see http://gis.hsr.ch/wiki/images/3/3d/9dem_springer.pdf
+*/
+struct de9im
+{
+ int ii, ib, ie,
+ bi, bb, be,
+ ei, eb, ee;
+
+ inline de9im()
+ : ii(-1), ib(-1), ie(-1)
+ , bi(-1), bb(-1), be(-1)
+ , ei(-1), eb(-1), ee(-1)
+ {
+ }
+
+ inline de9im(int ii0, int ib0, int ie0,
+ int bi0, int bb0, int be0,
+ int ei0, int eb0, int ee0)
+ : ii(ii0), ib(ib0), ie(ie0)
+ , bi(bi0), bb(bb0), be(be0)
+ , ei(ei0), eb(eb0), ee(ee0)
+ {}
+
+ inline bool equals() const
+ {
+ return ii >= 0 && ie < 0 && be < 0 && ei < 0 && eb < 0;
+ }
+
+ inline bool disjoint() const
+ {
+ return ii < 0 && ib < 0 && bi < 0 && bb < 0;
+ }
+
+ inline bool intersects() const
+ {
+ return ii >= 0 || bb >= 0 || bi >= 0 || ib >= 0;
+ }
+
+ inline bool touches() const
+ {
+ return ii < 0 && (bb >= 0 || bi >= 0 || ib >= 0);
+ }
+
+ inline bool crosses() const
+ {
+ return (ii >= 0 && ie >= 0) || (ii == 0);
+ }
+
+ inline bool overlaps() const
+ {
+ return ii >= 0 && ie >= 0 && ei >= 0;
+ }
+
+ inline bool within() const
+ {
+ return ii >= 0 && ie < 0 && be < 0;
+ }
+
+ inline bool contains() const
+ {
+ return ii >= 0 && ei < 0 && eb < 0;
+ }
+
+
+ static inline char as_char(int v)
+ {
+ return v >= 0 && v < 10 ? ('0' + char(v)) : '-';
+ }
+
+#if defined(HAVE_MATRIX_AS_STRING)
+ inline std::string matrix_as_string(std::string const& tab, std::string const& nl) const
+ {
+ std::string ret;
+ ret.reserve(9 + tab.length() * 3 + nl.length() * 3);
+ ret += tab; ret += as_char(ii); ret += as_char(ib); ret += as_char(ie); ret += nl;
+ ret += tab; ret += as_char(bi); ret += as_char(bb); ret += as_char(be); ret += nl;
+ ret += tab; ret += as_char(ei); ret += as_char(eb); ret += as_char(ee);
+ return ret;
+ }
+
+ inline std::string matrix_as_string() const
+ {
+ return matrix_as_string("", "");
+ }
+#endif
+
+};
+
+struct de9im_segment : public de9im
+{
+ bool collinear; // true if segments are aligned (for equal,overlap,touch)
+ bool opposite; // true if direction is reversed (for equal,overlap,touch)
+ bool parallel; // true if disjoint but parallel
+ bool degenerate; // true for segment(s) of zero length
+
+ double ra, rb; // temp
+
+ inline de9im_segment()
+ : de9im()
+ , collinear(false)
+ , opposite(false)
+ , parallel(false)
+ , degenerate(false)
+ {}
+
+ inline de9im_segment(double a, double b,
+ int ii0, int ib0, int ie0,
+ int bi0, int bb0, int be0,
+ int ei0, int eb0, int ee0,
+ bool c = false, bool o = false, bool p = false, bool d = false)
+ : de9im(ii0, ib0, ie0, bi0, bb0, be0, ei0, eb0, ee0)
+ , collinear(c)
+ , opposite(o)
+ , parallel(p)
+ , degenerate(d)
+ , ra(a), rb(b)
+ {}
+
+
+#if defined(HAVE_MATRIX_AS_STRING)
+ inline std::string as_string() const
+ {
+ std::string ret = matrix_as_string();
+ ret += collinear ? "c" : "-";
+ ret += opposite ? "o" : "-";
+ return ret;
+ }
+#endif
+};
+
+
+
+template <typename Point>
+struct segment_intersection_points
+{
+ std::size_t count;
+ Point intersections[2];
+ typedef Point point_type;
+
+ segment_intersection_points()
+ : count(0)
+ {}
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_INTERSECTION_RESULT_HPP
diff --git a/boost/geometry/strategies/side.hpp b/boost/geometry/strategies/side.hpp
new file mode 100644
index 000000000..376f2fdf1
--- /dev/null
+++ b/boost/geometry/strategies/side.hpp
@@ -0,0 +1,55 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SIDE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SIDE_HPP
+
+
+#include <boost/geometry/strategies/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace side
+{
+
+namespace services
+{
+
+/*!
+\brief Traits class binding a side determination strategy to a coordinate system
+\ingroup util
+\tparam Tag tag of coordinate system of point-type
+\tparam CalculationType \tparam_calculation
+*/
+template <typename Tag, typename CalculationType = void>
+struct default_strategy
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_TYPE
+ , (types<Tag>)
+ );
+};
+
+
+} // namespace services
+
+
+}} // namespace strategy::side
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SIDE_HPP
diff --git a/boost/geometry/strategies/side_info.hpp b/boost/geometry/strategies/side_info.hpp
new file mode 100644
index 000000000..3c2c1798a
--- /dev/null
+++ b/boost/geometry/strategies/side_info.hpp
@@ -0,0 +1,176 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP
+
+#include <cmath>
+#include <utility>
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+#include <iostream>
+#endif
+
+namespace boost { namespace geometry
+{
+
+// Silence warning C4127: conditional expression is constant
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4127)
+#endif
+
+/*!
+\brief Class side_info: small class wrapping for sides (-1,0,1)
+*/
+class side_info
+{
+public :
+ inline side_info(int side_a1 = 0, int side_a2 = 0,
+ int side_b1 = 0, int side_b2 = 0)
+ {
+ sides[0].first = side_a1;
+ sides[0].second = side_a2;
+ sides[1].first = side_b1;
+ sides[1].second = side_b2;
+ }
+
+ template <int Which>
+ inline void set(int first, int second)
+ {
+ sides[Which].first = first;
+ sides[Which].second = second;
+ }
+
+ template <int Which, int Index>
+ inline void correct_to_zero()
+ {
+ if (Index == 0)
+ {
+ sides[Which].first = 0;
+ }
+ else
+ {
+ sides[Which].second = 0;
+ }
+ }
+
+ template <int Which, int Index>
+ inline int get() const
+ {
+ return Index == 0 ? sides[Which].first : sides[Which].second;
+ }
+
+
+ // Returns true if both lying on the same side WRT the other
+ // (so either 1,1 or -1-1)
+ template <int Which>
+ inline bool same() const
+ {
+ return sides[Which].first * sides[Which].second == 1;
+ }
+
+ inline bool collinear() const
+ {
+ return sides[0].first == 0
+ && sides[0].second == 0
+ && sides[1].first == 0
+ && sides[1].second == 0;
+ }
+
+ inline bool crossing() const
+ {
+ return sides[0].first * sides[0].second == -1
+ && sides[1].first * sides[1].second == -1;
+ }
+
+ inline bool touching() const
+ {
+ return (sides[0].first * sides[1].first == -1
+ && sides[0].second == 0 && sides[1].second == 0)
+ || (sides[1].first * sides[0].first == -1
+ && sides[1].second == 0 && sides[0].second == 0);
+ }
+
+ template <int Which>
+ inline bool one_touching() const
+ {
+ // This is normally a situation which can't occur:
+ // If one is completely left or right, the other cannot touch
+ return one_zero<Which>()
+ && sides[1 - Which].first * sides[1 - Which].second == 1;
+ }
+
+ inline bool meeting() const
+ {
+ // Two of them (in each segment) zero, two not
+ return one_zero<0>() && one_zero<1>();
+ }
+
+ template <int Which>
+ inline bool zero() const
+ {
+ return sides[Which].first == 0 && sides[Which].second == 0;
+ }
+
+ template <int Which>
+ inline bool one_zero() const
+ {
+ return (sides[Which].first == 0 && sides[Which].second != 0)
+ || (sides[Which].first != 0 && sides[Which].second == 0);
+ }
+
+ inline bool one_of_all_zero() const
+ {
+ int const sum = std::abs(sides[0].first)
+ + std::abs(sides[0].second)
+ + std::abs(sides[1].first)
+ + std::abs(sides[1].second);
+ return sum == 3;
+ }
+
+
+ template <int Which>
+ inline int zero_index() const
+ {
+ return sides[Which].first == 0 ? 0 : 1;
+ }
+
+#ifdef BOOST_GEOMETRY_DEBUG_INTERSECTION
+ inline void debug() const
+ {
+ std::cout << sides[0].first << " "
+ << sides[0].second << " "
+ << sides[1].first << " "
+ << sides[1].second
+ << std::endl;
+ }
+#endif
+
+ inline void reverse()
+ {
+ std::swap(sides[0], sides[1]);
+ }
+
+//private :
+ std::pair<int, int> sides[2];
+
+};
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SIDE_INFO_HPP
diff --git a/boost/geometry/strategies/spherical/area_huiller.hpp b/boost/geometry/strategies/spherical/area_huiller.hpp
new file mode 100644
index 000000000..1bef9b5f2
--- /dev/null
+++ b/boost/geometry/strategies/spherical/area_huiller.hpp
@@ -0,0 +1,202 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP
+
+
+
+#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
+
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/util/math.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace area
+{
+
+
+
+/*!
+\brief Area calculation by spherical excess / Huiller's formula
+\ingroup strategies
+\tparam PointOfSegment point type of segments of rings/polygons
+\tparam CalculationType \tparam_calculation
+\author Barend Gehrels. Adapted from:
+- http://www.soe.ucsc.edu/~pang/160/f98/Gems/GemsIV/sph_poly.c
+- http://williams.best.vwh.net/avform.htm
+\note The version in Gems didn't account for polygons crossing the 180 meridian.
+\note This version works for convex and non-convex polygons, for 180 meridian
+crossing polygons and for polygons with holes. However, some cases (especially
+180 meridian cases) must still be checked.
+\note The version which sums angles, which is often seen, doesn't handle non-convex
+polygons correctly.
+\note The version which sums longitudes, see
+http://trs-new.jpl.nasa.gov/dspace/bitstream/2014/40409/1/07-03.pdf, is simple
+and works well in most cases but not in 180 meridian crossing cases. This probably
+could be solved.
+
+\note This version is made for spherical equatorial coordinate systems
+
+\qbk{
+
+[heading Example]
+[area_with_strategy]
+[area_with_strategy_output]
+
+
+[heading See also]
+[link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)]
+}
+
+*/
+template
+<
+ typename PointOfSegment,
+ typename CalculationType = void
+>
+class huiller
+{
+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 calculation_type;
+
+protected :
+ struct excess_sum
+ {
+ calculation_type sum;
+
+ // Distances are calculated on unit sphere here
+ strategy::distance::haversine<PointOfSegment, PointOfSegment>
+ distance_over_unit_sphere;
+
+
+ inline excess_sum()
+ : sum(0)
+ , distance_over_unit_sphere(1)
+ {}
+ inline calculation_type area(calculation_type radius) const
+ {
+ return - sum * radius * radius;
+ }
+ };
+
+public :
+ typedef calculation_type return_type;
+ typedef PointOfSegment segment_point_type;
+ typedef excess_sum state_type;
+
+ inline huiller(calculation_type radius = 1.0)
+ : m_radius(radius)
+ {}
+
+ inline void apply(PointOfSegment const& p1,
+ PointOfSegment const& p2,
+ excess_sum& state) const
+ {
+ if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
+ {
+ calculation_type const half = 0.5;
+ calculation_type const two = 2.0;
+ calculation_type const four = 4.0;
+ calculation_type const two_pi = two * geometry::math::pi<calculation_type>();
+ calculation_type const half_pi = half * geometry::math::pi<calculation_type>();
+
+ // Distance p1 p2
+ calculation_type a = state.distance_over_unit_sphere.apply(p1, p2);
+
+ // Sides on unit sphere to south pole
+ calculation_type b = half_pi - geometry::get_as_radian<1>(p2);
+ calculation_type c = half_pi - geometry::get_as_radian<1>(p1);
+
+ // Semi parameter
+ calculation_type s = half * (a + b + c);
+
+ // E: spherical excess, using l'Huiller's formula
+ // [tg(e / 4)]2 = tg[s / 2] tg[(s-a) / 2] tg[(s-b) / 2] tg[(s-c) / 2]
+ calculation_type E = four * atan(sqrt(geometry::math::abs(tan(s / two)
+ * tan((s - a) / two)
+ * tan((s - b) / two)
+ * tan((s - c) / two))));
+
+ E = geometry::math::abs(E);
+
+ // In right direction: positive, add area. In left direction: negative, subtract area.
+ // Longitude comparisons are not so obvious. If one is negative, other is positive,
+ // we have to take the dateline into account.
+ // TODO: check this / enhance this, should be more robust. See also the "grow" for ll
+ // TODO: use minmax or "smaller"/"compare" strategy for this
+ calculation_type lon1 = geometry::get_as_radian<0>(p1) < 0
+ ? geometry::get_as_radian<0>(p1) + two_pi
+ : geometry::get_as_radian<0>(p1);
+
+ calculation_type lon2 = geometry::get_as_radian<0>(p2) < 0
+ ? geometry::get_as_radian<0>(p2) + two_pi
+ : geometry::get_as_radian<0>(p2);
+
+ if (lon2 < lon1)
+ {
+ E = -E;
+ }
+
+ state.sum += E;
+ }
+ }
+
+ inline return_type result(excess_sum const& state) const
+ {
+ return state.area(m_radius);
+ }
+
+private :
+ /// Radius of the sphere
+ calculation_type m_radius;
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+
+template <typename Point>
+struct default_strategy<spherical_equatorial_tag, Point>
+{
+ typedef strategy::area::huiller<Point> type;
+};
+
+// Note: spherical polar coordinate system requires "get_as_radian_equatorial"
+/***template <typename Point>
+struct default_strategy<spherical_polar_tag, Point>
+{
+ typedef strategy::area::huiller<Point> type;
+};***/
+
+} // namespace services
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::area
+
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP
diff --git a/boost/geometry/strategies/spherical/compare_circular.hpp b/boost/geometry/strategies/spherical/compare_circular.hpp
new file mode 100644
index 000000000..2f890dfd8
--- /dev/null
+++ b/boost/geometry/strategies/spherical/compare_circular.hpp
@@ -0,0 +1,152 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP
+
+#include <boost/math/constants/constants.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/strategies/compare.hpp>
+#include <boost/geometry/util/math.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace compare
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Units>
+struct shift
+{
+};
+
+template <>
+struct shift<degree>
+{
+ static inline double full() { return 360.0; }
+ static inline double half() { return 180.0; }
+};
+
+template <>
+struct shift<radian>
+{
+ static inline double full() { return 2.0 * boost::math::constants::pi<double>(); }
+ static inline double half() { return boost::math::constants::pi<double>(); }
+};
+
+} // namespace detail
+#endif
+
+/*!
+\brief Compare (in one direction) strategy for spherical coordinates
+\ingroup strategies
+\tparam Point point-type
+\tparam Dimension dimension
+*/
+template <typename CoordinateType, typename Units, typename Compare>
+struct circular_comparator
+{
+ static inline CoordinateType put_in_range(CoordinateType const& c,
+ double min_border, double max_border)
+ {
+ CoordinateType value = c;
+ while (value < min_border)
+ {
+ value += detail::shift<Units>::full();
+ }
+ while (value > max_border)
+ {
+ value -= detail::shift<Units>::full();
+ }
+ return value;
+ }
+
+ inline bool operator()(CoordinateType const& c1, CoordinateType const& c2) const
+ {
+ Compare compare;
+
+ // Check situation that one of them is e.g. std::numeric_limits.
+ static const double full = detail::shift<Units>::full();
+ double mx = 10.0 * full;
+ if (c1 < -mx || c1 > mx || c2 < -mx || c2 > mx)
+ {
+ // do normal comparison, using circular is not useful
+ return compare(c1, c2);
+ }
+
+ static const double half = full / 2.0;
+ CoordinateType v1 = put_in_range(c1, -half, half);
+ CoordinateType v2 = put_in_range(c2, -half, half);
+
+ // Two coordinates on a circle are
+ // at max <= half a circle away from each other.
+ // So if it is more, shift origin.
+ CoordinateType diff = geometry::math::abs(v1 - v2);
+ if (diff > half)
+ {
+ v1 = put_in_range(v1, 0, full);
+ v2 = put_in_range(v2, 0, full);
+ }
+
+ return compare(v1, v2);
+ }
+};
+
+}} // namespace strategy::compare
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+// Specialize for the longitude (dim 0)
+template
+<
+ typename Point,
+ template<typename> class CoordinateSystem,
+ typename Units
+>
+struct strategy_compare<spherical_polar_tag, 1, Point, CoordinateSystem<Units>, 0>
+{
+ typedef typename coordinate_type<Point>::type coordinate_type;
+ typedef strategy::compare::circular_comparator
+ <
+ coordinate_type,
+ Units,
+ std::less<coordinate_type>
+ > type;
+};
+
+template
+<
+ typename Point,
+ template<typename> class CoordinateSystem,
+ typename Units
+>
+struct strategy_compare<spherical_polar_tag, -1, Point, CoordinateSystem<Units>, 0>
+{
+ typedef typename coordinate_type<Point>::type coordinate_type;
+ typedef strategy::compare::circular_comparator
+ <
+ coordinate_type,
+ Units,
+ std::greater<coordinate_type>
+ > type;
+};
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP
diff --git a/boost/geometry/strategies/spherical/distance_cross_track.hpp b/boost/geometry/strategies/spherical/distance_cross_track.hpp
new file mode 100644
index 000000000..7b353020e
--- /dev/null
+++ b/boost/geometry/strategies/spherical/distance_cross_track.hpp
@@ -0,0 +1,382 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+
+
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/concepts/distance_concept.hpp>
+
+#include <boost/geometry/util/promote_floating_point.hpp>
+#include <boost/geometry/util/math.hpp>
+
+#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
+# include <boost/geometry/io/dsv/write.hpp>
+#endif
+
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace distance
+{
+
+/*!
+\brief Strategy functor for distance point to segment calculation
+\ingroup strategies
+\details Class which calculates the distance of a point to a segment, using latlong points
+\see http://williams.best.vwh.net/avform.htm
+\tparam Point point type
+\tparam PointOfSegment \tparam_segment_point
+\tparam CalculationType \tparam_calculation
+\tparam Strategy underlying point-point distance strategy, defaults to haversine
+
+\qbk{
+[heading See also]
+[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
+}
+
+*/
+template
+<
+ typename Point,
+ typename PointOfSegment = Point,
+ typename CalculationType = void,
+ typename Strategy = typename services::default_strategy<point_tag, Point>::type
+>
+class cross_track
+{
+public :
+ typedef typename promote_floating_point
+ <
+ typename select_calculation_type
+ <
+ Point,
+ PointOfSegment,
+ CalculationType
+ >::type
+ >::type return_type;
+
+ inline cross_track()
+ {
+ m_strategy = Strategy();
+ m_radius = m_strategy.radius();
+ }
+
+ inline cross_track(return_type const& r)
+ : m_radius(r)
+ , m_strategy(r)
+ {}
+
+ inline cross_track(Strategy const& s)
+ : m_strategy(s)
+ {
+ m_radius = m_strategy.radius();
+ }
+
+
+ // It might be useful in the future
+ // to overload constructor with strategy info.
+ // crosstrack(...) {}
+
+
+ inline return_type apply(Point const& p,
+ PointOfSegment const& sp1, PointOfSegment const& sp2) const
+ {
+ // http://williams.best.vwh.net/avform.htm#XTE
+ return_type d1 = m_strategy.apply(sp1, p);
+ return_type d3 = m_strategy.apply(sp1, sp2);
+
+ if (geometry::math::equals(d3, 0.0))
+ {
+ // "Degenerate" segment, return either d1 or d2
+ return d1;
+ }
+
+ return_type d2 = m_strategy.apply(sp2, p);
+
+ return_type crs_AD = course(sp1, p);
+ return_type crs_AB = course(sp1, sp2);
+ return_type crs_BA = crs_AB - geometry::math::pi<return_type>();
+ return_type crs_BD = course(sp2, p);
+ return_type d_crs1 = crs_AD - crs_AB;
+ return_type d_crs2 = crs_BD - crs_BA;
+
+ // d1, d2, d3 are in principle not needed, only the sign matters
+ return_type projection1 = cos( d_crs1 ) * d1 / d3;
+ return_type projection2 = cos( d_crs2 ) * d2 / d3;
+
+#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
+ std::cout << "Course " << dsv(sp1) << " to " << dsv(p) << " " << crs_AD * geometry::math::r2d << std::endl;
+ std::cout << "Course " << dsv(sp1) << " to " << dsv(sp2) << " " << crs_AB * geometry::math::r2d << std::endl;
+ std::cout << "Course " << dsv(sp2) << " to " << dsv(p) << " " << crs_BD * geometry::math::r2d << std::endl;
+ std::cout << "Projection AD-AB " << projection1 << " : " << d_crs1 * geometry::math::r2d << std::endl;
+ std::cout << "Projection BD-BA " << projection2 << " : " << d_crs2 * geometry::math::r2d << std::endl;
+#endif
+
+ if(projection1 > 0.0 && projection2 > 0.0)
+ {
+ return_type XTD = m_radius * geometry::math::abs( asin( sin( d1 / m_radius ) * sin( d_crs1 ) ));
+
+ #ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
+ std::cout << "Projection ON the segment" << std::endl;
+ std::cout << "XTD: " << XTD << " d1: " << d1 << " d2: " << d2 << std::endl;
+#endif
+
+ // Return shortest distance, projected point on segment sp1-sp2
+ return return_type(XTD);
+ }
+ else
+ {
+#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
+ std::cout << "Projection OUTSIDE the segment" << std::endl;
+#endif
+
+ // Return shortest distance, project either on point sp1 or sp2
+ return return_type( (std::min)( d1 , d2 ) );
+ }
+ }
+
+ inline return_type radius() const { return m_radius; }
+
+private :
+ BOOST_CONCEPT_ASSERT
+ (
+ (geometry::concept::PointDistanceStrategy<Strategy >)
+ );
+
+
+ return_type m_radius;
+
+ // Point-point distances are calculated in radians, on the unit sphere
+ Strategy m_strategy;
+
+ /// Calculate course (bearing) between two points. Might be moved to a "course formula" ...
+ inline return_type course(Point const& p1, Point const& p2) const
+ {
+ // http://williams.best.vwh.net/avform.htm#Crs
+ return_type dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1);
+ return_type cos_p2lat = cos(get_as_radian<1>(p2));
+
+ // "An alternative formula, not requiring the pre-computation of d"
+ return atan2(sin(dlon) * cos_p2lat,
+ cos(get_as_radian<1>(p1)) * sin(get_as_radian<1>(p2))
+ - sin(get_as_radian<1>(p1)) * cos_p2lat * cos(dlon));
+ }
+
+};
+
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
+struct tag<cross_track<Point, PointOfSegment, CalculationType, Strategy> >
+{
+ typedef strategy_tag_distance_point_segment type;
+};
+
+
+template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
+struct return_type<cross_track<Point, PointOfSegment, CalculationType, Strategy> >
+{
+ typedef typename cross_track<Point, PointOfSegment, CalculationType, Strategy>::return_type type;
+};
+
+
+template
+<
+ typename Point,
+ typename PointOfSegment,
+ typename CalculationType,
+ typename Strategy,
+ typename P,
+ typename PS
+>
+struct similar_type<cross_track<Point, PointOfSegment, CalculationType, Strategy>, P, PS>
+{
+ typedef cross_track<Point, PointOfSegment, CalculationType, Strategy> type;
+};
+
+
+template
+<
+ typename Point,
+ typename PointOfSegment,
+ typename CalculationType,
+ typename Strategy,
+ typename P,
+ typename PS
+>
+struct get_similar<cross_track<Point, PointOfSegment, CalculationType, Strategy>, P, PS>
+{
+ static inline typename similar_type
+ <
+ cross_track<Point, PointOfSegment, CalculationType, Strategy>, P, PS
+ >::type apply(cross_track<Point, PointOfSegment, CalculationType, Strategy> const& strategy)
+ {
+ return cross_track<P, PS, CalculationType, Strategy>(strategy.radius());
+ }
+};
+
+
+template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
+struct comparable_type<cross_track<Point, PointOfSegment, CalculationType, Strategy> >
+{
+ // Comparable type is here just the strategy
+ typedef typename similar_type
+ <
+ cross_track
+ <
+ Point, PointOfSegment, CalculationType, Strategy
+ >, Point, PointOfSegment
+ >::type type;
+};
+
+
+template
+<
+ typename Point, typename PointOfSegment,
+ typename CalculationType,
+ typename Strategy
+>
+struct get_comparable<cross_track<Point, PointOfSegment, CalculationType, Strategy> >
+{
+ typedef typename comparable_type
+ <
+ cross_track<Point, PointOfSegment, CalculationType, Strategy>
+ >::type comparable_type;
+public :
+ static inline comparable_type apply(cross_track<Point, PointOfSegment, CalculationType, Strategy> const& strategy)
+ {
+ return comparable_type(strategy.radius());
+ }
+};
+
+
+template
+<
+ typename Point, typename PointOfSegment,
+ typename CalculationType,
+ typename Strategy
+>
+struct result_from_distance<cross_track<Point, PointOfSegment, CalculationType, Strategy> >
+{
+private :
+ typedef typename cross_track<Point, PointOfSegment, CalculationType, Strategy>::return_type return_type;
+public :
+ template <typename T>
+ static inline return_type apply(cross_track<Point, PointOfSegment, CalculationType, Strategy> const& , T const& distance)
+ {
+ return distance;
+ }
+};
+
+
+template
+<
+ typename Point, typename PointOfSegment,
+ typename CalculationType,
+ typename Strategy
+>
+struct strategy_point_point<cross_track<Point, PointOfSegment, CalculationType, Strategy> >
+{
+ typedef Strategy type;
+};
+
+
+
+/*
+
+TODO: spherical polar coordinate system requires "get_as_radian_equatorial<>"
+
+template <typename Point, typename PointOfSegment, typename Strategy>
+struct default_strategy
+ <
+ segment_tag, Point, PointOfSegment,
+ spherical_polar_tag, spherical_polar_tag,
+ Strategy
+ >
+{
+ typedef cross_track
+ <
+ Point,
+ PointOfSegment,
+ void,
+ typename boost::mpl::if_
+ <
+ boost::is_void<Strategy>,
+ typename default_strategy
+ <
+ point_tag, Point, PointOfSegment,
+ spherical_polar_tag, spherical_polar_tag
+ >::type,
+ Strategy
+ >::type
+ > type;
+};
+*/
+
+template <typename Point, typename PointOfSegment, typename Strategy>
+struct default_strategy
+ <
+ segment_tag, Point, PointOfSegment,
+ spherical_equatorial_tag, spherical_equatorial_tag,
+ Strategy
+ >
+{
+ typedef cross_track
+ <
+ Point,
+ PointOfSegment,
+ void,
+ typename boost::mpl::if_
+ <
+ boost::is_void<Strategy>,
+ typename default_strategy
+ <
+ point_tag, Point, PointOfSegment,
+ spherical_equatorial_tag, spherical_equatorial_tag
+ >::type,
+ Strategy
+ >::type
+ > type;
+};
+
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::distance
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+#endif
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_CROSS_TRACK_HPP
diff --git a/boost/geometry/strategies/spherical/distance_haversine.hpp b/boost/geometry/strategies/spherical/distance_haversine.hpp
new file mode 100644
index 000000000..5a866c2ed
--- /dev/null
+++ b/boost/geometry/strategies/spherical/distance_haversine.hpp
@@ -0,0 +1,330 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_HAVERSINE_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_HAVERSINE_HPP
+
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+
+#include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/util/promote_floating_point.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace distance
+{
+
+
+namespace comparable
+{
+
+// Comparable haversine.
+// To compare distances, we can avoid:
+// - multiplication with radius and 2.0
+// - applying sqrt
+// - applying asin (which is strictly (monotone) increasing)
+template
+<
+ typename Point1,
+ typename Point2 = Point1,
+ typename CalculationType = void
+>
+class haversine
+{
+public :
+ typedef typename promote_floating_point
+ <
+ typename select_calculation_type
+ <
+ Point1,
+ Point2,
+ CalculationType
+ >::type
+ >::type calculation_type;
+
+ inline haversine(calculation_type const& r = 1.0)
+ : m_radius(r)
+ {}
+
+
+ static inline calculation_type apply(Point1 const& p1, Point2 const& p2)
+ {
+ return calculate(get_as_radian<0>(p1), get_as_radian<1>(p1),
+ get_as_radian<0>(p2), get_as_radian<1>(p2));
+ }
+
+ inline calculation_type radius() const
+ {
+ return m_radius;
+ }
+
+
+private :
+
+ static inline calculation_type calculate(calculation_type const& lon1,
+ calculation_type const& lat1,
+ calculation_type const& lon2,
+ calculation_type const& lat2)
+ {
+ return math::hav(lat2 - lat1)
+ + cos(lat1) * cos(lat2) * math::hav(lon2 - lon1);
+ }
+
+ calculation_type m_radius;
+};
+
+
+
+} // namespace comparable
+
+/*!
+\brief Distance calculation for spherical coordinates
+on a perfect sphere using haversine
+\ingroup strategies
+\tparam Point1 \tparam_first_point
+\tparam Point2 \tparam_second_point
+\tparam CalculationType \tparam_calculation
+\author Adapted from: http://williams.best.vwh.net/avform.htm
+\see http://en.wikipedia.org/wiki/Great-circle_distance
+\note (from Wiki:) The great circle distance d between two
+points with coordinates {lat1,lon1} and {lat2,lon2} is given by:
+ d=acos(sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos(lon1-lon2))
+A mathematically equivalent formula, which is less subject
+ to rounding error for short distances is:
+ d=2*asin(sqrt((sin((lat1-lat2) / 2))^2
+ + cos(lat1)*cos(lat2)*(sin((lon1-lon2) / 2))^2))
+
+
+\qbk{
+[heading See also]
+[link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)]
+}
+
+*/
+template
+<
+ typename Point1,
+ typename Point2 = Point1,
+ typename CalculationType = void
+>
+class haversine
+{
+ typedef comparable::haversine<Point1, Point2, CalculationType> comparable_type;
+
+public :
+
+ typedef typename services::return_type<comparable_type>::type calculation_type;
+
+ /*!
+ \brief Constructor
+ \param radius radius of the sphere, defaults to 1.0 for the unit sphere
+ */
+ inline haversine(calculation_type const& radius = 1.0)
+ : m_radius(radius)
+ {}
+
+ /*!
+ \brief applies the distance calculation
+ \return the calculated distance (including multiplying with radius)
+ \param p1 first point
+ \param p2 second point
+ */
+ inline calculation_type apply(Point1 const& p1, Point2 const& p2) const
+ {
+ calculation_type const a = comparable_type::apply(p1, p2);
+ calculation_type const c = calculation_type(2.0) * asin(sqrt(a));
+ return m_radius * c;
+ }
+
+ /*!
+ \brief access to radius value
+ \return the radius
+ */
+ inline calculation_type radius() const
+ {
+ return m_radius;
+ }
+
+private :
+ calculation_type m_radius;
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct tag<haversine<Point1, Point2, CalculationType> >
+{
+ typedef strategy_tag_distance_point_point type;
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct return_type<haversine<Point1, Point2, CalculationType> >
+{
+ typedef typename haversine<Point1, Point2, CalculationType>::calculation_type type;
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType, typename P1, typename P2>
+struct similar_type<haversine<Point1, Point2, CalculationType>, P1, P2>
+{
+ typedef haversine<P1, P2, CalculationType> type;
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType, typename P1, typename P2>
+struct get_similar<haversine<Point1, Point2, CalculationType>, P1, P2>
+{
+private :
+ typedef haversine<Point1, Point2, CalculationType> this_type;
+public :
+ static inline typename similar_type<this_type, P1, P2>::type apply(this_type const& input)
+ {
+ return haversine<P1, P2, CalculationType>(input.radius());
+ }
+};
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct comparable_type<haversine<Point1, Point2, CalculationType> >
+{
+ typedef comparable::haversine<Point1, Point2, CalculationType> type;
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct get_comparable<haversine<Point1, Point2, CalculationType> >
+{
+private :
+ typedef haversine<Point1, Point2, CalculationType> this_type;
+ typedef comparable::haversine<Point1, Point2, CalculationType> comparable_type;
+public :
+ static inline comparable_type apply(this_type const& input)
+ {
+ return comparable_type(input.radius());
+ }
+};
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct result_from_distance<haversine<Point1, Point2, CalculationType> >
+{
+private :
+ typedef haversine<Point1, Point2, CalculationType> this_type;
+ typedef typename return_type<this_type>::type return_type;
+public :
+ template <typename T>
+ static inline return_type apply(this_type const& , T const& value)
+ {
+ return return_type(value);
+ }
+};
+
+
+// Specializations for comparable::haversine
+template <typename Point1, typename Point2, typename CalculationType>
+struct tag<comparable::haversine<Point1, Point2, CalculationType> >
+{
+ typedef strategy_tag_distance_point_point type;
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct return_type<comparable::haversine<Point1, Point2, CalculationType> >
+{
+ typedef typename comparable::haversine<Point1, Point2, CalculationType>::calculation_type type;
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType, typename P1, typename P2>
+struct similar_type<comparable::haversine<Point1, Point2, CalculationType>, P1, P2>
+{
+ typedef comparable::haversine<P1, P2, CalculationType> type;
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType, typename P1, typename P2>
+struct get_similar<comparable::haversine<Point1, Point2, CalculationType>, P1, P2>
+{
+private :
+ typedef comparable::haversine<Point1, Point2, CalculationType> this_type;
+public :
+ static inline typename similar_type<this_type, P1, P2>::type apply(this_type const& input)
+ {
+ return comparable::haversine<P1, P2, CalculationType>(input.radius());
+ }
+};
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct comparable_type<comparable::haversine<Point1, Point2, CalculationType> >
+{
+ typedef comparable::haversine<Point1, Point2, CalculationType> type;
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct get_comparable<comparable::haversine<Point1, Point2, CalculationType> >
+{
+private :
+ typedef comparable::haversine<Point1, Point2, CalculationType> this_type;
+public :
+ static inline this_type apply(this_type const& input)
+ {
+ return input;
+ }
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct result_from_distance<comparable::haversine<Point1, Point2, CalculationType> >
+{
+private :
+ typedef comparable::haversine<Point1, Point2, CalculationType> strategy_type;
+ typedef typename return_type<strategy_type>::type return_type;
+public :
+ template <typename T>
+ static inline return_type apply(strategy_type const& strategy, T const& distance)
+ {
+ return_type const s = sin((distance / strategy.radius()) / return_type(2));
+ return s * s;
+ }
+};
+
+
+// Register it as the default for point-types
+// in a spherical equatorial coordinate system
+template <typename Point1, typename Point2>
+struct default_strategy<point_tag, Point1, Point2, spherical_equatorial_tag, spherical_equatorial_tag>
+{
+ typedef strategy::distance::haversine<Point1, Point2> type;
+};
+
+// Note: spherical polar coordinate system requires "get_as_radian_equatorial"
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::distance
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_DISTANCE_HAVERSINE_HPP
diff --git a/boost/geometry/strategies/spherical/side_by_cross_track.hpp b/boost/geometry/strategies/spherical/side_by_cross_track.hpp
new file mode 100644
index 000000000..b7cf279d5
--- /dev/null
+++ b/boost/geometry/strategies/spherical/side_by_cross_track.hpp
@@ -0,0 +1,100 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+
+#include <boost/geometry/util/select_coordinate_type.hpp>
+#include <boost/geometry/util/math.hpp>
+
+#include <boost/geometry/strategies/side.hpp>
+//#include <boost/geometry/strategies/concepts/side_concept.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace side
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+/// Calculate course (bearing) between two points. Might be moved to a "course formula" ...
+template <typename Point>
+static inline double course(Point const& p1, Point const& p2)
+{
+ // http://williams.best.vwh.net/avform.htm#Crs
+ double dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1);
+ double cos_p2lat = cos(get_as_radian<1>(p2));
+
+ // "An alternative formula, not requiring the pre-computation of d"
+ return atan2(sin(dlon) * cos_p2lat,
+ cos(get_as_radian<1>(p1)) * sin(get_as_radian<1>(p2))
+ - sin(get_as_radian<1>(p1)) * cos_p2lat * cos(dlon));
+}
+
+}
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+/*!
+\brief Check at which side of a Great Circle segment a point lies
+ left of segment (> 0), right of segment (< 0), on segment (0)
+\ingroup strategies
+\tparam CalculationType \tparam_calculation
+ */
+template <typename CalculationType = void>
+class side_by_cross_track
+{
+
+public :
+ template <typename P1, typename P2, typename P>
+ static inline int apply(P1 const& p1, P2 const& p2, P const& p)
+ {
+ typedef typename boost::mpl::if_c
+ <
+ boost::is_void<CalculationType>::type::value,
+ typename select_most_precise
+ <
+ typename select_most_precise
+ <
+ typename coordinate_type<P1>::type,
+ typename coordinate_type<P2>::type
+ >::type,
+ typename coordinate_type<P>::type
+ >::type,
+ CalculationType
+ >::type coordinate_type;
+
+ double d1 = 0.001; // m_strategy.apply(sp1, p);
+ double crs_AD = detail::course(p1, p);
+ double crs_AB = detail::course(p1, p2);
+ double XTD = asin(sin(d1) * sin(crs_AD - crs_AB));
+
+ return math::equals(XTD, 0) ? 0 : XTD < 0 ? 1 : -1;
+ }
+};
+
+}} // namespace strategy::side
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP
diff --git a/boost/geometry/strategies/spherical/ssf.hpp b/boost/geometry/strategies/spherical/ssf.hpp
new file mode 100644
index 000000000..ab7c67559
--- /dev/null
+++ b/boost/geometry/strategies/spherical/ssf.hpp
@@ -0,0 +1,136 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SSF_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SSF_HPP
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+
+#include <boost/geometry/util/select_coordinate_type.hpp>
+#include <boost/geometry/util/math.hpp>
+
+#include <boost/geometry/strategies/side.hpp>
+//#include <boost/geometry/strategies/concepts/side_concept.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategy { namespace side
+{
+
+
+/*!
+\brief Check at which side of a Great Circle segment a point lies
+ left of segment (> 0), right of segment (< 0), on segment (0)
+\ingroup strategies
+\tparam CalculationType \tparam_calculation
+ */
+template <typename CalculationType = void>
+class spherical_side_formula
+{
+
+public :
+ template <typename P1, typename P2, typename P>
+ static inline int apply(P1 const& p1, P2 const& p2, P const& p)
+ {
+ typedef typename boost::mpl::if_c
+ <
+ boost::is_void<CalculationType>::type::value,
+
+ // Select at least a double...
+ typename select_most_precise
+ <
+ typename select_most_precise
+ <
+ typename select_most_precise
+ <
+ typename coordinate_type<P1>::type,
+ typename coordinate_type<P2>::type
+ >::type,
+ typename coordinate_type<P>::type
+ >::type,
+ double
+ >::type,
+ CalculationType
+ >::type coordinate_type;
+
+ // Convenient shortcuts
+ typedef coordinate_type ct;
+ ct const lambda1 = get_as_radian<0>(p1);
+ ct const delta1 = get_as_radian<1>(p1);
+ ct const lambda2 = get_as_radian<0>(p2);
+ ct const delta2 = get_as_radian<1>(p2);
+ ct const lambda = get_as_radian<0>(p);
+ ct const delta = get_as_radian<1>(p);
+
+ // Create temporary points (vectors) on unit a sphere
+ ct const cos_delta1 = cos(delta1);
+ ct const c1x = cos_delta1 * cos(lambda1);
+ ct const c1y = cos_delta1 * sin(lambda1);
+ ct const c1z = sin(delta1);
+
+ ct const cos_delta2 = cos(delta2);
+ ct const c2x = cos_delta2 * cos(lambda2);
+ ct const c2y = cos_delta2 * sin(lambda2);
+ ct const c2z = sin(delta2);
+
+ // (Third point is converted directly)
+ ct const cos_delta = cos(delta);
+
+ // Apply the "Spherical Side Formula" as presented on my blog
+ ct const dist
+ = (c1y * c2z - c1z * c2y) * cos_delta * cos(lambda)
+ + (c1z * c2x - c1x * c2z) * cos_delta * sin(lambda)
+ + (c1x * c2y - c1y * c2x) * sin(delta);
+
+ ct zero = ct();
+ return dist > zero ? 1
+ : dist < zero ? -1
+ : 0;
+ }
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+/*template <typename CalculationType>
+struct default_strategy<spherical_polar_tag, CalculationType>
+{
+ typedef spherical_side_formula<CalculationType> type;
+};*/
+
+template <typename CalculationType>
+struct default_strategy<spherical_equatorial_tag, CalculationType>
+{
+ typedef spherical_side_formula<CalculationType> type;
+};
+
+template <typename CalculationType>
+struct default_strategy<geographic_tag, CalculationType>
+{
+ typedef spherical_side_formula<CalculationType> type;
+};
+
+}
+#endif
+
+}} // namespace strategy::side
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SSF_HPP
diff --git a/boost/geometry/strategies/strategies.hpp b/boost/geometry/strategies/strategies.hpp
new file mode 100644
index 000000000..3aa9ab00f
--- /dev/null
+++ b/boost/geometry/strategies/strategies.hpp
@@ -0,0 +1,59 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_STRATEGIES_HPP
+#define BOOST_GEOMETRY_STRATEGIES_STRATEGIES_HPP
+
+
+#include <boost/geometry/strategies/tags.hpp>
+
+#include <boost/geometry/strategies/area.hpp>
+#include <boost/geometry/strategies/centroid.hpp>
+#include <boost/geometry/strategies/compare.hpp>
+#include <boost/geometry/strategies/convex_hull.hpp>
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/intersection.hpp>
+#include <boost/geometry/strategies/side.hpp>
+#include <boost/geometry/strategies/transform.hpp>
+#include <boost/geometry/strategies/within.hpp>
+
+#include <boost/geometry/strategies/cartesian/area_surveyor.hpp>
+#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
+#include <boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp>
+#include <boost/geometry/strategies/cartesian/centroid_weighted_length.hpp>
+#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
+#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp>
+#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
+#include <boost/geometry/strategies/cartesian/point_in_poly_franklin.hpp>
+#include <boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp>
+#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
+
+#include <boost/geometry/strategies/spherical/area_huiller.hpp>
+#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
+#include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
+#include <boost/geometry/strategies/spherical/compare_circular.hpp>
+#include <boost/geometry/strategies/spherical/ssf.hpp>
+
+#include <boost/geometry/strategies/agnostic/hull_graham_andrew.hpp>
+#include <boost/geometry/strategies/agnostic/point_in_box_by_side.hpp>
+#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
+#include <boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp>
+
+#include <boost/geometry/strategies/strategy_transform.hpp>
+
+#include <boost/geometry/strategies/transform/matrix_transformers.hpp>
+#include <boost/geometry/strategies/transform/map_transformer.hpp>
+#include <boost/geometry/strategies/transform/inverse_transformer.hpp>
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_STRATEGIES_HPP
diff --git a/boost/geometry/strategies/strategy_transform.hpp b/boost/geometry/strategies/strategy_transform.hpp
new file mode 100644
index 000000000..2b75d202e
--- /dev/null
+++ b/boost/geometry/strategies/strategy_transform.hpp
@@ -0,0 +1,504 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP
+#define BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP
+
+#include <cstddef>
+#include <cmath>
+#include <functional>
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/strategies/transform.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace transform
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template
+<
+ typename Src, typename Dst,
+ std::size_t D, std::size_t N,
+ template <typename> class F
+>
+struct transform_coordinates
+{
+ template <typename T>
+ static inline void transform(Src const& source, Dst& dest, T value)
+ {
+ typedef typename select_coordinate_type<Src, Dst>::type coordinate_type;
+
+ F<coordinate_type> function;
+ set<D>(dest, boost::numeric_cast<coordinate_type>(function(get<D>(source), value)));
+ transform_coordinates<Src, Dst, D + 1, N, F>::transform(source, dest, value);
+ }
+};
+
+template
+<
+ typename Src, typename Dst,
+ std::size_t N,
+ template <typename> class F
+>
+struct transform_coordinates<Src, Dst, N, N, F>
+{
+ template <typename T>
+ static inline void transform(Src const& , Dst& , T )
+ {
+ }
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief Transformation strategy to copy one point to another using assignment operator
+ \ingroup transform
+ \tparam P point type
+ */
+template <typename P>
+struct copy_direct
+{
+ inline bool apply(P const& p1, P& p2) const
+ {
+ p2 = p1;
+ return true;
+ }
+};
+
+/*!
+ \brief Transformation strategy to do copy a point, copying per coordinate.
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ */
+template <typename P1, typename P2>
+struct copy_per_coordinate
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ // Defensive check, dimensions are equal, selected by specialization
+ assert_dimension_equal<P1, P2>();
+
+ geometry::convert(p1, p2);
+ return true;
+ }
+};
+
+
+/*!
+ \brief Transformation strategy to go from degree to radian and back
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ \tparam F additional functor to divide or multiply with d2r
+ */
+template <typename P1, typename P2, template <typename> class F>
+struct degree_radian_vv
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ // Spherical coordinates always have 2 coordinates measured in angles
+ // The optional third one is distance/height, provided in another strategy
+ // Polar coordinates having one angle, will be also in another strategy
+ assert_dimension<P1, 2>();
+ assert_dimension<P2, 2>();
+
+ detail::transform_coordinates<P1, P2, 0, 2, F>::transform(p1, p2, math::d2r);
+ return true;
+ }
+};
+
+template <typename P1, typename P2, template <typename> class F>
+struct degree_radian_vv_3
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ assert_dimension<P1, 3>();
+ assert_dimension<P2, 3>();
+
+ detail::transform_coordinates<P1, P2, 0, 2, F>::transform(p1, p2, math::d2r);
+ // Copy height or other third dimension
+ set<2>(p2, get<2>(p1));
+ return true;
+ }
+};
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+ /// Helper function for conversion, phi/theta are in radians
+ template <typename P, typename T, typename R>
+ inline void spherical_polar_to_cartesian(T phi, T theta, R r, P& p)
+ {
+ assert_dimension<P, 3>();
+
+ // http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_spherical_coordinates
+ // http://www.vias.org/comp_geometry/math_coord_convert_3d.htm
+ // https://moodle.polymtl.ca/file.php/1183/Autres_Documents/Derivation_for_Spherical_Co-ordinates.pdf
+ // http://en.citizendium.org/wiki/Spherical_polar_coordinates
+
+ // Phi = first, theta is second, r is third, see documentation on cs::spherical
+
+ // (calculations are splitted to implement ttmath)
+
+ T r_sin_theta = r;
+ T r_cos_theta = r;
+ r_sin_theta *= sin(theta);
+ r_cos_theta *= cos(theta);
+
+ set<0>(p, r_sin_theta * cos(phi));
+ set<1>(p, r_sin_theta * sin(phi));
+ set<2>(p, r_cos_theta);
+ }
+
+ /// Helper function for conversion, lambda/delta (lon lat) are in radians
+ template <typename P, typename T, typename R>
+ inline void spherical_equatorial_to_cartesian(T lambda, T delta, R r, P& p)
+ {
+ assert_dimension<P, 3>();
+
+ // http://mathworld.wolfram.com/GreatCircle.html
+ // http://www.spenvis.oma.be/help/background/coortran/coortran.html WRONG
+
+ T r_cos_delta = r;
+ T r_sin_delta = r;
+ r_cos_delta *= cos(delta);
+ r_sin_delta *= sin(delta);
+
+ set<0>(p, r_cos_delta * cos(lambda));
+ set<1>(p, r_cos_delta * sin(lambda));
+ set<2>(p, r_sin_delta);
+ }
+
+
+ /// Helper function for conversion
+ template <typename P, typename T>
+ inline bool cartesian_to_spherical2(T x, T y, T z, P& p)
+ {
+ assert_dimension<P, 2>();
+
+ // http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_Cartesian_coordinates
+
+#if defined(BOOST_GEOMETRY_TRANSFORM_CHECK_UNIT_SPHERE)
+ // TODO: MAYBE ONLY IF TO BE CHECKED?
+ T const r = /*sqrt not necessary, sqrt(1)=1*/ (x * x + y * y + z * z);
+
+ // Unit sphere, so r should be 1
+ if (geometry::math::abs(r - 1.0) > T(1e-6))
+ {
+ return false;
+ }
+ // end todo
+#endif
+
+ set_from_radian<0>(p, atan2(y, x));
+ set_from_radian<1>(p, acos(z));
+ return true;
+ }
+
+ template <typename P, typename T>
+ inline bool cartesian_to_spherical_equatorial2(T x, T y, T z, P& p)
+ {
+ assert_dimension<P, 2>();
+
+ set_from_radian<0>(p, atan2(y, x));
+ set_from_radian<1>(p, asin(z));
+ return true;
+ }
+
+
+ template <typename P, typename T>
+ inline bool cartesian_to_spherical3(T x, T y, T z, P& p)
+ {
+ assert_dimension<P, 3>();
+
+ // http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_Cartesian_coordinates
+ T const r = sqrt(x * x + y * y + z * z);
+ set<2>(p, r);
+ set_from_radian<0>(p, atan2(y, x));
+ if (r > 0.0)
+ {
+ set_from_radian<1>(p, acos(z / r));
+ return true;
+ }
+ return false;
+ }
+
+ template <typename P, typename T>
+ inline bool cartesian_to_spherical_equatorial3(T x, T y, T z, P& p)
+ {
+ assert_dimension<P, 3>();
+
+ // http://en.wikipedia.org/wiki/List_of_canonical_coordinate_transformations#From_Cartesian_coordinates
+ T const r = sqrt(x * x + y * y + z * z);
+ set<2>(p, r);
+ set_from_radian<0>(p, atan2(y, x));
+ if (r > 0.0)
+ {
+ set_from_radian<1>(p, asin(z / r));
+ return true;
+ }
+ return false;
+ }
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief Transformation strategy for 2D spherical (phi,theta) to 3D cartesian (x,y,z)
+ \details on Unit sphere
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ */
+template <typename P1, typename P2>
+struct from_spherical_polar_2_to_cartesian_3
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ assert_dimension<P1, 2>();
+ detail::spherical_polar_to_cartesian(get_as_radian<0>(p1), get_as_radian<1>(p1), 1.0, p2);
+ return true;
+ }
+};
+
+template <typename P1, typename P2>
+struct from_spherical_equatorial_2_to_cartesian_3
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ assert_dimension<P1, 2>();
+ detail::spherical_equatorial_to_cartesian(get_as_radian<0>(p1), get_as_radian<1>(p1), 1.0, p2);
+ return true;
+ }
+};
+
+
+/*!
+ \brief Transformation strategy for 3D spherical (phi,theta,r) to 3D cartesian (x,y,z)
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ */
+template <typename P1, typename P2>
+struct from_spherical_polar_3_to_cartesian_3
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ assert_dimension<P1, 3>();
+ detail::spherical_polar_to_cartesian(
+ get_as_radian<0>(p1), get_as_radian<1>(p1), get<2>(p1), p2);
+ return true;
+ }
+};
+
+template <typename P1, typename P2>
+struct from_spherical_equatorial_3_to_cartesian_3
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ assert_dimension<P1, 3>();
+ detail::spherical_equatorial_to_cartesian(
+ get_as_radian<0>(p1), get_as_radian<1>(p1), get<2>(p1), p2);
+ return true;
+ }
+};
+
+
+/*!
+ \brief Transformation strategy for 3D cartesian (x,y,z) to 2D spherical (phi,theta)
+ \details on Unit sphere
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ \note If x,y,z point is not lying on unit sphere, transformation will return false
+ */
+template <typename P1, typename P2>
+struct from_cartesian_3_to_spherical_polar_2
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ assert_dimension<P1, 3>();
+ return detail::cartesian_to_spherical2(get<0>(p1), get<1>(p1), get<2>(p1), p2);
+ }
+};
+
+template <typename P1, typename P2>
+struct from_cartesian_3_to_spherical_equatorial_2
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ assert_dimension<P1, 3>();
+ return detail::cartesian_to_spherical_equatorial2(get<0>(p1), get<1>(p1), get<2>(p1), p2);
+ }
+};
+
+
+/*!
+ \brief Transformation strategy for 3D cartesian (x,y,z) to 3D spherical (phi,theta,r)
+ \ingroup transform
+ \tparam P1 first point type
+ \tparam P2 second point type
+ */
+template <typename P1, typename P2>
+struct from_cartesian_3_to_spherical_polar_3
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ assert_dimension<P1, 3>();
+ return detail::cartesian_to_spherical3(get<0>(p1), get<1>(p1), get<2>(p1), p2);
+ }
+};
+
+template <typename P1, typename P2>
+struct from_cartesian_3_to_spherical_equatorial_3
+{
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ assert_dimension<P1, 3>();
+ return detail::cartesian_to_spherical_equatorial3(get<0>(p1), get<1>(p1), get<2>(p1), p2);
+ }
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+/// Specialization for same coordinate system family, same system, same dimension, same point type, can be copied
+template <typename CoordSysTag, typename CoordSys, std::size_t D, typename P>
+struct default_strategy<CoordSysTag, CoordSysTag, CoordSys, CoordSys, D, D, P, P>
+{
+ typedef copy_direct<P> type;
+};
+
+/// Specialization for same coordinate system family and system, same dimension, different point type, copy per coordinate
+template <typename CoordSysTag, typename CoordSys, std::size_t D, typename P1, typename P2>
+struct default_strategy<CoordSysTag, CoordSysTag, CoordSys, CoordSys, D, D, P1, P2>
+{
+ typedef copy_per_coordinate<P1, P2> type;
+};
+
+/// Specialization to transform from degree to radian for any coordinate system / point type combination
+template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
+struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<degree>, CoordSys<radian>, 2, 2, P1, P2>
+{
+ typedef degree_radian_vv<P1, P2, std::multiplies> type;
+};
+
+/// Specialization to transform from radian to degree for any coordinate system / point type combination
+template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
+struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<radian>, CoordSys<degree>, 2, 2, P1, P2>
+{
+ typedef degree_radian_vv<P1, P2, std::divides> type;
+};
+
+
+/// Specialization degree->radian in 3D
+template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
+struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<degree>, CoordSys<radian>, 3, 3, P1, P2>
+{
+ typedef degree_radian_vv_3<P1, P2, std::multiplies> type;
+};
+
+/// Specialization radian->degree in 3D
+template <typename CoordSysTag, template<typename> class CoordSys, typename P1, typename P2>
+struct default_strategy<CoordSysTag, CoordSysTag, CoordSys<radian>, CoordSys<degree>, 3, 3, P1, P2>
+{
+ typedef degree_radian_vv_3<P1, P2, std::divides> type;
+};
+
+/// Specialization to transform from unit sphere(phi,theta) to XYZ
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
+struct default_strategy<spherical_polar_tag, cartesian_tag, CoordSys1, CoordSys2, 2, 3, P1, P2>
+{
+ typedef from_spherical_polar_2_to_cartesian_3<P1, P2> type;
+};
+
+/// Specialization to transform from sphere(phi,theta,r) to XYZ
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
+struct default_strategy<spherical_polar_tag, cartesian_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
+{
+ typedef from_spherical_polar_3_to_cartesian_3<P1, P2> type;
+};
+
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
+struct default_strategy<spherical_equatorial_tag, cartesian_tag, CoordSys1, CoordSys2, 2, 3, P1, P2>
+{
+ typedef from_spherical_equatorial_2_to_cartesian_3<P1, P2> type;
+};
+
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
+struct default_strategy<spherical_equatorial_tag, cartesian_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
+{
+ typedef from_spherical_equatorial_3_to_cartesian_3<P1, P2> type;
+};
+
+/// Specialization to transform from XYZ to unit sphere(phi,theta)
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
+struct default_strategy<cartesian_tag, spherical_polar_tag, CoordSys1, CoordSys2, 3, 2, P1, P2>
+{
+ typedef from_cartesian_3_to_spherical_polar_2<P1, P2> type;
+};
+
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
+struct default_strategy<cartesian_tag, spherical_equatorial_tag, CoordSys1, CoordSys2, 3, 2, P1, P2>
+{
+ typedef from_cartesian_3_to_spherical_equatorial_2<P1, P2> type;
+};
+
+/// Specialization to transform from XYZ to sphere(phi,theta,r)
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
+struct default_strategy<cartesian_tag, spherical_polar_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
+{
+ typedef from_cartesian_3_to_spherical_polar_3<P1, P2> type;
+};
+template <typename CoordSys1, typename CoordSys2, typename P1, typename P2>
+struct default_strategy<cartesian_tag, spherical_equatorial_tag, CoordSys1, CoordSys2, 3, 3, P1, P2>
+{
+ typedef from_cartesian_3_to_spherical_equatorial_3<P1, P2> type;
+};
+
+
+} // namespace services
+
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::transform
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_STRATEGY_TRANSFORM_HPP
diff --git a/boost/geometry/strategies/tags.hpp b/boost/geometry/strategies/tags.hpp
new file mode 100644
index 000000000..39f2f2303
--- /dev/null
+++ b/boost/geometry/strategies/tags.hpp
@@ -0,0 +1,41 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_TAGS_HPP
+#define BOOST_GEOMETRY_STRATEGIES_TAGS_HPP
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy
+{
+ /*!
+ \brief Indicate compiler/library user that strategy is not implemented.
+ \details Strategies are defined for point types or for point type
+ combinations. If there is no implementation for that specific point type, or point type
+ combination, the calculation cannot be done. To indicate this, this not_implemented
+ class is used as a typedef stub.
+
+ */
+ struct not_implemented {};
+}
+
+
+struct strategy_tag_distance_point_point {};
+struct strategy_tag_distance_point_segment {};
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_TAGS_HPP
diff --git a/boost/geometry/strategies/transform.hpp b/boost/geometry/strategies/transform.hpp
new file mode 100644
index 000000000..3c806acac
--- /dev/null
+++ b/boost/geometry/strategies/transform.hpp
@@ -0,0 +1,63 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_HPP
+#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_HPP
+
+#include <cstddef>
+
+#include <boost/mpl/assert.hpp>
+
+#include <boost/geometry/strategies/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace transform { namespace services
+{
+
+/*!
+ \brief Traits class binding a transformation strategy to a coordinate system
+ \ingroup transform
+ \details Can be specialized
+ - per coordinate system family (tag)
+ - per coordinate system (or groups of them)
+ - per dimension
+ - per point type
+ \tparam CoordinateSystemTag 1,2 coordinate system tags
+ \tparam CoordinateSystem 1,2 coordinate system
+ \tparam D 1, 2 dimension
+ \tparam Point 1, 2 point type
+ */
+template
+<
+ typename CoordinateSystemTag1, typename CoordinateSystemTag2,
+ typename CoordinateSystem1, typename CoordinateSystem2,
+ std::size_t Dimension1, std::size_t Dimension2,
+ typename Point1, typename Point2
+>
+struct default_strategy
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPES
+ , (types<Point1, Point2>)
+ );
+};
+
+}}} // namespace strategy::transform::services
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_HPP
diff --git a/boost/geometry/strategies/transform/inverse_transformer.hpp b/boost/geometry/strategies/transform/inverse_transformer.hpp
new file mode 100644
index 000000000..845a71ded
--- /dev/null
+++ b/boost/geometry/strategies/transform/inverse_transformer.hpp
@@ -0,0 +1,78 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP
+#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP
+
+// Remove the ublas checking, otherwise the inverse might fail
+// (while nothing seems to be wrong)
+#define BOOST_UBLAS_TYPE_CHECK 0
+
+#include <boost/numeric/ublas/lu.hpp>
+#include <boost/numeric/ublas/io.hpp>
+
+#include <boost/geometry/strategies/transform/matrix_transformers.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace transform
+{
+
+/*!
+\brief Transformation strategy to do an inverse ransformation in Cartesian system
+\ingroup strategies
+\tparam P1 first point type
+\tparam P2 second point type
+ */
+template <typename P1, typename P2>
+class inverse_transformer
+ : public ublas_transformer<P1, P2, dimension<P1>::type::value, dimension<P2>::type::value>
+{
+ typedef typename select_coordinate_type<P1, P2>::type T;
+
+public :
+ template <typename Transformer>
+ inline inverse_transformer(Transformer const& input)
+ {
+ typedef boost::numeric::ublas::matrix<T> matrix_type;
+
+ // create a working copy of the input
+ matrix_type copy(input.matrix());
+
+ // create a permutation matrix for the LU-factorization
+ typedef boost::numeric::ublas::permutation_matrix<> permutation_matrix;
+ permutation_matrix pm(copy.size1());
+
+ // perform LU-factorization
+ int res = boost::numeric::ublas::lu_factorize<matrix_type>(copy, pm);
+ if( res == 0 )
+ {
+ // create identity matrix
+ this->m_matrix.assign(boost::numeric::ublas::identity_matrix<T>(copy.size1()));
+
+ // backsubstitute to get the inverse
+ boost::numeric::ublas::lu_substitute(copy, pm, this->m_matrix);
+ }
+ }
+
+};
+
+
+}} // namespace strategy::transform
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_INVERSE_TRANSFORMER_HPP
diff --git a/boost/geometry/strategies/transform/map_transformer.hpp b/boost/geometry/strategies/transform/map_transformer.hpp
new file mode 100644
index 000000000..2755d5353
--- /dev/null
+++ b/boost/geometry/strategies/transform/map_transformer.hpp
@@ -0,0 +1,173 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP
+#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP
+
+
+#include <cstddef>
+
+#include <boost/geometry/strategies/transform/matrix_transformers.hpp>
+
+namespace boost { namespace geometry
+{
+
+// Silence warning C4127: conditional expression is constant
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4127)
+#endif
+
+namespace strategy { namespace transform
+{
+
+/*!
+\brief Transformation strategy to do map from one to another Cartesian system
+\ingroup strategies
+\tparam P1 first point type
+\tparam P2 second point type
+\tparam Mirror if true map is mirrored upside-down (in most cases pixels
+ are from top to bottom, while map is from bottom to top)
+ */
+template
+<
+ typename P1, typename P2,
+ bool Mirror = false, bool SameScale = true,
+ std::size_t Dimension1 = dimension<P1>::type::value,
+ std::size_t Dimension2 = dimension<P2>::type::value
+>
+class map_transformer
+ : public ublas_transformer<P1, P2, Dimension1, Dimension2>
+{
+ typedef typename select_coordinate_type<P1, P2>::type T;
+ typedef boost::numeric::ublas::matrix<T> M;
+
+public :
+ template <typename B, typename D>
+ explicit inline map_transformer(B const& box, D const& width, D const& height)
+ {
+ set_transformation(
+ get<min_corner, 0>(box), get<min_corner, 1>(box),
+ get<max_corner, 0>(box), get<max_corner, 1>(box),
+ width, height);
+ }
+
+ template <typename W, typename D>
+ explicit inline map_transformer(W const& wx1, W const& wy1, W const& wx2, W const& wy2,
+ D const& width, D const& height)
+ {
+ set_transformation(wx1, wy1, wx2, wy2, width, height);
+ }
+
+
+private :
+ template <typename W, typename P, typename S>
+ inline void set_transformation_point(W const& wx, W const& wy,
+ P const& px, P const& py,
+ S const& scalex, S const& scaley)
+ {
+
+ // Translate to a coordinate system centered on world coordinates (-wx, -wy)
+ M t1(3,3);
+ t1(0,0) = 1; t1(0,1) = 0; t1(0,2) = -wx;
+ t1(1,0) = 0; t1(1,1) = 1; t1(1,2) = -wy;
+ t1(2,0) = 0; t1(2,1) = 0; t1(2,2) = 1;
+
+ // Scale the map
+ M s(3,3);
+ s(0,0) = scalex; s(0,1) = 0; s(0,2) = 0;
+ s(1,0) = 0; s(1,1) = scaley; s(1,2) = 0;
+ s(2,0) = 0; s(2,1) = 0; s(2,2) = 1;
+
+ // Translate to a coordinate system centered on the specified pixels (+px, +py)
+ M t2(3, 3);
+ t2(0,0) = 1; t2(0,1) = 0; t2(0,2) = px;
+ t2(1,0) = 0; t2(1,1) = 1; t2(1,2) = py;
+ t2(2,0) = 0; t2(2,1) = 0; t2(2,2) = 1;
+
+ // Calculate combination matrix in two steps
+ this->m_matrix = boost::numeric::ublas::prod(s, t1);
+ this->m_matrix = boost::numeric::ublas::prod(t2, this->m_matrix);
+ }
+
+
+ template <typename W, typename D>
+ void set_transformation(W const& wx1, W const& wy1, W const& wx2, W const& wy2,
+ D const& width, D const& height)
+ {
+ D px1 = 0;
+ D py1 = 0;
+ D px2 = width;
+ D py2 = height;
+
+ // Get the same type, but at least a double
+ typedef typename select_most_precise<D, double>::type type;
+
+
+ // Calculate appropriate scale, take min because whole box must fit
+ // Scale is in PIXELS/MAPUNITS (meters)
+ W wdx = wx2 - wx1;
+ W wdy = wy2 - wy1;
+ type sx = (px2 - px1) / boost::numeric_cast<type>(wdx);
+ type sy = (py2 - py1) / boost::numeric_cast<type>(wdy);
+
+ if (SameScale)
+ {
+ type scale = (std::min)(sx, sy);
+ sx = scale;
+ sy = scale;
+ }
+
+ // Calculate centerpoints
+ W wtx = wx1 + wx2;
+ W wty = wy1 + wy2;
+ W two = 2;
+ W wmx = wtx / two;
+ W wmy = wty / two;
+ type pmx = (px1 + px2) / 2.0;
+ type pmy = (py1 + py2) / 2.0;
+
+ set_transformation_point(wmx, wmy, pmx, pmy, sx, sy);
+
+ if (Mirror)
+ {
+ // Mirror in y-direction
+ M m(3,3);
+ m(0,0) = 1; m(0,1) = 0; m(0,2) = 0;
+ m(1,0) = 0; m(1,1) = -1; m(1,2) = 0;
+ m(2,0) = 0; m(2,1) = 0; m(2,2) = 1;
+
+ // Translate in y-direction such that it fits again
+ M y(3, 3);
+ y(0,0) = 1; y(0,1) = 0; y(0,2) = 0;
+ y(1,0) = 0; y(1,1) = 1; y(1,2) = height;
+ y(2,0) = 0; y(2,1) = 0; y(2,2) = 1;
+
+ // Calculate combination matrix in two steps
+ this->m_matrix = boost::numeric::ublas::prod(m, this->m_matrix);
+ this->m_matrix = boost::numeric::ublas::prod(y, this->m_matrix);
+ }
+ }
+};
+
+
+}} // namespace strategy::transform
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MAP_TRANSFORMER_HPP
diff --git a/boost/geometry/strategies/transform/matrix_transformers.hpp b/boost/geometry/strategies/transform/matrix_transformers.hpp
new file mode 100644
index 000000000..b37a3712e
--- /dev/null
+++ b/boost/geometry/strategies/transform/matrix_transformers.hpp
@@ -0,0 +1,422 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP
+#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP
+
+
+#include <cstddef>
+
+// Remove the ublas checking, otherwise the inverse might fail
+// (while nothing seems to be wrong)
+#define BOOST_UBLAS_TYPE_CHECK 0
+
+#include <boost/numeric/conversion/cast.hpp>
+#include <boost/numeric/ublas/vector.hpp>
+#include <boost/numeric/ublas/matrix.hpp>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_coordinate_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace transform
+{
+
+/*!
+\brief Affine transformation strategy in Cartesian system.
+\details The strategy serves as a generic definition of affine transformation matrix
+ and procedure of application it to given point.
+\see http://en.wikipedia.org/wiki/Affine_transformation
+ and http://www.devmaster.net/wiki/Transformation_matrices
+\ingroup strategies
+\tparam P1 first point type (source)
+\tparam P2 second point type (target)
+\tparam Dimension1 number of dimensions to transform from first point
+\tparam Dimension1 number of dimensions to transform to second point
+ */
+template
+<
+ typename P1, typename P2,
+ std::size_t Dimension1,
+ std::size_t Dimension2
+>
+class ublas_transformer
+{
+};
+
+
+template <typename P1, typename P2>
+class ublas_transformer<P1, P2, 2, 2>
+{
+protected :
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+ typedef coordinate_type ct; // Abbreviation
+ typedef boost::numeric::ublas::matrix<coordinate_type> matrix_type;
+ matrix_type m_matrix;
+
+public :
+
+ inline ublas_transformer(
+ ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
+ ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
+ ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
+ : m_matrix(3, 3)
+ {
+ m_matrix(0,0) = m_0_0; m_matrix(0,1) = m_0_1; m_matrix(0,2) = m_0_2;
+ m_matrix(1,0) = m_1_0; m_matrix(1,1) = m_1_1; m_matrix(1,2) = m_1_2;
+ m_matrix(2,0) = m_2_0; m_matrix(2,1) = m_2_1; m_matrix(2,2) = m_2_2;
+ }
+
+ inline ublas_transformer(matrix_type const& matrix)
+ : m_matrix(matrix)
+ {}
+
+
+ inline ublas_transformer() : m_matrix(3, 3) {}
+
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ assert_dimension_greater_equal<P1, 2>();
+ assert_dimension_greater_equal<P2, 2>();
+
+ coordinate_type const& c1 = get<0>(p1);
+ coordinate_type const& c2 = get<1>(p1);
+
+
+ coordinate_type p2x = c1 * m_matrix(0,0) + c2 * m_matrix(0,1) + m_matrix(0,2);
+ coordinate_type p2y = c1 * m_matrix(1,0) + c2 * m_matrix(1,1) + m_matrix(1,2);
+
+ typedef typename geometry::coordinate_type<P2>::type ct2;
+ set<0>(p2, boost::numeric_cast<ct2>(p2x));
+ set<1>(p2, boost::numeric_cast<ct2>(p2y));
+
+ return true;
+ }
+
+ matrix_type const& matrix() const { return m_matrix; }
+};
+
+
+// It IS possible to go from 3 to 2 coordinates
+template <typename P1, typename P2>
+class ublas_transformer<P1, P2, 3, 2> : public ublas_transformer<P1, P2, 2, 2>
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+ typedef coordinate_type ct; // Abbreviation
+
+public :
+ inline ublas_transformer(
+ ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
+ ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
+ ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
+ : ublas_transformer<P1, P2, 2, 2>(
+ m_0_0, m_0_1, m_0_2,
+ m_1_0, m_1_1, m_1_2,
+ m_2_0, m_2_1, m_2_2)
+ {}
+
+ inline ublas_transformer()
+ : ublas_transformer<P1, P2, 2, 2>()
+ {}
+};
+
+
+template <typename P1, typename P2>
+class ublas_transformer<P1, P2, 3, 3>
+{
+protected :
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+ typedef coordinate_type ct; // Abbreviation
+ typedef boost::numeric::ublas::matrix<coordinate_type> matrix_type;
+ matrix_type m_matrix;
+
+public :
+ inline ublas_transformer(
+ ct const& m_0_0, ct const& m_0_1, ct const& m_0_2, ct const& m_0_3,
+ ct const& m_1_0, ct const& m_1_1, ct const& m_1_2, ct const& m_1_3,
+ ct const& m_2_0, ct const& m_2_1, ct const& m_2_2, ct const& m_2_3,
+ ct const& m_3_0, ct const& m_3_1, ct const& m_3_2, ct const& m_3_3
+ )
+ : m_matrix(4, 4)
+ {
+ m_matrix(0,0) = m_0_0; m_matrix(0,1) = m_0_1; m_matrix(0,2) = m_0_2; m_matrix(0,3) = m_0_3;
+ m_matrix(1,0) = m_1_0; m_matrix(1,1) = m_1_1; m_matrix(1,2) = m_1_2; m_matrix(1,3) = m_1_3;
+ m_matrix(2,0) = m_2_0; m_matrix(2,1) = m_2_1; m_matrix(2,2) = m_2_2; m_matrix(2,3) = m_2_3;
+ m_matrix(3,0) = m_3_0; m_matrix(3,1) = m_3_1; m_matrix(3,2) = m_3_2; m_matrix(3,3) = m_3_3;
+ }
+
+ inline ublas_transformer() : m_matrix(4, 4) {}
+
+ inline bool apply(P1 const& p1, P2& p2) const
+ {
+ coordinate_type const& c1 = get<0>(p1);
+ coordinate_type const& c2 = get<1>(p1);
+ coordinate_type const& c3 = get<2>(p1);
+
+ typedef typename geometry::coordinate_type<P2>::type ct2;
+
+ set<0>(p2, boost::numeric_cast<ct2>(
+ c1 * m_matrix(0,0) + c2 * m_matrix(0,1) + c3 * m_matrix(0,2) + m_matrix(0,3)));
+ set<1>(p2, boost::numeric_cast<ct2>(
+ c1 * m_matrix(1,0) + c2 * m_matrix(1,1) + c3 * m_matrix(1,2) + m_matrix(1,3)));
+ set<2>(p2, boost::numeric_cast<ct2>(
+ c1 * m_matrix(2,0) + c2 * m_matrix(2,1) + c3 * m_matrix(2,2) + m_matrix(2,3)));
+
+ return true;
+ }
+
+ matrix_type const& matrix() const { return m_matrix; }
+};
+
+
+/*!
+\brief Strategy of translate transformation in Cartesian system.
+\details Translate moves a geometry a fixed distance in 2 or 3 dimensions.
+\see http://en.wikipedia.org/wiki/Translation_%28geometry%29
+\ingroup strategies
+\tparam P1 first point type
+\tparam P2 second point type
+\tparam Dimension1 number of dimensions to transform from first point
+\tparam Dimension1 number of dimensions to transform to second point
+ */
+template
+<
+ typename P1, typename P2,
+ std::size_t Dimension1 = geometry::dimension<P1>::type::value,
+ std::size_t Dimension2 = geometry::dimension<P2>::type::value
+>
+class translate_transformer
+{
+};
+
+
+template <typename P1, typename P2>
+class translate_transformer<P1, P2, 2, 2> : public ublas_transformer<P1, P2, 2, 2>
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+
+public :
+ // To have translate transformers compatible for 2/3 dimensions, the
+ // constructor takes an optional third argument doing nothing.
+ inline translate_transformer(coordinate_type const& translate_x,
+ coordinate_type const& translate_y,
+ coordinate_type const& = 0)
+ : ublas_transformer<P1, P2, 2, 2>(
+ 1, 0, translate_x,
+ 0, 1, translate_y,
+ 0, 0, 1)
+ {}
+};
+
+
+template <typename P1, typename P2>
+class translate_transformer<P1, P2, 3, 3> : public ublas_transformer<P1, P2, 3, 3>
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+
+public :
+ inline translate_transformer(coordinate_type const& translate_x,
+ coordinate_type const& translate_y,
+ coordinate_type const& translate_z)
+ : ublas_transformer<P1, P2, 3, 3>(
+ 1, 0, 0, translate_x,
+ 0, 1, 0, translate_y,
+ 0, 0, 1, translate_z,
+ 0, 0, 0, 1)
+ {}
+
+};
+
+
+/*!
+\brief Strategy of scale transformation in Cartesian system.
+\details Scale scales a geometry up or down in all its dimensions.
+\see http://en.wikipedia.org/wiki/Scaling_%28geometry%29
+\ingroup strategies
+\tparam P1 first point type
+\tparam P2 second point type
+\tparam Dimension1 number of dimensions to transform from first point
+\tparam Dimension1 number of dimensions to transform to second point
+*/
+template
+<
+ typename P1, typename P2 = P1,
+ std::size_t Dimension1 = geometry::dimension<P1>::type::value,
+ std::size_t Dimension2 = geometry::dimension<P2>::type::value
+>
+class scale_transformer
+{
+};
+
+
+template <typename P1, typename P2>
+class scale_transformer<P1, P2, 2, 2> : public ublas_transformer<P1, P2, 2, 2>
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+
+public :
+ inline scale_transformer(coordinate_type const& scale_x,
+ coordinate_type const& scale_y,
+ coordinate_type const& = 0)
+ : ublas_transformer<P1, P2, 2, 2>(
+ scale_x, 0, 0,
+ 0, scale_y, 0,
+ 0, 0, 1)
+ {}
+
+
+ inline scale_transformer(coordinate_type const& scale)
+ : ublas_transformer<P1, P2, 2, 2>(
+ scale, 0, 0,
+ 0, scale, 0,
+ 0, 0, 1)
+ {}
+};
+
+
+template <typename P1, typename P2>
+class scale_transformer<P1, P2, 3, 3> : public ublas_transformer<P1, P2, 3, 3>
+{
+ typedef typename select_coordinate_type<P1, P2>::type coordinate_type;
+
+public :
+ inline scale_transformer(coordinate_type const& scale_x,
+ coordinate_type const& scale_y,
+ coordinate_type const& scale_z)
+ : ublas_transformer<P1, P2, 3, 3>(
+ scale_x, 0, 0, 0,
+ 0, scale_y, 0, 0,
+ 0, 0, scale_z, 0,
+ 0, 0, 0, 1)
+ {}
+
+
+ inline scale_transformer(coordinate_type const& scale)
+ : ublas_transformer<P1, P2, 3, 3>(
+ scale, 0, 0, 0,
+ 0, scale, 0, 0,
+ 0, 0, scale, 0,
+ 0, 0, 0, 1)
+ {}
+};
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template <typename DegreeOrRadian>
+struct as_radian
+{};
+
+
+template <>
+struct as_radian<radian>
+{
+ template <typename T>
+ static inline T get(T const& value)
+ {
+ return value;
+ }
+};
+
+template <>
+struct as_radian<degree>
+{
+ template <typename T>
+ static inline T get(T const& value)
+ {
+ return value * math::d2r;
+ }
+
+};
+
+
+template
+<
+ typename P1, typename P2,
+ std::size_t Dimension1 = geometry::dimension<P1>::type::value,
+ std::size_t Dimension2 = geometry::dimension<P2>::type::value
+>
+class rad_rotate_transformer
+ : public ublas_transformer<P1, P2, Dimension1, Dimension2>
+{
+ // Angle has type of coordinate type, but at least a double
+ typedef typename select_most_precise
+ <
+ typename select_coordinate_type<P1, P2>::type,
+ double
+ >::type angle_type;
+
+public :
+ inline rad_rotate_transformer(angle_type const& angle)
+ : ublas_transformer<P1, P2, Dimension1, Dimension2>(
+ cos(angle), sin(angle), 0,
+ -sin(angle), cos(angle), 0,
+ 0, 0, 1)
+ {}
+};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+\brief Strategy of rotate transformation in Cartesian system.
+\details Rotate rotates a geometry of specified angle about a fixed point (e.g. origin).
+\see http://en.wikipedia.org/wiki/Rotation_%28mathematics%29
+\ingroup strategies
+\tparam P1 first point type
+\tparam P2 second point type
+\tparam DegreeOrRadian degree/or/radian, type of rotation angle specification
+\note A single angle is needed to specify a rotation in 2D.
+ Not yet in 3D, the 3D version requires special things to allow
+ for rotation around X, Y, Z or arbitrary axis.
+\todo The 3D version will not compile.
+ */
+template <typename P1, typename P2, typename DegreeOrRadian>
+class rotate_transformer : public detail::rad_rotate_transformer<P1, P2>
+{
+ // Angle has type of coordinate type, but at least a double
+ typedef typename select_most_precise
+ <
+ typename select_coordinate_type<P1, P2>::type,
+ double
+ >::type angle_type;
+
+public :
+ inline rotate_transformer(angle_type const& angle)
+ : detail::rad_rotate_transformer
+ <
+ P1, P2
+ >(detail::as_radian<DegreeOrRadian>::get(angle))
+ {}
+};
+
+
+}} // namespace strategy::transform
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP
diff --git a/boost/geometry/strategies/within.hpp b/boost/geometry/strategies/within.hpp
new file mode 100644
index 000000000..d625bc40e
--- /dev/null
+++ b/boost/geometry/strategies/within.hpp
@@ -0,0 +1,71 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_WITHIN_HPP
+#define BOOST_GEOMETRY_STRATEGIES_WITHIN_HPP
+
+#include <boost/mpl/assert.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace within
+{
+
+
+namespace services
+{
+
+/*!
+\brief Traits class binding a within determination strategy to a coordinate system
+\ingroup within
+\tparam TagContained tag (possibly casted) of point-type
+\tparam TagContained tag (possibly casted) of (possibly) containing type
+\tparam CsTagContained tag of coordinate system of point-type
+\tparam CsTagContaining tag of coordinate system of (possibly) containing type
+\tparam Geometry geometry-type of input (often point, or box)
+\tparam GeometryContaining geometry-type of input (possibly) containing type
+*/
+template
+<
+ typename TagContained,
+ typename TagContaining,
+ typename CastedTagContained,
+ typename CastedTagContaining,
+ typename CsTagContained,
+ typename CsTagContaining,
+ typename GeometryContained,
+ typename GeometryContaining
+>
+struct default_strategy
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_IMPLEMENTED_FOR_THESE_TYPES
+ , (types<GeometryContained, GeometryContaining>)
+ );
+};
+
+
+} // namespace services
+
+
+}} // namespace strategy::within
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_WITHIN_HPP
+
diff --git a/boost/geometry/util/add_const_if_c.hpp b/boost/geometry/util/add_const_if_c.hpp
new file mode 100644
index 000000000..9e0c01299
--- /dev/null
+++ b/boost/geometry/util/add_const_if_c.hpp
@@ -0,0 +1,56 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_ADD_CONST_IF_C_HPP
+#define BOOST_GEOMETRY_UTIL_ADD_CONST_IF_C_HPP
+
+
+#include <boost/mpl/if.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Meta-function to define a const or non const type
+ \ingroup utility
+ \details If the boolean template parameter is true, the type parameter
+ will be defined as const, otherwise it will be defined as it was.
+ This meta-function is used to have one implementation for both
+ const and non const references
+ \note This traits class is completely independant from Boost.Geometry
+ and might be a separate addition to Boost
+ \note Used in a.o. for_each, interior_rings, exterior_ring
+ \par Example
+ \code
+ void foo(typename add_const_if_c<IsConst, Point>::type& point)
+ \endcode
+*/
+template <bool IsConst, typename Type>
+struct add_const_if_c
+{
+ typedef typename boost::mpl::if_c
+ <
+ IsConst,
+ Type const,
+ Type
+ >::type type;
+};
+
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_UTIL_ADD_CONST_IF_C_HPP
diff --git a/boost/geometry/util/bare_type.hpp b/boost/geometry/util/bare_type.hpp
new file mode 100644
index 000000000..1b49de643
--- /dev/null
+++ b/boost/geometry/util/bare_type.hpp
@@ -0,0 +1,38 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2012 Mateusz Loskot, London, UK.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_BARE_TYPE_HPP
+#define BOOST_GEOMETRY_UTIL_BARE_TYPE_HPP
+
+#include <boost/type_traits.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace util
+{
+
+template <typename T>
+struct bare_type
+{
+ typedef typename boost::remove_const
+ <
+ typename boost::remove_pointer<T>::type
+ >::type type;
+};
+
+
+} // namespace util
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_UTIL_BARE_TYPE_HPP
diff --git a/boost/geometry/util/calculation_type.hpp b/boost/geometry/util/calculation_type.hpp
new file mode 100644
index 000000000..aef58909e
--- /dev/null
+++ b/boost/geometry/util/calculation_type.hpp
@@ -0,0 +1,176 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2012 Mateusz Loskot, London, UK.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP
+#define BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP
+
+#include <boost/config.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/util/select_coordinate_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace util
+{
+
+namespace detail
+{
+
+struct default_integral
+{
+#ifdef BOOST_HAS_LONG_LONG
+ typedef boost::long_long_type type;
+#else
+ typedef int type;
+#endif
+};
+
+/*!
+\details Selects the most appropriate:
+ - if calculation type is specified (not void), that one is used
+ - else if type is non-fundamental (user defined e.g. ttmath), that one
+ - else if type is floating point, the specified default FP is used
+ - else it is integral and the specified default integral is used
+ */
+template
+<
+ typename Type,
+ typename CalculationType,
+ typename DefaultFloatingPointCalculationType,
+ typename DefaultIntegralCalculationType
+>
+struct calculation_type
+{
+ BOOST_STATIC_ASSERT((
+ boost::is_fundamental
+ <
+ DefaultFloatingPointCalculationType
+ >::type::value
+ ));
+ BOOST_STATIC_ASSERT((
+ boost::is_fundamental
+ <
+ DefaultIntegralCalculationType
+ >::type::value
+ ));
+
+
+ typedef typename boost::mpl::if_
+ <
+ boost::is_void<CalculationType>,
+ typename boost::mpl::if_
+ <
+ boost::is_floating_point<Type>,
+ typename select_most_precise
+ <
+ DefaultFloatingPointCalculationType,
+ Type
+ >::type,
+ typename select_most_precise
+ <
+ DefaultIntegralCalculationType,
+ Type
+ >::type
+ >::type,
+ CalculationType
+ >::type type;
+};
+
+} // namespace detail
+
+
+namespace calculation_type
+{
+
+namespace geometric
+{
+
+template
+<
+ typename Geometry,
+ typename CalculationType,
+ typename DefaultFloatingPointCalculationType = double,
+ typename DefaultIntegralCalculationType = detail::default_integral::type
+>
+struct unary
+{
+ typedef typename detail::calculation_type
+ <
+ typename geometry::coordinate_type<Geometry>::type,
+ CalculationType,
+ DefaultFloatingPointCalculationType,
+ DefaultIntegralCalculationType
+ >::type type;
+};
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename CalculationType,
+ typename DefaultFloatingPointCalculationType = double,
+ typename DefaultIntegralCalculationType = detail::default_integral::type
+>
+struct binary
+{
+ typedef typename detail::calculation_type
+ <
+ typename select_coordinate_type<Geometry1, Geometry2>::type,
+ CalculationType,
+ DefaultFloatingPointCalculationType,
+ DefaultIntegralCalculationType
+ >::type type;
+};
+
+
+/*!
+\brief calculation type (ternary, for three geometry types)
+ */
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Geometry3,
+ typename CalculationType,
+ typename DefaultFloatingPointCalculationType = double,
+ typename DefaultIntegralCalculationType = detail::default_integral::type
+>
+struct ternary
+{
+ typedef typename detail::calculation_type
+ <
+ typename select_most_precise
+ <
+ typename coordinate_type<Geometry1>::type,
+ typename select_coordinate_type
+ <
+ Geometry2,
+ Geometry3
+ >::type
+ >::type,
+ CalculationType,
+ DefaultFloatingPointCalculationType,
+ DefaultIntegralCalculationType
+ >::type type;
+};
+
+}} // namespace calculation_type::geometric
+
+} // namespace util
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_UTIL_CALCULATION_TYPE_HPP
diff --git a/boost/geometry/util/closure_as_bool.hpp b/boost/geometry/util/closure_as_bool.hpp
new file mode 100644
index 000000000..57fcd5280
--- /dev/null
+++ b/boost/geometry/util/closure_as_bool.hpp
@@ -0,0 +1,46 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_CLOSURE_AS_BOOL_HPP
+#define BOOST_GEOMETRY_UTIL_CLOSURE_AS_BOOL_HPP
+
+#include <boost/geometry/core/closure.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+template<closure_selector Closure>
+struct closure_as_bool
+{};
+
+
+template<>
+struct closure_as_bool<closed>
+{
+ static const bool value = true;
+};
+
+
+template<>
+struct closure_as_bool<open>
+{
+ static const bool value = false;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_UTIL_CLOSURE_AS_BOOL_HPP
diff --git a/boost/geometry/util/coordinate_cast.hpp b/boost/geometry/util/coordinate_cast.hpp
new file mode 100644
index 000000000..16a15cca5
--- /dev/null
+++ b/boost/geometry/util/coordinate_cast.hpp
@@ -0,0 +1,55 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_COORDINATE_CAST_HPP
+#define BOOST_GEOMETRY_UTIL_COORDINATE_CAST_HPP
+
+#include <cstdlib>
+#include <string>
+#include <boost/lexical_cast.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+/*!
+\brief cast coordinates from a string to a coordinate type
+\detail By default it uses lexical_cast. However, lexical_cast seems not to support
+ ttmath / partial specializations. Therefore this small utility is added.
+ See also "define_pi" where the same issue is solved
+*/
+template <typename CoordinateType>
+struct coordinate_cast
+{
+ static inline CoordinateType apply(std::string const& source)
+ {
+#if defined(BOOST_GEOMETRY_NO_LEXICAL_CAST)
+ return atof(source.c_str());
+#else
+ return boost::lexical_cast<CoordinateType>(source);
+#endif
+ }
+};
+
+
+} // namespace detail
+#endif
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_UTIL_COORDINATE_CAST_HPP
diff --git a/boost/geometry/util/for_each_coordinate.hpp b/boost/geometry/util/for_each_coordinate.hpp
new file mode 100644
index 000000000..7a1f55b00
--- /dev/null
+++ b/boost/geometry/util/for_each_coordinate.hpp
@@ -0,0 +1,94 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_FOR_EACH_COORDINATE_HPP
+#define BOOST_GEOMETRY_UTIL_FOR_EACH_COORDINATE_HPP
+
+#include <boost/concept/requires.hpp>
+#include <boost/geometry/geometries/concepts/point_concept.hpp>
+#include <boost/geometry/util/add_const_if_c.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Point, int Dimension, int DimensionCount, bool IsConst>
+struct coordinates_scanner
+{
+ template <typename Op>
+ static inline Op apply(typename add_const_if_c
+ <
+ IsConst,
+ Point
+ >::type& point, Op operation)
+ {
+ operation.template apply<Point, Dimension>(point);
+ return coordinates_scanner
+ <
+ Point,
+ Dimension+1,
+ DimensionCount,
+ IsConst
+ >::apply(point, operation);
+ }
+};
+
+template <typename Point, int DimensionCount, bool IsConst>
+struct coordinates_scanner<Point, DimensionCount, DimensionCount, IsConst>
+{
+ template <typename Op>
+ static inline Op apply(typename add_const_if_c
+ <
+ IsConst,
+ Point
+ >::type& , Op operation)
+ {
+ return operation;
+ }
+};
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+template <typename Point, typename Op>
+inline void for_each_coordinate(Point& point, Op operation)
+{
+ BOOST_CONCEPT_ASSERT( (concept::Point<Point>) );
+
+ typedef typename detail::coordinates_scanner
+ <
+ Point, 0, dimension<Point>::type::value, false
+ > scanner;
+
+ scanner::apply(point, operation);
+}
+
+template <typename Point, typename Op>
+inline Op for_each_coordinate(Point const& point, Op operation)
+{
+ BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point>) );
+
+ typedef typename detail::coordinates_scanner
+ <
+ Point, 0, dimension<Point>::type::value, true
+ > scanner;
+
+ return scanner::apply(point, operation);
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_UTIL_FOR_EACH_COORDINATE_HPP
diff --git a/boost/geometry/util/math.hpp b/boost/geometry/util/math.hpp
new file mode 100644
index 000000000..8c152edd2
--- /dev/null
+++ b/boost/geometry/util/math.hpp
@@ -0,0 +1,237 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_MATH_HPP
+#define BOOST_GEOMETRY_UTIL_MATH_HPP
+
+#include <cmath>
+#include <limits>
+
+#include <boost/math/constants/constants.hpp>
+
+#include <boost/geometry/util/select_most_precise.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace math
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template <typename Type, bool IsFloatingPoint>
+struct equals
+{
+ static inline bool apply(Type const& a, Type const& b)
+ {
+ return a == b;
+ }
+};
+
+template <typename Type>
+struct equals<Type, true>
+{
+ static inline Type get_max(Type const& a, Type const& b, Type const& c)
+ {
+ return (std::max)((std::max)(a, b), c);
+ }
+
+ static inline bool apply(Type const& a, Type const& b)
+ {
+ if (a == b)
+ {
+ return true;
+ }
+
+ // See http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17,
+ // FUTURE: replace by some boost tool or boost::test::close_at_tolerance
+ return std::abs(a - b) <= std::numeric_limits<Type>::epsilon() * get_max(std::abs(a), std::abs(b), 1.0);
+ }
+};
+
+template <typename Type, bool IsFloatingPoint>
+struct smaller
+{
+ static inline bool apply(Type const& a, Type const& b)
+ {
+ return a < b;
+ }
+};
+
+template <typename Type>
+struct smaller<Type, true>
+{
+ static inline bool apply(Type const& a, Type const& b)
+ {
+ if (equals<Type, true>::apply(a, b))
+ {
+ return false;
+ }
+ return a < b;
+ }
+};
+
+
+template <typename Type, bool IsFloatingPoint>
+struct equals_with_epsilon : public equals<Type, IsFloatingPoint> {};
+
+
+/*!
+\brief Short construct to enable partial specialization for PI, currently not possible in Math.
+*/
+template <typename T>
+struct define_pi
+{
+ static inline T apply()
+ {
+ // Default calls Boost.Math
+ return boost::math::constants::pi<T>();
+ }
+};
+
+template <typename T>
+struct relaxed_epsilon
+{
+ static inline T apply(const T& factor)
+ {
+ return factor * std::numeric_limits<T>::epsilon();
+ }
+};
+
+
+} // namespace detail
+#endif
+
+
+template <typename T>
+inline T pi() { return detail::define_pi<T>::apply(); }
+
+template <typename T>
+inline T relaxed_epsilon(T const& factor)
+{
+ return detail::relaxed_epsilon<T>::apply(factor);
+}
+
+
+// Maybe replace this by boost equals or boost ublas numeric equals or so
+
+/*!
+ \brief returns true if both arguments are equal.
+ \ingroup utility
+ \param a first argument
+ \param b second argument
+ \return true if a == b
+ \note If both a and b are of an integral type, comparison is done by ==.
+ If one of the types is floating point, comparison is done by abs and
+ comparing with epsilon. If one of the types is non-fundamental, it might
+ be a high-precision number and comparison is done using the == operator
+ of that class.
+*/
+
+template <typename T1, typename T2>
+inline bool equals(T1 const& a, T2 const& b)
+{
+ typedef typename select_most_precise<T1, T2>::type select_type;
+ return detail::equals
+ <
+ select_type,
+ boost::is_floating_point<select_type>::type::value
+ >::apply(a, b);
+}
+
+template <typename T1, typename T2>
+inline bool equals_with_epsilon(T1 const& a, T2 const& b)
+{
+ typedef typename select_most_precise<T1, T2>::type select_type;
+ return detail::equals_with_epsilon
+ <
+ select_type,
+ boost::is_floating_point<select_type>::type::value
+ >::apply(a, b);
+}
+
+template <typename T1, typename T2>
+inline bool smaller(T1 const& a, T2 const& b)
+{
+ typedef typename select_most_precise<T1, T2>::type select_type;
+ return detail::smaller
+ <
+ select_type,
+ boost::is_floating_point<select_type>::type::value
+ >::apply(a, b);
+}
+
+template <typename T1, typename T2>
+inline bool larger(T1 const& a, T2 const& b)
+{
+ typedef typename select_most_precise<T1, T2>::type select_type;
+ return detail::smaller
+ <
+ select_type,
+ boost::is_floating_point<select_type>::type::value
+ >::apply(b, a);
+}
+
+
+
+double const d2r = geometry::math::pi<double>() / 180.0;
+double const r2d = 1.0 / d2r;
+
+/*!
+ \brief Calculates the haversine of an angle
+ \ingroup utility
+ \note See http://en.wikipedia.org/wiki/Haversine_formula
+ haversin(alpha) = sin2(alpha/2)
+*/
+template <typename T>
+inline T hav(T const& theta)
+{
+ T const half = T(0.5);
+ T const sn = sin(half * theta);
+ return sn * sn;
+}
+
+/*!
+\brief Short utility to return the square
+\ingroup utility
+\param value Value to calculate the square from
+\return The squared value
+*/
+template <typename T>
+inline T sqr(T const& value)
+{
+ return value * value;
+}
+
+
+/*!
+\brief Short utility to workaround gcc/clang problem that abs is converting to integer
+\ingroup utility
+*/
+template<typename T>
+inline T abs(const T& t)
+{
+ using std::abs;
+ return abs(t);
+}
+
+
+} // namespace math
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_UTIL_MATH_HPP
diff --git a/boost/geometry/util/order_as_direction.hpp b/boost/geometry/util/order_as_direction.hpp
new file mode 100644
index 000000000..6895ebf3f
--- /dev/null
+++ b/boost/geometry/util/order_as_direction.hpp
@@ -0,0 +1,46 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_ORDER_AS_DIRECTION_HPP
+#define BOOST_GEOMETRY_UTIL_ORDER_AS_DIRECTION_HPP
+
+#include <boost/geometry/core/point_order.hpp>
+#include <boost/geometry/views/reversible_view.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+template<order_selector Order>
+struct order_as_direction
+{};
+
+
+template<>
+struct order_as_direction<clockwise>
+{
+ static const iterate_direction value = iterate_forward;
+};
+
+
+template<>
+struct order_as_direction<counterclockwise>
+{
+ static const iterate_direction value = iterate_reverse;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_UTIL_ORDER_AS_DIRECTION_HPP
diff --git a/boost/geometry/util/parameter_type_of.hpp b/boost/geometry/util/parameter_type_of.hpp
new file mode 100644
index 000000000..b8872d52b
--- /dev/null
+++ b/boost/geometry/util/parameter_type_of.hpp
@@ -0,0 +1,75 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_PARAMETER_TYPE_OF_HPP
+#define BOOST_GEOMETRY_UTIL_PARAMETER_TYPE_OF_HPP
+
+
+#include <boost/function_types/function_arity.hpp>
+#include <boost/function_types/is_member_function_pointer.hpp>
+#include <boost/function_types/parameter_types.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/plus.hpp>
+#include <boost/type_traits.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+\brief Meta-function selecting a parameter type of a (member) function, by index
+\ingroup utility
+ */
+template <typename Method, std::size_t Index>
+struct parameter_type_of
+{
+ typedef typename boost::function_types::parameter_types
+ <
+ Method
+ >::type parameter_types;
+
+ typedef typename boost::mpl::if_
+ <
+ boost::function_types::is_member_function_pointer<Method>,
+ boost::mpl::int_<1>,
+ boost::mpl::int_<0>
+ >::type base_index_type;
+
+ typedef typename boost::mpl::if_c
+ <
+ Index == 0,
+ base_index_type,
+ typename boost::mpl::plus
+ <
+ base_index_type,
+ boost::mpl::int_<Index>
+ >::type
+ >::type indexed_type;
+
+ typedef typename boost::remove_reference
+ <
+ typename boost::mpl::at
+ <
+ parameter_types,
+ indexed_type
+ >::type
+ >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_UTIL_PARAMETER_TYPE_OF_HPP
diff --git a/boost/geometry/util/promote_floating_point.hpp b/boost/geometry/util/promote_floating_point.hpp
new file mode 100644
index 000000000..0c74cb8d6
--- /dev/null
+++ b/boost/geometry/util/promote_floating_point.hpp
@@ -0,0 +1,50 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
+#define BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Meta-function converting, if necessary, to "a floating point" type
+ \details
+ - if input type is integer, type is double
+ - else type is input type
+ \ingroup utility
+ */
+
+template <typename T, typename PromoteIntegerTo = double>
+struct promote_floating_point
+{
+ typedef typename
+ boost::mpl::if_
+ <
+ boost::is_integral<T>,
+ PromoteIntegerTo,
+ T
+ >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
diff --git a/boost/geometry/util/rational.hpp b/boost/geometry/util/rational.hpp
new file mode 100644
index 000000000..b397532bc
--- /dev/null
+++ b/boost/geometry/util/rational.hpp
@@ -0,0 +1,179 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2011-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2011-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_RATIONAL_HPP
+#define BOOST_GEOMETRY_UTIL_RATIONAL_HPP
+
+#include <boost/rational.hpp>
+#include <boost/numeric/conversion/bounds.hpp>
+
+#include <boost/geometry/util/coordinate_cast.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+namespace boost{ namespace geometry
+{
+
+
+// Specialize for Boost.Geometry's coordinate cast
+// (from string to coordinate type)
+namespace detail
+{
+
+template <typename T>
+struct coordinate_cast<rational<T> >
+{
+ static inline void split_parts(std::string const& source, std::string::size_type p,
+ T& before, T& after, bool& negate, std::string::size_type& len)
+ {
+ std::string before_part = source.substr(0, p);
+ std::string const after_part = source.substr(p + 1);
+
+ negate = false;
+
+ if (before_part.size() > 0 && before_part[0] == '-')
+ {
+ negate = true;
+ before_part.erase(0, 1);
+ }
+ before = atol(before_part.c_str());
+ after = atol(after_part.c_str());
+ len = after_part.length();
+ }
+
+
+ static inline rational<T> apply(std::string const& source)
+ {
+ T before, after;
+ bool negate;
+ std::string::size_type len;
+
+ // Note: decimal comma is not (yet) supported, it does (and should) not
+ // occur in a WKT, where points are comma separated.
+ std::string::size_type p = source.find(".");
+ if (p == std::string::npos)
+ {
+ p = source.find("/");
+ if (p == std::string::npos)
+ {
+ return rational<T>(atol(source.c_str()));
+ }
+ split_parts(source, p, before, after, negate, len);
+
+ return negate
+ ? -rational<T>(before, after)
+ : rational<T>(before, after)
+ ;
+
+ }
+
+ split_parts(source, p, before, after, negate, len);
+
+ T den = 1;
+ for (std::string::size_type i = 0; i < len; i++)
+ {
+ den *= 10;
+ }
+
+ return negate
+ ? -rational<T>(before) - rational<T>(after, den)
+ : rational<T>(before) + rational<T>(after, den)
+ ;
+ }
+};
+
+} // namespace detail
+
+// Specialize for Boost.Geometry's select_most_precise
+template <typename T1, typename T2>
+struct select_most_precise<boost::rational<T1>, boost::rational<T2> >
+{
+ typedef typename boost::rational
+ <
+ typename select_most_precise<T1, T2>::type
+ > type;
+};
+
+template <typename T>
+struct select_most_precise<boost::rational<T>, double>
+{
+ typedef typename boost::rational<T> type;
+};
+
+
+}} // namespace boost::geometry
+
+
+// Specializes boost::rational to boost::numeric::bounds
+namespace boost { namespace numeric
+{
+
+template<class T>
+struct bounds<rational<T> >
+{
+ static inline rational<T> lowest()
+ {
+ return rational<T>(bounds<T>::lowest(), 1);
+ }
+ static inline rational<T> highest()
+ {
+ return rational<T>(bounds<T>::highest(), 1);
+ }
+};
+
+}} // namespace boost::numeric
+
+
+// Support for boost::numeric_cast to int and to double (necessary for SVG-mapper)
+namespace boost { namespace numeric
+{
+
+template
+<
+ typename T,
+ typename Traits,
+ typename OverflowHandler,
+ typename Float2IntRounder,
+ typename RawConverter,
+ typename UserRangeChecker
+>
+struct converter<int, rational<T>, Traits, OverflowHandler, Float2IntRounder, RawConverter, UserRangeChecker>
+{
+ static inline int convert(rational<T> const& arg)
+ {
+ return int(rational_cast<double>(arg));
+ }
+};
+
+template
+<
+ typename T,
+ typename Traits,
+ typename OverflowHandler,
+ typename Float2IntRounder,
+ typename RawConverter,
+ typename UserRangeChecker
+>
+struct converter<double, rational<T>, Traits, OverflowHandler, Float2IntRounder, RawConverter, UserRangeChecker>
+{
+ static inline double convert(rational<T> const& arg)
+ {
+ return rational_cast<double>(arg);
+ }
+};
+
+
+}}
+
+
+#endif // BOOST_GEOMETRY_UTIL_RATIONAL_HPP
diff --git a/boost/geometry/util/readme.txt b/boost/geometry/util/readme.txt
new file mode 100644
index 000000000..7a1bf88be
--- /dev/null
+++ b/boost/geometry/util/readme.txt
@@ -0,0 +1,17 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2011 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2011 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+This folder contains several headerfiles not fitting in one of the other folders,
+or meta-functions which would fit into boost as a separate trait or utility,
+such as add_const_if_c
+
diff --git a/boost/geometry/util/select_calculation_type.hpp b/boost/geometry/util/select_calculation_type.hpp
new file mode 100644
index 000000000..4946c45e8
--- /dev/null
+++ b/boost/geometry/util/select_calculation_type.hpp
@@ -0,0 +1,57 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_SELECT_CALCULATION_TYPE_HPP
+#define BOOST_GEOMETRY_UTIL_SELECT_CALCULATION_TYPE_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/util/select_coordinate_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Meta-function selecting the "calculation" type
+ \details Based on two input geometry types, and an input calculation type,
+ (which defaults to void in the calling function), this meta-function
+ selects the most appropriate:
+ - if calculation type is specified, that one is used,
+ - if it is void, the most precise of the two points is used
+ \ingroup utility
+ */
+template <typename Geometry1, typename Geometry2, typename CalculationType>
+struct select_calculation_type
+{
+ typedef typename
+ boost::mpl::if_
+ <
+ boost::is_void<CalculationType>,
+ typename select_coordinate_type
+ <
+ Geometry1,
+ Geometry2
+ >::type,
+ CalculationType
+ >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_UTIL_SELECT_CALCULATION_TYPE_HPP
diff --git a/boost/geometry/util/select_coordinate_type.hpp b/boost/geometry/util/select_coordinate_type.hpp
new file mode 100644
index 000000000..8309da42b
--- /dev/null
+++ b/boost/geometry/util/select_coordinate_type.hpp
@@ -0,0 +1,45 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_SELECT_COORDINATE_TYPE_HPP
+#define BOOST_GEOMETRY_UTIL_SELECT_COORDINATE_TYPE_HPP
+
+
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+ \brief Meta-function selecting the most precise coordinate type
+ of two geometries
+ \ingroup utility
+ */
+template <typename T1, typename T2>
+struct select_coordinate_type
+{
+ typedef typename select_most_precise
+ <
+ typename coordinate_type<T1>::type,
+ typename coordinate_type<T2>::type
+ >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_UTIL_SELECT_COORDINATE_TYPE_HPP
diff --git a/boost/geometry/util/select_most_precise.hpp b/boost/geometry/util/select_most_precise.hpp
new file mode 100644
index 000000000..d55fdbfd9
--- /dev/null
+++ b/boost/geometry/util/select_most_precise.hpp
@@ -0,0 +1,162 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
+#define BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+
+namespace detail { namespace select_most_precise
+{
+
+
+// At least one of the types is non-fundamental. Take that one.
+// if both are non-fundamental, the type-to-be-selected
+// is unknown, it should be defined by explicit specialization.
+template <bool Fundamental1, bool Fundamental2, typename T1, typename T2>
+struct select_non_fundamental
+{
+ typedef T1 type;
+};
+
+template <typename T1, typename T2>
+struct select_non_fundamental<true, false, T1, T2>
+{
+ typedef T2 type;
+};
+
+template <typename T1, typename T2>
+struct select_non_fundamental<false, true, T1, T2>
+{
+ typedef T1 type;
+};
+
+
+// Selection of largest type (e.g. int of <short int,int>
+// It defaults takes the first one, if second is larger, take the second one
+template <bool SecondLarger, typename T1, typename T2>
+struct select_largest
+{
+ typedef T1 type;
+};
+
+template <typename T1, typename T2>
+struct select_largest<true, T1, T2>
+{
+ typedef T2 type;
+};
+
+
+
+// Selection of floating point and specializations:
+// both FP or both !FP does never occur...
+template <bool FP1, bool FP2, typename T1, typename T2>
+struct select_floating_point
+{
+ typedef char type;
+};
+
+
+// ... so if ONE but not both of these types is floating point, take that one
+template <typename T1, typename T2>
+struct select_floating_point<true, false, T1, T2>
+{
+ typedef T1 type;
+};
+
+
+template <typename T1, typename T2>
+struct select_floating_point<false, true, T1, T2>
+{
+ typedef T2 type;
+};
+
+
+}} // namespace detail::select_most_precise
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+ \brief Meta-function to select, of two types, the most accurate type for
+ calculations
+ \ingroup utility
+ \details select_most_precise classes, compares two types on compile time.
+ For example, if an addition must be done with a double and an integer, the
+ result must be a double.
+ If both types are integer, the result can be an integer.
+ \note It is different from the "promote" class, already in boost. That
+ class promotes e.g. a (one) float to a double. This class selects a
+ type from two types. It takes the most accurate, but does not promote
+ afterwards.
+ \note This traits class is completely independant from GGL and might be a
+ separate addition to Boost
+ \note If the input is a non-fundamental type, it might be a calculation
+ type such as a GMP-value or another high precision value. Therefore,
+ if one is non-fundamental, that one is chosen.
+ \note If both types are non-fundamental, the result is indeterminate and
+ currently the first one is chosen.
+*/
+template <typename T1, typename T2>
+struct select_most_precise
+{
+ static const bool second_larger = sizeof(T2) > sizeof(T1);
+ static const bool one_not_fundamental = !
+ (boost::is_fundamental<T1>::type::value
+ && boost::is_fundamental<T2>::type::value);
+
+ static const bool both_same =
+ boost::is_floating_point<T1>::type::value
+ == boost::is_floating_point<T2>::type::value;
+
+ typedef typename boost::mpl::if_c
+ <
+ one_not_fundamental,
+ typename detail::select_most_precise::select_non_fundamental
+ <
+ boost::is_fundamental<T1>::type::value,
+ boost::is_fundamental<T2>::type::value,
+ T1,
+ T2
+ >::type,
+ typename boost::mpl::if_c
+ <
+ both_same,
+ typename detail::select_most_precise::select_largest
+ <
+ second_larger,
+ T1,
+ T2
+ >::type,
+ typename detail::select_most_precise::select_floating_point
+ <
+ boost::is_floating_point<T1>::type::value,
+ boost::is_floating_point<T2>::type::value,
+ T1,
+ T2
+ >::type
+ >::type
+ >::type type;
+};
+
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_UTIL_SELECT_MOST_PRECISE_HPP
diff --git a/boost/geometry/views/box_view.hpp b/boost/geometry/views/box_view.hpp
new file mode 100644
index 000000000..26608b086
--- /dev/null
+++ b/boost/geometry/views/box_view.hpp
@@ -0,0 +1,114 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_VIEWS_BOX_VIEW_HPP
+#define BOOST_GEOMETRY_VIEWS_BOX_VIEW_HPP
+
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/views/detail/points_view.hpp>
+#include <boost/geometry/algorithms/assign.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+\brief Makes a box behave like a ring or a range
+\details Adapts a box to the Boost.Range concept, enabling the user to iterating
+ box corners. The box_view is registered as a Ring Concept
+\tparam Box \tparam_geometry{Box}
+\tparam Clockwise If true, walks in clockwise direction, otherwise
+ it walks in counterclockwise direction
+\ingroup views
+
+\qbk{before.synopsis,
+[heading Model of]
+[link geometry.reference.concepts.concept_ring Ring Concept]
+}
+
+\qbk{[include reference/views/box_view.qbk]}
+*/
+template <typename Box, bool Clockwise = true>
+struct box_view
+ : public detail::points_view
+ <
+ typename geometry::point_type<Box>::type,
+ 5
+ >
+{
+ typedef typename geometry::point_type<Box>::type point_type;
+
+ /// Constructor accepting the box to adapt
+ explicit box_view(Box const& box)
+ : detail::points_view<point_type, 5>(copy_policy(box))
+ {}
+
+private :
+
+ class copy_policy
+ {
+ public :
+ inline copy_policy(Box const& box)
+ : m_box(box)
+ {}
+
+ inline void apply(point_type* points) const
+ {
+ detail::assign_box_corners_oriented<!Clockwise>(m_box, points);
+ points[4] = points[0];
+ }
+ private :
+ Box const& m_box;
+ };
+
+};
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+// All views on boxes are handled as rings
+namespace traits
+{
+
+template<typename Box, bool Clockwise>
+struct tag<box_view<Box, Clockwise> >
+{
+ typedef ring_tag type;
+};
+
+template<typename Box>
+struct point_order<box_view<Box, false> >
+{
+ static order_selector const value = counterclockwise;
+};
+
+
+template<typename Box>
+struct point_order<box_view<Box, true> >
+{
+ static order_selector const value = clockwise;
+};
+
+}
+
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_VIEWS_BOX_VIEW_HPP
diff --git a/boost/geometry/views/closeable_view.hpp b/boost/geometry/views/closeable_view.hpp
new file mode 100644
index 000000000..882de1ae6
--- /dev/null
+++ b/boost/geometry/views/closeable_view.hpp
@@ -0,0 +1,109 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_VIEWS_CLOSEABLE_VIEW_HPP
+#define BOOST_GEOMETRY_VIEWS_CLOSEABLE_VIEW_HPP
+
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/iterators/closing_iterator.hpp>
+
+#include <boost/geometry/views/identity_view.hpp>
+
+namespace boost { namespace geometry
+{
+
+// Silence warning C4512: assignment operator could not be generated
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4512)
+#endif
+
+#ifndef DOXYGEN_NO_DETAIL
+
+namespace detail
+{
+
+template <typename Range>
+struct closing_view
+{
+ // Keep this explicit, important for nested views/ranges
+ explicit inline closing_view(Range& r)
+ : m_range(r)
+ {}
+
+ typedef closing_iterator<Range> iterator;
+ typedef closing_iterator<Range const> const_iterator;
+
+ inline const_iterator begin() const { return const_iterator(m_range); }
+ inline const_iterator end() const { return const_iterator(m_range, true); }
+
+ inline iterator begin() { return iterator(m_range); }
+ inline iterator end() { return iterator(m_range, true); }
+private :
+ Range& m_range;
+};
+
+}
+
+#endif // DOXYGEN_NO_DETAIL
+
+
+/*!
+\brief View on a range, either closing it or leaving it as it is
+\details The closeable_view is used internally by the library to handle all rings,
+ either closed or open, the same way. The default method is closed, all
+ algorithms process rings as if they are closed. Therefore, if they are opened,
+ a view is created which closes them.
+ The closeable_view might be used by library users, but its main purpose is
+ internally.
+\tparam Range Original range
+\tparam Close Specifies if it the range is closed, if so, nothing will happen.
+ If it is open, it will iterate the first point after the last point.
+\ingroup views
+*/
+template <typename Range, closure_selector Close>
+struct closeable_view {};
+
+
+#ifndef DOXYGEN_NO_SPECIALIZATIONS
+
+template <typename Range>
+struct closeable_view<Range, closed>
+{
+ typedef identity_view<Range> type;
+};
+
+
+template <typename Range>
+struct closeable_view<Range, open>
+{
+ typedef detail::closing_view<Range> type;
+};
+
+#endif // DOXYGEN_NO_SPECIALIZATIONS
+
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_VIEWS_CLOSEABLE_VIEW_HPP
diff --git a/boost/geometry/views/detail/points_view.hpp b/boost/geometry/views/detail/points_view.hpp
new file mode 100644
index 000000000..91fbc41c1
--- /dev/null
+++ b/boost/geometry/views/detail/points_view.hpp
@@ -0,0 +1,141 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_POINTS_VIEW_HPP
+#define BOOST_GEOMETRY_VIEWS_DETAIL_POINTS_VIEW_HPP
+
+
+#include <boost/range.hpp>
+#include <boost/iterator.hpp>
+#include <boost/iterator/iterator_facade.hpp>
+#include <boost/iterator/iterator_categories.hpp>
+
+#include <boost/geometry/core/exception.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace detail
+{
+
+// Adapts pointer, on points, to a Boost.Range
+template <typename Point, int MaxSize>
+class points_view
+{
+ // Iterates over a series of points (indicated by pointer
+ // to have it lightweight). Probably there is already an
+ // equivalent of this within Boost. If so, TODO: use that one.
+ // This used to be "box_iterator" and "segment_iterator".
+ struct points_iterator
+ : public boost::iterator_facade
+ <
+ points_iterator,
+ Point const,
+ boost::random_access_traversal_tag
+ >
+ {
+ // Constructor: Begin iterator
+ inline points_iterator(Point const* p)
+ : m_points(p)
+ , m_index(0)
+ {}
+
+ // Constructor: End iterator
+ inline points_iterator(Point const* p, bool)
+ : m_points(p)
+ , m_index(MaxSize)
+ {}
+
+ // Constructor: default (for Range Concept checking).
+ inline points_iterator()
+ : m_points(NULL)
+ , m_index(MaxSize)
+ {}
+
+ typedef std::ptrdiff_t difference_type;
+
+ private:
+ friend class boost::iterator_core_access;
+
+ inline Point const& dereference() const
+ {
+ if (m_index >= 0 && m_index < MaxSize)
+ {
+ return m_points[m_index];
+ }
+
+ // If it index larger (or smaller) return first point
+ // (assuming initialized)
+ return m_points[0];
+ }
+
+ inline bool equal(points_iterator const& other) const
+ {
+ return other.m_index == this->m_index;
+ }
+
+ inline void increment()
+ {
+ m_index++;
+ }
+
+ inline void decrement()
+ {
+ m_index--;
+ }
+
+ inline difference_type distance_to(points_iterator const& other) const
+ {
+ return other.m_index - this->m_index;
+ }
+
+ inline void advance(difference_type n)
+ {
+ m_index += n;
+ }
+
+ Point const* m_points;
+ int m_index;
+ };
+
+public :
+
+ typedef points_iterator const_iterator;
+ typedef points_iterator iterator; // must be defined
+
+ const_iterator begin() const { return const_iterator(m_points); }
+ const_iterator end() const { return const_iterator(m_points, true); }
+
+ // It may NOT be used non-const, so commented:
+ //iterator begin() { return m_begin; }
+ //iterator end() { return m_end; }
+
+protected :
+
+ template <typename CopyPolicy>
+ explicit points_view(CopyPolicy const& copy)
+ {
+ copy.apply(m_points);
+ }
+
+private :
+ // Copy points here - box might define them otherwise
+ Point m_points[MaxSize];
+};
+
+}
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_VIEWS_DETAIL_POINTS_VIEW_HPP
diff --git a/boost/geometry/views/detail/range_type.hpp b/boost/geometry/views/detail/range_type.hpp
new file mode 100644
index 000000000..a40670cf9
--- /dev/null
+++ b/boost/geometry/views/detail/range_type.hpp
@@ -0,0 +1,106 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_RANGE_TYPE_HPP
+#define BOOST_GEOMETRY_VIEWS_DETAIL_RANGE_TYPE_HPP
+
+
+#include <boost/mpl/assert.hpp>
+#include <boost/type_traits.hpp>
+
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/views/box_view.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename GeometryTag, typename Geometry>
+struct range_type
+{
+ BOOST_MPL_ASSERT_MSG
+ (
+ false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
+ , (types<Geometry>)
+ );
+};
+
+
+template <typename Geometry>
+struct range_type<ring_tag, Geometry>
+{
+ typedef Geometry type;
+};
+
+template <typename Geometry>
+struct range_type<linestring_tag, Geometry>
+{
+ typedef Geometry type;
+};
+
+
+template <typename Geometry>
+struct range_type<polygon_tag, Geometry>
+{
+ typedef typename ring_type<Geometry>::type type;
+};
+
+template <typename Geometry>
+struct range_type<box_tag, Geometry>
+{
+ typedef box_view<Geometry> type;
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+// Will probably be replaced by the more generic "view_as", therefore in detail
+namespace detail
+{
+
+
+/*!
+\brief Meta-function defining a type which is a boost-range.
+\details
+- For linestrings and rings, it defines the type itself.
+- For polygons it defines the ring type.
+- For multi-points, it defines the type itself
+- For multi-polygons and multi-linestrings, it defines the single-version
+ (so in the end the linestring and ring-type-of-multi-polygon)
+\ingroup iterators
+*/
+template <typename Geometry>
+struct range_type
+{
+ typedef typename dispatch::range_type
+ <
+ typename tag<Geometry>::type,
+ Geometry
+ >::type type;
+};
+
+}
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_VIEWS_DETAIL_RANGE_TYPE_HPP
diff --git a/boost/geometry/views/identity_view.hpp b/boost/geometry/views/identity_view.hpp
new file mode 100644
index 000000000..5cb9d91f7
--- /dev/null
+++ b/boost/geometry/views/identity_view.hpp
@@ -0,0 +1,61 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_VIEWS_IDENTITY_VIEW_HPP
+#define BOOST_GEOMETRY_VIEWS_IDENTITY_VIEW_HPP
+
+
+#include <boost/range.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+// Silence warning C4512: assignment operator could not be generated
+#if defined(_MSC_VER)
+#pragma warning(push)
+#pragma warning(disable : 4512)
+#endif
+
+/*!
+\brief View on a range, not modifying anything
+\tparam Range original range
+\ingroup views
+*/
+template <typename Range>
+struct identity_view
+{
+ typedef typename boost::range_iterator<Range const>::type const_iterator;
+ typedef typename boost::range_iterator<Range>::type iterator;
+
+ explicit inline identity_view(Range& r)
+ : m_range(r)
+ {}
+
+ inline const_iterator begin() const { return boost::begin(m_range); }
+ inline const_iterator end() const { return boost::end(m_range); }
+
+ inline iterator begin() { return boost::begin(m_range); }
+ inline iterator end() { return boost::end(m_range); }
+private :
+ Range& m_range;
+};
+
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_VIEWS_IDENTITY_VIEW_HPP
diff --git a/boost/geometry/views/reversible_view.hpp b/boost/geometry/views/reversible_view.hpp
new file mode 100644
index 000000000..ad22136c8
--- /dev/null
+++ b/boost/geometry/views/reversible_view.hpp
@@ -0,0 +1,74 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_VIEWS_REVERSIBLE_VIEW_HPP
+#define BOOST_GEOMETRY_VIEWS_REVERSIBLE_VIEW_HPP
+
+
+#include <boost/version.hpp>
+#include <boost/range.hpp>
+#include <boost/range/adaptor/reversed.hpp>
+
+#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/views/identity_view.hpp>
+
+namespace boost { namespace geometry
+{
+
+/*!
+\brief Flag for iterating a reversible_view in forward or reverse direction
+\ingroup views
+*/
+enum iterate_direction { iterate_forward, iterate_reverse };
+
+/*!
+\brief View on a range, reversing direction if necessary
+\tparam Range original range
+\tparam Direction direction of iteration
+\ingroup views
+*/
+template <typename Range, iterate_direction Direction>
+struct reversible_view {};
+
+
+
+#ifndef DOXYGEN_NO_SPECIALIZATIONS
+
+template <typename Range>
+struct reversible_view<Range, iterate_forward>
+{
+ typedef identity_view<Range> type;
+};
+
+
+template <typename Range>
+struct reversible_view<Range, iterate_reverse>
+{
+#if BOOST_VERSION > 104500
+ typedef boost::reversed_range<Range> type;
+#else
+ // For older versions of Boost
+ typedef boost::range_detail::reverse_range<Range> type;
+#endif
+};
+
+#endif // DOXYGEN_NO_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_VIEWS_REVERSIBLE_VIEW_HPP
diff --git a/boost/geometry/views/segment_view.hpp b/boost/geometry/views/segment_view.hpp
new file mode 100644
index 000000000..50ff617a8
--- /dev/null
+++ b/boost/geometry/views/segment_view.hpp
@@ -0,0 +1,100 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
+
+// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
+// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
+
+// Use, modification and distribution is subject to the Boost Software License,
+// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_GEOMETRY_VIEWS_SEGMENT_VIEW_HPP
+#define BOOST_GEOMETRY_VIEWS_SEGMENT_VIEW_HPP
+
+
+#include <boost/range.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/views/detail/points_view.hpp>
+#include <boost/geometry/algorithms/assign.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+\brief Makes a segment behave like a linestring or a range
+\details Adapts a segment to the Boost.Range concept, enabling the user to
+ iterate the two segment points. The segment_view is registered as a LineString Concept
+\tparam Segment \tparam_geometry{Segment}
+\ingroup views
+
+\qbk{before.synopsis,
+[heading Model of]
+[link geometry.reference.concepts.concept_linestring LineString Concept]
+}
+
+\qbk{[include reference/views/segment_view.qbk]}
+
+*/
+template <typename Segment>
+struct segment_view
+ : public detail::points_view
+ <
+ typename geometry::point_type<Segment>::type,
+ 2
+ >
+{
+ typedef typename geometry::point_type<Segment>::type point_type;
+
+ /// Constructor accepting the segment to adapt
+ explicit segment_view(Segment const& segment)
+ : detail::points_view<point_type, 2>(copy_policy(segment))
+ {}
+
+private :
+
+ class copy_policy
+ {
+ public :
+ inline copy_policy(Segment const& segment)
+ : m_segment(segment)
+ {}
+
+ inline void apply(point_type* points) const
+ {
+ geometry::detail::assign_point_from_index<0>(m_segment, points[0]);
+ geometry::detail::assign_point_from_index<1>(m_segment, points[1]);
+ }
+ private :
+ Segment const& m_segment;
+ };
+
+};
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+// All segment ranges can be handled as linestrings
+namespace traits
+{
+
+template<typename Segment>
+struct tag<segment_view<Segment> >
+{
+ typedef linestring_tag type;
+};
+
+}
+
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_VIEWS_SEGMENT_VIEW_HPP