summaryrefslogtreecommitdiff
path: root/boost/geometry
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry')
-rw-r--r--boost/geometry/algorithms/append.hpp12
-rw-r--r--boost/geometry/algorithms/area.hpp13
-rw-r--r--boost/geometry/algorithms/area_result.hpp11
-rw-r--r--boost/geometry/algorithms/assign.hpp60
-rw-r--r--boost/geometry/algorithms/azimuth.hpp16
-rw-r--r--boost/geometry/algorithms/buffer.hpp256
-rw-r--r--boost/geometry/algorithms/centroid.hpp86
-rw-r--r--boost/geometry/algorithms/clear.hpp6
-rw-r--r--boost/geometry/algorithms/closest_points.hpp16
-rw-r--r--boost/geometry/algorithms/convert.hpp39
-rw-r--r--boost/geometry/algorithms/correct.hpp268
-rw-r--r--boost/geometry/algorithms/correct_closure.hpp114
-rw-r--r--boost/geometry/algorithms/covered_by.hpp5
-rw-r--r--boost/geometry/algorithms/crosses.hpp285
-rw-r--r--boost/geometry/algorithms/densify.hpp129
-rw-r--r--boost/geometry/algorithms/detail/as_range.hpp91
-rw-r--r--[-rwxr-xr-x]boost/geometry/algorithms/detail/buffer/buffer_box.hpp0
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp84
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffer_policies.hpp2
-rw-r--r--boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp228
-rw-r--r--boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp17
-rw-r--r--boost/geometry/algorithms/detail/buffer/implementation.hpp214
-rw-r--r--boost/geometry/algorithms/detail/buffer/interface.hpp279
-rw-r--r--boost/geometry/algorithms/detail/buffer/piece_border.hpp63
-rw-r--r--boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp21
-rw-r--r--boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp55
-rw-r--r--boost/geometry/algorithms/detail/calculate_point_order.hpp45
-rw-r--r--boost/geometry/algorithms/detail/calculate_sum.hpp3
-rw-r--r--boost/geometry/algorithms/detail/centroid/translating_transformer.hpp2
-rw-r--r--boost/geometry/algorithms/detail/check_iterator_range.hpp71
-rw-r--r--boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp4
-rw-r--r--boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp2
-rw-r--r--boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp2
-rw-r--r--boost/geometry/algorithms/detail/closest_points/implementation.hpp28
-rw-r--r--boost/geometry/algorithms/detail/closest_points/interface.hpp225
-rw-r--r--boost/geometry/algorithms/detail/closest_points/linear_or_areal_to_areal.hpp261
-rw-r--r--boost/geometry/algorithms/detail/closest_points/linear_to_linear.hpp155
-rw-r--r--boost/geometry/algorithms/detail/closest_points/multipoint_to_geometry.hpp325
-rw-r--r--boost/geometry/algorithms/detail/closest_points/point_to_geometry.hpp456
-rw-r--r--boost/geometry/algorithms/detail/closest_points/range_to_geometry_rtree.hpp110
-rw-r--r--boost/geometry/algorithms/detail/closest_points/segment_to_segment.hpp145
-rw-r--r--boost/geometry/algorithms/detail/closest_points/utilities.hpp69
-rw-r--r--boost/geometry/algorithms/detail/comparable_distance/interface.hpp278
-rw-r--r--boost/geometry/algorithms/detail/convert_point_to_point.hpp6
-rw-r--r--boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp131
-rw-r--r--boost/geometry/algorithms/detail/convex_hull/interface.hpp619
-rw-r--r--boost/geometry/algorithms/detail/counting.hpp15
-rw-r--r--boost/geometry/algorithms/detail/covered_by/implementation.hpp129
-rw-r--r--boost/geometry/algorithms/detail/covered_by/implementation_gc.hpp46
-rw-r--r--boost/geometry/algorithms/detail/covered_by/interface.hpp146
-rw-r--r--boost/geometry/algorithms/detail/direction_code.hpp134
-rw-r--r--boost/geometry/algorithms/detail/disjoint/areal_areal.hpp11
-rw-r--r--boost/geometry/algorithms/detail/disjoint/linear_areal.hpp41
-rw-r--r--boost/geometry/algorithms/detail/disjoint/linear_linear.hpp17
-rw-r--r--boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp57
-rw-r--r--boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp21
-rw-r--r--boost/geometry/algorithms/detail/disjoint/point_geometry.hpp6
-rw-r--r--boost/geometry/algorithms/detail/disjoint/segment_box.hpp5
-rw-r--r--boost/geometry/algorithms/detail/distance/geometry_collection.hpp237
-rw-r--r--boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp48
-rw-r--r--boost/geometry/algorithms/detail/distance/implementation.hpp3
-rw-r--r--boost/geometry/algorithms/detail/distance/interface.hpp254
-rw-r--r--boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp6
-rw-r--r--boost/geometry/algorithms/detail/distance/linear_to_linear.hpp2
-rw-r--r--boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp23
-rw-r--r--boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp2
-rw-r--r--boost/geometry/algorithms/detail/distance/segment_to_box.hpp12
-rw-r--r--boost/geometry/algorithms/detail/envelope/areal.hpp29
-rw-r--r--boost/geometry/algorithms/detail/envelope/geometry_collection.hpp62
-rw-r--r--boost/geometry/algorithms/detail/envelope/implementation.hpp3
-rw-r--r--boost/geometry/algorithms/detail/envelope/interface.hpp53
-rw-r--r--boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp4
-rw-r--r--boost/geometry/algorithms/detail/envelope/range.hpp73
-rw-r--r--boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp40
-rw-r--r--boost/geometry/algorithms/detail/equals/collect_vectors.hpp173
-rw-r--r--boost/geometry/algorithms/detail/equals/implementation.hpp117
-rw-r--r--boost/geometry/algorithms/detail/equals/implementation_gc.hpp114
-rw-r--r--boost/geometry/algorithms/detail/equals/interface.hpp159
-rw-r--r--boost/geometry/algorithms/detail/expand/indexed.hpp2
-rw-r--r--boost/geometry/algorithms/detail/expand/interface.hpp85
-rw-r--r--boost/geometry/algorithms/detail/expand_by_epsilon.hpp2
-rw-r--r--boost/geometry/algorithms/detail/extreme_points.hpp18
-rw-r--r--boost/geometry/algorithms/detail/gc_group_elements.hpp196
-rw-r--r--boost/geometry/algorithms/detail/gc_make_rtree.hpp118
-rw-r--r--boost/geometry/algorithms/detail/gc_topological_dimension.hpp51
-rw-r--r--boost/geometry/algorithms/detail/has_self_intersections.hpp4
-rw-r--r--boost/geometry/algorithms/detail/interior_iterator.hpp2
-rw-r--r--boost/geometry/algorithms/detail/intersection/areal_areal.hpp2
-rw-r--r--boost/geometry/algorithms/detail/intersection/gc.hpp329
-rw-r--r--boost/geometry/algorithms/detail/intersection/implementation.hpp5
-rw-r--r--boost/geometry/algorithms/detail/intersection/interface.hpp226
-rw-r--r--boost/geometry/algorithms/detail/intersection/multi.hpp73
-rw-r--r--boost/geometry/algorithms/detail/is_simple/areal.hpp23
-rw-r--r--boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp10
-rw-r--r--boost/geometry/algorithms/detail/is_simple/linear.hpp29
-rw-r--r--boost/geometry/algorithms/detail/is_simple/multipoint.hpp6
-rw-r--r--boost/geometry/algorithms/detail/is_valid/complement_graph.hpp16
-rw-r--r--boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp19
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp29
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_spikes.hpp21
-rw-r--r--boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp18
-rw-r--r--boost/geometry/algorithms/detail/is_valid/interface.hpp72
-rw-r--r--boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp2
-rw-r--r--boost/geometry/algorithms/detail/is_valid/linear.hpp32
-rw-r--r--boost/geometry/algorithms/detail/is_valid/multipolygon.hpp42
-rw-r--r--boost/geometry/algorithms/detail/is_valid/polygon.hpp34
-rw-r--r--boost/geometry/algorithms/detail/make/make.hpp14
-rw-r--r--boost/geometry/algorithms/detail/max_interval_gap.hpp2
-rw-r--r--boost/geometry/algorithms/detail/multi_modify.hpp21
-rw-r--r--boost/geometry/algorithms/detail/multi_modify_with_predicate.hpp5
-rw-r--r--boost/geometry/algorithms/detail/multi_sum.hpp9
-rw-r--r--boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp13
-rw-r--r--boost/geometry/algorithms/detail/overlaps/implementation.hpp78
-rw-r--r--boost/geometry/algorithms/detail/overlaps/interface.hpp103
-rw-r--r--boost/geometry/algorithms/detail/overlay/add_rings.hpp24
-rw-r--r--boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp21
-rw-r--r--boost/geometry/algorithms/detail/overlay/approximately_equals.hpp4
-rw-r--r--boost/geometry/algorithms/detail/overlay/assign_parents.hpp60
-rw-r--r--boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp16
-rw-r--r--boost/geometry/algorithms/detail/overlay/check_enrich.hpp27
-rw-r--r--boost/geometry/algorithms/detail/overlay/clip_linestring.hpp5
-rw-r--r--boost/geometry/algorithms/detail/overlay/cluster_exits.hpp32
-rw-r--r--boost/geometry/algorithms/detail/overlay/colocate_clusters.hpp107
-rw-r--r--boost/geometry/algorithms/detail/overlay/convert_ring.hpp1
-rw-r--r--boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp6
-rw-r--r--boost/geometry/algorithms/detail/overlay/copy_segments.hpp10
-rw-r--r--boost/geometry/algorithms/detail/overlay/discard_duplicate_turns.hpp6
-rw-r--r--boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp335
-rw-r--r--boost/geometry/algorithms/detail/overlay/follow.hpp46
-rw-r--r--boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp10
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_clusters.hpp18
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp87
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info.hpp420
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp8
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp44
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp38
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp61
-rw-r--r--boost/geometry/algorithms/detail/overlay/get_turns.hpp56
-rw-r--r--boost/geometry/algorithms/detail/overlay/handle_colocations.hpp118
-rw-r--r--boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp55
-rw-r--r--boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp2
-rw-r--r--boost/geometry/algorithms/detail/overlay/intersection_insert.hpp38
-rw-r--r--boost/geometry/algorithms/detail/overlay/is_self_turn.hpp3
-rw-r--r--boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp21
-rw-r--r--boost/geometry/algorithms/detail/overlay/linear_linear.hpp10
-rw-r--r--boost/geometry/algorithms/detail/overlay/overlay.hpp31
-rw-r--r--boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp2
-rw-r--r--boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp5
-rw-r--r--boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp29
-rw-r--r--boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp6
-rw-r--r--boost/geometry/algorithms/detail/overlay/ring_properties.hpp6
-rw-r--r--boost/geometry/algorithms/detail/overlay/select_rings.hpp44
-rw-r--r--boost/geometry/algorithms/detail/overlay/self_turn_points.hpp111
-rw-r--r--boost/geometry/algorithms/detail/overlay/sort_by_side.hpp36
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal.hpp175
-rw-r--r--boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp143
-rw-r--r--boost/geometry/algorithms/detail/overlay/traverse.hpp9
-rw-r--r--boost/geometry/algorithms/detail/overlay/turn_info.hpp10
-rw-r--r--boost/geometry/algorithms/detail/partition.hpp169
-rw-r--r--boost/geometry/algorithms/detail/point_on_border.hpp53
-rw-r--r--boost/geometry/algorithms/detail/recalculate.hpp7
-rw-r--r--boost/geometry/algorithms/detail/relate/areal_areal.hpp63
-rw-r--r--boost/geometry/algorithms/detail/relate/boundary_checker.hpp175
-rw-r--r--boost/geometry/algorithms/detail/relate/box_areal.hpp70
-rw-r--r--boost/geometry/algorithms/detail/relate/de9im.hpp39
-rw-r--r--boost/geometry/algorithms/detail/relate/follow_helpers.hpp130
-rw-r--r--boost/geometry/algorithms/detail/relate/implementation.hpp36
-rw-r--r--boost/geometry/algorithms/detail/relate/implementation_gc.hpp696
-rw-r--r--boost/geometry/algorithms/detail/relate/interface.hpp157
-rw-r--r--boost/geometry/algorithms/detail/relate/linear_areal.hpp513
-rw-r--r--boost/geometry/algorithms/detail/relate/linear_linear.hpp169
-rw-r--r--boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp69
-rw-r--r--boost/geometry/algorithms/detail/relate/point_geometry.hpp33
-rw-r--r--boost/geometry/algorithms/detail/relate/point_point.hpp89
-rw-r--r--boost/geometry/algorithms/detail/relate/result.hpp284
-rw-r--r--boost/geometry/algorithms/detail/relate/topology_check.hpp26
-rw-r--r--boost/geometry/algorithms/detail/relate/turns.hpp39
-rw-r--r--boost/geometry/algorithms/detail/relation/interface.hpp138
-rw-r--r--boost/geometry/algorithms/detail/sections/section_functions.hpp25
-rw-r--r--boost/geometry/algorithms/detail/sections/sectionalize.hpp200
-rw-r--r--boost/geometry/algorithms/detail/select_geometry_type.hpp78
-rw-r--r--boost/geometry/algorithms/detail/sweep.hpp7
-rw-r--r--boost/geometry/algorithms/detail/touches/implementation.hpp141
-rw-r--r--boost/geometry/algorithms/detail/touches/interface.hpp165
-rw-r--r--boost/geometry/algorithms/detail/tupled_output.hpp5
-rw-r--r--boost/geometry/algorithms/detail/turns/remove_duplicate_turns.hpp43
-rw-r--r--boost/geometry/algorithms/detail/visit.hpp70
-rw-r--r--boost/geometry/algorithms/detail/within/implementation.hpp16
-rw-r--r--boost/geometry/algorithms/detail/within/implementation_gc.hpp46
-rw-r--r--boost/geometry/algorithms/detail/within/interface.hpp151
-rw-r--r--boost/geometry/algorithms/detail/within/multi_point.hpp26
-rw-r--r--boost/geometry/algorithms/detail/within/point_in_geometry.hpp55
-rw-r--r--boost/geometry/algorithms/detail/within/within_no_turns.hpp93
-rw-r--r--boost/geometry/algorithms/difference.hpp449
-rw-r--r--boost/geometry/algorithms/discrete_frechet_distance.hpp10
-rw-r--r--boost/geometry/algorithms/discrete_hausdorff_distance.hpp2
-rw-r--r--boost/geometry/algorithms/dispatch/closest_points.hpp67
-rw-r--r--boost/geometry/algorithms/dispatch/distance.hpp29
-rw-r--r--boost/geometry/algorithms/equals.hpp5
-rw-r--r--boost/geometry/algorithms/for_each.hpp25
-rw-r--r--boost/geometry/algorithms/is_convex.hpp115
-rw-r--r--boost/geometry/algorithms/is_empty.hpp69
-rw-r--r--boost/geometry/algorithms/length.hpp13
-rw-r--r--boost/geometry/algorithms/line_interpolate.hpp27
-rw-r--r--boost/geometry/algorithms/make.hpp5
-rw-r--r--boost/geometry/algorithms/merge_elements.hpp424
-rw-r--r--boost/geometry/algorithms/num_points.hpp71
-rw-r--r--boost/geometry/algorithms/num_segments.hpp59
-rw-r--r--boost/geometry/algorithms/perimeter.hpp68
-rw-r--r--boost/geometry/algorithms/point_on_surface.hpp26
-rw-r--r--boost/geometry/algorithms/relate.hpp4
-rw-r--r--boost/geometry/algorithms/relation.hpp1
-rw-r--r--boost/geometry/algorithms/remove_spikes.hpp32
-rw-r--r--boost/geometry/algorithms/reverse.hpp68
-rw-r--r--boost/geometry/algorithms/simplify.hpp360
-rw-r--r--boost/geometry/algorithms/sym_difference.hpp307
-rw-r--r--boost/geometry/algorithms/transform.hpp36
-rw-r--r--boost/geometry/algorithms/union.hpp523
-rw-r--r--boost/geometry/algorithms/unique.hpp14
-rw-r--r--boost/geometry/algorithms/within.hpp5
-rw-r--r--boost/geometry/arithmetic/arithmetic.hpp30
-rw-r--r--boost/geometry/arithmetic/dot_product.hpp2
-rw-r--r--boost/geometry/arithmetic/normalize.hpp2
-rw-r--r--boost/geometry/core/config.hpp34
-rw-r--r--boost/geometry/core/coordinate_promotion.hpp111
-rw-r--r--boost/geometry/core/coordinate_type.hpp10
-rw-r--r--boost/geometry/core/geometry_id.hpp22
-rw-r--r--boost/geometry/core/interior_rings.hpp6
-rw-r--r--boost/geometry/core/mutable_range.hpp6
-rw-r--r--boost/geometry/core/point_type.hpp36
-rw-r--r--boost/geometry/core/radian_access.hpp3
-rw-r--r--boost/geometry/core/topological_dimension.hpp8
-rw-r--r--boost/geometry/formulas/area_formulas.hpp170
-rw-r--r--boost/geometry/formulas/differential_quantities.hpp27
-rw-r--r--boost/geometry/formulas/geographic.hpp16
-rw-r--r--boost/geometry/formulas/gnomonic_intersection.hpp11
-rw-r--r--boost/geometry/formulas/gnomonic_spheroid.hpp6
-rw-r--r--boost/geometry/formulas/interpolate_point_spherical.hpp5
-rw-r--r--boost/geometry/formulas/karney_direct.hpp49
-rw-r--r--boost/geometry/formulas/karney_inverse.hpp9
-rw-r--r--boost/geometry/formulas/meridian_direct.hpp11
-rw-r--r--boost/geometry/formulas/meridian_inverse.hpp13
-rw-r--r--boost/geometry/formulas/sjoberg_intersection.hpp43
-rw-r--r--boost/geometry/formulas/spherical.hpp2
-rw-r--r--boost/geometry/formulas/thomas_inverse.hpp6
-rw-r--r--boost/geometry/formulas/vertex_longitude.hpp2
-rw-r--r--boost/geometry/formulas/vincenty_direct.hpp2
-rw-r--r--boost/geometry/formulas/vincenty_inverse.hpp4
-rw-r--r--boost/geometry/geometries/adapted/boost_variant.hpp12
-rw-r--r--boost/geometry/geometries/adapted/std_array.hpp14
-rw-r--r--boost/geometry/geometries/concepts/box_concept.hpp15
-rw-r--r--boost/geometry/geometries/concepts/check.hpp9
-rw-r--r--boost/geometry/geometries/concepts/geometry_collection_concept.hpp4
-rw-r--r--boost/geometry/geometries/concepts/linestring_concept.hpp39
-rw-r--r--boost/geometry/geometries/concepts/multi_linestring_concept.hpp14
-rw-r--r--boost/geometry/geometries/concepts/multi_point_concept.hpp11
-rw-r--r--boost/geometry/geometries/concepts/multi_polygon_concept.hpp15
-rw-r--r--boost/geometry/geometries/concepts/point_concept.hpp57
-rw-r--r--boost/geometry/geometries/concepts/ring_concept.hpp16
-rw-r--r--boost/geometry/geometries/concepts/segment_concept.hpp19
-rw-r--r--boost/geometry/geometries/helper_geometry.hpp47
-rw-r--r--boost/geometry/geometries/linestring.hpp6
-rw-r--r--boost/geometry/geometries/multi_linestring.hpp7
-rw-r--r--boost/geometry/geometries/multi_point.hpp6
-rw-r--r--boost/geometry/geometries/multi_polygon.hpp8
-rw-r--r--boost/geometry/geometries/point_xyz.hpp2
-rw-r--r--boost/geometry/geometries/polygon.hpp8
-rw-r--r--boost/geometry/geometries/register/point.hpp6
-rw-r--r--boost/geometry/geometries/ring.hpp6
-rw-r--r--boost/geometry/geometry.hpp13
-rw-r--r--boost/geometry/index/detail/algorithms/bounds.hpp9
-rw-r--r--boost/geometry/index/detail/algorithms/comparable_distance_centroid.hpp9
-rw-r--r--boost/geometry/index/detail/algorithms/comparable_distance_far.hpp7
-rw-r--r--boost/geometry/index/detail/algorithms/comparable_distance_near.hpp7
-rw-r--r--boost/geometry/index/detail/algorithms/content.hpp20
-rw-r--r--boost/geometry/index/detail/algorithms/diff_abs.hpp6
-rw-r--r--boost/geometry/index/detail/algorithms/intersection_content.hpp7
-rw-r--r--boost/geometry/index/detail/algorithms/is_valid.hpp5
-rw-r--r--boost/geometry/index/detail/algorithms/margin.hpp20
-rw-r--r--boost/geometry/index/detail/algorithms/minmaxdist.hpp2
-rw-r--r--boost/geometry/index/detail/algorithms/path_intersection.hpp13
-rw-r--r--boost/geometry/index/detail/algorithms/segment_intersection.hpp9
-rw-r--r--boost/geometry/index/detail/bounded_view.hpp2
-rw-r--r--boost/geometry/index/detail/distance_predicates.hpp14
-rw-r--r--boost/geometry/index/detail/maxmin_heap.hpp107
-rw-r--r--boost/geometry/index/detail/minmax_heap.hpp521
-rw-r--r--boost/geometry/index/detail/predicates.hpp41
-rw-r--r--boost/geometry/index/detail/priority_dequeue.hpp150
-rw-r--r--boost/geometry/index/detail/rtree/adaptors.hpp8
-rw-r--r--boost/geometry/index/detail/rtree/iterators.hpp10
-rw-r--r--boost/geometry/index/detail/rtree/kmeans/kmeans.hpp6
-rw-r--r--boost/geometry/index/detail/rtree/kmeans/split.hpp45
-rw-r--r--boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp46
-rw-r--r--boost/geometry/index/detail/rtree/node/node.hpp6
-rw-r--r--boost/geometry/index/detail/rtree/node/node_elements.hpp5
-rw-r--r--boost/geometry/index/detail/rtree/node/pairs.hpp35
-rw-r--r--boost/geometry/index/detail/rtree/node/scoped_deallocator.hpp6
-rw-r--r--boost/geometry/index/detail/rtree/node/variant_dynamic.hpp28
-rw-r--r--boost/geometry/index/detail/rtree/node/variant_static.hpp19
-rw-r--r--boost/geometry/index/detail/rtree/node/weak_dynamic.hpp59
-rw-r--r--boost/geometry/index/detail/rtree/node/weak_static.hpp23
-rw-r--r--boost/geometry/index/detail/rtree/node/weak_visitor.hpp6
-rw-r--r--boost/geometry/index/detail/rtree/pack_create.hpp51
-rw-r--r--boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp8
-rw-r--r--boost/geometry/index/detail/rtree/query_iterators.hpp135
-rw-r--r--boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp8
-rw-r--r--boost/geometry/index/detail/rtree/rstar/insert.hpp25
-rw-r--r--boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp17
-rw-r--r--boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp6
-rw-r--r--boost/geometry/index/detail/rtree/utilities/are_counts_ok.hpp10
-rw-r--r--boost/geometry/index/detail/rtree/utilities/are_levels_ok.hpp8
-rw-r--r--boost/geometry/index/detail/rtree/utilities/gl_draw.hpp15
-rw-r--r--boost/geometry/index/detail/rtree/utilities/print.hpp17
-rw-r--r--boost/geometry/index/detail/rtree/utilities/statistics.hpp23
-rw-r--r--boost/geometry/index/detail/rtree/utilities/view.hpp2
-rw-r--r--boost/geometry/index/detail/rtree/visitors/children_box.hpp8
-rw-r--r--boost/geometry/index/detail/rtree/visitors/copy.hpp2
-rw-r--r--boost/geometry/index/detail/rtree/visitors/count.hpp11
-rw-r--r--boost/geometry/index/detail/rtree/visitors/destroy.hpp9
-rw-r--r--boost/geometry/index/detail/rtree/visitors/distance_query.hpp641
-rw-r--r--boost/geometry/index/detail/rtree/visitors/insert.hpp18
-rw-r--r--boost/geometry/index/detail/rtree/visitors/iterator.hpp9
-rw-r--r--boost/geometry/index/detail/rtree/visitors/remove.hpp17
-rw-r--r--boost/geometry/index/detail/rtree/visitors/spatial_query.hpp218
-rw-r--r--boost/geometry/index/detail/serialization.hpp47
-rw-r--r--boost/geometry/index/detail/translator.hpp6
-rw-r--r--boost/geometry/index/detail/utilities.hpp6
-rw-r--r--boost/geometry/index/detail/varray.hpp247
-rw-r--r--boost/geometry/index/detail/varray_detail.hpp89
-rw-r--r--boost/geometry/index/distance_predicates.hpp12
-rw-r--r--boost/geometry/index/equal_to.hpp21
-rw-r--r--boost/geometry/index/indexable.hpp17
-rw-r--r--boost/geometry/index/inserter.hpp2
-rw-r--r--boost/geometry/index/parameters.hpp12
-rw-r--r--boost/geometry/index/predicates.hpp20
-rw-r--r--boost/geometry/index/rtree.hpp243
-rw-r--r--boost/geometry/io/dsv/write.hpp24
-rw-r--r--boost/geometry/io/svg/svg_mapper.hpp24
-rw-r--r--boost/geometry/io/svg/write.hpp31
-rw-r--r--boost/geometry/io/wkt/detail/prefix.hpp16
-rw-r--r--boost/geometry/io/wkt/detail/wkt_multi.hpp45
-rw-r--r--boost/geometry/io/wkt/read.hpp270
-rw-r--r--boost/geometry/io/wkt/write.hpp166
-rw-r--r--boost/geometry/iterators/detail/point_iterator/inner_range_type.hpp2
-rw-r--r--boost/geometry/iterators/flatten_iterator.hpp2
-rw-r--r--boost/geometry/multi/io/wkt/detail/prefix.hpp5
-rw-r--r--boost/geometry/policies/compare.hpp280
-rw-r--r--boost/geometry/policies/is_valid/failing_reason_policy.hpp30
-rw-r--r--boost/geometry/policies/predicate_based_interrupt_policy.hpp38
-rw-r--r--boost/geometry/policies/relate/intersection_points.hpp11
-rw-r--r--boost/geometry/policies/robustness/get_rescale_policy.hpp2
-rw-r--r--boost/geometry/policies/robustness/segment_ratio.hpp99
-rw-r--r--boost/geometry/srs/epsg.hpp2
-rw-r--r--boost/geometry/srs/esri.hpp2
-rw-r--r--boost/geometry/srs/iau2000.hpp2
-rw-r--r--boost/geometry/srs/projection.hpp11
-rw-r--r--boost/geometry/srs/projections/dpar.hpp105
-rw-r--r--boost/geometry/srs/projections/epsg.hpp11
-rw-r--r--boost/geometry/srs/projections/epsg_params.hpp5
-rw-r--r--boost/geometry/srs/projections/epsg_traits.hpp9
-rw-r--r--boost/geometry/srs/projections/esri_params.hpp2
-rw-r--r--boost/geometry/srs/projections/factory.hpp13
-rw-r--r--boost/geometry/srs/projections/iau2000_params.hpp2
-rw-r--r--boost/geometry/srs/projections/impl/base_dynamic.hpp2
-rw-r--r--boost/geometry/srs/projections/impl/dms_parser.hpp10
-rw-r--r--boost/geometry/srs/projections/impl/geocent.hpp18
-rw-r--r--boost/geometry/srs/projections/impl/pj_apply_gridshift.hpp8
-rw-r--r--boost/geometry/srs/projections/impl/pj_datum_set.hpp12
-rw-r--r--boost/geometry/srs/projections/impl/pj_ell_set.hpp4
-rw-r--r--boost/geometry/srs/projections/impl/pj_fwd.hpp10
-rw-r--r--boost/geometry/srs/projections/impl/pj_generic_inverse.hpp163
-rw-r--r--boost/geometry/srs/projections/impl/pj_gridinfo.hpp28
-rw-r--r--boost/geometry/srs/projections/impl/pj_gridlist.hpp16
-rw-r--r--boost/geometry/srs/projections/impl/pj_init.hpp88
-rw-r--r--boost/geometry/srs/projections/impl/pj_inv.hpp18
-rw-r--r--boost/geometry/srs/projections/impl/pj_mlfn.hpp2
-rw-r--r--boost/geometry/srs/projections/impl/pj_param.hpp20
-rw-r--r--boost/geometry/srs/projections/impl/pj_qsfn.hpp2
-rw-r--r--boost/geometry/srs/projections/impl/pj_transform.hpp21
-rw-r--r--boost/geometry/srs/projections/impl/projects.hpp6
-rw-r--r--boost/geometry/srs/projections/par_data.hpp102
-rw-r--r--boost/geometry/srs/projections/proj/aea.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/aeqd.hpp4
-rw-r--r--boost/geometry/srs/projections/proj/airy.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/august.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/bipc.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/cass.hpp67
-rw-r--r--boost/geometry/srs/projections/proj/cc.hpp4
-rw-r--r--boost/geometry/srs/projections/proj/cea.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/chamb.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/col_urban.hpp166
-rw-r--r--boost/geometry/srs/projections/proj/collg.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/crast.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/denoy.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/eck1.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/eck2.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/eck3.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/eck4.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/eck5.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/eqc.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/eqdc.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/etmerc.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/fahey.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/fouc_s.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/gall.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/geocent.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/geos.hpp10
-rw-r--r--boost/geometry/srs/projections/proj/gins8.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/gn_sinu.hpp4
-rw-r--r--boost/geometry/srs/projections/proj/gnom.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/goode.hpp4
-rw-r--r--boost/geometry/srs/projections/proj/gstmerc.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/hammer.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/hatano.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/healpix.hpp6
-rw-r--r--boost/geometry/srs/projections/proj/igh.hpp7
-rw-r--r--boost/geometry/srs/projections/proj/imw_p.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/isea.hpp6
-rw-r--r--boost/geometry/srs/projections/proj/krovak.hpp15
-rw-r--r--boost/geometry/srs/projections/proj/labrd.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/laea.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/lagrng.hpp4
-rw-r--r--boost/geometry/srs/projections/proj/larr.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/lask.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/latlong.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/lcc.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/lcca.hpp4
-rw-r--r--boost/geometry/srs/projections/proj/loxim.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/lsat.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/mbt_fps.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/mbtfpp.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/mbtfpq.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/merc.hpp39
-rw-r--r--boost/geometry/srs/projections/proj/mill.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/mod_ster.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/moll.hpp4
-rw-r--r--boost/geometry/srs/projections/proj/nsper.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/ob_tran.hpp17
-rw-r--r--boost/geometry/srs/projections/proj/omerc.hpp45
-rw-r--r--boost/geometry/srs/projections/proj/putp3.hpp4
-rw-r--r--boost/geometry/srs/projections/proj/putp4p.hpp4
-rw-r--r--boost/geometry/srs/projections/proj/putp5.hpp6
-rw-r--r--boost/geometry/srs/projections/proj/putp6.hpp6
-rw-r--r--boost/geometry/srs/projections/proj/qsc.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/sconics.hpp8
-rw-r--r--boost/geometry/srs/projections/proj/somerc.hpp4
-rw-r--r--boost/geometry/srs/projections/proj/stere.hpp37
-rw-r--r--boost/geometry/srs/projections/proj/sterea.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/sts.hpp4
-rw-r--r--boost/geometry/srs/projections/proj/tcc.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/tcea.hpp4
-rw-r--r--boost/geometry/srs/projections/proj/tmerc.hpp751
-rw-r--r--boost/geometry/srs/projections/proj/tpeqd.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/urm5.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/urmfps.hpp4
-rw-r--r--boost/geometry/srs/projections/proj/vandg.hpp6
-rw-r--r--boost/geometry/srs/projections/proj/vandg2.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/vandg4.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/wag2.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/wag3.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/wag7.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/wink1.hpp2
-rw-r--r--boost/geometry/srs/projections/proj/wink2.hpp4
-rw-r--r--boost/geometry/srs/projections/proj4.hpp2
-rw-r--r--boost/geometry/srs/projections/spar.hpp32
-rw-r--r--boost/geometry/srs/projections/str_cast.hpp14
-rw-r--r--boost/geometry/srs/shared_grids.hpp2
-rw-r--r--boost/geometry/srs/shared_grids_boost.hpp5
-rw-r--r--boost/geometry/srs/shared_grids_std.hpp2
-rw-r--r--boost/geometry/srs/spheroid.hpp2
-rw-r--r--boost/geometry/srs/transformation.hpp4
-rw-r--r--boost/geometry/strategies/agnostic/buffer_distance_asymmetric.hpp5
-rw-r--r--boost/geometry/strategies/agnostic/buffer_distance_symmetric.hpp5
-rw-r--r--boost/geometry/strategies/agnostic/point_in_box_by_side.hpp26
-rw-r--r--boost/geometry/strategies/agnostic/point_in_poly_winding.hpp13
-rw-r--r--boost/geometry/strategies/area/geographic.hpp5
-rw-r--r--boost/geometry/strategies/azimuth/spherical.hpp2
-rw-r--r--boost/geometry/strategies/buffer.hpp30
-rw-r--r--boost/geometry/strategies/buffer/cartesian.hpp25
-rw-r--r--boost/geometry/strategies/buffer/geographic.hpp23
-rw-r--r--boost/geometry/strategies/buffer/spherical.hpp25
-rw-r--r--boost/geometry/strategies/cartesian.hpp2
-rw-r--r--boost/geometry/strategies/cartesian/azimuth.hpp2
-rw-r--r--boost/geometry/strategies/cartesian/box_in_box.hpp4
-rw-r--r--boost/geometry/strategies/cartesian/buffer_end_flat.hpp21
-rw-r--r--boost/geometry/strategies/cartesian/buffer_end_round.hpp29
-rw-r--r--boost/geometry/strategies/cartesian/buffer_join_miter.hpp4
-rw-r--r--boost/geometry/strategies/cartesian/buffer_join_round.hpp22
-rw-r--r--boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp24
-rw-r--r--boost/geometry/strategies/cartesian/buffer_point_circle.hpp7
-rw-r--r--boost/geometry/strategies/cartesian/buffer_side_straight.hpp4
-rw-r--r--boost/geometry/strategies/cartesian/centroid_average.hpp2
-rw-r--r--boost/geometry/strategies/cartesian/centroid_weighted_length.hpp8
-rw-r--r--boost/geometry/strategies/cartesian/closest_points_pt_seg.hpp146
-rw-r--r--boost/geometry/strategies/cartesian/densify.hpp4
-rw-r--r--boost/geometry/strategies/cartesian/disjoint_segment_box.hpp2
-rw-r--r--boost/geometry/strategies/cartesian/distance_projected_point.hpp60
-rw-r--r--boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp2
-rw-r--r--boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp2
-rw-r--r--boost/geometry/strategies/cartesian/distance_segment_box.hpp1
-rw-r--r--boost/geometry/strategies/cartesian/intersection.hpp119
-rw-r--r--boost/geometry/strategies/cartesian/point_in_poly_winding.hpp68
-rw-r--r--boost/geometry/strategies/cartesian/side_by_triangle.hpp270
-rw-r--r--boost/geometry/strategies/cartesian/side_rounded_input.hpp65
-rw-r--r--boost/geometry/strategies/cartesian/turn_in_ring_winding.hpp187
-rw-r--r--boost/geometry/strategies/closest_points/cartesian.hpp68
-rw-r--r--boost/geometry/strategies/closest_points/geographic.hpp78
-rw-r--r--boost/geometry/strategies/closest_points/services.hpp48
-rw-r--r--boost/geometry/strategies/closest_points/spherical.hpp78
-rw-r--r--boost/geometry/strategies/comparable_distance_result.hpp2
-rw-r--r--boost/geometry/strategies/compare.hpp57
-rw-r--r--boost/geometry/strategies/convex_hull/cartesian.hpp34
-rw-r--r--boost/geometry/strategies/convex_hull/geographic.hpp26
-rw-r--r--boost/geometry/strategies/convex_hull/spherical.hpp26
-rw-r--r--boost/geometry/strategies/distance/backward_compatibility.hpp2
-rw-r--r--boost/geometry/strategies/distance/comparable.hpp4
-rw-r--r--boost/geometry/strategies/distance/services.hpp2
-rw-r--r--boost/geometry/strategies/envelope/cartesian.hpp36
-rw-r--r--boost/geometry/strategies/envelope/geographic.hpp43
-rw-r--r--boost/geometry/strategies/envelope/spherical.hpp43
-rw-r--r--boost/geometry/strategies/geographic.hpp2
-rw-r--r--boost/geometry/strategies/geographic/buffer_end_round.hpp153
-rw-r--r--boost/geometry/strategies/geographic/buffer_helper.hpp101
-rw-r--r--boost/geometry/strategies/geographic/buffer_join_miter.hpp132
-rw-r--r--boost/geometry/strategies/geographic/buffer_join_round.hpp123
-rw-r--r--boost/geometry/strategies/geographic/buffer_point_circle.hpp96
-rw-r--r--boost/geometry/strategies/geographic/buffer_side_straight.hpp119
-rw-r--r--boost/geometry/strategies/geographic/closest_points_pt_seg.hpp100
-rw-r--r--boost/geometry/strategies/geographic/disjoint_segment_box.hpp2
-rw-r--r--boost/geometry/strategies/geographic/distance.hpp2
-rw-r--r--boost/geometry/strategies/geographic/distance_cross_track.hpp480
-rw-r--r--boost/geometry/strategies/geographic/distance_segment_box.hpp3
-rw-r--r--boost/geometry/strategies/geographic/intersection.hpp10
-rw-r--r--boost/geometry/strategies/geographic/intersection_elliptic.hpp2
-rw-r--r--boost/geometry/strategies/geographic/mapping_ssf.hpp2
-rw-r--r--boost/geometry/strategies/geographic/side.hpp2
-rw-r--r--boost/geometry/strategies/index/services.hpp2
-rw-r--r--boost/geometry/strategies/intersection_result.hpp6
-rw-r--r--boost/geometry/strategies/intersection_strategies.hpp2
-rw-r--r--boost/geometry/strategies/is_convex/cartesian.hpp22
-rw-r--r--boost/geometry/strategies/is_convex/geographic.hpp27
-rw-r--r--boost/geometry/strategies/is_convex/spherical.hpp19
-rw-r--r--boost/geometry/strategies/relate/cartesian.hpp27
-rw-r--r--boost/geometry/strategies/relate/geographic.hpp20
-rw-r--r--boost/geometry/strategies/relate/spherical.hpp11
-rw-r--r--boost/geometry/strategies/simplify/spherical.hpp1
-rw-r--r--boost/geometry/strategies/spherical.hpp2
-rw-r--r--boost/geometry/strategies/spherical/closest_points_pt_seg.hpp200
-rw-r--r--boost/geometry/strategies/spherical/compare.hpp72
-rw-r--r--boost/geometry/strategies/spherical/distance_cross_track.hpp199
-rw-r--r--boost/geometry/strategies/spherical/distance_haversine.hpp2
-rw-r--r--boost/geometry/strategies/spherical/distance_segment_box.hpp1
-rw-r--r--boost/geometry/strategies/spherical/intersection.hpp14
-rw-r--r--boost/geometry/strategies/spherical/point_in_point.hpp3
-rw-r--r--boost/geometry/strategies/spherical/point_in_poly_winding.hpp55
-rw-r--r--boost/geometry/strategies/spherical/side_by_cross_track.hpp2
-rw-r--r--boost/geometry/strategies/spherical/ssf.hpp2
-rw-r--r--boost/geometry/strategies/strategies.hpp7
-rw-r--r--boost/geometry/strategies/strategy_transform.hpp2
-rw-r--r--boost/geometry/strategies/transform/matrix_transformers.hpp2
-rw-r--r--boost/geometry/strategies/transform/srs_transformer.hpp2
-rw-r--r--boost/geometry/strategy/cartesian/area.hpp4
-rw-r--r--boost/geometry/strategy/cartesian/area_box.hpp2
-rw-r--r--boost/geometry/strategy/cartesian/envelope_boxes.hpp66
-rw-r--r--boost/geometry/strategy/cartesian/envelope_range.hpp56
-rw-r--r--boost/geometry/strategy/cartesian/envelope_segment.hpp2
-rw-r--r--boost/geometry/strategy/cartesian/side_by_triangle.hpp258
-rw-r--r--boost/geometry/strategy/cartesian/side_non_robust.hpp49
-rw-r--r--boost/geometry/strategy/cartesian/side_robust.hpp105
-rw-r--r--boost/geometry/strategy/geographic/area_box.hpp4
-rw-r--r--boost/geometry/strategy/geographic/envelope_range.hpp118
-rw-r--r--boost/geometry/strategy/relate.hpp2
-rw-r--r--boost/geometry/strategy/spherical/area_box.hpp2
-rw-r--r--boost/geometry/strategy/spherical/envelope_boxes.hpp59
-rw-r--r--boost/geometry/strategy/spherical/envelope_multipoint.hpp64
-rw-r--r--boost/geometry/strategy/spherical/envelope_range.hpp278
-rw-r--r--boost/geometry/strategy/spherical/envelope_segment.hpp7
-rw-r--r--boost/geometry/strategy/spherical/expand_box.hpp2
-rw-r--r--boost/geometry/util/combine_if.hpp4
-rw-r--r--boost/geometry/util/constexpr.hpp27
-rw-r--r--boost/geometry/util/for_each_with_index.hpp49
-rw-r--r--boost/geometry/util/has_infinite_coordinate.hpp2
-rw-r--r--boost/geometry/util/has_nan_coordinate.hpp2
-rw-r--r--boost/geometry/util/has_non_finite_coordinate.hpp2
-rw-r--r--boost/geometry/util/math.hpp76
-rw-r--r--boost/geometry/util/normalize_spheroidal_box_coordinates.hpp11
-rw-r--r--boost/geometry/util/normalize_spheroidal_coordinates.hpp12
-rw-r--r--boost/geometry/util/parameter_type_of.hpp2
-rw-r--r--boost/geometry/util/precise_math.hpp43
-rw-r--r--boost/geometry/util/promote_floating_point.hpp32
-rw-r--r--boost/geometry/util/promote_integral.hpp2
-rw-r--r--boost/geometry/util/range.hpp2
-rw-r--r--boost/geometry/util/sequence.hpp129
-rw-r--r--boost/geometry/util/series_expansion.hpp9
-rw-r--r--boost/geometry/util/type_traits.hpp57
-rw-r--r--boost/geometry/views/closeable_view.hpp56
-rw-r--r--boost/geometry/views/detail/boundary_view/implementation.hpp2
-rw-r--r--boost/geometry/views/detail/closed_clockwise_view.hpp30
-rw-r--r--boost/geometry/views/detail/geometry_collection_view.hpp84
-rw-r--r--boost/geometry/views/detail/random_access_view.hpp222
-rw-r--r--boost/geometry/views/reversible_view.hpp56
601 files changed, 20544 insertions, 10848 deletions
diff --git a/boost/geometry/algorithms/append.hpp b/boost/geometry/algorithms/append.hpp
index b1bd575745..4bb25fcb11 100644
--- a/boost/geometry/algorithms/append.hpp
+++ b/boost/geometry/algorithms/append.hpp
@@ -4,8 +4,9 @@
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2023.
+// Modifications copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -27,7 +28,6 @@
#include <boost/geometry/algorithms/num_interior_rings.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.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>
@@ -91,17 +91,15 @@ struct to_polygon_point
signed_size_type ring_index, signed_size_type = 0)
{
using ring_type = typename ring_type<Polygon>::type;
- using exterior_ring_type = typename ring_return_type<Polygon>::type;
- using interior_ring_range_type = typename interior_return_type<Polygon>::type;
if (ring_index == -1)
{
- exterior_ring_type ext_ring = exterior_ring(polygon);
+ auto&& ext_ring = exterior_ring(polygon);
to_range_point::apply<ring_type, Point>(ext_ring, point);
}
else if (ring_index < signed_size_type(num_interior_rings(polygon)))
{
- interior_ring_range_type int_rings = interior_rings(polygon);
+ auto&& int_rings = interior_rings(polygon);
to_range_point::apply<ring_type, Point>(range::at(int_rings, ring_index), point);
}
}
diff --git a/boost/geometry/algorithms/area.hpp b/boost/geometry/algorithms/area.hpp
index 4b4a0bb9c3..9b5af61e12 100644
--- a/boost/geometry/algorithms/area.hpp
+++ b/boost/geometry/algorithms/area.hpp
@@ -3,10 +3,11 @@
// 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.
-// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2017-2022 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017-2021.
-// Modifications copyright (c) 2017-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2023.
+// Modifications copyright (c) 2017-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -53,8 +54,6 @@
#include <boost/geometry/strategies/concepts/area_concept.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
-#include <boost/geometry/util/math.hpp>
-
#include <boost/geometry/views/detail/closed_clockwise_view.hpp>
@@ -69,7 +68,7 @@ namespace detail { namespace area
struct box_area
{
template <typename Box, typename Strategies>
- static inline typename coordinate_type<Box>::type
+ static inline auto
apply(Box const& box, Strategies const& strategies)
{
// Currently only works for 2D Cartesian boxes
@@ -107,7 +106,7 @@ struct ring_area
auto const end = boost::end(view);
strategy_type const strategy = strategies.area(ring);
- typename strategy_type::template state<Ring> state;
+ typename strategy_type::template state<Ring> state;
for (auto previous = it++; it != end; ++previous, ++it)
{
diff --git a/boost/geometry/algorithms/area_result.hpp b/boost/geometry/algorithms/area_result.hpp
index 686b26c73e..73d9f52c5d 100644
--- a/boost/geometry/algorithms/area_result.hpp
+++ b/boost/geometry/algorithms/area_result.hpp
@@ -2,8 +2,9 @@
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2020-2021.
-// Modifications copyright (c) 2020-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2023.
+// Modifications copyright (c) 2020-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -19,18 +20,12 @@
#include <boost/geometry/algorithms/detail/select_geometry_type.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
-#include <boost/geometry/core/cs.hpp>
-#include <boost/geometry/core/geometry_types.hpp>
-#include <boost/geometry/core/tag.hpp>
-#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/area/services.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
-#include <boost/geometry/util/sequence.hpp>
-#include <boost/geometry/util/type_traits.hpp>
namespace boost { namespace geometry
{
diff --git a/boost/geometry/algorithms/assign.hpp b/boost/geometry/algorithms/assign.hpp
index 8ab4745d2e..dabf1b4a57 100644
--- a/boost/geometry/algorithms/assign.hpp
+++ b/boost/geometry/algorithms/assign.hpp
@@ -5,8 +5,9 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
-// This file was modified by Oracle on 2020-2021.
-// Modifications copyright (c) 2020-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2023.
+// Modifications copyright (c) 2020-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -19,29 +20,18 @@
#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/numeric/conversion/bounds.hpp>
-#include <boost/numeric/conversion/cast.hpp>
-
-#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
+#include <boost/geometry/algorithms/append.hpp>
+#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/convert.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/static_assert.hpp>
-#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -231,7 +221,7 @@ struct assign
concepts::check<Geometry1>();
concepts::check<Geometry2 const>();
concepts::check_concepts_and_equal_dimensions<Geometry1, Geometry2 const>();
-
+
static bool const same_point_order
= point_order<Geometry1>::value == point_order<Geometry2>::value;
BOOST_GEOMETRY_STATIC_ASSERT(
@@ -244,23 +234,23 @@ struct assign
same_closure,
"Assign is not supported for different closures.",
Geometry1, Geometry2);
-
+
dispatch::convert<Geometry2, Geometry1>::apply(geometry2, geometry1);
}
};
-
-
+
+
template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
{
struct visitor: static_visitor<void>
{
Geometry2 const& m_geometry2;
-
+
visitor(Geometry2 const& geometry2)
: m_geometry2(geometry2)
{}
-
+
template <typename Geometry1>
result_type operator()(Geometry1& geometry1) const
{
@@ -272,7 +262,7 @@ struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
(geometry1, m_geometry2);
}
};
-
+
static inline void
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry1,
Geometry2 const& geometry2)
@@ -280,19 +270,19 @@ struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
return boost::apply_visitor(visitor(geometry2), geometry1);
}
};
-
-
+
+
template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct assign<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
{
struct visitor: static_visitor<void>
{
Geometry1& m_geometry1;
-
+
visitor(Geometry1 const& geometry1)
: m_geometry1(geometry1)
{}
-
+
template <typename Geometry2>
result_type operator()(Geometry2 const& geometry2) const
{
@@ -304,7 +294,7 @@ struct assign<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
(m_geometry1, geometry2);
}
};
-
+
static inline void
apply(Geometry1& geometry1,
variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)
@@ -312,8 +302,8 @@ struct assign<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
return boost::apply_visitor(visitor(geometry1), geometry2);
}
};
-
-
+
+
template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
{
@@ -332,7 +322,7 @@ struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM
(geometry1, geometry2);
}
};
-
+
static inline void
apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)
@@ -340,9 +330,9 @@ struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM
return boost::apply_visitor(visitor(), geometry1, geometry2);
}
};
-
+
} // namespace resolve_variant
-
+
/*!
\brief Assigns one geometry to another geometry
diff --git a/boost/geometry/algorithms/azimuth.hpp b/boost/geometry/algorithms/azimuth.hpp
index 28e5491e7a..7056c512c9 100644
--- a/boost/geometry/algorithms/azimuth.hpp
+++ b/boost/geometry/algorithms/azimuth.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2023.
+// Modifications copyright (c) 2014-2023, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -17,20 +17,16 @@
#include <boost/geometry/algorithms/not_implemented.hpp>
-#include <boost/geometry/core/cs.hpp>
-#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/tag.hpp>
-#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/azimuth/cartesian.hpp>
#include <boost/geometry/strategies/azimuth/geographic.hpp>
#include <boost/geometry/strategies/azimuth/spherical.hpp>
-#include <boost/geometry/util/math.hpp>
-
-
namespace boost { namespace geometry
{
@@ -38,7 +34,7 @@ namespace boost { namespace geometry
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
-
+
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
@@ -181,7 +177,7 @@ inline auto azimuth(Point1 const& point1, Point2 const& point2)
{
concepts::check<Point1 const>();
concepts::check<Point2 const>();
-
+
return resolve_strategy::azimuth
<
default_strategy
diff --git a/boost/geometry/algorithms/buffer.hpp b/boost/geometry/algorithms/buffer.hpp
index 4720c880e3..5fae384855 100644
--- a/boost/geometry/algorithms/buffer.hpp
+++ b/boost/geometry/algorithms/buffer.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2017-2021.
-// Modifications copyright (c) 2017-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2022.
+// Modifications copyright (c) 2017-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -18,255 +18,7 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
#define BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
-#include <cstddef>
-
-#include <boost/numeric/conversion/cast.hpp>
-
-#include <boost/range/value_type.hpp>
-
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
-#include <boost/geometry/algorithms/clear.hpp>
-#include <boost/geometry/algorithms/envelope.hpp>
-#include <boost/geometry/algorithms/is_empty.hpp>
-#include <boost/geometry/algorithms/not_implemented.hpp>
-#include <boost/geometry/arithmetic/arithmetic.hpp>
-#include <boost/geometry/geometries/concepts/check.hpp>
-#include <boost/geometry/geometries/box.hpp>
-#include <boost/geometry/util/math.hpp>
-
-#include <boost/geometry/algorithms/detail/buffer/buffer_box.hpp>
-#include <boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp>
-
-#include <boost/geometry/strategies/buffer/cartesian.hpp>
-#include <boost/geometry/strategies/buffer/geographic.hpp>
-#include <boost/geometry/strategies/buffer/spherical.hpp>
-
-namespace boost { namespace geometry
-{
-
-#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& , BoxOut& box_out)
- {
- detail::buffer::buffer_box(box_in, distance, box_out);
- }
-};
-
-} // namespace dispatch
-#endif // DOXYGEN_NO_DISPATCH
-
-
-namespace resolve_variant {
-
-template <typename Geometry>
-struct buffer
-{
- template <typename Distance, typename GeometryOut>
- static inline void apply(Geometry const& geometry,
- Distance const& distance,
- Distance const& chord_length,
- GeometryOut& out)
- {
- dispatch::buffer<Geometry, GeometryOut>::apply(geometry, distance, chord_length, out);
- }
-};
-
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct buffer<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
-{
- template <typename Distance, typename GeometryOut>
- struct visitor: boost::static_visitor<void>
- {
- Distance const& m_distance;
- Distance const& m_chord_length;
- GeometryOut& m_out;
-
- visitor(Distance const& distance,
- Distance const& chord_length,
- GeometryOut& out)
- : m_distance(distance),
- m_chord_length(chord_length),
- m_out(out)
- {}
-
- template <typename Geometry>
- void operator()(Geometry const& geometry) const
- {
- buffer<Geometry>::apply(geometry, m_distance, m_chord_length, m_out);
- }
- };
-
- template <typename Distance, typename GeometryOut>
- static inline void apply(
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- Distance const& distance,
- Distance const& chord_length,
- GeometryOut& out
- )
- {
- boost::apply_visitor(visitor<Distance, GeometryOut>(distance, chord_length, out), geometry);
- }
-};
-
-} // namespace resolve_variant
-
-
-/*!
-\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
-
-\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)
-{
- concepts::check<Input const>();
- concepts::check<Output>();
-
- resolve_variant::buffer<Input>::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 (RESERVED, NOT YET USED)
-\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)
-{
- concepts::check<Input const>();
- concepts::check<Output>();
-
- Output geometry_out;
-
- resolve_variant::buffer<Input>::apply(geometry, distance, chord_length, geometry_out);
-
- return geometry_out;
-}
-
-/*!
-\brief \brief_calc{buffer}
-\ingroup buffer
-\details \details_calc{buffer, \det_buffer}.
-\tparam GeometryIn \tparam_geometry
-\tparam MultiPolygon \tparam_geometry{MultiPolygon}
-\tparam DistanceStrategy A strategy defining distance (or radius)
-\tparam SideStrategy A strategy defining creation along sides
-\tparam JoinStrategy A strategy defining creation around convex corners
-\tparam EndStrategy A strategy defining creation at linestring ends
-\tparam PointStrategy A strategy defining creation around points
-\param geometry_in \param_geometry
-\param geometry_out output multi polygon (or std:: collection of polygons),
- will contain a buffered version of the input geometry
-\param distance_strategy The distance strategy to be used
-\param side_strategy The side strategy to be used
-\param join_strategy The join strategy to be used
-\param end_strategy The end strategy to be used
-\param point_strategy The point strategy to be used
-
-\qbk{distinguish,with strategies}
-\qbk{[include reference/algorithms/buffer_with_strategies.qbk]}
- */
-template
-<
- typename GeometryIn,
- typename MultiPolygon,
- typename DistanceStrategy,
- typename SideStrategy,
- typename JoinStrategy,
- typename EndStrategy,
- typename PointStrategy
->
-inline void buffer(GeometryIn const& geometry_in,
- MultiPolygon& geometry_out,
- DistanceStrategy const& distance_strategy,
- SideStrategy const& side_strategy,
- JoinStrategy const& join_strategy,
- EndStrategy const& end_strategy,
- PointStrategy const& point_strategy)
-{
- typedef typename boost::range_value<MultiPolygon>::type polygon_type;
- concepts::check<GeometryIn const>();
- concepts::check<polygon_type>();
-
- typedef typename point_type<GeometryIn>::type point_type;
- typedef typename rescale_policy_type
- <
- point_type,
- typename geometry::cs_tag<point_type>::type
- >::type rescale_policy_type;
-
- geometry_out.clear();
-
- if (geometry::is_empty(geometry_in))
- {
- // Then output geometry is kept empty as well
- return;
- }
-
- model::box<point_type> box;
- geometry::envelope(geometry_in, box);
- geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy));
-
- typename strategies::buffer::services::default_strategy
- <
- GeometryIn
- >::type strategies;
-
- rescale_policy_type rescale_policy
- = boost::geometry::get_rescale_policy<rescale_policy_type>(
- box, strategies);
-
- detail::buffer::buffer_inserter<polygon_type>(geometry_in,
- range::back_inserter(geometry_out),
- distance_strategy,
- side_strategy,
- join_strategy,
- end_strategy,
- point_strategy,
- strategies,
- rescale_policy);
-}
-
-
-}} // namespace boost::geometry
+#include <boost/geometry/algorithms/detail/buffer/interface.hpp>
+#include <boost/geometry/algorithms/detail/buffer/implementation.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
diff --git a/boost/geometry/algorithms/centroid.hpp b/boost/geometry/algorithms/centroid.hpp
index 621a4f5c00..9559f06b92 100644
--- a/boost/geometry/algorithms/centroid.hpp
+++ b/boost/geometry/algorithms/centroid.hpp
@@ -5,10 +5,11 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+// This file was modified by Oracle on 2014-2023.
+// Modifications copyright (c) 2014-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -28,28 +29,21 @@
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/throw_exception.hpp>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.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/core/tags.hpp>
#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/visit.hpp>
-#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/centroid/translating_transformer.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/centroid/cartesian.hpp>
@@ -61,6 +55,7 @@
#include <boost/geometry/util/algorithm.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
+#include <boost/geometry/util/type_traits_std.hpp>
#include <boost/geometry/views/closeable_view.hpp>
@@ -217,7 +212,7 @@ struct centroid_range
{
// prepare translation transformer
translating_transformer<Range> transformer(*boost::begin(range));
-
+
typename Strategy::template state_type
<
typename geometry::point_type<Range>::type,
@@ -225,7 +220,7 @@ struct centroid_range
>::type state;
centroid_range_state::apply(range, transformer, strategy, state);
-
+
if ( strategy.result(state, centroid) )
{
// translate the result back
@@ -254,11 +249,9 @@ struct centroid_polygon_state
{
centroid_range_state::apply(exterior_ring(poly), transformer, strategy, state);
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(poly);
-
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ auto const& rings = interior_rings(poly);
+ auto const end = boost::end(rings);
+ for (auto it = boost::begin(rings); it != end; ++it)
{
centroid_range_state::apply(*it, transformer, strategy, state);
}
@@ -276,7 +269,7 @@ struct centroid_polygon
// prepare translation transformer
translating_transformer<Polygon>
transformer(*boost::begin(exterior_ring(poly)));
-
+
typename Strategy::template state_type
<
typename geometry::point_type<Polygon>::type,
@@ -284,7 +277,7 @@ struct centroid_polygon
>::type state;
centroid_polygon_state::apply(poly, transformer, strategy, state);
-
+
if ( strategy.result(state, centroid) )
{
// translate the result back
@@ -351,21 +344,18 @@ struct centroid_multi
Point
>::type state;
- for (typename boost::range_iterator<Multi const>::type
- it = boost::begin(multi);
- it != boost::end(multi);
- ++it)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
Policy::apply(*it, transformer, strategy, state);
}
- if ( strategy.result(state, centroid) )
+ if (strategy.result(state, centroid))
{
// translate the result back
transformer.apply_reverse(centroid);
return true;
}
-
+
return false;
}
};
@@ -540,9 +530,9 @@ struct centroid<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant {
+namespace resolve_dynamic {
-template <typename Geometry>
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct centroid
{
template <typename Point, typename Strategy>
@@ -553,37 +543,22 @@ struct centroid
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct centroid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct centroid<Geometry, dynamic_geometry_tag>
{
template <typename Point, typename Strategy>
- struct visitor: boost::static_visitor<void>
+ static inline void apply(Geometry const& geometry,
+ Point& out,
+ Strategy const& strategy)
{
- Point& m_out;
- Strategy const& m_strategy;
-
- visitor(Point& out, Strategy const& strategy)
- : m_out(out), m_strategy(strategy)
- {}
-
- template <typename Geometry>
- void operator()(Geometry const& geometry) const
+ traits::visit<Geometry>::apply([&](auto const& g)
{
- centroid<Geometry>::apply(geometry, m_out, m_strategy);
- }
- };
-
- template <typename Point, typename Strategy>
- static inline void
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- Point& out,
- Strategy const& strategy)
- {
- boost::apply_visitor(visitor<Point, Strategy>(out, strategy), geometry);
+ centroid<util::remove_cref_t<decltype(g)>>::apply(g, out, strategy);
+ }, geometry);
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -604,10 +579,9 @@ struct centroid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
*/
template<typename Geometry, typename Point, typename Strategy>
-inline void centroid(Geometry const& geometry, Point& c,
- Strategy const& strategy)
+inline void centroid(Geometry const& geometry, Point& c, Strategy const& strategy)
{
- resolve_variant::centroid<Geometry>::apply(geometry, c, strategy);
+ resolve_dynamic::centroid<Geometry>::apply(geometry, c, strategy);
}
diff --git a/boost/geometry/algorithms/clear.hpp b/boost/geometry/algorithms/clear.hpp
index 26d60c57f2..df3acc8bdc 100644
--- a/boost/geometry/algorithms/clear.hpp
+++ b/boost/geometry/algorithms/clear.hpp
@@ -4,8 +4,9 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2020-2021.
-// Modifications copyright (c) 2020-2021, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2023.
+// Modifications copyright (c) 2020-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -22,7 +23,6 @@
#include <type_traits>
#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>
diff --git a/boost/geometry/algorithms/closest_points.hpp b/boost/geometry/algorithms/closest_points.hpp
new file mode 100644
index 0000000000..b20c651cca
--- /dev/null
+++ b/boost/geometry/algorithms/closest_points.hpp
@@ -0,0 +1,16 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_CLOSEST_POINTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_CLOSEST_POINTS_HPP
+
+#include <boost/geometry/algorithms/detail/closest_points/interface.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/implementation.hpp>
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_CLOSEST_POINTS_HPP
diff --git a/boost/geometry/algorithms/convert.hpp b/boost/geometry/algorithms/convert.hpp
index 166441e1e1..2d07ce2b7f 100644
--- a/boost/geometry/algorithms/convert.hpp
+++ b/boost/geometry/algorithms/convert.hpp
@@ -5,8 +5,9 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017-2021.
-// Modifications copyright (c) 2017-2021, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2023.
+// Modifications copyright (c) 2017-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -28,7 +29,6 @@
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
-#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
@@ -37,12 +37,8 @@
#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/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
-#include <boost/geometry/arithmetic/arithmetic.hpp>
-
-#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -128,7 +124,7 @@ struct segment_to_range
{
traits::resize<Range>::apply(range, 2);
- typename boost::range_iterator<Range>::type it = boost::begin(range);
+ auto it = boost::begin(range);
assign_point_from_index<0>(segment, *it);
++it;
@@ -152,7 +148,7 @@ struct range_to_range
geometry::detail::conversion::convert_point_to_point(point1, point2);
}
};
-
+
static inline void apply(Range1 const& source, Range2& destination)
{
apply(source, destination, default_policy());
@@ -186,8 +182,7 @@ struct range_to_range
// but ok, sice below it == end()
size_type i = 0;
- for (typename boost::range_iterator<view_type const>::type it
- = boost::begin(view);
+ for (auto it = boost::begin(view);
it != boost::end(view) && i < n;
++it, ++i)
{
@@ -227,15 +222,11 @@ struct polygon_to_polygon
>::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);
+ auto const& rings_source = interior_rings(source);
+ auto&& rings_dest = interior_rings(destination);
- typename detail::interior_iterator<Polygon1 const>::type
- it_source = boost::begin(rings_source);
- typename detail::interior_iterator<Polygon2>::type
- it_dest = boost::begin(rings_dest);
+ auto it_source = boost::begin(rings_source);
+ auto it_dest = boost::begin(rings_dest);
for ( ; it_source != boost::end(rings_source); ++it_source, ++it_dest)
{
@@ -263,10 +254,8 @@ struct multi_to_multi: private Policy
{
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);
+ auto it1 = boost::begin(multi1);
+ auto it2 = boost::begin(multi2);
for (; it1 != boost::end(multi1); ++it1, ++it2)
{
@@ -284,6 +273,10 @@ struct multi_to_multi: private Policy
namespace dispatch
{
+// TODO: We could use std::is_assignable instead of std::is_same.
+// Then we should rather check ! std::is_array<Geometry2>::value
+// which is Destination.
+
template
<
typename Geometry1, typename Geometry2,
diff --git a/boost/geometry/algorithms/correct.hpp b/boost/geometry/algorithms/correct.hpp
index 3c338916bf..20a94de85c 100644
--- a/boost/geometry/algorithms/correct.hpp
+++ b/boost/geometry/algorithms/correct.hpp
@@ -5,8 +5,9 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017-2020.
-// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2023.
+// Modifications copyright (c) 2017-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -21,33 +22,31 @@
#include <algorithm>
-#include <cstddef>
#include <functional>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
-#include <boost/range/value_type.hpp>
-
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
+#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/correct_closure.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
+#include <boost/geometry/algorithms/detail/multi_modify.hpp>
+#include <boost/geometry/algorithms/detail/visit.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/mutable_range.hpp>
-#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
-#include <boost/geometry/algorithms/area.hpp>
-#include <boost/geometry/algorithms/detail/multi_modify.hpp>
-#include <boost/geometry/util/order_as_direction.hpp>
+#include <boost/geometry/strategies/area/cartesian.hpp>
+#include <boost/geometry/strategies/area/geographic.hpp>
+#include <boost/geometry/strategies/area/spherical.hpp>
+#include <boost/geometry/strategies/detail.hpp>
+
+#include <boost/geometry/util/algorithm.hpp>
+
namespace boost { namespace geometry
{
@@ -62,92 +61,56 @@ namespace boost { namespace geometry
namespace detail { namespace correct
{
-template <typename Geometry>
struct correct_nop
{
- template <typename Strategy>
+ template <typename Geometry, typename Strategy>
static inline void apply(Geometry& , Strategy const& )
{}
};
-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
{
- template <typename Strategy>
+ template <typename Box, typename Strategy>
static inline void apply(Box& box, Strategy const& )
{
+ using coordinate_type = typename geometry::coordinate_type<Box>::type;
+
// 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);
+ detail::for_each_dimension<Box>([&](auto dimension)
+ {
+ 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);
+ }
+ });
}
};
// Close a ring, if not closed
-template <typename Ring, template <typename> class Predicate>
+template <typename Predicate = std::less<>>
struct correct_ring
{
- typedef typename point_type<Ring>::type point_type;
- typedef typename coordinate_type<Ring>::type coordinate_type;
-
- template <typename Strategy>
+ template <typename Ring, typename Strategy>
static inline void apply(Ring& r, Strategy const& strategy)
{
// Correct closure if necessary
- detail::correct_closure::close_or_open_ring<Ring>::apply(r);
+ detail::correct_closure::close_or_open_ring::apply(r);
+
+ // NOTE: calculate_point_order should probably be used here instead.
// Check area
- typedef typename area_result<Ring, Strategy>::type area_result_type;
- Predicate<area_result_type> predicate;
- area_result_type const zero = 0;
- if (predicate(detail::area::ring_area::apply(
- r,
- // TEMP - in the future (umbrella) strategy will be passed
- geometry::strategies::area::services::strategy_converter
- <
- Strategy
- >::get(strategy)),
- zero))
+ using area_t = typename area_result<Ring, Strategy>::type;
+ area_t const zero = 0;
+ if (Predicate()(detail::area::ring_area::apply(r, strategy), zero))
{
std::reverse(boost::begin(r), boost::end(r));
}
@@ -156,30 +119,18 @@ struct correct_ring
// 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;
-
- template <typename Strategy>
+ template <typename Polygon, typename Strategy>
static inline void apply(Polygon& poly, Strategy const& strategy)
{
- correct_ring
- <
- ring_type,
- std::less
- >::apply(exterior_ring(poly), strategy);
-
- typename interior_return_type<Polygon>::type
- rings = interior_rings(poly);
- for (typename detail::interior_iterator<Polygon>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ correct_ring<std::less<>>::apply(exterior_ring(poly), strategy);
+
+ auto&& rings = interior_rings(poly);
+ auto const end = boost::end(rings);
+ for (auto it = boost::begin(rings); it != end; ++it)
{
- correct_ring
- <
- ring_type,
- std::greater
- >::apply(*it, strategy);
+ correct_ring<std::greater<>>::apply(*it, strategy);
}
}
};
@@ -199,62 +150,51 @@ struct correct: not_implemented<Tag>
template <typename Point>
struct correct<Point, point_tag>
- : detail::correct::correct_nop<Point>
+ : detail::correct::correct_nop
{};
template <typename LineString>
struct correct<LineString, linestring_tag>
- : detail::correct::correct_nop<LineString>
+ : detail::correct::correct_nop
{};
template <typename Segment>
struct correct<Segment, segment_tag>
- : detail::correct::correct_nop<Segment>
+ : detail::correct::correct_nop
{};
template <typename Box>
struct correct<Box, box_tag>
- : detail::correct::correct_box<Box>
+ : detail::correct::correct_box
{};
template <typename Ring>
struct correct<Ring, ring_tag>
- : detail::correct::correct_ring
- <
- Ring,
- std::less
- >
+ : detail::correct::correct_ring<>
{};
template <typename Polygon>
struct correct<Polygon, polygon_tag>
- : detail::correct::correct_polygon<Polygon>
+ : detail::correct::correct_polygon
{};
template <typename MultiPoint>
struct correct<MultiPoint, multi_point_tag>
- : detail::correct::correct_nop<MultiPoint>
+ : detail::correct::correct_nop
{};
template <typename MultiLineString>
struct correct<MultiLineString, multi_linestring_tag>
- : detail::correct::correct_nop<MultiLineString>
+ : detail::correct::correct_nop
{};
template <typename Geometry>
struct correct<Geometry, multi_polygon_tag>
- : detail::multi_modify
- <
- Geometry,
- detail::correct::correct_polygon
- <
- typename boost::range_value<Geometry>::type
- >
- >
+ : detail::multi_modify<detail::correct::correct_polygon>
{};
@@ -262,45 +202,96 @@ struct correct<Geometry, multi_polygon_tag>
#endif // DOXYGEN_NO_DISPATCH
-namespace resolve_variant {
+namespace resolve_strategy
+{
-template <typename Geometry>
+template
+<
+ typename Strategy,
+ bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
+>
struct correct
{
- template <typename Strategy>
+ template <typename Geometry>
static inline void apply(Geometry& geometry, Strategy const& strategy)
{
- concepts::check<Geometry const>();
dispatch::correct<Geometry>::apply(geometry, strategy);
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Strategy>
+struct correct<Strategy, false>
{
- template <typename Strategy>
- struct visitor: boost::static_visitor<void>
+ template <typename Geometry>
+ static inline void apply(Geometry& geometry, Strategy const& strategy)
+ {
+ // NOTE: calculate_point_order strategy should probably be used here instead.
+ using geometry::strategies::area::services::strategy_converter;
+ dispatch::correct<Geometry>::apply(geometry, strategy_converter<Strategy>::get(strategy));
+ }
+};
+
+template <>
+struct correct<default_strategy, false>
+{
+ template <typename Geometry>
+ static inline void apply(Geometry& geometry, default_strategy const& )
{
- Strategy const& m_strategy;
+ // NOTE: calculate_point_order strategy should probably be used here instead.
+ using strategy_type = typename strategies::area::services::default_strategy
+ <
+ Geometry
+ >::type;
+ dispatch::correct<Geometry>::apply(geometry, strategy_type());
+ }
+};
+
+} // namespace resolve_strategy
- visitor(Strategy const& strategy): m_strategy(strategy) {}
- template <typename Geometry>
- void operator()(Geometry& geometry) const
+namespace resolve_dynamic
+{
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct correct
+{
+ template <typename Strategy>
+ static inline void apply(Geometry& geometry, Strategy const& strategy)
+ {
+ concepts::check<Geometry>();
+ resolve_strategy::correct<Strategy>::apply(geometry, strategy);
+ }
+};
+
+template <typename Geometry>
+struct correct<Geometry, dynamic_geometry_tag>
+{
+ template <typename Strategy>
+ static inline void apply(Geometry& geometry, Strategy const& strategy)
+ {
+ traits::visit<Geometry>::apply([&](auto & g)
{
- correct<Geometry>::apply(geometry, m_strategy);
- }
- };
+ correct<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
+ }, geometry);
+ }
+};
+template <typename Geometry>
+struct correct<Geometry, geometry_collection_tag>
+{
template <typename Strategy>
- static inline void
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry, Strategy const& strategy)
+ static inline void apply(Geometry& geometry, Strategy const& strategy)
{
- boost::apply_visitor(visitor<Strategy>(strategy), geometry);
+ detail::visit_breadth_first([&](auto & g)
+ {
+ correct<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
+ return true;
+ }, geometry);
}
};
-} // namespace resolve_variant
+
+} // namespace resolve_dynamic
/*!
@@ -318,14 +309,7 @@ struct correct<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline void correct(Geometry& geometry)
{
- typedef typename point_type<Geometry>::type point_type;
-
- typedef typename strategy::area::services::default_strategy
- <
- typename cs_tag<point_type>::type
- >::type strategy_type;
-
- resolve_variant::correct<Geometry>::apply(geometry, strategy_type());
+ resolve_dynamic::correct<Geometry>::apply(geometry, default_strategy());
}
/*!
@@ -347,7 +331,7 @@ inline void correct(Geometry& geometry)
template <typename Geometry, typename Strategy>
inline void correct(Geometry& geometry, Strategy const& strategy)
{
- resolve_variant::correct<Geometry>::apply(geometry, strategy);
+ resolve_dynamic::correct<Geometry>::apply(geometry, strategy);
}
#if defined(_MSC_VER)
diff --git a/boost/geometry/algorithms/correct_closure.hpp b/boost/geometry/algorithms/correct_closure.hpp
index 4160f256f3..38d982c91b 100644
--- a/boost/geometry/algorithms/correct_closure.hpp
+++ b/boost/geometry/algorithms/correct_closure.hpp
@@ -2,8 +2,9 @@
// Copyright (c) 2017 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2023.
+// Modifications copyright (c) 2020-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -13,29 +14,18 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_CORRECT_CLOSURE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_CORRECT_CLOSURE_HPP
-#include <cstddef>
-
-#include <boost/range/begin.hpp>
-#include <boost/range/end.hpp>
-#include <boost/range/size.hpp>
-#include <boost/range/value_type.hpp>
-
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
+#include <boost/geometry/algorithms/detail/multi_modify.hpp>
+#include <boost/geometry/algorithms/disjoint.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/tags.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
-#include <boost/geometry/algorithms/disjoint.hpp>
-#include <boost/geometry/algorithms/detail/multi_modify.hpp>
+#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry
{
@@ -50,59 +40,55 @@ namespace boost { namespace geometry
namespace detail { namespace correct_closure
{
-template <typename Geometry>
struct nop
{
+ template <typename Geometry>
static inline void apply(Geometry& )
{}
};
-
// Close a ring, if not closed, or open it
-template <typename Ring>
struct close_or_open_ring
{
+ template <typename Ring>
static inline void apply(Ring& r)
{
- if (boost::size(r) <= 2)
+ auto size = boost::size(r);
+ if (size <= 2)
{
return;
}
- bool const disjoint = geometry::disjoint(*boost::begin(r),
- *(boost::end(r) - 1));
- closure_selector const s = geometry::closure<Ring>::value;
+ // TODO: This requires relate(pt, pt) strategy
+ bool const disjoint = geometry::disjoint(*boost::begin(r), *(boost::end(r) - 1));
+ closure_selector const closure = geometry::closure<Ring>::value;
- if (disjoint && s == closed)
+ if (disjoint && closure == closed)
{
// Close it by adding first point
geometry::append(r, *boost::begin(r));
}
- else if (! disjoint && s != closed)
+ else if (! disjoint && closure == open)
{
// Open it by removing last point
- geometry::traits::resize<Ring>::apply(r, boost::size(r) - 1);
+ range::resize(r, size - 1);
}
}
};
// Close/open exterior ring and all its interior rings
-template <typename Polygon>
struct close_or_open_polygon
{
- typedef typename ring_type<Polygon>::type ring_type;
-
+ template <typename Polygon>
static inline void apply(Polygon& poly)
{
- close_or_open_ring<ring_type>::apply(exterior_ring(poly));
+ close_or_open_ring::apply(exterior_ring(poly));
- typename interior_return_type<Polygon>::type
- rings = interior_rings(poly);
-
- for (typename detail::interior_iterator<Polygon>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ auto&& rings = interior_rings(poly);
+ auto const end = boost::end(rings);
+ for (auto it = boost::begin(rings); it != end; ++it)
{
- close_or_open_ring<ring_type>::apply(*it);
+ close_or_open_ring::apply(*it);
}
}
};
@@ -121,45 +107,45 @@ struct correct_closure: not_implemented<Tag>
template <typename Point>
struct correct_closure<Point, point_tag>
- : detail::correct_closure::nop<Point>
+ : detail::correct_closure::nop
{};
template <typename LineString>
struct correct_closure<LineString, linestring_tag>
- : detail::correct_closure::nop<LineString>
+ : detail::correct_closure::nop
{};
template <typename Segment>
struct correct_closure<Segment, segment_tag>
- : detail::correct_closure::nop<Segment>
+ : detail::correct_closure::nop
{};
template <typename Box>
struct correct_closure<Box, box_tag>
- : detail::correct_closure::nop<Box>
+ : detail::correct_closure::nop
{};
template <typename Ring>
struct correct_closure<Ring, ring_tag>
- : detail::correct_closure::close_or_open_ring<Ring>
+ : detail::correct_closure::close_or_open_ring
{};
template <typename Polygon>
struct correct_closure<Polygon, polygon_tag>
- : detail::correct_closure::close_or_open_polygon<Polygon>
+ : detail::correct_closure::close_or_open_polygon
{};
template <typename MultiPoint>
struct correct_closure<MultiPoint, multi_point_tag>
- : detail::correct_closure::nop<MultiPoint>
+ : detail::correct_closure::nop
{};
template <typename MultiLineString>
struct correct_closure<MultiLineString, multi_linestring_tag>
- : detail::correct_closure::nop<MultiLineString>
+ : detail::correct_closure::nop
{};
@@ -167,11 +153,7 @@ template <typename Geometry>
struct correct_closure<Geometry, multi_polygon_tag>
: detail::multi_modify
<
- Geometry,
detail::correct_closure::close_or_open_polygon
- <
- typename boost::range_value<Geometry>::type
- >
>
{};
@@ -183,7 +165,7 @@ struct correct_closure<Geometry, multi_polygon_tag>
namespace resolve_variant
{
-template <typename Geometry>
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct correct_closure
{
static inline void apply(Geometry& geometry)
@@ -193,29 +175,37 @@ struct correct_closure
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct correct_closure<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct correct_closure<Geometry, dynamic_geometry_tag>
{
- struct visitor: boost::static_visitor<void>
+ static void apply(Geometry& geometry)
{
- template <typename Geometry>
- void operator()(Geometry& geometry) const
+ traits::visit<Geometry>::apply([](auto & g)
{
- correct_closure<Geometry>::apply(geometry);
- }
- };
+ correct_closure<util::remove_cref_t<decltype(g)>>::apply(g);
+ }, geometry);
+ }
+};
- static inline void
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)
+template <typename Geometry>
+struct correct_closure<Geometry, geometry_collection_tag>
+{
+ static void apply(Geometry& geometry)
{
- visitor vis;
- boost::apply_visitor(vis, geometry);
+ detail::visit_breadth_first([](auto & g)
+ {
+ correct_closure<util::remove_cref_t<decltype(g)>>::apply(g);
+ return true;
+ }, geometry);
}
};
} // namespace resolve_variant
+// TODO: This algorithm should use relate(pt, pt) strategy
+
+
/*!
\brief Closes or opens a geometry, according to its type
\details Corrects a geometry w.r.t. closure points to all rings which do not
diff --git a/boost/geometry/algorithms/covered_by.hpp b/boost/geometry/algorithms/covered_by.hpp
index d68429673a..b564e02844 100644
--- a/boost/geometry/algorithms/covered_by.hpp
+++ b/boost/geometry/algorithms/covered_by.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2013, 2014, 2017.
-// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -22,6 +22,7 @@
#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation_gc.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_COVERED_BY_HPP
diff --git a/boost/geometry/algorithms/crosses.hpp b/boost/geometry/algorithms/crosses.hpp
index b35456554d..040076d3d3 100644
--- a/boost/geometry/algorithms/crosses.hpp
+++ b/boost/geometry/algorithms/crosses.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Samuel Debionne, Grenoble, France.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -22,19 +22,18 @@
#include <cstddef>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
-#include <boost/geometry/algorithms/relate.hpp>
+#include <boost/geometry/algorithms/detail/gc_topological_dimension.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
+#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/cartesian.hpp>
#include <boost/geometry/strategies/relate/geographic.hpp>
#include <boost/geometry/strategies/relate/spherical.hpp>
+#include <boost/geometry/views/detail/geometry_collection_view.hpp>
namespace boost { namespace geometry
@@ -62,6 +61,82 @@ struct crosses
{};
+template <typename Geometry1, typename Geometry2>
+struct crosses<Geometry1, Geometry2, geometry_collection_tag, geometry_collection_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ int const dimension1 = detail::gc_topological_dimension(geometry1);
+ int const dimension2 = detail::gc_topological_dimension(geometry2);
+
+ if (dimension1 >= 0 && dimension2 >= 0)
+ {
+ if (dimension1 < dimension2)
+ {
+ return detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_crosses_d1_le_d2_type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
+ }
+ else if (dimension1 > dimension2)
+ {
+ return detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_crosses_d2_le_d1_type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
+ }
+ else if (dimension1 == 1 && dimension2 == 1)
+ {
+ return detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_crosses_d1_1_d2_1_type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
+ }
+ }
+
+ return false;
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct crosses<Geometry1, Geometry2, Tag1, geometry_collection_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ using gc1_view_t = detail::geometry_collection_view<Geometry1>;
+ return crosses
+ <
+ gc1_view_t, Geometry2
+ >::apply(gc1_view_t(geometry1), geometry2, strategy);
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct crosses<Geometry1, Geometry2, geometry_collection_tag, Tag2>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ using gc2_view_t = detail::geometry_collection_view<Geometry2>;
+ return crosses
+ <
+ Geometry1, gc2_view_t
+ >::apply(geometry1, gc2_view_t(geometry2), strategy);
+ }
+};
+
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
@@ -134,130 +209,96 @@ struct crosses<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
- template <typename Geometry1, typename Geometry2>
- struct crosses
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
+struct crosses
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- template <typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
+ return resolve_strategy::crosses
+ <
+ Strategy
+ >::apply(geometry1, geometry2, strategy);
+ }
+};
+
+
+template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
+struct crosses<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
+{
+ template <typename Strategy>
+ static inline bool apply(DynamicGeometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ bool result = false;
+ traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
{
- return resolve_strategy::crosses
+ result = resolve_strategy::crosses
<
Strategy
- >::apply(geometry1, geometry2, strategy);
- }
- };
-
-
- template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
- struct crosses<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
- {
- template <typename Strategy>
- struct visitor: static_visitor<bool>
- {
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Strategy const& strategy)
- : m_geometry2(geometry2)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- result_type operator()(Geometry1 const& geometry1) const
- {
- return crosses
- <
- Geometry1,
- Geometry2
- >::apply(geometry1, m_geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
- }
- };
-
-
- template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
- struct crosses<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+ >::apply(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
+ }
+};
+
+
+template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
+struct crosses<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ DynamicGeometry2 const& geometry2,
+ Strategy const& strategy)
{
- template <typename Strategy>
- struct visitor: static_visitor<bool>
+ bool result = false;
+ traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
{
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Strategy const& strategy)
- : m_geometry1(geometry1)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- result_type operator()(Geometry2 const& geometry2) const
- {
- return crosses
- <
- Geometry1,
- Geometry2
- >::apply(m_geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
- }
- };
-
-
- template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
- struct crosses<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
+ result = resolve_strategy::crosses
+ <
+ Strategy
+ >::apply(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
+ }
+};
+
+
+template <typename DynamicGeometry1, typename DynamicGeometry2>
+struct crosses<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(DynamicGeometry1 const& geometry1,
+ DynamicGeometry2 const& geometry2,
+ Strategy const& strategy)
{
- template <typename Strategy>
- struct visitor: static_visitor<bool>
+ bool result = false;
+ traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
{
- Strategy const& m_strategy;
+ result = resolve_strategy::crosses
+ <
+ Strategy
+ >::apply(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
+ }
+};
+
+
+} // namespace resolve_dynamic
- visitor(Strategy const& strategy)
- : m_strategy(strategy)
- {}
- template <typename Geometry1, typename Geometry2>
- result_type operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
- {
- return crosses
- <
- Geometry1,
- Geometry2
- >::apply(geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
- }
- };
-
-} // namespace resolve_variant
-
-
/*!
\brief \brief_check2{crosses}
\ingroup crosses
@@ -277,7 +318,7 @@ inline bool crosses(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
- return resolve_variant::crosses
+ return resolve_dynamic::crosses
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
@@ -302,7 +343,7 @@ inline bool crosses(Geometry1 const& geometry1,
template <typename Geometry1, typename Geometry2>
inline bool crosses(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- return resolve_variant::crosses
+ return resolve_dynamic::crosses
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, default_strategy());
diff --git a/boost/geometry/algorithms/densify.hpp b/boost/geometry/algorithms/densify.hpp
index d601bd3c83..3af062ebd3 100644
--- a/boost/geometry/algorithms/densify.hpp
+++ b/boost/geometry/algorithms/densify.hpp
@@ -1,7 +1,9 @@
// Boost.Geometry
-// Copyright (c) 2017-2021, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2017-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
@@ -11,28 +13,29 @@
#define BOOST_GEOMETRY_ALGORITHMS_DENSIFY_HPP
+#include <boost/range/size.hpp>
+#include <boost/range/value_type.hpp>
+#include <boost/throw_exception.hpp>
+
#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/closure.hpp>
-#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/exception.hpp>
-#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/densify/cartesian.hpp>
#include <boost/geometry/strategies/densify/geographic.hpp>
#include <boost/geometry/strategies/densify/spherical.hpp>
#include <boost/geometry/strategies/detail.hpp>
-#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/constexpr.hpp>
#include <boost/geometry/util/range.hpp>
-#include <boost/range/size.hpp>
-#include <boost/range/value_type.hpp>
-
-#include <boost/throw_exception.hpp>
-
namespace boost { namespace geometry
{
@@ -75,21 +78,20 @@ struct densify_range
static inline void apply(FwdRng const& rng, MutRng & rng_out,
T const& len, Strategies const& strategies)
{
- typedef typename boost::range_iterator<FwdRng const>::type iterator_t;
typedef typename boost::range_value<FwdRng>::type point_t;
- iterator_t it = boost::begin(rng);
- iterator_t end = boost::end(rng);
+ auto it = boost::begin(rng);
+ auto const end = boost::end(rng);
if (it == end) // empty(rng)
{
return;
}
-
+
auto strategy = strategies.densify(rng);
push_back_policy<MutRng> policy(rng_out);
- iterator_t prev = it;
+ auto prev = it;
for ( ++it ; it != end ; prev = it++)
{
point_t const& p0 = *prev;
@@ -100,7 +102,7 @@ struct densify_range
strategy.apply(p0, p1, policy, len);
}
- if (BOOST_GEOMETRY_CONDITION(AppendLastPoint))
+ if BOOST_GEOMETRY_CONSTEXPR (AppendLastPoint)
{
convert_and_push_back(rng_out, *prev); // back(rng)
}
@@ -120,16 +122,15 @@ struct densify_ring
if (boost::size(ring) <= 1)
return;
- typedef typename point_type<Geometry>::type point_t;
- point_t const& p0 = range::back(ring);
- point_t const& p1 = range::front(ring);
+ auto const& p0 = range::back(ring);
+ auto const& p1 = range::front(ring);
auto strategy = strategies.densify(ring);
push_back_policy<GeometryOut> policy(ring_out);
strategy.apply(p0, p1, policy, len);
- if (BOOST_GEOMETRY_CONDITION(IsClosed2))
+ if BOOST_GEOMETRY_CONSTEXPR (IsClosed2)
{
convert_and_push_back(ring_out, p1);
}
@@ -146,6 +147,15 @@ struct densify_ring<true, false>
: densify_range<false>
{};
+struct densify_convert
+{
+ template <typename GeometryIn, typename GeometryOut, typename T, typename Strategy>
+ static void apply(GeometryIn const& in, GeometryOut &out,
+ T const& , Strategy const& )
+ {
+ geometry::convert(in, out);
+ }
+};
}} // namespace detail::densify
#endif // DOXYGEN_NO_DETAIL
@@ -168,6 +178,26 @@ struct densify
{};
template <typename Geometry, typename GeometryOut>
+struct densify<Geometry, GeometryOut, point_tag, point_tag>
+ : geometry::detail::densify::densify_convert
+{};
+
+template <typename Geometry, typename GeometryOut>
+struct densify<Geometry, GeometryOut, segment_tag, segment_tag>
+ : geometry::detail::densify::densify_convert
+{};
+
+template <typename Geometry, typename GeometryOut>
+struct densify<Geometry, GeometryOut, box_tag, box_tag>
+ : geometry::detail::densify::densify_convert
+{};
+
+template <typename Geometry, typename GeometryOut>
+struct densify<Geometry, GeometryOut, multi_point_tag, multi_point_tag>
+ : geometry::detail::densify::densify_convert
+{};
+
+template <typename Geometry, typename GeometryOut>
struct densify<Geometry, GeometryOut, linestring_tag, linestring_tag>
: geometry::detail::densify::densify_range<>
{};
@@ -317,7 +347,7 @@ struct densify<default_strategy, false>
<
Geometry
>::type strategies_type;
-
+
dispatch::densify
<
Geometry, Geometry
@@ -328,9 +358,9 @@ struct densify<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant {
+namespace resolve_dynamic {
-template <typename Geometry>
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct densify
{
template <typename Distance, typename Strategy>
@@ -346,43 +376,48 @@ struct densify
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct densify<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct densify<Geometry, dynamic_geometry_tag>
{
template <typename Distance, typename Strategy>
- struct visitor: boost::static_visitor<void>
+ static inline void
+ apply(Geometry const& geometry,
+ Geometry& out,
+ Distance const& max_distance,
+ Strategy const& strategy)
{
- Distance const& m_max_distance;
- Strategy const& m_strategy;
-
- visitor(Distance const& max_distance, Strategy const& strategy)
- : m_max_distance(max_distance)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry>
- void operator()(Geometry const& geometry, Geometry& out) const
+ traits::visit<Geometry>::apply([&](auto const& g)
{
- densify<Geometry>::apply(geometry, out, m_max_distance, m_strategy);
- }
- };
+ using geom_t = util::remove_cref_t<decltype(g)>;
+ geom_t o;
+ densify<geom_t>::apply(g, o, max_distance, strategy);
+ out = std::move(o);
+ }, geometry);
+ }
+};
+template <typename Geometry>
+struct densify<Geometry, geometry_collection_tag>
+{
template <typename Distance, typename Strategy>
static inline void
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& out,
+ apply(Geometry const& geometry,
+ Geometry& out,
Distance const& max_distance,
Strategy const& strategy)
{
- boost::apply_visitor(
- visitor<Distance, Strategy>(max_distance, strategy),
- geometry,
- out
- );
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ using geom_t = util::remove_cref_t<decltype(g)>;
+ geom_t o;
+ densify<geom_t>::apply(g, o, max_distance, strategy);
+ traits::emplace_back<Geometry>::apply(out, std::move(o));
+ return true;
+ }, geometry);
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -428,7 +463,7 @@ inline void densify(Geometry const& geometry,
geometry::clear(out);
- resolve_variant::densify
+ resolve_dynamic::densify
<
Geometry
>::apply(geometry, out, max_distance, strategy);
diff --git a/boost/geometry/algorithms/detail/as_range.hpp b/boost/geometry/algorithms/detail/as_range.hpp
deleted file mode 100644
index fe2016be5e..0000000000
--- a/boost/geometry/algorithms/detail/as_range.hpp
+++ /dev/null
@@ -1,91 +0,0 @@
-// 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.
-
-// This file was modified by Oracle on 2020-2021.
-// Modifications copyright (c) 2020-2021 Oracle and/or its affiliates.
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
-// 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/geometry/algorithms/not_implemented.hpp>
-
-#include <boost/geometry/core/exterior_ring.hpp>
-#include <boost/geometry/core/ring_type.hpp>
-#include <boost/geometry/core/tag.hpp>
-#include <boost/geometry/core/tags.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-
-#ifndef DOXYGEN_NO_DISPATCH
-namespace dispatch
-{
-
-
-template <typename Geometry, typename Tag = typename tag<Geometry>::type>
-struct as_range : not_implemented<Geometry, Tag>
-{};
-
-template <typename Geometry>
-struct as_range<Geometry, linestring_tag>
-{
- static inline typename ring_return_type<Geometry>::type get(Geometry& geometry)
- {
- return geometry;
- }
-};
-
-template <typename Geometry>
-struct as_range<Geometry, ring_tag>
- : as_range<Geometry, linestring_tag>
-{};
-
-template <typename Geometry>
-struct as_range<Geometry, polygon_tag>
-{
- static inline typename ring_return_type<Geometry>::type get(Geometry& geometry)
- {
- return exterior_ring(geometry);
- }
-};
-
-
-} // 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 Geometry>
-inline typename ring_return_type<Geometry>::type as_range(Geometry& geometry)
-{
- return dispatch::as_range<Geometry>::get(geometry);
-}
-
-}
-
-}} // namespace boost::geometry
-
-
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AS_RANGE_HPP
diff --git a/boost/geometry/algorithms/detail/buffer/buffer_box.hpp b/boost/geometry/algorithms/detail/buffer/buffer_box.hpp
index f19a91d6ba..f19a91d6ba 100755..100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_box.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_box.hpp
diff --git a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
index cc5c41d11b..5e8635c3d7 100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp
@@ -1,9 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2020 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2022-2023 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017-2021.
-// Modifications copyright (c) 2017-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2022.
+// Modifications copyright (c) 2017-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -37,10 +38,13 @@
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/geometries/linestring.hpp>
+#include <boost/geometry/geometries/ring.hpp>
+
#include <boost/geometry/strategies/buffer.hpp>
#include <boost/geometry/strategies/side.hpp>
-#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/constexpr.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/type_traits.hpp>
@@ -54,11 +58,11 @@ namespace boost { namespace geometry
namespace detail { namespace buffer
{
-template <typename Range, typename DistanceStrategy, typename Strategies>
-inline void simplify_input(Range const& range,
- DistanceStrategy const& distance,
- Range& simplified,
- Strategies const& strategies)
+template <typename RangeIn, typename DistanceStrategy, typename RangeOut, typename Strategies>
+inline void simplify_input(RangeIn const& range,
+ DistanceStrategy const& distance,
+ RangeOut& simplified,
+ Strategies const& strategies)
{
// We have to simplify the ring before to avoid very small-scaled
// features in the original (convex/concave/convex) being enlarged
@@ -291,7 +295,7 @@ struct buffer_range
robust_policy, strategies);
}
- collection.add_side_piece(*prev, *it, generated_side, first);
+ collection.add_side_piece(*prev, *it, generated_side, first, distance_strategy.empty(side));
if (first && mark_flat)
{
@@ -350,10 +354,7 @@ struct buffer_multi
RobustPolicy const& robust_policy,
Strategies const& strategies)
{
- for (typename boost::range_iterator<Multi const>::type
- it = boost::begin(multi);
- it != boost::end(multi);
- ++it)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
Policy::apply(*it, collection,
distance_strategy, segment_strategy,
@@ -453,7 +454,7 @@ template
>
struct buffer_inserter_ring
{
- typedef typename point_type<RingOutput>::type output_point_type;
+ using output_point_type = typename point_type<RingOutput>::type;
template
<
@@ -524,7 +525,14 @@ struct buffer_inserter_ring
RobustPolicy const& robust_policy,
Strategies const& strategies)
{
- RingInput simplified;
+ // Use helper geometry to support non-mutable input Rings
+ using simplified_ring_t = model::ring
+ <
+ output_point_type,
+ point_order<RingInput>::value != counterclockwise,
+ closure<RingInput>::value != open
+ >;
+ simplified_ring_t simplified;
detail::buffer::simplify_input(ring, distance, simplified, strategies);
geometry::strategy::buffer::result_code code = geometry::strategy::buffer::result_no_output;
@@ -532,12 +540,12 @@ struct buffer_inserter_ring
std::size_t n = boost::size(simplified);
std::size_t const min_points = core_detail::closure::minimum_ring_size
<
- geometry::closure<RingInput>::value
+ geometry::closure<simplified_ring_t>::value
>::value;
if (n >= min_points)
{
- detail::closed_clockwise_view<RingInput const> view(simplified);
+ detail::closed_clockwise_view<simplified_ring_t const> view(simplified);
if (distance.negative())
{
// Walk backwards (rings will be reversed afterwards)
@@ -615,9 +623,8 @@ template
>
struct buffer_inserter<linestring_tag, Linestring, Polygon>
{
- typedef typename ring_type<Polygon>::type output_ring_type;
- typedef typename point_type<output_ring_type>::type output_point_type;
- typedef typename point_type<Linestring>::type input_point_type;
+ using output_ring_type = typename ring_type<Polygon>::type;
+ using output_point_type = typename point_type<output_ring_type>::type;
template
<
@@ -641,8 +648,8 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
Strategies const& strategies,
output_point_type& first_p1)
{
- input_point_type const& ultimate_point = *(end - 1);
- input_point_type const& penultimate_point = *(end - 2);
+ output_point_type const& ultimate_point = *(end - 1);
+ output_point_type const& penultimate_point = *(end - 2);
// For the end-cap, we need to have the last perpendicular point on the
// other side of the linestring. If it is the second pass (right),
@@ -708,7 +715,8 @@ struct buffer_inserter<linestring_tag, Linestring, Polygon>
RobustPolicy const& robust_policy,
Strategies const& strategies)
{
- Linestring simplified;
+ // Use helper geometry to support non-mutable input Linestrings
+ model::linestring<output_point_type> simplified;
detail::buffer::simplify_input(linestring, distance, simplified, strategies);
geometry::strategy::buffer::result_code code = geometry::strategy::buffer::result_no_output;
@@ -934,17 +942,17 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
{
boost::ignore_unused(visit_pieces_policy);
- typedef detail::buffer::buffered_piece_collection
- <
- typename geometry::ring_type<GeometryOutput>::type,
- Strategies,
- DistanceStrategy,
- RobustPolicy
- > collection_type;
+ using collection_type = detail::buffer::buffered_piece_collection
+ <
+ typename geometry::ring_type<GeometryOutput>::type,
+ Strategies,
+ DistanceStrategy,
+ RobustPolicy
+ >;
collection_type collection(strategies, distance_strategy, robust_policy);
collection_type const& const_collection = collection;
- bool const areal = util::is_areal<GeometryInput>::value;
+ static constexpr bool areal = util::is_areal<GeometryInput>::value;
dispatch::buffer_inserter
<
@@ -961,7 +969,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
robust_policy, strategies);
collection.get_turns();
- if (BOOST_GEOMETRY_CONDITION(areal))
+ if BOOST_GEOMETRY_CONSTEXPR (areal)
{
collection.check_turn_in_original();
}
@@ -981,7 +989,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
// phase 1: turns (after enrichment/clustering)
visit_pieces_policy.apply(const_collection, 1);
- if (BOOST_GEOMETRY_CONDITION(areal))
+ if BOOST_GEOMETRY_CONSTEXPR (areal)
{
collection.deflate_check_turns();
}
@@ -993,8 +1001,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
// - the output is counter clockwise
// and avoid reversing twice
bool reverse = distance_strategy.negative() && areal;
- if (BOOST_GEOMETRY_CONDITION(
- geometry::point_order<GeometryOutput>::value == counterclockwise))
+ if BOOST_GEOMETRY_CONSTEXPR (geometry::point_order<GeometryOutput>::value == counterclockwise)
{
reverse = ! reverse;
}
@@ -1003,9 +1010,12 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator
collection.reverse();
}
- if (BOOST_GEOMETRY_CONDITION(distance_strategy.negative() && areal))
+ if BOOST_GEOMETRY_CONSTEXPR (areal)
{
- collection.discard_nonintersecting_deflated_rings();
+ if (distance_strategy.negative())
+ {
+ collection.discard_nonintersecting_deflated_rings();
+ }
}
collection.template assign<GeometryOutput>(out);
diff --git a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
index 05d5c6fdac..e75532c3f3 100644
--- a/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffer_policies.hpp
@@ -158,7 +158,6 @@ struct buffer_turn_info
// or (for deflate) if there are not enough points to traverse it.
bool is_turn_traversable;
- bool close_to_offset;
bool is_linear_end_point;
bool within_original;
signed_size_type count_in_original; // increased by +1 for in ext.ring, -1 for int.ring
@@ -166,7 +165,6 @@ struct buffer_turn_info
inline buffer_turn_info()
: turn_index(0)
, is_turn_traversable(true)
- , close_to_offset(false)
, is_linear_end_point(false)
, within_original(false)
, count_in_original(0)
diff --git a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
index 65571c9211..8aa9493420 100644
--- a/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
+++ b/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp
@@ -1,10 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2014 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2017-2023 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2016-2021.
-// Modifications copyright (c) 2016-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2016-2022.
+// Modifications copyright (c) 2016-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -59,6 +59,7 @@
#include <boost/geometry/algorithms/detail/sections/section_box_policies.hpp>
#include <boost/geometry/views/detail/closed_clockwise_view.hpp>
+#include <boost/geometry/util/for_each_with_index.hpp>
#include <boost/geometry/util/range.hpp>
@@ -289,77 +290,15 @@ struct buffered_piece_collection
, m_robust_policy(robust_policy)
{}
- inline bool is_following(buffer_turn_info_type const& turn,
- buffer_turn_operation_type const& op)
- {
- return turn.operations[0].seg_id.segment_index == op.seg_id.segment_index
- || turn.operations[1].seg_id.segment_index == op.seg_id.segment_index;
- }
-
- // Verify if turns which are classified as OK (outside or on border of
- // offsetted ring) do not traverse through other turns which are classified
- // as WITHIN (inside a piece). This can happen if turns are nearly colocated
- // and due to floating point precision just classified as within, while
- // they should not be within.
- // In those cases the turns are fine to travel through (and should),
- // but they are not made startable.
- template <typename Vector>
- inline void pretraverse(Vector const& indexed_operations)
- {
- // Verify if the turns which are OK don't skip segments
- typedef typename boost::range_value<Vector>::type indexed_type;
- buffer_turn_operation_type last_traversable_operation;
- buffer_turn_info_type last_traversable_turn;
- bool first = true;
- for (std::size_t i = 0; i < indexed_operations.size(); i++)
- {
- indexed_type const & itop = indexed_operations[i];
- buffer_turn_info_type const& turn = m_turns[itop.turn_index];
-
- if (turn.is_turn_traversable && ! first)
- {
- // Check previous and next turns. The first is handled
- BOOST_GEOMETRY_ASSERT(i > 0);
- indexed_type const& previous_itop = indexed_operations[i - 1];
- std::size_t const next_index = i + 1 < indexed_operations.size() ? i + 1 : 0;
- indexed_type const& next_itop = indexed_operations[next_index];
-
- buffer_turn_info_type& previous_turn = m_turns[previous_itop.turn_index];
- buffer_turn_info_type& next_turn = m_turns[next_itop.turn_index];
-
- if (previous_turn.close_to_offset
- && is_following(previous_turn, last_traversable_operation))
- {
- previous_turn.is_turn_traversable = true;
- }
- else if (next_turn.close_to_offset
- && is_following(next_turn, last_traversable_operation))
- {
- next_turn.is_turn_traversable = true;
- }
- }
-
- if (turn.is_turn_traversable)
- {
- first = false;
- last_traversable_operation = *itop.subject;
- last_traversable_turn = turn;
- }
- }
- }
-
inline void check_linear_endpoints(buffer_turn_info_type& turn) const
{
// TODO this is quadratic. But the #endpoints, expected, is low,
// and only applicable for linear features
// (in a multi linestring with many short lines, the #endpoints can be
// much higher)
- for (typename boost::range_iterator<std::vector<point_type> const>::type it
- = boost::begin(m_linear_end_points);
- it != boost::end(m_linear_end_points);
- ++it)
+ for (auto const& p : m_linear_end_points)
{
- if (detail::equals::equals_point_point(turn.point, *it, m_strategy))
+ if (detail::equals::equals_point_point(turn.point, p, m_strategy))
{
turn.is_linear_end_point = true;
}
@@ -383,20 +322,9 @@ struct buffered_piece_collection
enriched_map_buffer_include_policy());
// Sort turns over offsetted ring(s)
- for (typename mapped_vector_type::iterator mit
- = mapped_vector.begin();
- mit != mapped_vector.end();
- ++mit)
- {
- std::sort(mit->second.begin(), mit->second.end(), buffer_less());
- }
-
- for (typename mapped_vector_type::iterator mit
- = mapped_vector.begin();
- mit != mapped_vector.end();
- ++mit)
+ for (auto& pair : mapped_vector)
{
- pretraverse(mit->second);
+ std::sort(pair.second.begin(), pair.second.end(), buffer_less());
}
}
@@ -409,17 +337,14 @@ struct buffered_piece_collection
// Deflated rings may not travel to themselves, there should at least
// be three turns (which cannot be checked here - TODO: add to traverse)
- for (typename boost::range_iterator<turn_vector_type>::type it =
- boost::begin(m_turns); it != boost::end(m_turns); ++it)
+ for (auto& turn : m_turns)
{
- buffer_turn_info_type& turn = *it;
if (! turn.is_turn_traversable)
{
continue;
}
- for (int i = 0; i < 2; i++)
+ for (auto& op : turn.operations)
{
- buffer_turn_operation_type& op = turn.operations[i];
if (op.enriched.get_next_turn_index() == static_cast<signed_size_type>(turn.turn_index)
&& m_pieces[op.seg_id.piece_index].is_deflated)
{
@@ -452,10 +377,8 @@ struct buffered_piece_collection
bool const deflate = m_distance_strategy.negative();
- for (typename boost::range_iterator<turn_vector_type>::type it =
- boost::begin(m_turns); it != boost::end(m_turns); ++it)
+ for (auto& turn : m_turns)
{
- buffer_turn_info_type& turn = *it;
if (turn.is_turn_traversable)
{
if (deflate && turn.count_in_original <= 0)
@@ -475,21 +398,16 @@ struct buffered_piece_collection
inline void update_turn_administration()
{
- std::size_t index = 0;
- for (typename boost::range_iterator<turn_vector_type>::type it =
- boost::begin(m_turns); it != boost::end(m_turns); ++it, ++index)
+ for_each_with_index(m_turns, [this](std::size_t index, auto& turn)
{
- buffer_turn_info_type& turn = *it;
-
- // Update member used
turn.turn_index = index;
// Verify if a turn is a linear endpoint
if (! turn.is_linear_end_point)
{
- check_linear_endpoints(turn);
+ this->check_linear_endpoints(turn);
}
- }
+ });
}
// Calculate properties of piece borders which are not influenced
@@ -501,11 +419,8 @@ struct buffered_piece_collection
// - (if pieces are reversed)
inline void update_piece_administration()
{
- for (typename piece_vector_type::iterator it = boost::begin(m_pieces);
- it != boost::end(m_pieces);
- ++it)
+ for (auto& pc : m_pieces)
{
- piece& pc = *it;
piece_border_type& border = pc.m_piece_border;
buffered_ring<Ring> const& ring = offsetted_rings[pc.first_seg_id.multi_index];
@@ -561,8 +476,8 @@ struct buffered_piece_collection
turn_in_piece_visitor
<
typename geometry::cs_tag<point_type>::type,
- turn_vector_type, piece_vector_type, DistanceStrategy
- > visitor(m_turns, m_pieces, m_distance_strategy);
+ turn_vector_type, piece_vector_type, DistanceStrategy, Strategy
+ > visitor(m_turns, m_pieces, m_distance_strategy, m_strategy);
geometry::partition
<
@@ -694,7 +609,7 @@ struct buffered_piece_collection
return;
}
- if (! input_ring.empty())
+ if (! boost::empty(input_ring))
{
// Assign the ring to the original_ring collection
// For rescaling, it is recalculated. Without rescaling, it
@@ -705,8 +620,7 @@ struct buffered_piece_collection
using view_type = detail::closed_clockwise_view<InputRing const>;
view_type const view(input_ring);
- for (typename boost::range_iterator<view_type const>::type it =
- boost::begin(view); it != boost::end(view); ++it)
+ for (auto it = boost::begin(view); it != boost::end(view); ++it)
{
clockwise_ring.push_back(*it);
}
@@ -798,11 +712,10 @@ struct buffered_piece_collection
inline void sectionalize(piece const& pc, buffered_ring<Ring> const& ring)
{
- typedef geometry::detail::sectionalize::sectionalize_part
+ using sectionalizer = geometry::detail::sectionalize::sectionalize_part
<
- point_type,
std::integer_sequence<std::size_t, 0, 1> // x,y dimension
- > sectionalizer;
+ >;
// Create a ring-identifier. The source-index is the piece index
// The multi_index is as in this collection (the ring), but not used here
@@ -860,7 +773,7 @@ struct buffered_piece_collection
{
BOOST_GEOMETRY_ASSERT(boost::size(range) != 0u);
- typename Range::const_iterator it = boost::begin(range);
+ auto it = boost::begin(range);
// If it follows a non-join (so basically the same piece-type) point b1 should be added.
// There should be two intersections later and it should be discarded.
@@ -918,12 +831,16 @@ struct buffered_piece_collection
template <typename Range>
inline void add_side_piece(point_type const& original_point1,
point_type const& original_point2,
- Range const& range, bool first)
+ Range const& range, bool is_first, bool is_empty)
{
BOOST_GEOMETRY_ASSERT(boost::size(range) >= 2u);
- piece& pc = create_piece(strategy::buffer::buffered_segment, ! first);
- add_range_to_piece(pc, range, first);
+ auto const piece_type = is_empty
+ ? strategy::buffer::buffered_empty_side
+ : strategy::buffer::buffered_segment;
+
+ piece& pc = create_piece(piece_type, ! is_first);
+ add_range_to_piece(pc, range, is_first);
// Add the four points of the side, starting with the last point of the
// range, and reversing the order of the originals to keep it clockwise
@@ -993,18 +910,17 @@ struct buffered_piece_collection
// Those can never be traversed and should not be part of the output.
inline void discard_rings()
{
- for (typename boost::range_iterator<turn_vector_type const>::type it =
- boost::begin(m_turns); it != boost::end(m_turns); ++it)
+ for (auto const& turn : m_turns)
{
- if (it->is_turn_traversable)
+ if (turn.is_turn_traversable)
{
- offsetted_rings[it->operations[0].seg_id.multi_index].has_accepted_intersections = true;
- offsetted_rings[it->operations[1].seg_id.multi_index].has_accepted_intersections = true;
+ offsetted_rings[turn.operations[0].seg_id.multi_index].has_accepted_intersections = true;
+ offsetted_rings[turn.operations[1].seg_id.multi_index].has_accepted_intersections = true;
}
else
{
- offsetted_rings[it->operations[0].seg_id.multi_index].has_discarded_intersections = true;
- offsetted_rings[it->operations[1].seg_id.multi_index].has_discarded_intersections = true;
+ offsetted_rings[turn.operations[0].seg_id.multi_index].has_discarded_intersections = true;
+ offsetted_rings[turn.operations[1].seg_id.multi_index].has_discarded_intersections = true;
}
}
}
@@ -1017,12 +933,8 @@ struct buffered_piece_collection
// any of the robust original rings
// This can go quadratic if the input has many rings, and there
// are many untouched deflated rings around
- for (typename std::vector<original_ring>::const_iterator it
- = original_rings.begin();
- it != original_rings.end();
- ++it)
+ for (auto const& original : original_rings)
{
- original_ring const& original = *it;
if (original.m_ring.empty())
{
continue;
@@ -1064,12 +976,8 @@ struct buffered_piece_collection
// be discarded
inline void discard_nonintersecting_deflated_rings()
{
- for(typename buffered_ring_collection<buffered_ring<Ring> >::iterator it
- = boost::begin(offsetted_rings);
- it != boost::end(offsetted_rings);
- ++it)
+ for (auto& ring : offsetted_rings)
{
- buffered_ring<Ring>& ring = *it;
if (! ring.has_intersections()
&& boost::size(ring) > 0u
&& geometry::area(ring, m_strategy) < 0)
@@ -1084,10 +992,8 @@ struct buffered_piece_collection
inline void block_turns()
{
- for (typename boost::range_iterator<turn_vector_type>::type it =
- boost::begin(m_turns); it != boost::end(m_turns); ++it)
+ for (auto& turn : m_turns)
{
- buffer_turn_info_type& turn = *it;
if (! turn.is_turn_traversable)
{
// Discard this turn (don't set it to blocked to avoid colocated
@@ -1120,21 +1026,16 @@ struct buffered_piece_collection
inline void reverse()
{
- for(typename buffered_ring_collection<buffered_ring<Ring> >::iterator it = boost::begin(offsetted_rings);
- it != boost::end(offsetted_rings);
- ++it)
+ for (auto& ring : offsetted_rings)
{
- if (! it->has_intersections())
+ if (! ring.has_intersections())
{
- std::reverse(it->begin(), it->end());
+ std::reverse(ring.begin(), ring.end());
}
}
- for (typename boost::range_iterator<buffered_ring_collection<Ring> >::type
- it = boost::begin(traversed_rings);
- it != boost::end(traversed_rings);
- ++it)
+ for (auto& ring : traversed_rings)
{
- std::reverse(it->begin(), it->end());
+ std::reverse(ring.begin(), ring.end());
}
}
@@ -1156,37 +1057,30 @@ struct buffered_piece_collection
// Inner rings, for deflate, which do not have intersections, and
// which are outside originals, are skipped
// (other ones should be traversed)
- signed_size_type index = 0;
- for(typename buffered_ring_collection<buffered_ring<Ring> >::const_iterator it = boost::begin(offsetted_rings);
- it != boost::end(offsetted_rings);
- ++it, ++index)
- {
- if (! it->has_intersections()
- && ! it->is_untouched_outside_original)
+ for_each_with_index(offsetted_rings, [&](std::size_t index, auto const& ring)
{
- properties p = properties(*it, m_strategy);
- if (p.valid)
+ if (! ring.has_intersections()
+ && ! ring.is_untouched_outside_original)
{
- ring_identifier id(0, index, -1);
- selected[id] = p;
+ properties p = properties(ring, m_strategy);
+ if (p.valid)
+ {
+ ring_identifier id(0, index, -1);
+ selected[id] = p;
+ }
}
- }
- }
+ });
// Select all created rings
- index = 0;
- for (typename boost::range_iterator<buffered_ring_collection<Ring> const>::type
- it = boost::begin(traversed_rings);
- it != boost::end(traversed_rings);
- ++it, ++index)
- {
- properties p = properties(*it, m_strategy);
- if (p.valid)
+ for_each_with_index(traversed_rings, [&](std::size_t index, auto const& ring)
{
- ring_identifier id(2, index, -1);
- selected[id] = p;
- }
- }
+ properties p = properties(ring, m_strategy);
+ if (p.valid)
+ {
+ ring_identifier id(2, index, -1);
+ selected[id] = p;
+ }
+ });
detail::overlay::assign_parents<overlay_buffer>(offsetted_rings, traversed_rings,
selected, m_strategy);
diff --git a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
index 09fef75185..c5b0aedc75 100644
--- a/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
+++ b/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp
@@ -194,7 +194,6 @@ class piece_turn_visitor
{
typedef typename boost::range_value<Rings const>::type ring_type;
typedef typename boost::range_value<Turns const>::type turn_type;
- typedef typename boost::range_iterator<ring_type const>::type iterator;
signed_size_type const piece1_first_index = piece1.first_seg_id.segment_index;
signed_size_type const piece2_first_index = piece2.first_seg_id.segment_index;
@@ -213,12 +212,12 @@ class piece_turn_visitor
// get geometry and iterators over these sections
ring_type const& ring1 = m_rings[piece1.first_seg_id.multi_index];
- iterator it1_first = boost::begin(ring1) + sec1_first_index;
- iterator it1_beyond = boost::begin(ring1) + sec1_last_index + 1;
+ auto it1_first = boost::begin(ring1) + sec1_first_index;
+ auto it1_beyond = boost::begin(ring1) + sec1_last_index + 1;
ring_type const& ring2 = m_rings[piece2.first_seg_id.multi_index];
- iterator it2_first = boost::begin(ring2) + sec2_first_index;
- iterator it2_beyond = boost::begin(ring2) + sec2_last_index + 1;
+ auto it2_first = boost::begin(ring2) + sec2_first_index;
+ auto it2_beyond = boost::begin(ring2) + sec2_last_index + 1;
// Set begin/end of monotonic ranges, in both x/y directions
signed_size_type index1 = sec1_first_index;
@@ -246,8 +245,8 @@ class piece_turn_visitor
the_model.operations[0].seg_id = piece1.first_seg_id;
the_model.operations[0].seg_id.segment_index = index1; // override
- iterator it1 = it1_first;
- for (iterator prev1 = it1++;
+ auto it1 = it1_first;
+ for (auto prev1 = it1++;
it1 != it1_beyond;
prev1 = it1++, the_model.operations[0].seg_id.segment_index++)
{
@@ -257,8 +256,8 @@ class piece_turn_visitor
unique_sub_range_from_piece<ring_type> unique_sub_range1(ring1, prev1, it1);
- iterator it2 = it2_first;
- for (iterator prev2 = it2++;
+ auto it2 = it2_first;
+ for (auto prev2 = it2++;
it2 != it2_beyond;
prev2 = it2++, the_model.operations[1].seg_id.segment_index++)
{
diff --git a/boost/geometry/algorithms/detail/buffer/implementation.hpp b/boost/geometry/algorithms/detail/buffer/implementation.hpp
new file mode 100644
index 0000000000..8b820e8f71
--- /dev/null
+++ b/boost/geometry/algorithms/detail/buffer/implementation.hpp
@@ -0,0 +1,214 @@
+// 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.
+
+// This file was modified by Oracle on 2017-2022.
+// Modifications copyright (c) 2017-2022 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// 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_BUFFER_IMPLEMENTATION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_IMPLEMENTATION_HPP
+
+#include <boost/range/value_type.hpp>
+
+#include <boost/geometry/algorithms/detail/buffer/buffer_box.hpp>
+#include <boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp>
+#include <boost/geometry/algorithms/detail/buffer/interface.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp> // for GC
+#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
+#include <boost/geometry/algorithms/union.hpp> // for GC
+#include <boost/geometry/arithmetic/arithmetic.hpp>
+#include <boost/geometry/geometries/box.hpp>
+#include <boost/geometry/strategies/buffer/cartesian.hpp>
+#include <boost/geometry/strategies/buffer/geographic.hpp>
+#include <boost/geometry/strategies/buffer/spherical.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/range.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename BoxIn, typename BoxOut>
+struct buffer_dc<BoxIn, BoxOut, box_tag, box_tag>
+{
+ template <typename Distance>
+ static inline void apply(BoxIn const& box_in, BoxOut& box_out,
+ Distance const& distance, Distance const& )
+ {
+ detail::buffer::buffer_box(box_in, distance, box_out);
+ }
+};
+
+
+template <typename Input, typename Output, typename TagIn>
+struct buffer_all<Input, Output, TagIn, multi_polygon_tag>
+{
+ template
+ <
+ typename DistanceStrategy,
+ typename SideStrategy,
+ typename JoinStrategy,
+ typename EndStrategy,
+ typename PointStrategy,
+ typename Strategies
+ >
+ static inline void apply(Input const& geometry_in,
+ Output& geometry_out,
+ DistanceStrategy const& distance_strategy,
+ SideStrategy const& side_strategy,
+ JoinStrategy const& join_strategy,
+ EndStrategy const& end_strategy,
+ PointStrategy const& point_strategy,
+ Strategies const& strategies)
+ {
+ typedef typename boost::range_value<Output>::type polygon_type;
+
+ typedef typename point_type<Input>::type point_type;
+ typedef typename rescale_policy_type
+ <
+ point_type,
+ typename geometry::cs_tag<point_type>::type
+ >::type rescale_policy_type;
+
+ if (geometry::is_empty(geometry_in))
+ {
+ // Then output geometry is kept empty as well
+ return;
+ }
+
+ model::box<point_type> box;
+ geometry::envelope(geometry_in, box);
+ geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy));
+
+ rescale_policy_type rescale_policy
+ = boost::geometry::get_rescale_policy<rescale_policy_type>(
+ box, strategies);
+
+ detail::buffer::buffer_inserter<polygon_type>(geometry_in,
+ range::back_inserter(geometry_out),
+ distance_strategy,
+ side_strategy,
+ join_strategy,
+ end_strategy,
+ point_strategy,
+ strategies,
+ rescale_policy);
+ }
+};
+
+
+template <typename Input, typename Output>
+struct buffer_all<Input, Output, geometry_collection_tag, multi_polygon_tag>
+{
+ template
+ <
+ typename DistanceStrategy,
+ typename SideStrategy,
+ typename JoinStrategy,
+ typename EndStrategy,
+ typename PointStrategy,
+ typename Strategies
+ >
+ static inline void apply(Input const& geometry_in,
+ Output& geometry_out,
+ DistanceStrategy const& distance_strategy,
+ SideStrategy const& side_strategy,
+ JoinStrategy const& join_strategy,
+ EndStrategy const& end_strategy,
+ PointStrategy const& point_strategy,
+ Strategies const& strategies)
+ {
+ // NOTE: The buffer normally calculates everything at once (by pieces) and traverses all
+ // of them to apply the union operation. Not even by merging elements. But that is
+ // complex and has led to issues as well. Here intermediate results are calculated
+ // with buffer and the results are merged afterwards.
+ // NOTE: This algorithm merges partial results iteratively.
+ // We could first gather all of the results and after that
+ // use some more optimal method like merge_elements().
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ Output buffer_result;
+ buffer_all
+ <
+ util::remove_cref_t<decltype(g)>, Output
+ >::apply(g, buffer_result, distance_strategy, side_strategy,
+ join_strategy, end_strategy, point_strategy, strategies);
+
+ if (! geometry::is_empty(buffer_result))
+ {
+ Output union_result;
+ geometry::union_(geometry_out, buffer_result, union_result, strategies);
+ geometry_out = std::move(union_result);
+ }
+
+ return true;
+ }, geometry_in);
+ }
+};
+
+template <typename Input, typename Output>
+struct buffer_all<Input, Output, geometry_collection_tag, geometry_collection_tag>
+{
+ template
+ <
+ typename DistanceStrategy,
+ typename SideStrategy,
+ typename JoinStrategy,
+ typename EndStrategy,
+ typename PointStrategy,
+ typename Strategies
+ >
+ static inline void apply(Input const& geometry_in,
+ Output& geometry_out,
+ DistanceStrategy const& distance_strategy,
+ SideStrategy const& side_strategy,
+ JoinStrategy const& join_strategy,
+ EndStrategy const& end_strategy,
+ PointStrategy const& point_strategy,
+ Strategies const& strategies)
+ {
+ // NOTE: We could also allow returning GC containing only polygons.
+ // We'd have to wrap them in model::multi_polygon and then
+ // iteratively emplace_back() into the GC.
+ using mpo_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Output>::type,
+ util::is_multi_polygon
+ >::type;
+ mpo_t result;
+ buffer_all
+ <
+ Input, mpo_t
+ >::apply(geometry_in, result, distance_strategy, side_strategy,
+ join_strategy, end_strategy, point_strategy, strategies);
+ range::emplace_back(geometry_out, std::move(result));
+ }
+};
+
+template <typename Input, typename Output, typename TagIn>
+struct buffer_all<Input, Output, TagIn, geometry_collection_tag>
+ : buffer_all<Input, Output, geometry_collection_tag, geometry_collection_tag>
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_IMPLEMENTATION_HPP
diff --git a/boost/geometry/algorithms/detail/buffer/interface.hpp b/boost/geometry/algorithms/detail/buffer/interface.hpp
new file mode 100644
index 0000000000..d19abd6efe
--- /dev/null
+++ b/boost/geometry/algorithms/detail/buffer/interface.hpp
@@ -0,0 +1,279 @@
+// 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.
+
+// This file was modified by Oracle on 2017-2022.
+// Modifications copyright (c) 2017-2022 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// 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_BUFFER_INTERFACE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_INTERFACE_HPP
+
+#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
+#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/strategies/buffer/services.hpp>
+#include <boost/geometry/util/type_traits_std.hpp>
+
+namespace boost { namespace geometry
+{
+
+#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_dc : not_implemented<TagIn, TagOut>
+{};
+
+template
+<
+ typename Input,
+ typename Output,
+ typename TagIn = typename tag<Input>::type,
+ typename TagOut = typename tag<Output>::type
+>
+struct buffer_all : not_implemented<TagIn, TagOut>
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+namespace resolve_dynamic
+{
+
+template
+<
+ typename Input,
+ typename TagIn = typename geometry::tag<Input>::type
+>
+struct buffer_dc
+{
+ template <typename Output, typename Distance>
+ static inline void apply(Input const& geometry_in,
+ Output& geometry_out,
+ Distance const& distance,
+ Distance const& chord_length)
+ {
+ dispatch::buffer_dc<Input, Output>::apply(geometry_in, geometry_out, distance, chord_length);
+ }
+};
+
+template <typename Input>
+struct buffer_dc<Input, dynamic_geometry_tag>
+{
+ template <typename Output, typename Distance>
+ static inline void apply(Input const& geometry_in,
+ Output& geometry_out,
+ Distance const& distance,
+ Distance const& chord_length)
+ {
+ traits::visit<Input>::apply([&](auto const& g)
+ {
+ dispatch::buffer_dc
+ <
+ util::remove_cref_t<decltype(g)>, Output
+ >::apply(g, geometry_out, distance, chord_length);
+ }, geometry_in);
+ }
+};
+
+
+template
+<
+ typename Input,
+ typename TagIn = typename geometry::tag<Input>::type
+>
+struct buffer_all
+{
+ template
+ <
+ typename Output,
+ typename DistanceStrategy,
+ typename SideStrategy,
+ typename JoinStrategy,
+ typename EndStrategy,
+ typename PointStrategy
+ >
+ static inline void apply(Input const& geometry_in,
+ Output& geometry_out,
+ DistanceStrategy const& distance_strategy,
+ SideStrategy const& side_strategy,
+ JoinStrategy const& join_strategy,
+ EndStrategy const& end_strategy,
+ PointStrategy const& point_strategy)
+ {
+ typename strategies::buffer::services::default_strategy
+ <
+ Input
+ >::type strategies;
+
+ dispatch::buffer_all
+ <
+ Input, Output
+ >::apply(geometry_in, geometry_out, distance_strategy, side_strategy,
+ join_strategy, end_strategy, point_strategy, strategies);
+ }
+};
+
+template <typename Input>
+struct buffer_all<Input, dynamic_geometry_tag>
+{
+ template
+ <
+ typename Output,
+ typename DistanceStrategy,
+ typename SideStrategy,
+ typename JoinStrategy,
+ typename EndStrategy,
+ typename PointStrategy
+ >
+ static inline void apply(Input const& geometry_in,
+ Output& geometry_out,
+ DistanceStrategy const& distance_strategy,
+ SideStrategy const& side_strategy,
+ JoinStrategy const& join_strategy,
+ EndStrategy const& end_strategy,
+ PointStrategy const& point_strategy)
+ {
+ traits::visit<Input>::apply([&](auto const& g)
+ {
+ buffer_all
+ <
+ util::remove_cref_t<decltype(g)>
+ >::apply(g, geometry_out, distance_strategy, side_strategy,
+ join_strategy, end_strategy, point_strategy);
+ }, geometry_in);
+ }
+};
+
+} // namespace resolve_dynamic
+
+
+/*!
+\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
+
+\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)
+{
+ concepts::check<Input const>();
+ concepts::check<Output>();
+
+ resolve_dynamic::buffer_dc<Input>::apply(geometry_in, geometry_out, distance, chord_length);
+}
+
+/*!
+\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 (RESERVED, NOT YET USED)
+\return \return_calc{buffer}
+ */
+template <typename Output, typename Input, typename Distance>
+inline Output return_buffer(Input const& geometry, Distance const& distance,
+ Distance const& chord_length = -1)
+{
+ concepts::check<Input const>();
+ concepts::check<Output>();
+
+ Output geometry_out;
+
+ resolve_dynamic::buffer_dc<Input>::apply(geometry, geometry_out, distance, chord_length);
+
+ return geometry_out;
+}
+
+/*!
+\brief \brief_calc{buffer}
+\ingroup buffer
+\details \details_calc{buffer, \det_buffer}.
+\tparam GeometryIn \tparam_geometry
+\tparam GeometryOut \tparam_geometry{GeometryOut}
+\tparam DistanceStrategy A strategy defining distance (or radius)
+\tparam SideStrategy A strategy defining creation along sides
+\tparam JoinStrategy A strategy defining creation around convex corners
+\tparam EndStrategy A strategy defining creation at linestring ends
+\tparam PointStrategy A strategy defining creation around points
+\param geometry_in \param_geometry
+\param geometry_out output geometry, e.g. multi polygon,
+ will contain a buffered version of the input geometry
+\param distance_strategy The distance strategy to be used
+\param side_strategy The side strategy to be used
+\param join_strategy The join strategy to be used
+\param end_strategy The end strategy to be used
+\param point_strategy The point strategy to be used
+
+\qbk{distinguish,with strategies}
+\qbk{[include reference/algorithms/buffer_with_strategies.qbk]}
+ */
+template
+<
+ typename GeometryIn,
+ typename GeometryOut,
+ typename DistanceStrategy,
+ typename SideStrategy,
+ typename JoinStrategy,
+ typename EndStrategy,
+ typename PointStrategy
+>
+inline void buffer(GeometryIn const& geometry_in,
+ GeometryOut& geometry_out,
+ DistanceStrategy const& distance_strategy,
+ SideStrategy const& side_strategy,
+ JoinStrategy const& join_strategy,
+ EndStrategy const& end_strategy,
+ PointStrategy const& point_strategy)
+{
+ concepts::check<GeometryIn const>();
+ concepts::check<GeometryOut>();
+
+ geometry::clear(geometry_out);
+
+ resolve_dynamic::buffer_all
+ <
+ GeometryIn, GeometryOut
+ >::apply(geometry_in, geometry_out, distance_strategy, side_strategy,
+ join_strategy, end_strategy, point_strategy);
+}
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_INTERFACE_HPP
diff --git a/boost/geometry/algorithms/detail/buffer/piece_border.hpp b/boost/geometry/algorithms/detail/buffer/piece_border.hpp
index ecd03d9c82..d773d32c36 100644
--- a/boost/geometry/algorithms/detail/buffer/piece_border.hpp
+++ b/boost/geometry/algorithms/detail/buffer/piece_border.hpp
@@ -1,9 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2020 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2020-2021 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2022.
+// Modifications copyright (c) 2020-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -14,7 +15,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_PIECE_BORDER_HPP
-#include <boost/array.hpp>
+#include <array>
+
#include <boost/core/addressof.hpp>
#include <boost/geometry/core/assert.hpp>
@@ -24,7 +26,6 @@
#include <boost/geometry/algorithms/comparable_distance.hpp>
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/expand.hpp>
-#include <boost/geometry/algorithms/detail/buffer/buffer_box.hpp>
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
#include <boost/geometry/strategies/cartesian/turn_in_ring_winding.hpp>
@@ -116,7 +117,7 @@ struct piece_border
// Points from the original (one or two, depending on piece shape)
// Note, if there are 2 points, they are REVERSED w.r.t. the original
// Therefore here we can walk in its order.
- boost::array<Point, 2> m_originals;
+ std::array<Point, 2> m_originals;
std::size_t m_original_size;
geometry::model::box<Point> m_envelope;
@@ -262,16 +263,21 @@ struct piece_border
if (m_original_size == 1)
{
// One point. Walk from last offsetted to point, and from point to first offsetted
- continue_processing = step(point, offsetted_back, m_originals[0], tir, por_from_offsetted, state)
- && step(point, m_originals[0], offsetted_front, tir, por_to_offsetted, state);
+ continue_processing = step(point, offsetted_back, m_originals[0],
+ tir, por_from_offsetted, state)
+ && step(point, m_originals[0], offsetted_front,
+ tir, por_to_offsetted, state);
}
else if (m_original_size == 2)
{
// Two original points. Walk from last offsetted point to first original point,
// then along original, then from second oginal to first offsetted point
- continue_processing = step(point, offsetted_back, m_originals[0], tir, por_from_offsetted, state)
- && step(point, m_originals[0], m_originals[1], tir, por_original, state)
- && step(point, m_originals[1], offsetted_front, tir, por_to_offsetted, state);
+ continue_processing = step(point, offsetted_back, m_originals[0],
+ tir, por_from_offsetted, state)
+ && step(point, m_originals[0], m_originals[1],
+ tir, por_original, state)
+ && step(point, m_originals[1], offsetted_front,
+ tir, por_to_offsetted, state);
}
if (continue_processing)
@@ -302,8 +308,15 @@ private :
: target;
}
- template <typename TurnPoint, typename Iterator, typename Strategy, typename State>
- bool walk_offsetted(TurnPoint const& point, Iterator begin, Iterator end, Strategy const & strategy, State& state) const
+ template
+ <
+ typename TurnPoint, typename Iterator,
+ typename TiRStrategy,
+ typename State
+ >
+ bool walk_offsetted(TurnPoint const& point, Iterator begin, Iterator end,
+ TiRStrategy const & strategy,
+ State& state) const
{
Iterator it = begin;
Iterator beyond = end;
@@ -327,7 +340,7 @@ private :
for (Iterator previous = it++ ; it != beyond ; ++previous, ++it )
{
if (! step(point, *previous, *it, strategy,
- geometry::strategy::buffer::place_on_ring_offsetted, state))
+ geometry::strategy::buffer::place_on_ring_offsetted, state))
{
return false;
}
@@ -336,27 +349,11 @@ private :
}
template <typename TurnPoint, typename TiRStrategy, typename State>
- bool step(TurnPoint const& point, Point const& p1, Point const& p2, TiRStrategy const & strategy,
+ bool step(TurnPoint const& point, Point const& p1, Point const& p2,
+ TiRStrategy const& strategy,
geometry::strategy::buffer::place_on_ring_type place_on_ring, State& state) const
{
- // A step between original/offsetted ring is always convex
- // (unless the join strategy generates points left of it -
- // future: convexity might be added to the buffer-join-strategy)
- // Therefore, if the state count > 0, it means the point is left of it,
- // and because it is convex, we can stop
-
- typedef typename geometry::coordinate_type<Point>::type coordinate_type;
- typedef geometry::detail::distance_measure<coordinate_type> dm_type;
- dm_type const dm = geometry::detail::get_distance_measure(point, p1, p2);
- if (m_is_convex && dm.measure > 0)
- {
- // The point is left of this segment of a convex piece
- state.m_count = 0;
- return false;
- }
- // Call strategy, and if it is on the border, return false
- // to stop further processing.
- return strategy.apply(point, p1, p2, dm, place_on_ring, state);
+ return strategy.apply(point, p1, p2, place_on_ring, m_is_convex, state);
}
template <typename It, typename Box, typename Strategy>
diff --git a/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp b/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp
index b1930dc0c4..daa59b618b 100644
--- a/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp
+++ b/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp
@@ -2,8 +2,9 @@
// Copyright (c) 2014 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2016-2020.
-// Modifications copyright (c) 2016-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2016-2023.
+// Modifications copyright (c) 2016-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -18,6 +19,7 @@
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/interface.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/strategies/agnostic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/buffer.hpp>
@@ -32,7 +34,7 @@ namespace detail { namespace buffer
{
-template <typename Strategy>
+template <typename Strategy>
struct original_get_box
{
explicit original_get_box(Strategy const& strategy)
@@ -190,20 +192,11 @@ inline int point_in_original(Point const& point, Original const& original,
return strategy.result(state);
}
- typedef typename Original::sections_type sections_type;
- typedef typename boost::range_iterator<sections_type const>::type iterator_type;
- typedef typename boost::range_value<sections_type const>::type section_type;
- typedef typename geometry::coordinate_type<Point>::type coordinate_type;
-
- coordinate_type const point_x = geometry::get<0>(point);
+ auto const point_x = geometry::get<0>(point);
// Walk through all monotonic sections of this original
- for (iterator_type it = boost::begin(original.m_sections);
- it != boost::end(original.m_sections);
- ++it)
+ for (auto const& section : original.m_sections)
{
- section_type const& section = *it;
-
if (! section.duplicate
&& section.begin_index < section.end_index
&& point_x >= geometry::get<min_corner, 0>(section.bounding_box)
diff --git a/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp b/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
index f51bd29007..bb7019c089 100644
--- a/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
+++ b/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp
@@ -3,8 +3,8 @@
// Copyright (c) 2012-2020 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2016, 2018.
-// Modifications copyright (c) 2016-2018 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2016-2022.
+// Modifications copyright (c) 2016-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -21,6 +21,7 @@
#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
+#include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
#include <boost/geometry/algorithms/detail/buffer/buffer_policies.hpp>
#include <boost/geometry/geometries/box.hpp>
@@ -38,7 +39,8 @@ template
typename CsTag,
typename Turns,
typename Pieces,
- typename DistanceStrategy
+ typename DistanceStrategy,
+ typename UmbrellaStrategy
>
class turn_in_piece_visitor
@@ -46,6 +48,7 @@ class turn_in_piece_visitor
Turns& m_turns; // because partition is currently operating on const input only
Pieces const& m_pieces; // to check for piece-type
DistanceStrategy const& m_distance_strategy; // to check if point is on original or one_sided
+ UmbrellaStrategy const& m_umbrella_strategy;
template <typename Operation, typename Piece>
inline bool skip(Operation const& op, Piece const& piece) const
@@ -94,10 +97,12 @@ class turn_in_piece_visitor
public:
inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces,
- DistanceStrategy const& distance_strategy)
+ DistanceStrategy const& distance_strategy,
+ UmbrellaStrategy const& umbrella_strategy)
: m_turns(turns)
, m_pieces(pieces)
, m_distance_strategy(distance_strategy)
+ , m_umbrella_strategy(umbrella_strategy)
{}
template <typename Turn, typename Piece>
@@ -127,20 +132,24 @@ public:
template <typename Turn, typename Piece, typename Border>
inline bool apply(Turn const& turn, Piece const& piece, Border const& border)
{
- if (! geometry::covered_by(turn.point, border.m_envelope))
+ if (! geometry::covered_by(turn.point, border.m_envelope, m_umbrella_strategy))
{
// Easy check: if turn is not in the (expanded) envelope
return true;
}
+ if (piece.type == geometry::strategy::buffer::buffered_empty_side)
+ {
+ return false;
+ }
+
if (piece.type == geometry::strategy::buffer::buffered_point)
{
// Optimization for a buffer around points: if distance from center
// is not between min/max radius, it is either inside or outside,
// and more expensive checks are not necessary.
- typedef typename Border::radius_type radius_type;
-
- radius_type const d = geometry::comparable_distance(piece.m_center, turn.point);
+ auto const d = geometry::comparable_distance(piece.m_center, turn.point,
+ m_umbrella_strategy);
if (d < border.m_min_comparable_radius)
{
@@ -155,38 +164,20 @@ public:
}
// Check if buffer is one-sided (at this point), because then a point
- // on the original is not considered as within.
+ // on the original border is not considered as within.
bool const one_sided = has_zero_distance_at(turn.point);
typename Border::state_type state;
- if (! border.point_on_piece(turn.point, one_sided, turn.is_linear_end_point, state))
+ if (! border.point_on_piece(turn.point, one_sided,
+ turn.is_linear_end_point, state))
{
return true;
}
- if (state.code() == 1)
+ if (state.is_inside() && ! state.is_on_boundary())
{
- // It is WITHIN a piece, or on the piece border, but not
- // on the offsetted part of it.
-
- // TODO - at further removing rescaling, this threshold can be
- // adapted, or ideally, go.
- // This threshold is minimized to the point where fragile
- // unit tests of hard cases start to fail (5 in multi_polygon)
- // But it is acknowlegded that such a threshold depends on the
- // scale of the input.
- if (state.m_min_distance > 1.0e-5 || ! state.m_close_to_offset)
- {
- Turn& mutable_turn = m_turns[turn.turn_index];
- mutable_turn.is_turn_traversable = false;
-
- // Keep track of the information if this turn was close
- // to an offset (without threshold). Because if it was,
- // it might have been classified incorrectly and in the
- // pretraversal step, it can in hindsight be classified
- // as "outside".
- mutable_turn.close_to_offset = state.m_close_to_offset;
- }
+ Turn& mutable_turn = m_turns[turn.turn_index];
+ mutable_turn.is_turn_traversable = false;
}
return true;
diff --git a/boost/geometry/algorithms/detail/calculate_point_order.hpp b/boost/geometry/algorithms/detail/calculate_point_order.hpp
index a9362b3613..191f71f3d8 100644
--- a/boost/geometry/algorithms/detail/calculate_point_order.hpp
+++ b/boost/geometry/algorithms/detail/calculate_point_order.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry
-// Copyright (c) 2019-2021, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2019-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
@@ -36,7 +37,7 @@ struct clean_point
, m_is_azi_valid(false), m_is_azi_diff_valid(false)
{}
- typename boost::iterators::iterator_reference<Iter>::type ref() const
+ decltype(auto) ref() const
{
return *m_iter;
}
@@ -108,8 +109,6 @@ struct calculate_point_order_by_azimuth
typedef typename boost::range_iterator<Ring const>::type iter_t;
typedef typename Strategy::template result_type<Ring>::type calc_t;
typedef clean_point<iter_t, calc_t> clean_point_t;
- typedef std::vector<clean_point_t> cleaned_container_t;
- typedef typename cleaned_container_t::iterator cleaned_iter_t;
calc_t const zero = 0;
calc_t const pi = math::pi<calc_t>();
@@ -121,21 +120,21 @@ struct calculate_point_order_by_azimuth
}
// non-duplicated, non-spike points
- cleaned_container_t cleaned;
+ std::vector<clean_point_t> cleaned;
cleaned.reserve(count);
for (iter_t it = boost::begin(ring); it != boost::end(ring); ++it)
{
// Add point
cleaned.push_back(clean_point_t(it));
-
+
while (cleaned.size() >= 3)
{
- cleaned_iter_t it0 = cleaned.end() - 3;
- cleaned_iter_t it1 = cleaned.end() - 2;
- cleaned_iter_t it2 = cleaned.end() - 1;
+ auto it0 = cleaned.end() - 3;
+ auto it1 = cleaned.end() - 2;
+ auto it2 = cleaned.end() - 1;
- calc_t diff;
+ calc_t diff;
if (get_or_calculate_azimuths_difference(*it0, *it1, *it2, diff, strategy)
&& ! math::equals(math::abs(diff), pi))
{
@@ -148,7 +147,7 @@ struct calculate_point_order_by_azimuth
// TODO: angles have to be invalidated only if spike is detected
// for duplicates it'd be ok to leave them
it0->set_azimuth_invalid();
- it0->set_azimuth_difference_invalid();
+ it0->set_azimuth_difference_invalid();
it2->set_azimuth_difference_invalid();
cleaned.erase(it1);
}
@@ -156,8 +155,8 @@ struct calculate_point_order_by_azimuth
}
// filter-out duplicates and spikes at the front and back of cleaned
- cleaned_iter_t cleaned_b = cleaned.begin();
- cleaned_iter_t cleaned_e = cleaned.end();
+ auto cleaned_b = cleaned.begin();
+ auto cleaned_e = cleaned.end();
std::size_t cleaned_count = cleaned.size();
bool found = false;
do
@@ -165,10 +164,10 @@ struct calculate_point_order_by_azimuth
found = false;
while(cleaned_count >= 3)
{
- cleaned_iter_t it0 = cleaned_e - 2;
- cleaned_iter_t it1 = cleaned_e - 1;
- cleaned_iter_t it2 = cleaned_b;
- cleaned_iter_t it3 = cleaned_b + 1;
+ auto it0 = cleaned_e - 2;
+ auto it1 = cleaned_e - 1;
+ auto it2 = cleaned_b;
+ auto it3 = cleaned_b + 1;
calc_t diff = 0;
if (! get_or_calculate_azimuths_difference(*it0, *it1, *it2, diff, strategy)
@@ -212,10 +211,10 @@ struct calculate_point_order_by_azimuth
// calculate the sum of external angles
calc_t angles_sum = zero;
- for (cleaned_iter_t it = cleaned_b; it != cleaned_e; ++it)
+ for (auto it = cleaned_b; it != cleaned_e; ++it)
{
- cleaned_iter_t it0 = (it == cleaned_b ? cleaned_e - 1 : it - 1);
- cleaned_iter_t it2 = (it == cleaned_e - 1 ? cleaned_b : it + 1);
+ auto it0 = (it == cleaned_b ? cleaned_e - 1 : it - 1);
+ auto it2 = (it == cleaned_e - 1 ? cleaned_b : it + 1);
calc_t diff = 0;
get_or_calculate_azimuths_difference(*it0, *it, *it2, diff, strategy);
@@ -269,7 +268,7 @@ private:
razi = p0.reverse_azimuth();
return true;
}
-
+
if (strategy.apply(p0.ref(), p1.ref(), azi, razi))
{
p0.set_azimuths(azi, razi);
@@ -336,7 +335,7 @@ namespace detail
template <typename Ring, typename Strategy>
inline geometry::order_selector calculate_point_order(Ring const& ring, Strategy const& strategy)
{
- concepts::check<Ring>();
+ concepts::check<Ring const>();
return dispatch::calculate_point_order<Strategy>::apply(ring, strategy);
}
@@ -349,7 +348,7 @@ inline geometry::order_selector calculate_point_order(Ring const& ring)
typename geometry::cs_tag<Ring>::type
>::type strategy_type;
- concepts::check<Ring>();
+ concepts::check<Ring const>();
return dispatch::calculate_point_order<strategy_type>::apply(ring, strategy_type());
}
diff --git a/boost/geometry/algorithms/detail/calculate_sum.hpp b/boost/geometry/algorithms/detail/calculate_sum.hpp
index 4af986fb62..4296d88e61 100644
--- a/boost/geometry/algorithms/detail/calculate_sum.hpp
+++ b/boost/geometry/algorithms/detail/calculate_sum.hpp
@@ -37,8 +37,7 @@ class calculate_polygon_sum
static inline ReturnType sum_interior_rings(Rings const& rings, Strategy const& strategy)
{
ReturnType sum = ReturnType(0);
- for (typename boost::range_iterator<Rings const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
sum += Policy::apply(*it, strategy);
}
diff --git a/boost/geometry/algorithms/detail/centroid/translating_transformer.hpp b/boost/geometry/algorithms/detail/centroid/translating_transformer.hpp
index 56a7e3ec91..042891e6e2 100644
--- a/boost/geometry/algorithms/detail/centroid/translating_transformer.hpp
+++ b/boost/geometry/algorithms/detail/centroid/translating_transformer.hpp
@@ -75,7 +75,7 @@ struct translating_transformer<Geometry, areal_tag, cartesian_tag>
{
typedef typename geometry::point_type<Geometry>::type point_type;
typedef point_type result_type;
-
+
explicit translating_transformer(Geometry const& geom)
: m_origin(NULL)
{
diff --git a/boost/geometry/algorithms/detail/check_iterator_range.hpp b/boost/geometry/algorithms/detail/check_iterator_range.hpp
deleted file mode 100644
index 9bd1d7ae27..0000000000
--- a/boost/geometry/algorithms/detail/check_iterator_range.hpp
+++ /dev/null
@@ -1,71 +0,0 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
-
-// Copyright (c) 2014, Oracle and/or its affiliates.
-
-// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
-
-// Licensed under the Boost Software License version 1.0.
-// http://www.boost.org/users/license.html
-
-#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CHECK_ITERATOR_RANGE_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CHECK_ITERATOR_RANGE_HPP
-
-#include <boost/core/ignore_unused.hpp>
-
-
-namespace boost { namespace geometry
-{
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail
-{
-
-// Check whether (each element of) an iterator range satisfies a given
-// predicate.
-// The predicate must be implemented as having a static apply unary
-// method that returns a bool.
-// By default an empty range is accepted
-template <typename Predicate, bool AllowEmptyRange = true>
-struct check_iterator_range
-{
- template <typename InputIterator>
- static inline bool apply(InputIterator first, InputIterator beyond)
- {
- for (InputIterator it = first; it != beyond; ++it)
- {
- if (! Predicate::apply(*it))
- {
- return false;
- }
- }
- return AllowEmptyRange || first != beyond;
- }
-
-
- // version where we can pass a predicate object
- template <typename InputIterator>
- static inline bool apply(InputIterator first,
- InputIterator beyond,
- Predicate const& predicate)
- {
- // in case predicate's apply method is static, MSVC will
- // complain that predicate is not used
- boost::ignore_unused(predicate);
-
- for (InputIterator it = first; it != beyond; ++it)
- {
- if (! predicate.apply(*it))
- {
- return false;
- }
- }
- return AllowEmptyRange || first != beyond;
- }
-};
-
-} // namespace detail
-#endif // DOXYGEN_NO_DETAIL
-
-}} // namespace boost::geometry
-
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CHECK_ITERATOR_RANGE_HPP
diff --git a/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp b/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp
index 4ac5ac6976..c5d331aaf3 100644
--- a/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp
+++ b/boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp
@@ -92,7 +92,7 @@ public:
typename RangeIterator,
typename Strategy,
typename Distance
- >
+ >
static inline RangeIterator apply(Geometry const& geometry,
RangeIterator first,
RangeIterator last,
@@ -111,7 +111,7 @@ public:
typename Geometry,
typename RangeIterator,
typename Strategy
- >
+ >
static inline RangeIterator apply(Geometry const& geometry,
RangeIterator first,
RangeIterator last,
diff --git a/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp b/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp
index 8ca0b3a7b9..ed2efd6fce 100644
--- a/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp
+++ b/boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp
@@ -189,7 +189,7 @@ private:
it_min1 = it_back;
it_min2 = first;
}
- }
+ }
public:
typedef typename std::pair<iterator_type, iterator_type> return_type;
diff --git a/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp b/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp
index 52b2495d12..be1729a86f 100644
--- a/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp
+++ b/boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp
@@ -150,7 +150,7 @@ public:
apply(rtree_first, rtree_last, queries_first, queries_last,
strategy, rtree_min, qit_min, dist_min);
- return std::make_pair(rtree_min, qit_min);
+ return std::make_pair(rtree_min, qit_min);
}
diff --git a/boost/geometry/algorithms/detail/closest_points/implementation.hpp b/boost/geometry/algorithms/detail/closest_points/implementation.hpp
new file mode 100644
index 0000000000..4accfa21b1
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/implementation.hpp
@@ -0,0 +1,28 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_IMPLEMENTATION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_IMPLEMENTATION_HPP
+
+#include <boost/geometry/algorithms/detail/distance/implementation.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/point_to_geometry.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/multipoint_to_geometry.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/linear_to_linear.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/linear_or_areal_to_areal.hpp>
+//#include <boost/geometry/algorithms/detail/closest_points/linear_to_box.hpp>
+//#include <boost/geometry/algorithms/detail/closest_points/geometry_to_segment_or_box.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/segment_to_segment.hpp>
+//#include <boost/geometry/algorithms/detail/closest_points/segment_to_box.hpp>
+//#include <boost/geometry/algorithms/detail/closest_points/box_to_box.hpp>
+
+#include <boost/geometry/strategies/closest_points/cartesian.hpp>
+#include <boost/geometry/strategies/closest_points/geographic.hpp>
+#include <boost/geometry/strategies/closest_points/spherical.hpp>
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_IMPLEMENTATION_HPP
diff --git a/boost/geometry/algorithms/detail/closest_points/interface.hpp b/boost/geometry/algorithms/detail/closest_points/interface.hpp
new file mode 100644
index 0000000000..622c47ba7f
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/interface.hpp
@@ -0,0 +1,225 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_INTERFACE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_INTERFACE_HPP
+
+#include <boost/concept_check.hpp>
+
+#include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
+
+#include <boost/geometry/algorithms/dispatch/closest_points.hpp>
+
+#include <boost/geometry/algorithms/detail/distance/interface.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
+#include <boost/geometry/geometries/concepts/check.hpp>
+
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/detail.hpp>
+#include <boost/geometry/strategies/closest_points/services.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+// If reversal is needed, perform it
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename Tag1,
+ typename Tag2
+>
+struct closest_points
+<
+ Geometry1, Geometry2,
+ Tag1, Tag2, true
+>
+ : closest_points<Geometry2, Geometry1, Tag2, Tag1, false>
+{
+ template <typename Segment, typename Strategy>
+ static inline void apply(Geometry1 const& g1, Geometry2 const& g2,
+ Segment& shortest_seg, Strategy const& strategy)
+ {
+ closest_points
+ <
+ Geometry2, Geometry1, Tag2, Tag1, false
+ >::apply(g2, g1, shortest_seg, strategy);
+
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+namespace resolve_strategy
+{
+
+template<typename Strategy>
+struct closest_points
+{
+ template <typename Geometry1, typename Geometry2, typename Segment>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Segment& shortest_seg,
+ Strategy const& strategy)
+ {
+ dispatch::closest_points
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, shortest_seg, strategy);
+ }
+};
+
+template <>
+struct closest_points<default_strategy>
+{
+ template <typename Geometry1, typename Geometry2, typename Segment>
+ static inline void
+ apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Segment& shortest_seg,
+ default_strategy)
+ {
+ using strategy_type = typename strategies::closest_points::services::default_strategy
+ <
+ Geometry1, Geometry2
+ >::type;
+
+ dispatch::closest_points
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, shortest_seg, strategy_type());
+ }
+};
+
+} // namespace resolve_strategy
+
+
+namespace resolve_variant
+{
+
+
+template <typename Geometry1, typename Geometry2>
+struct closest_points
+{
+ template <typename Segment, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Segment& shortest_seg,
+ Strategy const& strategy)
+ {
+ resolve_strategy::closest_points
+ <
+ Strategy
+ >::apply(geometry1, geometry2, shortest_seg, strategy);
+ }
+};
+
+//TODO: Add support for DG/GC
+
+} // namespace resolve_variant
+
+
+/*!
+\brief Calculate the closest points between two geometries \brief_strategy
+\ingroup closest_points
+\details
+\details The free function closest_points calculates the distance between two geometries \brief_strategy. \details_strategy_reasons
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Segment Any type fulfilling a Segment Concept
+\tparam Strategy \tparam_strategy{Closest Points}
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param shortest_seg Output segment containing the closest points
+\param strategy \param_strategy{closest_points}
+\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 Example]
+[closest_points_strategy]
+[closest_points_strategy_output]
+
+[heading See also]
+\* [link geometry.reference.algorithms.distance distance]
+}
+*/
+
+template <typename Geometry1, typename Geometry2, typename Segment, typename Strategy>
+inline void closest_points(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Segment& shortest_seg,
+ Strategy const& strategy)
+{
+ concepts::check<Geometry1 const>();
+ concepts::check<Geometry2 const>();
+
+ detail::throw_on_empty_input(geometry1);
+ detail::throw_on_empty_input(geometry2);
+
+ resolve_variant::closest_points
+ <
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, shortest_seg, strategy);
+}
+
+
+/*!
+\brief Compute the closest points between two geometries.
+\ingroup closest_points
+\details The free function closest_points calculates the closest points between two geometries. \details_default_strategy
+\tparam Geometry1 \tparam_geometry
+\tparam Geometry2 \tparam_geometry
+\tparam Segment Any type fulfilling a Segment Concept
+\param geometry1 \param_geometry
+\param geometry2 \param_geometry
+\param shortest_seg Output segment containing the closest points
+
+\qbk{
+
+[heading Example]
+[closest_points]
+[closest_points_output]
+
+[heading See also]
+\* [link geometry.reference.algorithms.distance distance]
+}
+*/
+
+template <typename Geometry1, typename Geometry2, typename Segment>
+inline void closest_points(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Segment& shortest_seg)
+{
+ closest_points(geometry1, geometry2, shortest_seg, default_strategy());
+}
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_INTERFACE_HPP
diff --git a/boost/geometry/algorithms/detail/closest_points/linear_or_areal_to_areal.hpp b/boost/geometry/algorithms/detail/closest_points/linear_or_areal_to_areal.hpp
new file mode 100644
index 0000000000..6d643e1aca
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/linear_or_areal_to_areal.hpp
@@ -0,0 +1,261 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_OR_AREAL_TO_AREAL_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_OR_AREAL_TO_AREAL_HPP
+
+#include <boost/geometry/algorithms/detail/closest_points/linear_to_linear.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
+
+#include <boost/geometry/algorithms/intersection.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/geometries/geometries.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace closest_points
+{
+
+struct linear_to_areal
+{
+ template <typename Linear, typename Areal, typename Segment, typename Strategies>
+ static inline void apply(Linear const& linear,
+ Areal const& areal,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using most_precise_type = typename select_coordinate_type<Linear, Areal>::type;
+
+ using point_type = typename std::conditional
+ <
+ std::is_same<typename coordinate_type<Linear>::type, most_precise_type>::value,
+ typename point_type<Linear>::type,
+ typename point_type<Areal>::type
+ >::type;
+
+ using linestring_type = geometry::model::linestring<point_type>;
+
+ /* TODO: currently intersection does not support some cases of tupled input
+ * such as linestring - multipolygon
+ * this could be implemented directly with dynamic geometries
+ using polygon_type = geometry::model::polygon<point_type>;
+ std::tuple
+ <
+ geometry::model::multi_point<point_type>,
+ geometry::model::multi_linestring<linestring_type>,
+ geometry::model::multi_polygon<polygon_type>
+ > tp;
+ bool intersect_tp = geometry::intersection(linear, areal, tp, strategies);
+ */
+
+ geometry::model::multi_point<point_type> mp_out;
+ geometry::intersection(linear, areal, mp_out, strategies);
+
+ if (! boost::empty(mp_out))
+ {
+ set_segment_from_points::apply(*boost::begin(mp_out),
+ *boost::begin(mp_out),
+ shortest_seg);
+ return;
+ }
+
+ // if there are no intersection points then check if the linear geometry
+ // (or part of it) is inside the areal and return any point of this part
+ geometry::model::multi_linestring<linestring_type> ln_out;
+ geometry::intersection(linear, areal, ln_out, strategies);
+
+ if (! boost::empty(ln_out))
+ {
+ set_segment_from_points::apply(*boost::begin(*boost::begin(ln_out)),
+ *boost::begin(*boost::begin(ln_out)),
+ shortest_seg);
+ return;
+ }
+
+ linear_to_linear::apply(linear, areal, shortest_seg, strategies, false);
+ }
+};
+
+struct areal_to_linear
+{
+ template <typename Linear, typename Areal, typename Segment, typename Strategies>
+ static inline void apply(Areal const& areal,
+ Linear const& linear,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ linear_to_areal::apply(linear, areal, shortest_seg, strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ }
+};
+
+struct segment_to_areal
+{
+ template <typename Segment, typename Areal, typename OutSegment, typename Strategies>
+ static inline void apply(Segment const& segment,
+ Areal const& areal,
+ OutSegment& shortest_seg,
+ Strategies const& strategies,
+ bool = false)
+ {
+ using linestring_type = geometry::model::linestring<typename point_type<Segment>::type>;
+ linestring_type linestring;
+ convert(segment, linestring);
+ linear_to_areal::apply(linestring, areal, shortest_seg, strategies);
+ }
+};
+
+struct areal_to_segment
+{
+ template <typename Areal, typename Segment, typename OutSegment, typename Strategies>
+ static inline void apply(Areal const& areal,
+ Segment const& segment,
+ OutSegment& shortest_seg,
+ Strategies const& strategies,
+ bool = false)
+ {
+ segment_to_areal::apply(segment, areal, shortest_seg, strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ }
+};
+
+struct areal_to_areal
+{
+ template <typename Areal1, typename Areal2, typename Segment, typename Strategies>
+ static inline void apply(Areal1 const& areal1,
+ Areal2 const& areal2,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using most_precise_type = typename select_coordinate_type<Areal1, Areal2>::type;
+
+ using point_type = typename std::conditional
+ <
+ std::is_same<typename coordinate_type<Areal1>::type, most_precise_type>::value,
+ typename point_type<Areal1>::type,
+ typename point_type<Areal2>::type
+ >::type;
+
+ using linestring_type = geometry::model::linestring<point_type>;
+ using polygon_type = geometry::model::polygon<point_type>;
+
+ /* TODO: currently intersection does not support tupled input
+ * this should be implemented directly with dynamic geometries
+ */
+
+ geometry::model::multi_point<point_type> mp_out;
+ geometry::intersection(areal1, areal2, mp_out, strategies);
+
+ if (! boost::empty(mp_out))
+ {
+ set_segment_from_points::apply(*boost::begin(mp_out),
+ *boost::begin(mp_out),
+ shortest_seg);
+ return;
+ }
+
+ // if there are no intersection points then the linear geometry (or part of it)
+ // is inside the areal; return any point of this part
+ geometry::model::multi_linestring<linestring_type> ln_out;
+ geometry::intersection(areal1, areal2, ln_out, strategies);
+
+ if (! boost::empty(ln_out))
+ {
+ set_segment_from_points::apply(*boost::begin(*boost::begin(ln_out)),
+ *boost::begin(*boost::begin(ln_out)),
+ shortest_seg);
+ return;
+ }
+
+ geometry::model::multi_polygon<polygon_type> pl_out;
+ geometry::intersection(areal1, areal2, pl_out, strategies);
+
+ if (! boost::empty(pl_out))
+ {
+ set_segment_from_points::apply(
+ *boost::begin(boost::geometry::exterior_ring(*boost::begin(pl_out))),
+ *boost::begin(boost::geometry::exterior_ring(*boost::begin(pl_out))),
+ shortest_seg);
+ return;
+ }
+
+ linear_to_linear::apply(areal1, areal2, shortest_seg, strategies, false);
+ }
+};
+
+
+}} // namespace detail::closest_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Linear, typename Areal>
+struct closest_points
+ <
+ Linear, Areal,
+ linear_tag, areal_tag,
+ false
+ >
+ : detail::closest_points::linear_to_areal
+{};
+
+template <typename Areal, typename Linear>
+struct closest_points
+ <
+ Areal, Linear,
+ areal_tag, linear_tag,
+ false
+ >
+ : detail::closest_points::areal_to_linear
+{};
+
+template <typename Segment, typename Areal>
+struct closest_points
+ <
+ Segment, Areal,
+ segment_tag, areal_tag,
+ false
+ >
+ : detail::closest_points::segment_to_areal
+{};
+
+template <typename Areal, typename Segment>
+struct closest_points
+ <
+ Areal, Segment,
+ areal_tag, segment_tag,
+ false
+ >
+ : detail::closest_points::areal_to_segment
+{};
+
+template <typename Areal1, typename Areal2>
+struct closest_points
+ <
+ Areal1, Areal2,
+ areal_tag, areal_tag,
+ false
+ >
+ : detail::closest_points::areal_to_areal
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_OR_AREAL_TO_AREAL_HPP
diff --git a/boost/geometry/algorithms/detail/closest_points/linear_to_linear.hpp b/boost/geometry/algorithms/detail/closest_points/linear_to_linear.hpp
new file mode 100644
index 0000000000..d2927a6d39
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/linear_to_linear.hpp
@@ -0,0 +1,155 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_TO_LINEAR_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_TO_LINEAR_HPP
+
+#include <boost/geometry/algorithms/detail/closest_points/range_to_geometry_rtree.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
+
+#include <boost/geometry/algorithms/num_points.hpp>
+#include <boost/geometry/algorithms/num_segments.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/iterators/point_iterator.hpp>
+#include <boost/geometry/iterators/segment_iterator.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace closest_points
+{
+
+
+struct linear_to_linear
+{
+ template <typename Linear1, typename Linear2, typename Segment, typename Strategies>
+ static inline void apply(Linear1 const& linear1,
+ Linear2 const& linear2,
+ Segment& shortest_seg,
+ Strategies const& strategies,
+ bool = false)
+ {
+ if (geometry::num_points(linear1) == 1)
+ {
+ dispatch::closest_points
+ <
+ typename point_type<Linear1>::type,
+ Linear2
+ >::apply(*points_begin(linear1), linear2, shortest_seg, strategies);
+ return;
+ }
+
+ if (geometry::num_points(linear2) == 1)
+ {
+ dispatch::closest_points
+ <
+ typename point_type<Linear2>::type,
+ Linear1
+ >::apply(*points_begin(linear2), linear1, shortest_seg, strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ return;
+ }
+
+ if (geometry::num_segments(linear1) < geometry::num_segments(linear2))
+ {
+ point_or_segment_range_to_geometry_rtree::apply(
+ geometry::segments_begin(linear2),
+ geometry::segments_end(linear2),
+ linear1,
+ shortest_seg,
+ strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ return;
+ }
+
+ point_or_segment_range_to_geometry_rtree::apply(
+ geometry::segments_begin(linear1),
+ geometry::segments_end(linear1),
+ linear2,
+ shortest_seg,
+ strategies);
+ }
+};
+
+struct segment_to_linear
+{
+ template <typename Segment, typename Linear, typename OutSegment, typename Strategies>
+ static inline void apply(Segment const& segment,
+ Linear const& linear,
+ OutSegment& shortest_seg,
+ Strategies const& strategies,
+ bool = false)
+ {
+ using linestring_type = geometry::model::linestring
+ <typename point_type<Segment>::type>;
+ linestring_type linestring;
+ convert(segment, linestring);
+ linear_to_linear::apply(linestring, linear, shortest_seg, strategies);
+ }
+};
+
+struct linear_to_segment
+{
+ template <typename Linear, typename Segment, typename OutSegment, typename Strategies>
+ static inline void apply(Linear const& linear,
+ Segment const& segment,
+ OutSegment& shortest_seg,
+ Strategies const& strategies,
+ bool = false)
+ {
+ segment_to_linear::apply(segment, linear, shortest_seg, strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ }
+};
+
+}} // namespace detail::closest_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template <typename Linear1, typename Linear2>
+struct closest_points
+ <
+ Linear1, Linear2,
+ linear_tag, linear_tag,
+ false
+ > : detail::closest_points::linear_to_linear
+{};
+
+template <typename Segment, typename Linear>
+struct closest_points
+ <
+ Segment, Linear,
+ segment_tag, linear_tag,
+ false
+ > : detail::closest_points::segment_to_linear
+{};
+
+template <typename Linear, typename Segment>
+struct closest_points
+ <
+ Linear, Segment,
+ linear_tag, segment_tag,
+ false
+ > : detail::closest_points::linear_to_segment
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_LINEAR_TO_LINEAR_HPP
diff --git a/boost/geometry/algorithms/detail/closest_points/multipoint_to_geometry.hpp b/boost/geometry/algorithms/detail/closest_points/multipoint_to_geometry.hpp
new file mode 100644
index 0000000000..f59c85a9b5
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/multipoint_to_geometry.hpp
@@ -0,0 +1,325 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_MULTIPOINT_TO_GEOMETRY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_MULTIPOINT_TO_GEOMETRY_HPP
+
+#include <iterator>
+
+#include <boost/geometry/algorithms/covered_by.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/range_to_geometry_rtree.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
+#include <boost/geometry/algorithms/dispatch/closest_points.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/geometries/linestring.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace closest_points
+{
+
+
+struct multipoint_to_multipoint
+{
+ template
+ <
+ typename MultiPoint1,
+ typename MultiPoint2,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(MultiPoint1 const& multipoint1,
+ MultiPoint2 const& multipoint2,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ if (boost::size(multipoint1) < boost::size(multipoint2))
+ {
+ point_or_segment_range_to_geometry_rtree::apply(
+ boost::begin(multipoint2),
+ boost::end(multipoint2),
+ multipoint1,
+ shortest_seg,
+ strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ return;
+ }
+ point_or_segment_range_to_geometry_rtree::apply(
+ boost::begin(multipoint1),
+ boost::end(multipoint1),
+ multipoint2,
+ shortest_seg,
+ strategies);
+ }
+};
+
+struct multipoint_to_linear
+{
+ template
+ <
+ typename MultiPoint,
+ typename Linear,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(MultiPoint const& multipoint,
+ Linear const& linear,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ point_or_segment_range_to_geometry_rtree::apply(
+ boost::begin(multipoint),
+ boost::end(multipoint),
+ linear,
+ shortest_seg,
+ strategies);
+ }
+};
+
+struct linear_to_multipoint
+{
+ template
+ <
+ typename Linear,
+ typename MultiPoint,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(Linear const& linear,
+ MultiPoint const& multipoint,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ multipoint_to_linear::apply(multipoint, linear, shortest_seg, strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ }
+};
+
+struct segment_to_multipoint
+{
+ template
+ <
+ typename Segment,
+ typename MultiPoint,
+ typename OutSegment,
+ typename Strategies
+ >
+ static inline void apply(Segment const& segment,
+ MultiPoint const& multipoint,
+ OutSegment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using linestring_type = geometry::model::linestring
+ <
+ typename point_type<Segment>::type
+ >;
+ linestring_type linestring;
+ convert(segment, linestring);
+ multipoint_to_linear::apply(multipoint, linestring, shortest_seg, strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ }
+};
+
+struct multipoint_to_segment
+{
+ template
+ <
+ typename MultiPoint,
+ typename Segment,
+ typename OutSegment,
+ typename Strategies
+ >
+ static inline void apply(MultiPoint const& multipoint,
+ Segment const& segment,
+ OutSegment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using linestring_type = geometry::model::linestring
+ <
+ typename point_type<Segment>::type
+ >;
+ linestring_type linestring;
+ convert(segment, linestring);
+ multipoint_to_linear::apply(multipoint, linestring, shortest_seg,
+ strategies);
+ }
+};
+
+
+struct multipoint_to_areal
+{
+
+private:
+
+ template <typename Areal, typename Strategies>
+ struct covered_by_areal
+ {
+ covered_by_areal(Areal const& areal, Strategies const& strategy)
+ : m_areal(areal), m_strategy(strategy)
+ {}
+
+ template <typename Point>
+ inline bool operator()(Point const& point) const
+ {
+ return geometry::covered_by(point, m_areal, m_strategy);
+ }
+
+ Areal const& m_areal;
+ Strategies const& m_strategy;
+ };
+
+public:
+
+ template
+ <
+ typename MultiPoint,
+ typename Areal,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(MultiPoint const& multipoint,
+ Areal const& areal,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ covered_by_areal<Areal, Strategies> predicate(areal, strategies);
+
+ auto it = std::find_if(
+ boost::begin(multipoint),
+ boost::end(multipoint),
+ predicate);
+
+ if (it != boost::end(multipoint))
+ {
+ return set_segment_from_points::apply(*it, *it, shortest_seg);
+
+ }
+
+ point_or_segment_range_to_geometry_rtree::apply(
+ boost::begin(multipoint),
+ boost::end(multipoint),
+ areal,
+ shortest_seg,
+ strategies);
+ }
+};
+
+struct areal_to_multipoint
+{
+ template
+ <
+ typename Areal,
+ typename MultiPoint,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(Areal const& areal,
+ MultiPoint const& multipoint,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ multipoint_to_areal::apply(multipoint, areal, shortest_seg, strategies);
+ detail::closest_points::swap_segment_points::apply(shortest_seg);
+ }
+};
+
+}} // namespace detail::closest_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename MultiPoint1, typename MultiPoint2>
+struct closest_points
+ <
+ MultiPoint1, MultiPoint2,
+ multi_point_tag, multi_point_tag,
+ false
+ > : detail::closest_points::multipoint_to_multipoint
+{};
+
+
+template <typename MultiPoint, typename Linear>
+struct closest_points
+ <
+ MultiPoint, Linear,
+ multi_point_tag, linear_tag,
+ false
+ > : detail::closest_points::multipoint_to_linear
+{};
+
+
+template <typename Linear, typename MultiPoint>
+struct closest_points
+ <
+ Linear, MultiPoint,
+ linear_tag, multi_point_tag,
+ false
+ > : detail::closest_points::linear_to_multipoint
+{};
+
+
+template <typename MultiPoint, typename Segment>
+struct closest_points
+ <
+ MultiPoint, Segment,
+ multi_point_tag, segment_tag,
+ false
+ > : detail::closest_points::multipoint_to_segment
+{};
+
+
+template <typename Segment, typename MultiPoint>
+struct closest_points
+ <
+ Segment, MultiPoint,
+ segment_tag, multi_point_tag,
+ false
+ > : detail::closest_points::segment_to_multipoint
+{};
+
+
+template <typename MultiPoint, typename Areal>
+struct closest_points
+ <
+ MultiPoint, Areal,
+ multi_point_tag, areal_tag,
+ false
+ > : detail::closest_points::multipoint_to_areal
+{};
+
+
+template <typename Areal, typename MultiPoint>
+struct closest_points
+ <
+ Areal, MultiPoint,
+ areal_tag, multi_point_tag,
+ false
+ > : detail::closest_points::areal_to_multipoint
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_MULTIPOINT_TO_GEOMETRY_HPP
diff --git a/boost/geometry/algorithms/detail/closest_points/point_to_geometry.hpp b/boost/geometry/algorithms/detail/closest_points/point_to_geometry.hpp
new file mode 100644
index 0000000000..5771858518
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/point_to_geometry.hpp
@@ -0,0 +1,456 @@
+// Boost.Geometry
+
+// Copyright (c) 2021-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_POINT_TO_GEOMETRY_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_POINT_TO_GEOMETRY_HPP
+
+#include <iterator>
+#include <type_traits>
+
+#include <boost/core/ignore_unused.hpp>
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/size.hpp>
+#include <boost/range/value_type.hpp>
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>
+#include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
+#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
+#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
+#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
+#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
+#include <boost/geometry/algorithms/dispatch/closest_points.hpp>
+#include <boost/geometry/algorithms/dispatch/distance.hpp>
+
+#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/point_type.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/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/relate/services.hpp>
+#include <boost/geometry/strategies/tags.hpp>
+
+#include <boost/geometry/util/math.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace closest_points
+{
+
+struct point_to_point
+{
+ template <typename P1, typename P2, typename Segment, typename Strategies>
+ static inline void apply(P1 const& p1, P2 const& p2,
+ Segment& shortest_seg, Strategies const&)
+ {
+ set_segment_from_points::apply(p1, p2, shortest_seg);
+ }
+};
+
+struct point_to_segment
+{
+ template <typename Point, typename Segment, typename OutputSegment, typename Strategies>
+ static inline void apply(Point const& point, Segment const& segment,
+ OutputSegment& shortest_seg, Strategies const& strategies)
+ {
+ 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]);
+
+ boost::ignore_unused(strategies);
+
+ auto closest_point = strategies.closest_points(point, segment)
+ .apply(point, p[0], p[1]);
+
+ set_segment_from_points::apply(point, closest_point, shortest_seg);
+ }
+};
+
+/*
+struct point_to_box
+{
+ template<typename Point, typename Box, typename Strategies>
+static inline auto apply(Point const& point, Box const& box,
+ Strategies const& strategies)
+ {
+ boost::ignore_unused(strategies);
+ return strategies.closest_points(point, box).apply(point, box);
+ }
+};
+*/
+
+template <closure_selector Closure>
+class point_to_range
+{
+public:
+
+ template <typename Point, typename Range, typename Segment, typename Strategies>
+ static inline void apply(Point const& point, Range const& range,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using point_to_point_range = detail::closest_feature::point_to_point_range
+ <
+ Point, Range, Closure
+ >;
+
+ if (boost::size(range) == 0)
+ {
+ set_segment_from_points::apply(point, point, shortest_seg);
+ return;
+ }
+
+ closest_points::creturn_t<Point, Range, Strategies> cd_min;
+
+ auto comparable_distance = strategy::distance::services::get_comparable
+ <
+ decltype(strategies.distance(point, range))
+ >::apply(strategies.distance(point, range));
+
+ auto closest_segment = point_to_point_range::apply(point,
+ boost::begin(range),
+ boost::end(range),
+ comparable_distance,
+ cd_min);
+
+ auto closest_point = strategies.closest_points(point, range)
+ .apply(point, *closest_segment.first, *closest_segment.second);
+
+ set_segment_from_points::apply(point, closest_point, shortest_seg);
+ }
+};
+
+
+template<closure_selector Closure>
+struct point_to_ring
+{
+ template <typename Point, typename Ring, typename Segment, typename Strategies>
+ static inline auto apply(Point const& point,
+ Ring const& ring,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ if (within::within_point_geometry(point, ring, strategies))
+ {
+ set_segment_from_points::apply(point, point, shortest_seg);
+ }
+ else
+ {
+ point_to_range
+ <
+ closure<Ring>::value
+ >::apply(point, ring, shortest_seg, strategies);
+ }
+
+ }
+};
+
+
+template <closure_selector Closure>
+class point_to_polygon
+{
+ template <typename Polygon>
+ struct distance_to_interior_rings
+ {
+ template
+ <
+ typename Point,
+ typename InteriorRingIterator,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(Point const& point,
+ InteriorRingIterator first,
+ InteriorRingIterator last,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using per_ring = point_to_range<Closure>;
+
+ for (InteriorRingIterator it = first; it != last; ++it)
+ {
+ if (within::within_point_geometry(point, *it, strategies))
+ {
+ // the point is inside a polygon hole, so its distance
+ // to the polygon is its distance to the polygon's
+ // hole boundary
+ per_ring::apply(point, *it, shortest_seg, strategies);
+ return;
+ }
+ }
+ set_segment_from_points::apply(point, point, shortest_seg);
+ }
+
+ template
+ <
+ typename Point,
+ typename InteriorRings,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(Point const& point, InteriorRings const& interior_rings,
+ Segment& shortest_seg, Strategies const& strategies)
+ {
+ apply(point,
+ boost::begin(interior_rings),
+ boost::end(interior_rings),
+ shortest_seg,
+ strategies);
+ }
+ };
+
+
+public:
+ template
+ <
+ typename Point,
+ typename Polygon,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(Point const& point,
+ Polygon const& polygon,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using per_ring = point_to_range<Closure>;
+
+ if (! within::covered_by_point_geometry(point, exterior_ring(polygon),
+ strategies))
+ {
+ // the point is outside the exterior ring, so its distance
+ // to the polygon is its distance to the polygon's exterior ring
+ per_ring::apply(point, exterior_ring(polygon), shortest_seg, strategies);
+ return;
+ }
+
+ // Check interior rings
+ distance_to_interior_rings<Polygon>::apply(point,
+ interior_rings(polygon),
+ shortest_seg,
+ strategies);
+ }
+};
+
+
+template
+<
+ typename MultiGeometry,
+ bool CheckCoveredBy = std::is_same
+ <
+ typename tag<MultiGeometry>::type, multi_polygon_tag
+ >::value
+>
+class point_to_multigeometry
+{
+private:
+ using geometry_to_range = detail::closest_feature::geometry_to_range;
+
+public:
+
+ template
+ <
+ typename Point,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(Point const& point,
+ MultiGeometry const& multigeometry,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using selector_type = distance::iterator_selector<MultiGeometry const>;
+
+ closest_points::creturn_t<Point, MultiGeometry, Strategies> cd;
+
+ auto comparable_distance = strategy::distance::services::get_comparable
+ <
+ decltype(strategies.distance(point, multigeometry))
+ >::apply(strategies.distance(point, multigeometry));
+
+ typename selector_type::iterator_type it_min
+ = geometry_to_range::apply(point,
+ selector_type::begin(multigeometry),
+ selector_type::end(multigeometry),
+ comparable_distance,
+ cd);
+
+ dispatch::closest_points
+ <
+ Point,
+ typename std::iterator_traits
+ <
+ typename selector_type::iterator_type
+ >::value_type
+ >::apply(point, *it_min, shortest_seg, strategies);
+ }
+};
+
+
+// this is called only for multipolygons, hence the change in the
+// template parameter name MultiGeometry to MultiPolygon
+template <typename MultiPolygon>
+struct point_to_multigeometry<MultiPolygon, true>
+{
+ template
+ <
+ typename Point,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(Point const& point,
+ MultiPolygon const& multipolygon,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ if (within::covered_by_point_geometry(point, multipolygon, strategies))
+ {
+ set_segment_from_points::apply(point, point, shortest_seg);
+ return;
+ }
+
+ return point_to_multigeometry
+ <
+ MultiPolygon, false
+ >::apply(point, multipolygon, shortest_seg, strategies);
+ }
+};
+
+
+}} // namespace detail::closest_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename P1, typename P2>
+struct closest_points
+ <
+ P1, P2, point_tag, point_tag, false
+ > : detail::closest_points::point_to_point
+{};
+
+
+template <typename Point, typename Linestring>
+struct closest_points
+ <
+ Point, Linestring, point_tag, linestring_tag, false
+ > : detail::closest_points::point_to_range<closed>
+{};
+
+
+template <typename Point, typename Ring>
+struct closest_points
+ <
+ Point, Ring, point_tag, ring_tag, false
+ > : detail::closest_points::point_to_ring
+ <
+ closure<Ring>::value
+ >
+{};
+
+
+template <typename Point, typename Polygon>
+struct closest_points
+ <
+ Point, Polygon, point_tag, polygon_tag, false
+ > : detail::closest_points::point_to_polygon
+ <
+ closure<Polygon>::value
+ >
+{};
+
+
+template <typename Point, typename Segment>
+struct closest_points
+ <
+ Point, Segment, point_tag, segment_tag, false
+ > : detail::closest_points::point_to_segment
+{};
+
+/*
+template <typename Point, typename Box>
+struct closest_points
+ <
+ Point, Box, point_tag, box_tag,
+ strategy_tag_distance_point_box, false
+ > : detail::closest_points::point_to_box<Point, Box>
+{};
+*/
+
+template<typename Point, typename MultiPoint>
+struct closest_points
+ <
+ Point, MultiPoint, point_tag, multi_point_tag, false
+ > : detail::closest_points::point_to_multigeometry<MultiPoint>
+{};
+
+
+template<typename Point, typename MultiLinestring>
+struct closest_points
+ <
+ Point, MultiLinestring, point_tag, multi_linestring_tag, false
+ > : detail::closest_points::point_to_multigeometry<MultiLinestring>
+{};
+
+
+template<typename Point, typename MultiPolygon>
+struct closest_points
+ <
+ Point, MultiPolygon, point_tag, multi_polygon_tag, false
+ > : detail::closest_points::point_to_multigeometry<MultiPolygon>
+{};
+
+
+template <typename Point, typename Linear>
+struct closest_points
+ <
+ Point, Linear, point_tag, linear_tag, false
+ > : closest_points
+ <
+ Point, Linear,
+ point_tag, typename tag<Linear>::type, false
+ >
+{};
+
+
+template <typename Point, typename Areal>
+struct closest_points
+ <
+ Point, Areal, point_tag, areal_tag, false
+ > : closest_points
+ <
+ Point, Areal,
+ point_tag, typename tag<Areal>::type, false
+ >
+{};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_POINT_TO_GEOMETRY_HPP
diff --git a/boost/geometry/algorithms/detail/closest_points/range_to_geometry_rtree.hpp b/boost/geometry/algorithms/detail/closest_points/range_to_geometry_rtree.hpp
new file mode 100644
index 0000000000..1bb44b53cd
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/range_to_geometry_rtree.hpp
@@ -0,0 +1,110 @@
+// Boost.Geometry
+
+// Copyright (c) 2021-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_RANGE_TO_GEOMETRY_RTREE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_RANGE_TO_GEOMETRY_RTREE_HPP
+
+#include <iterator>
+#include <utility>
+
+#include <boost/geometry/algorithms/detail/closest_feature/range_to_range.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
+#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
+#include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
+#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
+#include <boost/geometry/algorithms/dispatch/closest_points.hpp>
+
+#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/point_type.hpp>
+
+#include <boost/geometry/iterators/detail/has_one_element.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace closest_points
+{
+
+class point_or_segment_range_to_geometry_rtree
+{
+public:
+
+ template
+ <
+ typename PointOrSegmentIterator,
+ typename Geometry,
+ typename Segment,
+ typename Strategies
+ >
+ static inline void apply(PointOrSegmentIterator first,
+ PointOrSegmentIterator last,
+ Geometry const& geometry,
+ Segment& shortest_seg,
+ Strategies const& strategies)
+ {
+ typedef typename std::iterator_traits
+ <
+ PointOrSegmentIterator
+ >::value_type point_or_segment_type;
+
+ typedef distance::iterator_selector<Geometry const> selector_type;
+
+ typedef detail::closest_feature::range_to_range_rtree range_to_range;
+
+ BOOST_GEOMETRY_ASSERT( first != last );
+
+ //TODO: Is this special case needed?
+ //if ( detail::has_one_element(first, last) )
+ //{
+ // dispatch::closest_points
+ // <
+ // point_or_segment_type, Geometry
+ // >::apply(*first, geometry, shortest_seg, strategies);
+ //}
+
+ closest_points::creturn_t<point_or_segment_type, Geometry, Strategies> cd;
+
+ std::pair
+ <
+ point_or_segment_type,
+ typename selector_type::iterator_type
+ > closest_features
+ = range_to_range::apply(first,
+ last,
+ selector_type::begin(geometry),
+ selector_type::end(geometry),
+ strategies,
+ cd);
+ dispatch::closest_points
+ <
+ point_or_segment_type,
+ typename std::iterator_traits
+ <
+ typename selector_type::iterator_type
+ >::value_type
+ >::apply(closest_features.first,
+ *closest_features.second,
+ shortest_seg,
+ strategies);
+ }
+};
+
+
+}} // namespace detail::closest_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_RANGE_TO_GEOMETRY_RTREE_HPP
diff --git a/boost/geometry/algorithms/detail/closest_points/segment_to_segment.hpp b/boost/geometry/algorithms/detail/closest_points/segment_to_segment.hpp
new file mode 100644
index 0000000000..15d28cd690
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/segment_to_segment.hpp
@@ -0,0 +1,145 @@
+// Boost.Geometry
+
+// Copyright (c) 2021-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_SEGMENT_TO_SEGMENT_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_SEGMENT_TO_SEGMENT_HPP
+
+#include <algorithm>
+#include <iterator>
+
+#include <boost/core/addressof.hpp>
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
+#include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
+#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
+#include <boost/geometry/algorithms/dispatch/closest_points.hpp>
+#include <boost/geometry/algorithms/dispatch/distance.hpp>
+#include <boost/geometry/algorithms/intersects.hpp>
+
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/tags.hpp>
+
+#include <boost/geometry/util/condition.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace closest_points
+{
+
+
+
+// compute segment-segment closest-points
+class segment_to_segment
+{
+public:
+
+ template <typename Segment1, typename Segment2, typename OutputSegment, typename Strategies>
+ static inline void apply(Segment1 const& segment1, Segment2 const& segment2,
+ OutputSegment& shortest_seg,
+ Strategies const& strategies)
+ {
+ using intersection_return_type = segment_intersection_points
+ <
+ typename point_type<Segment1>::type
+ >;
+
+ using intersection_policy = policies::relate::segments_intersection_points
+ <
+ intersection_return_type
+ >;
+
+ detail::segment_as_subrange<Segment1> sub_range1(segment1);
+ detail::segment_as_subrange<Segment2> sub_range2(segment2);
+ auto is = strategies.relate().apply(sub_range1, sub_range2,
+ intersection_policy());
+ if (is.count > 0)
+ {
+ set_segment_from_points::apply(is.intersections[0],
+ is.intersections[0],
+ shortest_seg);
+ return;
+ }
+
+ typename point_type<Segment1>::type p[2];
+ detail::assign_point_from_index<0>(segment1, p[0]);
+ detail::assign_point_from_index<1>(segment1, p[1]);
+
+ typename point_type<Segment2>::type q[2];
+ detail::assign_point_from_index<0>(segment2, q[0]);
+ detail::assign_point_from_index<1>(segment2, q[1]);
+
+ auto cp0 = strategies.closest_points(q[0], segment1).apply(q[0], p[0], p[1]);
+ auto cp1 = strategies.closest_points(q[1], segment1).apply(q[1], p[0], p[1]);
+ auto cp2 = strategies.closest_points(p[0], segment2).apply(p[0], q[0], q[1]);
+ auto cp3 = strategies.closest_points(p[1], segment2).apply(p[1], q[0], q[1]);
+
+ closest_points::creturn_t<Segment1, Segment2, Strategies> d[4];
+
+ auto const cds = strategies::distance::detail::make_comparable(strategies)
+ .distance(detail::dummy_point(), detail::dummy_point());
+
+ d[0] = cds.apply(cp0, q[0]);
+ d[1] = cds.apply(cp1, q[1]);
+ d[2] = cds.apply(p[0], cp2);
+ d[3] = cds.apply(p[1], cp3);
+
+ std::size_t imin = std::distance(boost::addressof(d[0]), std::min_element(d, d + 4));
+
+ switch (imin)
+ {
+ case 0:
+ set_segment_from_points::apply(cp0, q[0], shortest_seg);
+ return;
+ case 1:
+ set_segment_from_points::apply(cp1, q[1], shortest_seg);
+ return;
+ case 2:
+ set_segment_from_points::apply(p[0], cp2, shortest_seg);
+ return;
+ default:
+ set_segment_from_points::apply(p[1], cp3, shortest_seg);
+ return;
+ }
+ }
+};
+
+
+}} // namespace detail::closest_points
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+// segment-segment
+template <typename Segment1, typename Segment2>
+struct closest_points
+ <
+ Segment1, Segment2, segment_tag, segment_tag, false
+ > : detail::closest_points::segment_to_segment
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_SEGMENT_TO_SEGMENT_HPP
diff --git a/boost/geometry/algorithms/detail/closest_points/utilities.hpp b/boost/geometry/algorithms/detail/closest_points/utilities.hpp
new file mode 100644
index 0000000000..858c86efb8
--- /dev/null
+++ b/boost/geometry/algorithms/detail/closest_points/utilities.hpp
@@ -0,0 +1,69 @@
+// Boost.Geometry
+
+// Copyright (c) 2021-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_UTILITIES_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_UTILITIES_HPP
+
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
+#include <boost/geometry/util/algorithm.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace detail { namespace closest_points
+{
+
+struct set_segment_from_points
+{
+ template <typename Point1, typename Point2, typename Segment>
+ static inline void apply(Point1 const& p1, Point2 const& p2, Segment& segment)
+ {
+ assign_point_to_index<0>(p1, segment);
+ assign_point_to_index<1>(p2, segment);
+ }
+};
+
+
+struct swap_segment_points
+{
+ template <typename Segment>
+ static inline void apply(Segment& segment)
+ {
+ geometry::detail::for_each_dimension<Segment>([&](auto index)
+ {
+ auto temp = get<0,index>(segment);
+ set<0,index>(segment, get<1,index>(segment));
+ set<1,index>(segment, temp);
+ });
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Strategies>
+using distance_strategy_t = decltype(
+ std::declval<Strategies>().distance(std::declval<Geometry1>(), std::declval<Geometry2>()));
+
+template <typename Geometry1, typename Geometry2, typename Strategies>
+using creturn_t = typename strategy::distance::services::return_type
+ <
+ typename strategy::distance::services::comparable_type
+ <
+ distance_strategy_t<Geometry1, Geometry2, Strategies>
+ >::type,
+ typename point_type<Geometry1>::type,
+ typename point_type<Geometry2>::type
+ >::type;
+
+
+}} // namespace detail::closest_points
+
+}} // namespace boost::geometry
+
+#endif //BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_UTILITIES_HPP
diff --git a/boost/geometry/algorithms/detail/comparable_distance/interface.hpp b/boost/geometry/algorithms/detail/comparable_distance/interface.hpp
index 14e2940d3b..d582dc9254 100644
--- a/boost/geometry/algorithms/detail/comparable_distance/interface.hpp
+++ b/boost/geometry/algorithms/detail/comparable_distance/interface.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
@@ -50,11 +51,9 @@ template
struct comparable_distance
{
template <typename Geometry1, typename Geometry2>
- static inline
- typename comparable_distance_result<Geometry1, Geometry2, Strategies>::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategies const& strategies)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategies const& strategies)
{
return dispatch::distance
<
@@ -70,21 +69,17 @@ template <typename Strategy>
struct comparable_distance<Strategy, false>
{
template <typename Geometry1, typename Geometry2>
- static inline
- typename comparable_distance_result<Geometry1, Geometry2, Strategy>::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
using strategies::distance::services::strategy_converter;
- typedef decltype(strategy_converter<Strategy>::get(strategy))
- strategies_type;
- typedef strategies::distance::detail::comparable
+ using comparable_strategies_type = strategies::distance::detail::comparable
<
- strategies_type
- > comparable_strategies_type;
-
+ decltype(strategy_converter<Strategy>::get(strategy))
+ >;
+
return dispatch::distance
<
Geometry1, Geometry2,
@@ -100,21 +95,17 @@ template <>
struct comparable_distance<default_strategy, false>
{
template <typename Geometry1, typename Geometry2>
- static inline typename comparable_distance_result
- <
- Geometry1, Geometry2, default_strategy
- >::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- default_strategy)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ default_strategy)
{
- typedef strategies::distance::detail::comparable
+ using comparable_strategy_type = strategies::distance::detail::comparable
<
typename strategies::distance::services::default_strategy
<
Geometry1, Geometry2
>::type
- > comparable_strategy_type;
+ >;
return dispatch::distance
<
@@ -126,19 +117,22 @@ struct comparable_distance<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry1, typename Geometry2>
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct comparable_distance
{
template <typename Strategy>
- static inline
- typename comparable_distance_result<Geometry1, Geometry2, Strategy>::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
return resolve_strategy::comparable_distance
<
@@ -148,190 +142,85 @@ struct comparable_distance
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct comparable_distance
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Geometry2
- >
+template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
+struct comparable_distance<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Strategy>
- struct visitor: static_visitor
- <
- typename comparable_distance_result
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Geometry2,
- Strategy
- >::type
- >
+ static inline auto apply(DynamicGeometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2,
- Strategy const& strategy)
- : m_geometry2(geometry2),
- m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- typename comparable_distance_result
+ using result_t = typename geometry::comparable_distance_result
<
- Geometry1, Geometry2, Strategy
- >::type
- operator()(Geometry1 const& geometry1) const
+ DynamicGeometry1, Geometry2, Strategy
+ >::type;
+ result_t result = 0;
+ traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
{
- return comparable_distance
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- Strategy
- >(geometry1, m_geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline typename comparable_distance_result
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Geometry2,
- Strategy
- >::type
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
+ result = resolve_strategy::comparable_distance
+ <
+ Strategy
+ >::apply(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct comparable_distance
- <
- Geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>
- >
+template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
+struct comparable_distance<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: static_visitor
- <
- typename comparable_distance_result
- <
- Geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Strategy
- >::type
- >
+ static inline auto apply(Geometry1 const& geometry1,
+ DynamicGeometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1,
- Strategy const& strategy)
- : m_geometry1(geometry1),
- m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- typename comparable_distance_result
+ using result_t = typename geometry::comparable_distance_result
<
- Geometry1, Geometry2, Strategy
- >::type
- operator()(Geometry2 const& geometry2) const
+ Geometry1, DynamicGeometry2, Strategy
+ >::type;
+ result_t result = 0;
+ traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
{
- return comparable_distance
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- Strategy
- >(m_geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline typename comparable_distance_result
- <
- Geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Strategy
- >::type
- apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
+ result = resolve_strategy::comparable_distance
+ <
+ Strategy
+ >::apply(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
}
};
-template
-<
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
+template <typename DynamicGeometry1, typename DynamicGeometry2>
struct comparable_distance
<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
+ DynamicGeometry1, DynamicGeometry2,
+ dynamic_geometry_tag, dynamic_geometry_tag
>
{
template <typename Strategy>
- struct visitor: static_visitor
- <
- typename comparable_distance_result
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
- Strategy
- >::type
- >
+ static inline auto apply(DynamicGeometry1 const& geometry1,
+ DynamicGeometry2 const& geometry2,
+ Strategy const& strategy)
{
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy)
- : m_strategy(strategy)
- {}
-
- template <typename Geometry1, typename Geometry2>
- typename comparable_distance_result
+ using result_t = typename geometry::comparable_distance_result
<
- Geometry1, Geometry2, Strategy
- >::type
- operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const
+ DynamicGeometry1, DynamicGeometry2, Strategy
+ >::type;
+ result_t result = 0;
+ traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
{
- return comparable_distance
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- Strategy
- >(geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline typename comparable_distance_result
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
- Strategy
- >::type
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
+ result = resolve_strategy::comparable_distance
+ <
+ Strategy
+ >::apply(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
@@ -354,14 +243,14 @@ struct comparable_distance
\qbk{distinguish,with strategy}
*/
template <typename Geometry1, typename Geometry2, typename Strategy>
-inline typename comparable_distance_result<Geometry1, Geometry2, Strategy>::type
-comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2,
- Strategy const& strategy)
+inline auto comparable_distance(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
- return resolve_variant::comparable_distance
+ return resolve_dynamic::comparable_distance
<
Geometry1,
Geometry2
@@ -387,12 +276,9 @@ comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2,
\qbk{[include reference/algorithms/comparable_distance.qbk]}
*/
template <typename Geometry1, typename Geometry2>
-inline typename default_comparable_distance_result<Geometry1, Geometry2>::type
-comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2)
+inline auto comparable_distance(Geometry1 const& geometry1,
+ Geometry2 const& geometry2)
{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
-
return geometry::comparable_distance(geometry1, geometry2, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/convert_point_to_point.hpp b/boost/geometry/algorithms/detail/convert_point_to_point.hpp
index c7d37b6ca4..8762cd6687 100644
--- a/boost/geometry/algorithms/detail/convert_point_to_point.hpp
+++ b/boost/geometry/algorithms/detail/convert_point_to_point.hpp
@@ -32,6 +32,12 @@ namespace detail { namespace conversion
{
+// TODO: Use assignment if possible.
+// WARNING: This utility is called in various places for a subset of dimensions.
+// In such cases only some of the coordinates should be copied. Alternatively
+// there should be a different utility for that called differently than
+// convert_xxx, e.g. set_coordinates.
+
template <typename Source, typename Destination, std::size_t Dimension, std::size_t DimensionCount>
struct point_to_point
{
diff --git a/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp b/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp
index 9584f6a2f1..64d81054e8 100644
--- a/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp
+++ b/boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2023.
+// Modifications copyright (c) 2014-2023 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -23,20 +23,19 @@
#include <algorithm>
#include <vector>
-#include <boost/range/begin.hpp>
-#include <boost/range/empty.hpp>
-#include <boost/range/end.hpp>
-#include <boost/range/size.hpp>
-
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/policies/compare.hpp>
#include <boost/geometry/strategies/convex_hull/cartesian.hpp>
#include <boost/geometry/strategies/convex_hull/geographic.hpp>
#include <boost/geometry/strategies/convex_hull/spherical.hpp>
+#include <boost/geometry/util/range.hpp>
+
namespace boost { namespace geometry
{
@@ -45,13 +44,15 @@ namespace boost { namespace geometry
namespace detail { namespace convex_hull
{
-template <typename Geometry, typename Point, typename Less>
-inline void get_extremes(Geometry const& geometry,
+// TODO: All of the copies could be avoided if this function stored pointers to points.
+// But would it be possible considering that a range can return proxy reference?
+template <typename InputProxy, typename Point, typename Less>
+inline void get_extremes(InputProxy const& in_proxy,
Point& left, Point& right,
Less const& less)
{
bool first = true;
- geometry::detail::for_each_range(geometry, [&](auto const& range)
+ in_proxy.for_each_range([&](auto const& range)
{
if (boost::empty(range))
{
@@ -107,19 +108,13 @@ inline void get_extremes(Geometry const& geometry,
}
-template
-<
- typename Geometry,
- typename Point,
- typename Container,
- typename SideStrategy
->
-inline void assign_ranges(Geometry const& geometry,
+template <typename InputProxy, typename Point, typename Container, typename SideStrategy>
+inline void assign_ranges(InputProxy const& in_proxy,
Point const& most_left, Point const& most_right,
Container& lower_points, Container& upper_points,
SideStrategy const& side)
{
- geometry::detail::for_each_range(geometry, [&](auto const& range)
+ in_proxy.for_each_range([&](auto const& range)
{
// Put points in one of the two output sequences
for (auto it = boost::begin(range); it != boost::end(range); ++it)
@@ -145,33 +140,14 @@ inline void assign_ranges(Geometry const& geometry,
}
-template <typename Range, typename Less>
-inline void sort(Range& range, Less const& less)
-{
- std::sort(boost::begin(range), boost::end(range), less);
-}
-
-} // namespace convex_hull
-
-
/*!
\brief Graham scan algorithm to calculate convex hull
*/
-template <typename InputGeometry, typename OutputPoint>
+template <typename InputPoint>
class graham_andrew
{
-public :
- typedef OutputPoint point_type;
- typedef InputGeometry geometry_type;
-
-private:
-
- typedef typename cs_tag<point_type>::type cs_tag;
-
+ typedef InputPoint point_type;
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
{
@@ -182,14 +158,23 @@ private:
container_type m_copied_input;
};
-
public:
- typedef partitions state_type;
+ template <typename InputProxy, typename OutputRing, typename Strategy>
+ static void apply(InputProxy const& in_proxy, OutputRing & out_ring, Strategy& strategy)
+ {
+ partitions state;
+
+ apply(in_proxy, state, strategy);
- template <typename Strategy>
- inline void apply(InputGeometry const& geometry,
- partitions& state,
- Strategy& strategy) const
+ result(state,
+ range::back_inserter(out_ring),
+ geometry::point_order<OutputRing>::value == clockwise,
+ geometry::closure<OutputRing>::value != open);
+ }
+
+private:
+ template <typename InputProxy, typename Strategy>
+ static void apply(InputProxy const& in_proxy, partitions& state, Strategy& strategy)
{
// First pass.
// Get min/max (in most cases left / right) points
@@ -203,14 +188,11 @@ public:
// For symmetry and to get often more balanced lower/upper halves
// we keep it.
- typedef typename geometry::point_type<InputGeometry>::type point_type;
-
point_type most_left, most_right;
- // TODO: User-defined CS-specific less-compare
- geometry::less<point_type> less;
+ geometry::less_exact<point_type, -1, Strategy> less;
- detail::convex_hull::get_extremes(geometry, most_left, most_right, less);
+ detail::convex_hull::get_extremes(in_proxy, most_left, most_right, less);
container_type lower_points, upper_points;
@@ -219,13 +201,13 @@ public:
// Bounding left/right points
// Second pass, now that extremes are found, assign all points
// in either lower, either upper
- detail::convex_hull::assign_ranges(geometry, most_left, most_right,
+ detail::convex_hull::assign_ranges(in_proxy, most_left, most_right,
lower_points, upper_points,
side_strategy);
// Sort both collections, first on x(, then on y)
- detail::convex_hull::sort(lower_points, less);
- detail::convex_hull::sort(upper_points, less);
+ std::sort(boost::begin(lower_points), boost::end(lower_points), less);
+ std::sort(boost::begin(upper_points), boost::end(upper_points), less);
// And decide which point should be in the final hull
build_half_hull<-1>(lower_points, state.m_lower_hull,
@@ -236,26 +218,6 @@ public:
side_strategy);
}
-
- template <typename OutputIterator>
- inline void result(partitions const& state,
- OutputIterator out,
- bool clockwise,
- bool closed) const
- {
- if (clockwise)
- {
- output_ranges(state.m_upper_hull, state.m_lower_hull, out, closed);
- }
- else
- {
- output_ranges(state.m_lower_hull, state.m_upper_hull, out, closed);
- }
- }
-
-
-private:
-
template <int Factor, typename SideStrategy>
static inline void build_half_hull(container_type const& input,
container_type& output,
@@ -263,9 +225,9 @@ private:
SideStrategy const& side)
{
output.push_back(left);
- for(iterator it = input.begin(); it != input.end(); ++it)
+ for (auto const& i : input)
{
- add_to_hull<Factor>(*it, output, side);
+ add_to_hull<Factor>(i, output, side);
}
add_to_hull<Factor>(right, output, side);
}
@@ -279,7 +241,7 @@ private:
std::size_t output_size = output.size();
while (output_size >= 3)
{
- rev_iterator rit = output.rbegin();
+ auto rit = output.rbegin();
point_type const last = *rit++;
point_type const& last2 = *rit++;
@@ -301,6 +263,19 @@ private:
template <typename OutputIterator>
+ static void result(partitions const& state, OutputIterator out, bool clockwise, bool closed)
+ {
+ if (clockwise)
+ {
+ output_ranges(state.m_upper_hull, state.m_lower_hull, out, closed);
+ }
+ else
+ {
+ output_ranges(state.m_lower_hull, state.m_upper_hull, out, closed);
+ }
+ }
+
+ template <typename OutputIterator>
static inline void output_ranges(container_type const& first,
container_type const& second,
OutputIterator out,
@@ -327,7 +302,7 @@ private:
};
-} // namespace detail
+}} // namespace detail::convex_hull
#endif // DOXYGEN_NO_DETAIL
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/convex_hull/interface.hpp b/boost/geometry/algorithms/detail/convex_hull/interface.hpp
index ce61c99802..b820cc4bf4 100644
--- a/boost/geometry/algorithms/detail/convex_hull/interface.hpp
+++ b/boost/geometry/algorithms/detail/convex_hull/interface.hpp
@@ -3,6 +3,7 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
@@ -21,86 +22,171 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_CONVEX_HULL_INTERFACE_HPP
-#include <boost/array.hpp>
+#include <array>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
-#include <boost/geometry/algorithms/detail/as_range.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
#include <boost/geometry/algorithms/detail/convex_hull/graham_andrew.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
+#include <boost/geometry/algorithms/detail/for_each_range.hpp>
+#include <boost/geometry/algorithms/detail/select_geometry_type.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
+#include <boost/geometry/core/geometry_types.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/ring_type.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/geometries/ring.hpp>
-#include <boost/geometry/strategies/convex_hull/services.hpp>
+#include <boost/geometry/strategies/convex_hull/cartesian.hpp>
+#include <boost/geometry/strategies/convex_hull/geographic.hpp>
+#include <boost/geometry/strategies/convex_hull/spherical.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/range.hpp>
+#include <boost/geometry/util/sequence.hpp>
+#include <boost/geometry/util/type_traits.hpp>
namespace boost { namespace geometry
{
+// TODO: This file is named interface.hpp but the code below is not the interface.
+// It's the implementation of the algorithm.
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace convex_hull
{
-template <order_selector Order, closure_selector Closure>
-struct hull_insert
+// Abstraction representing ranges/rings of a geometry
+template <typename Geometry>
+struct input_geometry_proxy
{
- // 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)
+ input_geometry_proxy(Geometry const& geometry)
+ : m_geometry(geometry)
+ {}
+
+ template <typename UnaryFunction>
+ inline void for_each_range(UnaryFunction fun) const
{
- typedef graham_andrew
- <
- Geometry,
- typename point_type<Geometry>::type
- > ConvexHullAlgorithm;
+ geometry::detail::for_each_range(m_geometry, fun);
+ }
- ConvexHullAlgorithm algorithm;
- typename ConvexHullAlgorithm::state_type state;
+ Geometry const& m_geometry;
+};
- algorithm.apply(geometry, state, strategy);
- algorithm.result(state, out, Order == clockwise, Closure != open);
+// Abstraction representing ranges/rings of subgeometries of geometry collection
+// with boxes converted to rings
+template <typename Geometry, typename BoxRings>
+struct input_geometry_collection_proxy
+{
+ input_geometry_collection_proxy(Geometry const& geometry, BoxRings const& box_rings)
+ : m_geometry(geometry)
+ , m_box_rings(box_rings)
+ {}
+
+ template <typename UnaryFunction>
+ inline void for_each_range(UnaryFunction fun) const
+ {
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ input_geometry_collection_proxy::call_for_non_boxes(g, fun);
+ return true;
+ }, m_geometry);
- return out;
+ for (auto const& r : m_box_rings)
+ {
+ geometry::detail::for_each_range(r, fun);
+ }
}
-};
-struct hull_to_geometry
-{
- template <typename Geometry, typename OutputGeometry, typename Strategy>
- static inline void apply(Geometry const& geometry, OutputGeometry& out,
- Strategy const& strategy)
+private:
+ template <typename G, typename F, std::enable_if_t<! util::is_box<G>::value, int> = 0>
+ static inline void call_for_non_boxes(G const& g, F & f)
{
- // TODO: Why not handle multi-polygon here?
- // TODO: detail::as_range() is only used in this place in the whole library
- // it should probably be located here.
- // NOTE: A variable is created here because this can be a proxy range
- // and back_insert_iterator<> can store a pointer to it.
- // Handle linestring, ring and polygon the same:
- auto&& range = detail::as_range(out);
- hull_insert
- <
- geometry::point_order<OutputGeometry>::value,
- geometry::closure<OutputGeometry>::value
- >::apply(geometry, range::back_inserter(range), strategy);
+ geometry::detail::for_each_range(g, f);
}
+ template <typename G, typename F, std::enable_if_t<util::is_box<G>::value, int> = 0>
+ static inline void call_for_non_boxes(G const&, F &)
+ {}
+
+ Geometry const& m_geometry;
+ BoxRings const& m_box_rings;
+};
+
+
+// TODO: Or just implement point_type<> for GeometryCollection
+// and enforce the same point_type used in the whole sequence in check().
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct default_strategy
+{
+ using type = typename strategies::convex_hull::services::default_strategy
+ <
+ Geometry
+ >::type;
+};
+
+template <typename Geometry>
+struct default_strategy<Geometry, geometry_collection_tag>
+ : default_strategy<typename detail::first_geometry_type<Geometry>::type>
+{};
+
+
+// Utilities for output GC and DG
+template <typename G1, typename G2>
+struct output_polygonal_less
+{
+ template <typename G>
+ using priority = std::integral_constant
+ <
+ int,
+ (util::is_ring<G>::value ? 0 :
+ util::is_polygon<G>::value ? 1 :
+ util::is_multi_polygon<G>::value ? 2 : 3)
+ >;
+
+ static const bool value = priority<G1>::value < priority<G2>::value;
};
+template <typename G1, typename G2>
+struct output_linear_less
+{
+ template <typename G>
+ using priority = std::integral_constant
+ <
+ int,
+ (util::is_segment<G>::value ? 0 :
+ util::is_linestring<G>::value ? 1 :
+ util::is_multi_linestring<G>::value ? 2 : 3)
+ >;
+
+ static const bool value = priority<G1>::value < priority<G2>::value;
+};
+
+template <typename G1, typename G2>
+struct output_pointlike_less
+{
+ template <typename G>
+ using priority = std::integral_constant
+ <
+ int,
+ (util::is_point<G>::value ? 0 :
+ util::is_multi_point<G>::value ? 1 : 2)
+ >;
+
+ static const bool value = priority<G1>::value < priority<G2>::value;
+};
+
+
}} // namespace detail::convex_hull
#endif // DOXYGEN_NO_DETAIL
@@ -116,10 +202,23 @@ template
typename Tag = typename tag<Geometry>::type
>
struct convex_hull
- : detail::convex_hull::hull_to_geometry
-{};
+{
+ template <typename OutputGeometry, typename Strategy>
+ static inline void apply(Geometry const& geometry,
+ OutputGeometry& out,
+ Strategy const& strategy)
+ {
+ detail::convex_hull::input_geometry_proxy<Geometry> in_proxy(geometry);
+ detail::convex_hull::graham_andrew
+ <
+ typename point_type<Geometry>::type
+ >::apply(in_proxy, out, strategy);
+ }
+};
-// TODO: This is not correct in spherical and geographic CS
+
+// A hull for boxes is trivial. Any strategy is (currently) skipped.
+// TODO: This is not correct in spherical and geographic CS.
template <typename Box>
struct convex_hull<Box, box_tag>
{
@@ -133,185 +232,337 @@ struct convex_hull<Box, box_tag>
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);
+ std::array<typename point_type<OutputGeometry>::type, 4> arr;
+ // TODO: This assigns only 2d cooridnates!
+ // And it is also used in box_view<>!
+ geometry::detail::assign_box_corners_oriented<Reverse>(box, arr);
+
+ std::move(arr.begin(), arr.end(), range::back_inserter(out));
if (BOOST_GEOMETRY_CONDITION(Close))
{
- geometry::append(out, *boost::begin(range));
+ range::push_back(out, range::front(out));
}
}
};
+template <typename GeometryCollection>
+struct convex_hull<GeometryCollection, geometry_collection_tag>
+{
+ template <typename OutputGeometry, typename Strategy>
+ static inline void apply(GeometryCollection const& geometry,
+ OutputGeometry& out,
+ Strategy const& strategy)
+ {
+ // Assuming that single point_type is used by the GeometryCollection
+ using subgeometry_type = typename detail::first_geometry_type<GeometryCollection>::type;
+ using point_type = typename geometry::point_type<subgeometry_type>::type;
+ using ring_type = model::ring<point_type, true, false>;
+
+ // Calculate box rings once
+ std::vector<ring_type> box_rings;
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ convex_hull::add_ring_for_box(box_rings, g, strategy);
+ return true;
+ }, geometry);
-template <order_selector Order, closure_selector Closure>
-struct convex_hull_insert
- : detail::convex_hull::hull_insert<Order, Closure>
-{};
+ detail::convex_hull::input_geometry_collection_proxy
+ <
+ GeometryCollection, std::vector<ring_type>
+ > in_proxy(geometry, box_rings);
+ detail::convex_hull::graham_andrew
+ <
+ point_type
+ >::apply(in_proxy, out, strategy);
+ }
-} // namespace dispatch
-#endif // DOXYGEN_NO_DISPATCH
+private:
+ template
+ <
+ typename Ring, typename SubGeometry, typename Strategy,
+ std::enable_if_t<util::is_box<SubGeometry>::value, int> = 0
+ >
+ static inline void add_ring_for_box(std::vector<Ring> & rings, SubGeometry const& box,
+ Strategy const& strategy)
+ {
+ Ring ring;
+ convex_hull<SubGeometry>::apply(box, ring, strategy);
+ rings.push_back(std::move(ring));
+ }
+ template
+ <
+ typename Ring, typename SubGeometry, typename Strategy,
+ std::enable_if_t<! util::is_box<SubGeometry>::value, int> = 0
+ >
+ static inline void add_ring_for_box(std::vector<Ring> & , SubGeometry const& ,
+ Strategy const& )
+ {}
+};
-namespace resolve_strategy {
+template <typename OutputGeometry, typename Tag = typename tag<OutputGeometry>::type>
+struct convex_hull_out
+{
+ BOOST_GEOMETRY_STATIC_ASSERT_FALSE("This OutputGeometry is not supported.", OutputGeometry, Tag);
+};
-struct convex_hull
+template <typename OutputGeometry>
+struct convex_hull_out<OutputGeometry, ring_tag>
{
- template <typename Geometry, typename OutputGeometry, typename Strategy>
+ template <typename Geometry, typename Strategies>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
- Strategy const& strategy)
+ Strategies const& strategies)
{
- //BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy<Strategy>) );
- dispatch::convex_hull<Geometry>::apply(geometry, out, strategy);
+ dispatch::convex_hull<Geometry>::apply(geometry, out, strategies);
}
+};
- template <typename Geometry, typename OutputGeometry>
+template <typename OutputGeometry>
+struct convex_hull_out<OutputGeometry, polygon_tag>
+{
+ template <typename Geometry, typename Strategies>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
- default_strategy)
+ Strategies const& strategies)
{
- typedef typename strategies::convex_hull::services::default_strategy
- <
- Geometry
- >::type strategy_type;
+ auto&& ring = exterior_ring(out);
+ dispatch::convex_hull<Geometry>::apply(geometry, ring, strategies);
+ }
+};
- apply(geometry, out, strategy_type());
+template <typename OutputGeometry>
+struct convex_hull_out<OutputGeometry, multi_polygon_tag>
+{
+ template <typename Geometry, typename Strategies>
+ static inline void apply(Geometry const& geometry,
+ OutputGeometry& out,
+ Strategies const& strategies)
+ {
+ typename boost::range_value<OutputGeometry>::type polygon;
+ auto&& ring = exterior_ring(polygon);
+ dispatch::convex_hull<Geometry>::apply(geometry, ring, strategies);
+ // Empty input is checked so the output shouldn't be empty
+ range::push_back(out, std::move(polygon));
}
};
-struct convex_hull_insert
+template <typename OutputGeometry>
+struct convex_hull_out<OutputGeometry, geometry_collection_tag>
{
- template <typename Geometry, typename OutputIterator, typename Strategy>
- static inline OutputIterator apply(Geometry const& geometry,
- OutputIterator& out,
- Strategy const& strategy)
+ using polygonal_t = typename util::sequence_min_element
+ <
+ typename traits::geometry_types<OutputGeometry>::type,
+ detail::convex_hull::output_polygonal_less
+ >::type;
+ using linear_t = typename util::sequence_min_element
+ <
+ typename traits::geometry_types<OutputGeometry>::type,
+ detail::convex_hull::output_linear_less
+ >::type;
+ using pointlike_t = typename util::sequence_min_element
+ <
+ typename traits::geometry_types<OutputGeometry>::type,
+ detail::convex_hull::output_pointlike_less
+ >::type;
+
+ // select_element may define different kind of geometry than the one that is desired
+ BOOST_GEOMETRY_STATIC_ASSERT(util::is_polygonal<polygonal_t>::value,
+ "It must be possible to store polygonal geometry in OutputGeometry.", polygonal_t);
+ BOOST_GEOMETRY_STATIC_ASSERT(util::is_linear<linear_t>::value,
+ "It must be possible to store linear geometry in OutputGeometry.", linear_t);
+ BOOST_GEOMETRY_STATIC_ASSERT(util::is_pointlike<pointlike_t>::value,
+ "It must be possible to store pointlike geometry in OutputGeometry.", pointlike_t);
+
+ template <typename Geometry, typename Strategies>
+ static inline void apply(Geometry const& geometry,
+ OutputGeometry& out,
+ Strategies const& strategies)
{
- //BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy<Strategy>) );
+ polygonal_t polygonal;
+ convex_hull_out<polygonal_t>::apply(geometry, polygonal, strategies);
+ // Empty input is checked so the output shouldn't be empty
+ auto&& out_ring = ring(polygonal);
+
+ if (boost::size(out_ring) == detail::minimum_ring_size<polygonal_t>::value)
+ {
+ using detail::equals::equals_point_point;
+ if (equals_point_point(range::front(out_ring), range::at(out_ring, 1), strategies))
+ {
+ pointlike_t pointlike;
+ move_to_pointlike(out_ring, pointlike);
+ move_to_out(pointlike, out);
+ return;
+ }
+ if (equals_point_point(range::front(out_ring), range::at(out_ring, 2), strategies))
+ {
+ linear_t linear;
+ move_to_linear(out_ring, linear);
+ move_to_out(linear, out);
+ return;
+ }
+ }
- return dispatch::convex_hull_insert<
- geometry::point_order<Geometry>::value,
- geometry::closure<Geometry>::value
- >::apply(geometry, out, strategy);
+ move_to_out(polygonal, out);
}
- template <typename Geometry, typename OutputIterator>
- static inline OutputIterator apply(Geometry const& geometry,
- OutputIterator& out,
- default_strategy)
+private:
+ template <typename Polygonal, util::enable_if_ring_t<Polygonal, int> = 0>
+ static decltype(auto) ring(Polygonal const& polygonal)
{
- typedef typename strategies::convex_hull::services::default_strategy
- <
- Geometry
- >::type strategy_type;
+ return polygonal;
+ }
+ template <typename Polygonal, util::enable_if_polygon_t<Polygonal, int> = 0>
+ static decltype(auto) ring(Polygonal const& polygonal)
+ {
+ return exterior_ring(polygonal);
+ }
+ template <typename Polygonal, util::enable_if_multi_polygon_t<Polygonal, int> = 0>
+ static decltype(auto) ring(Polygonal const& polygonal)
+ {
+ return exterior_ring(range::front(polygonal));
+ }
- return apply(geometry, out, strategy_type());
+ template <typename Range, typename Linear, util::enable_if_segment_t<Linear, int> = 0>
+ static void move_to_linear(Range & out_range, Linear & seg)
+ {
+ detail::assign_point_to_index<0>(range::front(out_range), seg);
+ detail::assign_point_to_index<1>(range::at(out_range, 1), seg);
+ }
+ template <typename Range, typename Linear, util::enable_if_linestring_t<Linear, int> = 0>
+ static void move_to_linear(Range & out_range, Linear & ls)
+ {
+ std::move(boost::begin(out_range), boost::begin(out_range) + 2, range::back_inserter(ls));
+ }
+ template <typename Range, typename Linear, util::enable_if_multi_linestring_t<Linear, int> = 0>
+ static void move_to_linear(Range & out_range, Linear & mls)
+ {
+ typename boost::range_value<Linear>::type ls;
+ std::move(boost::begin(out_range), boost::begin(out_range) + 2, range::back_inserter(ls));
+ range::push_back(mls, std::move(ls));
+ }
+
+ template <typename Range, typename PointLike, util::enable_if_point_t<PointLike, int> = 0>
+ static void move_to_pointlike(Range & out_range, PointLike & pt)
+ {
+ pt = range::front(out_range);
+ }
+ template <typename Range, typename PointLike, util::enable_if_multi_point_t<PointLike, int> = 0>
+ static void move_to_pointlike(Range & out_range, PointLike & mpt)
+ {
+ range::push_back(mpt, std::move(range::front(out_range)));
+ }
+
+ template
+ <
+ typename Geometry, typename OutputGeometry_,
+ util::enable_if_geometry_collection_t<OutputGeometry_, int> = 0
+ >
+ static void move_to_out(Geometry & g, OutputGeometry_ & out)
+ {
+ range::emplace_back(out, std::move(g));
+ }
+ template
+ <
+ typename Geometry, typename OutputGeometry_,
+ util::enable_if_dynamic_geometry_t<OutputGeometry_, int> = 0
+ >
+ static void move_to_out(Geometry & g, OutputGeometry_ & out)
+ {
+ out = std::move(g);
}
};
-} // namespace resolve_strategy
+template <typename OutputGeometry>
+struct convex_hull_out<OutputGeometry, dynamic_geometry_tag>
+ : convex_hull_out<OutputGeometry, geometry_collection_tag>
+{};
-namespace resolve_variant {
+// For backward compatibility
+template <typename OutputGeometry>
+struct convex_hull_out<OutputGeometry, linestring_tag>
+ : convex_hull_out<OutputGeometry, ring_tag>
+{};
-template <typename Geometry>
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+namespace resolve_strategy {
+
+template <typename Strategies>
struct convex_hull
{
- template <typename OutputGeometry, typename Strategy>
+ template <typename Geometry, typename OutputGeometry>
static inline void apply(Geometry const& geometry,
OutputGeometry& out,
- Strategy const& strategy)
+ Strategies const& strategies)
{
- concepts::check_concepts_and_equal_dimensions<
- const Geometry,
- OutputGeometry
- >();
-
- resolve_strategy::convex_hull::apply(geometry, out, strategy);
+ dispatch::convex_hull_out<OutputGeometry>::apply(geometry, out, strategies);
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct convex_hull<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <>
+struct convex_hull<default_strategy>
{
- template <typename OutputGeometry, typename Strategy>
- struct visitor: boost::static_visitor<void>
+ template <typename Geometry, typename OutputGeometry>
+ static inline void apply(Geometry const& geometry,
+ OutputGeometry& out,
+ default_strategy const&)
{
- OutputGeometry& m_out;
- Strategy const& m_strategy;
-
- visitor(OutputGeometry& out, Strategy const& strategy)
- : m_out(out), m_strategy(strategy)
- {}
-
- template <typename Geometry>
- void operator()(Geometry const& geometry) const
- {
- convex_hull<Geometry>::apply(geometry, m_out, m_strategy);
- }
- };
+ using strategy_type = typename detail::convex_hull::default_strategy
+ <
+ Geometry
+ >::type;
- template <typename OutputGeometry, typename Strategy>
- static inline void
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- OutputGeometry& out,
- Strategy const& strategy)
- {
- boost::apply_visitor(visitor<OutputGeometry, Strategy>(out, strategy),
- geometry);
+ dispatch::convex_hull_out<OutputGeometry>::apply(geometry, out, strategy_type());
}
};
-template <typename Geometry>
-struct convex_hull_insert
+
+} // namespace resolve_strategy
+
+
+namespace resolve_dynamic {
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct convex_hull
{
- template <typename OutputIterator, typename Strategy>
- static inline OutputIterator apply(Geometry const& geometry,
- OutputIterator& out,
- Strategy const& strategy)
+ template <typename OutputGeometry, typename Strategy>
+ static inline void apply(Geometry const& geometry,
+ OutputGeometry& out,
+ Strategy const& strategy)
{
- // Concept: output point type = point type of input geometry
- concepts::check<Geometry const>();
- concepts::check<typename point_type<Geometry>::type>();
+ concepts::check_concepts_and_equal_dimensions<
+ const Geometry,
+ OutputGeometry
+ >();
- return resolve_strategy::convex_hull_insert::apply(geometry, out, strategy);
+ resolve_strategy::convex_hull<Strategy>::apply(geometry, out, strategy);
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct convex_hull_insert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct convex_hull<Geometry, dynamic_geometry_tag>
{
- template <typename OutputIterator, typename Strategy>
- struct visitor: boost::static_visitor<OutputIterator>
+ template <typename OutputGeometry, typename Strategy>
+ static inline void apply(Geometry const& geometry,
+ OutputGeometry& out,
+ Strategy const& strategy)
{
- OutputIterator& m_out;
- Strategy const& m_strategy;
-
- visitor(OutputIterator& out, Strategy const& strategy)
- : m_out(out), m_strategy(strategy)
- {}
-
- template <typename Geometry>
- OutputIterator operator()(Geometry const& geometry) const
+ traits::visit<Geometry>::apply([&](auto const& g)
{
- return convex_hull_insert<Geometry>::apply(geometry, m_out, m_strategy);
- }
- };
-
- template <typename OutputIterator, typename Strategy>
- static inline OutputIterator
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- OutputIterator& out,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<OutputIterator, Strategy>(out, strategy), geometry);
+ convex_hull<util::remove_cref_t<decltype(g)>>::apply(g, out, strategy);
+ }, geometry);
}
};
-} // namespace resolve_variant
+
+} // namespace resolve_dynamic
/*!
@@ -330,8 +581,7 @@ struct convex_hull_insert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
\qbk{[include reference/algorithms/convex_hull.qbk]}
*/
template<typename Geometry, typename OutputGeometry, typename Strategy>
-inline void convex_hull(Geometry const& geometry,
- OutputGeometry& out, Strategy const& strategy)
+inline void convex_hull(Geometry const& geometry, OutputGeometry& out, Strategy const& strategy)
{
if (geometry::is_empty(geometry))
{
@@ -339,7 +589,7 @@ inline void convex_hull(Geometry const& geometry,
return;
}
- resolve_variant::convex_hull<Geometry>::apply(geometry, out, strategy);
+ resolve_dynamic::convex_hull<Geometry>::apply(geometry, out, strategy);
}
@@ -355,52 +605,11 @@ inline void convex_hull(Geometry const& geometry,
\qbk{[include reference/algorithms/convex_hull.qbk]}
*/
template<typename Geometry, typename OutputGeometry>
-inline void convex_hull(Geometry const& geometry,
- OutputGeometry& hull)
+inline void convex_hull(Geometry const& geometry, OutputGeometry& hull)
{
geometry::convex_hull(geometry, hull, default_strategy());
}
-#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)
-{
- return resolve_variant::convex_hull_insert
- <
- Geometry
- >::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)
-{
- return convex_hull_insert(geometry, out, default_strategy());
-}
-
-
-}} // namespace detail::convex_hull
-#endif // DOXYGEN_NO_DETAIL
-
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/counting.hpp b/boost/geometry/algorithms/detail/counting.hpp
index 3580740b31..0199ec0b9a 100644
--- a/boost/geometry/algorithms/detail/counting.hpp
+++ b/boost/geometry/algorithms/detail/counting.hpp
@@ -30,8 +30,6 @@
#include <boost/geometry/util/range.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
-
namespace boost { namespace geometry
{
@@ -67,10 +65,8 @@ struct polygon_count
{
std::size_t n = RangeCount::apply(exterior_ring(poly));
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(poly);
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ auto const& rings = interior_rings(poly);
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
n += RangeCount::apply(*it);
}
@@ -84,13 +80,10 @@ template <typename SingleCount>
struct multi_count
{
template <typename MultiGeometry>
- static inline std::size_t apply(MultiGeometry const& geometry)
+ static inline std::size_t apply(MultiGeometry const& multi)
{
std::size_t n = 0;
- for (typename boost::range_iterator<MultiGeometry const>::type
- it = boost::begin(geometry);
- it != boost::end(geometry);
- ++it)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
n += SingleCount::apply(*it);
}
diff --git a/boost/geometry/algorithms/detail/covered_by/implementation.hpp b/boost/geometry/algorithms/detail/covered_by/implementation.hpp
index ca4e557caa..13626871aa 100644
--- a/boost/geometry/algorithms/detail/covered_by/implementation.hpp
+++ b/boost/geometry/algorithms/detail/covered_by/implementation.hpp
@@ -4,9 +4,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2013-2021.
-// Modifications copyright (c) 2013-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -37,7 +38,8 @@ namespace detail { namespace covered_by {
struct use_point_in_geometry
{
template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
return detail::within::covered_by_point_geometry(geometry1, geometry2, strategy);
}
@@ -46,44 +48,41 @@ struct use_point_in_geometry
struct use_relate
{
template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- typedef typename detail::de9im::static_mask_covered_by_type
+ return detail::relate::relate_impl
<
- Geometry1, Geometry2
- >::type covered_by_mask;
- return geometry::relate(geometry1, geometry2, covered_by_mask(), strategy);
+ detail::de9im::static_mask_covered_by_type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
}
};
-}} // namespace detail::covered_by
-#endif // DOXYGEN_NO_DETAIL
-
-#ifndef DOXYGEN_NO_DISPATCH
-namespace dispatch
-{
-
-template <typename Point, typename Box>
-struct covered_by<Point, Box, point_tag, box_tag>
+struct geometry_covered_by_box
{
- template <typename Strategy>
- static inline bool apply(Point const& point, Box const& box, Strategy const& strategy)
+ template <typename Geometry, typename Box, typename Strategy>
+ static inline bool apply(Geometry const& geometry, Box const& box, Strategy const& strategy)
{
- return strategy.covered_by(point, box).apply(point, box);
+ using point_type = typename point_type<Geometry>::type;
+ using mutable_point_type = typename helper_geometry<point_type>::type;
+ using box_type = model::box<mutable_point_type>;
+
+ // TODO: this is not optimal since the process should be able to terminate if a point is found
+ // outside of the box without computing the whole envelope
+ box_type box_areal;
+ geometry::envelope(geometry, box_areal, strategy);
+ return strategy.covered_by(box_areal, box).apply(box_areal, 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>();
- return strategy.covered_by(box1, box2).apply(box1, box2);
- }
-};
+}} // namespace detail::covered_by
+#endif // DOXYGEN_NO_DETAIL
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
// P/P
@@ -272,6 +271,76 @@ struct covered_by<MultiPolygon1, MultiPolygon2, multi_polygon_tag, multi_polygon
: public detail::covered_by::use_relate
{};
+// B/A
+
+template <typename Box, typename Polygon>
+struct covered_by<Box, Polygon, box_tag, ring_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename Box, typename Polygon>
+struct covered_by<Box, Polygon, box_tag, polygon_tag>
+ : public detail::covered_by::use_relate
+{};
+
+template <typename Box, typename Polygon>
+struct covered_by<Box, Polygon, box_tag, multi_polygon_tag>
+ : public detail::covered_by::use_relate
+{};
+
+// Geometry/Box
+
+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)
+ {
+ return strategy.covered_by(point, box).apply(point, box);
+ }
+};
+
+template <typename MultiPoint, typename Box>
+struct covered_by<MultiPoint, Box, multi_point_tag, box_tag>
+ : public detail::covered_by::geometry_covered_by_box
+{};
+
+template <typename Linestring, typename Box>
+struct covered_by<Linestring, Box, linestring_tag, box_tag>
+ : public detail::covered_by::geometry_covered_by_box
+{};
+
+template <typename MultiLinestring, typename Box>
+struct covered_by<MultiLinestring, Box, multi_linestring_tag, box_tag>
+ : public detail::covered_by::geometry_covered_by_box
+{};
+
+template <typename Ring, typename Box>
+struct covered_by<Ring, Box, ring_tag, box_tag>
+ : public detail::covered_by::geometry_covered_by_box
+{};
+
+template <typename Polygon, typename Box>
+struct covered_by<Polygon, Box, polygon_tag, box_tag>
+ : public detail::covered_by::geometry_covered_by_box
+{};
+
+template <typename MultiPolygon, typename Box>
+struct covered_by<MultiPolygon, Box, multi_polygon_tag, box_tag>
+ : public detail::covered_by::geometry_covered_by_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>();
+ return strategy.covered_by(box1, box2).apply(box1, box2);
+ }
+};
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/detail/covered_by/implementation_gc.hpp b/boost/geometry/algorithms/detail/covered_by/implementation_gc.hpp
new file mode 100644
index 0000000000..cd0a44bc8f
--- /dev/null
+++ b/boost/geometry/algorithms/detail/covered_by/implementation_gc.hpp
@@ -0,0 +1,46 @@
+// Boost.Geometry
+
+// Copyright (c) 2022 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// 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_COVERED_BY_IMPLEMENTATION_GC_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_GC_HPP
+
+
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation_gc.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+template <typename Geometry1, typename Geometry2>
+struct covered_by<Geometry1, Geometry2, geometry_collection_tag, geometry_collection_tag>
+ : detail::covered_by::use_relate
+{};
+
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct covered_by<Geometry1, Geometry2, Tag1, geometry_collection_tag>
+ : detail::covered_by::use_relate
+{};
+
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct covered_by<Geometry1, Geometry2, geometry_collection_tag, Tag2>
+ : detail::covered_by::use_relate
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_IMPLEMENTATION_GC_HPP
diff --git a/boost/geometry/algorithms/detail/covered_by/interface.hpp b/boost/geometry/algorithms/detail/covered_by/interface.hpp
index 20b22ff600..0488034381 100644
--- a/boost/geometry/algorithms/detail/covered_by/interface.hpp
+++ b/boost/geometry/algorithms/detail/covered_by/interface.hpp
@@ -19,10 +19,6 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COVERED_BY_INTERFACE_HPP
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
#include <boost/geometry/algorithms/detail/within/interface.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
@@ -121,9 +117,14 @@ struct covered_by<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant {
+namespace resolve_dynamic {
-template <typename Geometry1, typename Geometry2>
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct covered_by
{
template <typename Strategy>
@@ -131,107 +132,74 @@ struct covered_by
Geometry2 const& geometry2,
Strategy const& strategy)
{
- return resolve_strategy::covered_by<Strategy>
- ::apply(geometry1, geometry2, strategy);
+ return resolve_strategy::covered_by
+ <
+ Strategy
+ >::apply(geometry1, geometry2, strategy);
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct covered_by<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct covered_by<Geometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Strategy const& strategy)
- : m_geometry2(geometry2), m_strategy(strategy) {}
-
- template <typename Geometry1>
- bool operator()(Geometry1 const& geometry1) const
+ bool result = false;
+ traits::visit<Geometry1>::apply([&](auto const& g1)
{
- return covered_by<Geometry1, Geometry2>
- ::apply(geometry1, m_geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
+ result = resolve_strategy::covered_by
+ <
+ Strategy
+ >::apply(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct covered_by<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct covered_by<Geometry1, Geometry2, Tag1, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Strategy const& strategy)
- : m_geometry1(geometry1), m_strategy(strategy) {}
-
- template <typename Geometry2>
- bool operator()(Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry2>::apply([&](auto const& g2)
{
- return covered_by<Geometry1, Geometry2>
- ::apply(m_geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
+ result = resolve_strategy::covered_by
+ <
+ Strategy
+ >::apply(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
}
};
-template <
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
-struct covered_by<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
->
+template <typename Geometry1, typename Geometry2>
+struct covered_by<Geometry1, Geometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy): m_strategy(strategy) {}
-
- template <typename Geometry1, typename Geometry2>
- bool operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry1, Geometry2>::apply([&](auto const& g1, auto const& g2)
{
- return covered_by<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
+ result = resolve_strategy::covered_by
+ <
+ Strategy
+ >::apply(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -256,8 +224,10 @@ struct covered_by<
template<typename Geometry1, typename Geometry2>
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- return resolve_variant::covered_by<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, default_strategy());
+ return resolve_dynamic::covered_by
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, default_strategy());
}
/*!
@@ -280,8 +250,10 @@ template<typename Geometry1, typename Geometry2, typename Strategy>
inline bool covered_by(Geometry1 const& geometry1, Geometry2 const& geometry2,
Strategy const& strategy)
{
- return resolve_variant::covered_by<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, strategy);
+ return resolve_dynamic::covered_by
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
}
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/direction_code.hpp b/boost/geometry/algorithms/detail/direction_code.hpp
index 269e9b476f..ece34f15b4 100644
--- a/boost/geometry/algorithms/detail/direction_code.hpp
+++ b/boost/geometry/algorithms/detail/direction_code.hpp
@@ -46,16 +46,16 @@ struct direction_code_impl
template <>
struct direction_code_impl<cartesian_tag>
{
- template <typename Point1, typename Point2>
- static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
+ template <typename PointSegmentA, typename PointSegmentB, typename Point2>
+ static inline int apply(PointSegmentA const& segment_a, PointSegmentB const& segment_b,
Point2 const& point)
{
- typedef typename geometry::select_coordinate_type
+ using calc_t = typename geometry::select_coordinate_type
<
- Point1, Point2
- >::type calc_t;
+ PointSegmentA, PointSegmentB, Point2
+ >::type;
- typedef model::infinite_line<calc_t> line_type;
+ using line_type = model::infinite_line<calc_t>;
// Situation and construction of perpendicular line
//
@@ -79,49 +79,67 @@ struct direction_code_impl<cartesian_tag>
}
calc_t const sv = arithmetic::side_value(line, point);
- return sv == 0 ? 0 : sv > 0 ? 1 : -1;
+ static calc_t const zero = 0;
+ return sv == zero ? 0 : sv > zero ? 1 : -1;
}
};
template <>
struct direction_code_impl<spherical_equatorial_tag>
{
- template <typename Point1, typename Point2>
- static inline int apply(Point1 const& segment_a, Point1 const& segment_b,
+ template <typename PointSegmentA, typename PointSegmentB, typename Point2>
+ static inline int apply(PointSegmentA const& segment_a, PointSegmentB const& segment_b,
Point2 const& p)
{
- typedef typename coordinate_type<Point1>::type coord1_t;
- typedef typename coordinate_type<Point2>::type coord2_t;
- typedef typename cs_angular_units<Point1>::type units_t;
- typedef typename cs_angular_units<Point2>::type units2_t;
- BOOST_GEOMETRY_STATIC_ASSERT(
- (std::is_same<units_t, units2_t>::value),
- "Not implemented for different units.",
- units_t, units2_t);
-
- typedef typename geometry::select_coordinate_type <Point1, Point2>::type calc_t;
- typedef math::detail::constants_on_spheroid<coord1_t, units_t> constants1;
- typedef math::detail::constants_on_spheroid<coord2_t, units_t> constants2;
- static coord1_t const pi_half1 = constants1::max_latitude();
- static coord2_t const pi_half2 = constants2::max_latitude();
+ {
+ using units_sa_t = typename cs_angular_units<PointSegmentA>::type;
+ using units_sb_t = typename cs_angular_units<PointSegmentB>::type;
+ using units_p_t = typename cs_angular_units<Point2>::type;
+ BOOST_GEOMETRY_STATIC_ASSERT(
+ (std::is_same<units_sa_t, units_sb_t>::value),
+ "Not implemented for different units.",
+ units_sa_t, units_sb_t);
+ BOOST_GEOMETRY_STATIC_ASSERT(
+ (std::is_same<units_sa_t, units_p_t>::value),
+ "Not implemented for different units.",
+ units_sa_t, units_p_t);
+ }
+
+ using coor_sa_t = typename coordinate_type<PointSegmentA>::type;
+ using coor_sb_t = typename coordinate_type<PointSegmentB>::type;
+ using coor_p_t = typename coordinate_type<Point2>::type;
+
+ // Declare unit type (equal for all types) and calc type (coerced to most precise)
+ using units_t = typename cs_angular_units<Point2>::type;
+ using calc_t = typename geometry::select_coordinate_type
+ <
+ PointSegmentA, PointSegmentB, Point2
+ >::type;
+ using constants_sa_t = math::detail::constants_on_spheroid<coor_sa_t, units_t>;
+ using constants_sb_t = math::detail::constants_on_spheroid<coor_sb_t, units_t>;
+ using constants_p_t = math::detail::constants_on_spheroid<coor_p_t, units_t>;
+
+ static coor_sa_t const pi_half_sa = constants_sa_t::max_latitude();
+ static coor_sb_t const pi_half_sb = constants_sb_t::max_latitude();
+ static coor_p_t const pi_half_p = constants_p_t::max_latitude();
static calc_t const c0 = 0;
- coord1_t const a0 = geometry::get<0>(segment_a);
- coord1_t const a1 = geometry::get<1>(segment_a);
- coord1_t const b0 = geometry::get<0>(segment_b);
- coord1_t const b1 = geometry::get<1>(segment_b);
- coord2_t const p0 = geometry::get<0>(p);
- coord2_t const p1 = geometry::get<1>(p);
-
+ coor_sa_t const a0 = geometry::get<0>(segment_a);
+ coor_sa_t const a1 = geometry::get<1>(segment_a);
+ coor_sb_t const b0 = geometry::get<0>(segment_b);
+ coor_sb_t const b1 = geometry::get<1>(segment_b);
+ coor_p_t const p0 = geometry::get<0>(p);
+ coor_p_t const p1 = geometry::get<1>(p);
+
if ( (math::equals(b0, a0) && math::equals(b1, a1))
|| (math::equals(b0, p0) && math::equals(b1, p1)) )
{
return 0;
}
- bool const is_a_pole = math::equals(pi_half1, math::abs(a1));
- bool const is_b_pole = math::equals(pi_half1, math::abs(b1));
- bool const is_p_pole = math::equals(pi_half2, math::abs(p1));
+ bool const is_a_pole = math::equals(pi_half_sa, math::abs(a1));
+ bool const is_b_pole = math::equals(pi_half_sb, math::abs(b1));
+ bool const is_p_pole = math::equals(pi_half_p, math::abs(p1));
if ( is_b_pole && ((is_a_pole && math::sign(b1) == math::sign(a1))
|| (is_p_pole && math::sign(b1) == math::sign(p1))) )
@@ -139,12 +157,12 @@ struct direction_code_impl<spherical_equatorial_tag>
calc_t const dlat1 = latitude_distance_signed<units_t, calc_t>(b1, a1, dlon1, is_antilon1);
calc_t const dlat2 = latitude_distance_signed<units_t, calc_t>(b1, p1, dlon2, is_antilon2);
- calc_t mx = is_a_pole || is_b_pole || is_p_pole ?
- c0 :
- (std::min)(is_antilon1 ? c0 : math::abs(dlon1),
- is_antilon2 ? c0 : math::abs(dlon2));
- calc_t my = (std::min)(math::abs(dlat1),
- math::abs(dlat2));
+ calc_t const mx = is_a_pole || is_b_pole || is_p_pole
+ ? c0
+ : (std::min)(is_antilon1 ? c0 : math::abs(dlon1),
+ is_antilon2 ? c0 : math::abs(dlon2));
+ calc_t const my = (std::min)(math::abs(dlat1),
+ math::abs(dlat2));
int s1 = 0, s2 = 0;
if (mx >= my)
@@ -164,7 +182,7 @@ struct direction_code_impl<spherical_equatorial_tag>
template <typename Units, typename T>
static inline T latitude_distance_signed(T const& lat1, T const& lat2, T const& lon_ds, bool & is_antilon)
{
- typedef math::detail::constants_on_spheroid<T, Units> constants;
+ using constants = math::detail::constants_on_spheroid<T, Units>;
static T const pi = constants::half_period();
static T const c0 = 0;
@@ -187,27 +205,27 @@ struct direction_code_impl<spherical_equatorial_tag>
template <>
struct direction_code_impl<spherical_polar_tag>
{
- template <typename Point1, typename Point2>
- static inline int apply(Point1 segment_a, Point1 segment_b,
+ template <typename PointSegmentA, typename PointSegmentB, typename Point2>
+ static inline int apply(PointSegmentA segment_a, PointSegmentB segment_b,
Point2 p)
{
- typedef math::detail::constants_on_spheroid
+ using constants_sa_t = math::detail::constants_on_spheroid
<
- typename coordinate_type<Point1>::type,
- typename cs_angular_units<Point1>::type
- > constants1;
- typedef math::detail::constants_on_spheroid
+ typename coordinate_type<PointSegmentA>::type,
+ typename cs_angular_units<PointSegmentA>::type
+ >;
+ using constants_p_t = math::detail::constants_on_spheroid
<
typename coordinate_type<Point2>::type,
typename cs_angular_units<Point2>::type
- > constants2;
+ >;
geometry::set<1>(segment_a,
- constants1::max_latitude() - geometry::get<1>(segment_a));
+ constants_sa_t::max_latitude() - geometry::get<1>(segment_a));
geometry::set<1>(segment_b,
- constants1::max_latitude() - geometry::get<1>(segment_b));
+ constants_sa_t::max_latitude() - geometry::get<1>(segment_b));
geometry::set<1>(p,
- constants2::max_latitude() - geometry::get<1>(p));
+ constants_p_t::max_latitude() - geometry::get<1>(p));
return direction_code_impl
<
@@ -216,13 +234,13 @@ struct direction_code_impl<spherical_polar_tag>
}
};
-// if spherical_tag is passed then pick cs_tag based on Point1 type
+// if spherical_tag is passed then pick cs_tag based on PointSegmentA type
// with spherical_equatorial_tag as the default
template <>
struct direction_code_impl<spherical_tag>
{
- template <typename Point1, typename Point2>
- static inline int apply(Point1 segment_a, Point1 segment_b,
+ template <typename PointSegmentA, typename PointSegmentB, typename Point2>
+ static inline int apply(PointSegmentA segment_a, PointSegmentB segment_b,
Point2 p)
{
return direction_code_impl
@@ -231,7 +249,7 @@ struct direction_code_impl<spherical_tag>
<
std::is_same
<
- typename geometry::cs_tag<Point1>::type,
+ typename geometry::cs_tag<PointSegmentA>::type,
spherical_polar_tag
>::value,
spherical_polar_tag,
@@ -251,8 +269,10 @@ struct direction_code_impl<geographic_tag>
// Returns 1 if p goes forward, so extends (a,b)
// Returns 0 if p is equal with b, or if (a,b) is degenerate
// Note that it does not do any collinearity test, that should be done before
-template <typename CSTag, typename Point1, typename Point2>
-inline int direction_code(Point1 const& segment_a, Point1 const& segment_b,
+// In some cases the "segment" consists of different source points, and therefore
+// their types might differ.
+template <typename CSTag, typename PointSegmentA, typename PointSegmentB, typename Point2>
+inline int direction_code(PointSegmentA const& segment_a, PointSegmentB const& segment_b,
Point2 const& p)
{
return direction_code_impl<CSTag>::apply(segment_a, segment_b, p);
diff --git a/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp b/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp
index 934f90c875..880e503785 100644
--- a/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/areal_areal.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -23,13 +23,15 @@
#include <boost/geometry/core/point_type.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/disjoint/segment_box.hpp>
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
#include <boost/geometry/algorithms/for_each.hpp>
@@ -46,7 +48,8 @@ inline bool point_on_border_covered_by(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
- typename geometry::point_type<Geometry1>::type pt;
+ using point_type = typename geometry::point_type<Geometry1>::type;
+ typename helper_geometry<point_type>::type pt;
return geometry::point_on_border(pt, geometry1)
&& geometry::covered_by(pt, geometry2, strategy);
}
diff --git a/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp b/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp
index 0a1513fbed..8d71dd2e34 100644
--- a/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/linear_areal.hpp
@@ -5,11 +5,12 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2021.
-// Modifications copyright (c) 2013-2021, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022, Oracle and/or its affiliates.
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -36,11 +37,10 @@
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
@@ -51,6 +51,7 @@
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
+#include <boost/geometry/geometries/helper_geometry.hpp>
namespace boost { namespace geometry
{
@@ -70,8 +71,8 @@ struct disjoint_no_intersections_policy
template <typename Strategy>
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
- typedef typename point_type<Geometry1>::type point1_type;
- point1_type p;
+ using point_type = typename point_type<Geometry1>::type;
+ typename helper_geometry<point_type>::type p;
geometry::point_on_border(p, g1);
return ! geometry::covered_by(p, g2, strategy);
@@ -88,12 +89,11 @@ struct disjoint_no_intersections_policy<Geometry1, Geometry2, Tag1, multi_tag>
static inline bool apply(Geometry1 const& g1, Geometry2 const& g2, Strategy const& strategy)
{
// TODO: use partition or rtree on g2
- typedef typename boost::range_iterator<Geometry1 const>::type iterator;
- for ( iterator it = boost::begin(g1) ; it != boost::end(g1) ; ++it )
+ for (auto it = boost::begin(g1); it != boost::end(g1); ++it)
{
typedef typename boost::range_value<Geometry1 const>::type value_type;
- if ( ! disjoint_no_intersections_policy<value_type const, Geometry2>
- ::apply(*it, g2, strategy) )
+ if (! disjoint_no_intersections_policy<value_type const, Geometry2>
+ ::apply(*it, g2, strategy))
{
return false;
}
@@ -141,28 +141,25 @@ struct disjoint_segment_areal
template <typename Segment, typename Polygon>
class disjoint_segment_areal<Segment, Polygon, polygon_tag>
{
-private:
+
template <typename InteriorRings, typename Strategy>
static inline
bool check_interior_rings(InteriorRings const& interior_rings,
Segment const& segment,
Strategy const& strategy)
{
- typedef typename boost::range_value<InteriorRings>::type ring_type;
+ using ring_type = typename boost::range_value<InteriorRings>::type;
- typedef unary_disjoint_geometry_to_query_geometry
+ using unary_predicate_type = unary_disjoint_geometry_to_query_geometry
<
Segment,
Strategy,
disjoint_range_segment_or_box<ring_type, Segment>
- > unary_predicate_type;
-
- return check_iterator_range
- <
- unary_predicate_type
- >::apply(boost::begin(interior_rings),
- boost::end(interior_rings),
- unary_predicate_type(segment, strategy));
+ >;
+
+ return std::all_of(boost::begin(interior_rings),
+ boost::end(interior_rings),
+ unary_predicate_type(segment, strategy));
}
diff --git a/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp b/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp
index fc8e6a3511..00a6bff82d 100644
--- a/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/linear_linear.hpp
@@ -33,6 +33,8 @@
#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
#include <boost/geometry/algorithms/detail/overlay/segment_as_subrange.hpp>
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
#include <boost/geometry/policies/disjoint_interrupt_policy.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
@@ -91,20 +93,21 @@ struct disjoint_linear
Geometry2 const& geometry2,
Strategy const& strategy)
{
- typedef typename geometry::point_type<Geometry1>::type point_type;
- typedef geometry::segment_ratio
+ using point_type = typename geometry::point_type<Geometry1>::type;
+ using mutable_point_type = typename helper_geometry<point_type>::type;
+ using ratio_type = geometry::segment_ratio
<
typename coordinate_type<point_type>::type
- > ratio_type;
- typedef overlay::turn_info
+ > ;
+ using turn_info_type = overlay::turn_info
<
- point_type,
+ mutable_point_type,
ratio_type,
typename detail::get_turns::turn_operation_type
<
- Geometry1, Geometry2, ratio_type
+ Geometry1, Geometry2, mutable_point_type, ratio_type
>::type
- > turn_info_type;
+ >;
std::deque<turn_info_type> turns;
diff --git a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
index 9e3a57a29e..535c9006b5 100644
--- a/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/multipoint_geometry.hpp
@@ -2,7 +2,9 @@
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -31,7 +33,6 @@
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/expand.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp>
@@ -62,25 +63,25 @@ namespace detail { namespace disjoint
class multipoint_multipoint
{
private:
- template <typename Iterator, typename CSTag>
- class unary_disjoint_predicate
- : geometry::less<void, -1, CSTag>
+ template <typename Iterator, typename Strategy>
+ class unary_not_disjoint_predicate
+ : geometry::less<void, -1, Strategy>
{
private:
- typedef geometry::less<void, -1, CSTag> base_type;
+ using less_type = geometry::less<void, -1, Strategy>;
public:
- unary_disjoint_predicate(Iterator first, Iterator last)
- : base_type(), m_first(first), m_last(last)
+ unary_not_disjoint_predicate(Iterator first, Iterator last)
+ : less_type(), m_first(first), m_last(last)
{}
template <typename Point>
- inline bool apply(Point const& point) const
+ inline bool operator()(Point const& point) const
{
- return !std::binary_search(m_first,
- m_last,
- point,
- static_cast<base_type const&>(*this));
+ return std::binary_search(m_first,
+ m_last,
+ point,
+ static_cast<less_type const&>(*this));
}
private:
@@ -93,30 +94,25 @@ public:
MultiPoint2 const& multipoint2,
Strategy const&)
{
- typedef typename Strategy::cs_tag cs_tag;
- typedef geometry::less<void, -1, cs_tag> less_type;
-
BOOST_GEOMETRY_ASSERT( boost::size(multipoint1) <= boost::size(multipoint2) );
- typedef typename boost::range_value<MultiPoint1>::type point1_type;
+ using less_type = geometry::less<void, -1, Strategy>;
+ using point1_type = typename boost::range_value<MultiPoint1>::type;
std::vector<point1_type> points1(boost::begin(multipoint1),
boost::end(multipoint1));
std::sort(points1.begin(), points1.end(), less_type());
- typedef unary_disjoint_predicate
+ using predicate_type = unary_not_disjoint_predicate
<
typename std::vector<point1_type>::const_iterator,
- cs_tag
- > predicate_type;
+ Strategy
+ >;
- return check_iterator_range
- <
- predicate_type
- >::apply(boost::begin(multipoint2),
- boost::end(multipoint2),
- predicate_type(points1.begin(), points1.end()));
+ return none_of(boost::begin(multipoint2),
+ boost::end(multipoint2),
+ predicate_type(points1.begin(), points1.end()));
}
};
@@ -289,13 +285,12 @@ public:
typedef typename point_type<MultiPoint>::type point1_type;
typedef typename point_type<SingleGeometry>::type point2_type;
typedef model::box<point2_type> box2_type;
-
+
box2_type box2;
geometry::envelope(single_geometry, box2, strategy);
geometry::detail::expand_by_epsilon(box2);
- typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
- for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ for (auto it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it)
{
// The default strategy is enough for Point/Box
if (! detail::disjoint::disjoint_point_box(*it, box2, strategy)
@@ -434,7 +429,7 @@ public:
typedef model::box<point1_type> box1_type;
typedef model::box<point2_type> box2_type;
typedef std::pair<box2_type, std::size_t> box_pair_type;
-
+
std::size_t count2 = boost::size(multi_geometry);
std::vector<box_pair_type> boxes(count2);
for (std::size_t i = 0 ; i < count2 ; ++i)
@@ -533,7 +528,7 @@ struct disjoint
{
return detail::disjoint::multipoint_multipoint
::apply(multipoint2, multipoint1, strategy);
- }
+ }
return detail::disjoint::multipoint_multipoint
::apply(multipoint1, multipoint2, strategy);
diff --git a/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp
index 51945551bb..2dccbae934 100644
--- a/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/multirange_geometry.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -11,12 +12,12 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_MULTIRANGE_GEOMETRY_HPP
+#include <algorithm>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
@@ -34,13 +35,13 @@ class unary_disjoint_geometry_to_query_geometry
{
public:
unary_disjoint_geometry_to_query_geometry(Geometry const& geometry,
- Strategy const& strategy)
+ Strategy const& strategy)
: m_geometry(geometry)
, m_strategy(strategy)
{}
template <typename QueryGeometry>
- inline bool apply(QueryGeometry const& query_geometry) const
+ inline bool operator()(QueryGeometry const& query_geometry) const
{
return BinaryPredicate::apply(query_geometry, m_geometry, m_strategy);
}
@@ -59,7 +60,7 @@ struct multirange_constant_size_geometry
ConstantSizeGeometry const& constant_size_geometry,
Strategy const& strategy)
{
- typedef unary_disjoint_geometry_to_query_geometry
+ using disjoint = unary_disjoint_geometry_to_query_geometry
<
ConstantSizeGeometry,
Strategy,
@@ -68,13 +69,11 @@ struct multirange_constant_size_geometry
typename boost::range_value<MultiRange>::type,
ConstantSizeGeometry
>
- > unary_predicate_type;
+ >;
- return detail::check_iterator_range
- <
- unary_predicate_type
- >::apply(boost::begin(multirange), boost::end(multirange),
- unary_predicate_type(constant_size_geometry, strategy));
+ return std::all_of(boost::begin(multirange),
+ boost::end(multirange),
+ disjoint(constant_size_geometry, strategy));
}
template <typename Strategy>
diff --git a/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp b/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp
index 66bd7c26ce..4e22ac3a00 100644
--- a/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/point_geometry.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013, 2014, 2015.
-// Modifications copyright (c) 2013-2015, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -21,7 +21,7 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISJOINT_POINT_GEOMETRY_HPP
-#include <boost/geometry/algorithms/covered_by.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
diff --git a/boost/geometry/algorithms/detail/disjoint/segment_box.hpp b/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
index f6ba272690..1f2d669e53 100644
--- a/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
+++ b/boost/geometry/algorithms/detail/disjoint/segment_box.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2021.
+// Modifications copyright (c) 2013-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -33,7 +33,6 @@
#include <boost/geometry/algorithms/detail/envelope/segment.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/dispatch/disjoint.hpp>
-#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/formulas/vertex_longitude.hpp>
diff --git a/boost/geometry/algorithms/detail/distance/geometry_collection.hpp b/boost/geometry/algorithms/detail/distance/geometry_collection.hpp
new file mode 100644
index 0000000000..f230958437
--- /dev/null
+++ b/boost/geometry/algorithms/detail/distance/geometry_collection.hpp
@@ -0,0 +1,237 @@
+// Boost.Geometry
+
+// Copyright (c) 2021 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_COLLECTION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_GEOMETRY_COLLECTION_HPP
+
+
+#include <vector>
+
+#include <boost/geometry/algorithms/dispatch/distance.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
+#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/index/rtree.hpp>
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/distance_result.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace distance
+{
+
+
+template <typename Geometry, typename GeometryCollection, typename Strategies>
+inline auto geometry_to_collection(Geometry const& geometry,
+ GeometryCollection const& collection,
+ Strategies const& strategies)
+{
+ using result_t = typename geometry::distance_result<Geometry, GeometryCollection, Strategies>::type;
+ result_t result = 0;
+ bool is_first = true;
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ result_t r = dispatch::distance
+ <
+ Geometry, util::remove_cref_t<decltype(g)>, Strategies
+ >::apply(geometry, g, strategies);
+ if (is_first)
+ {
+ result = r;
+ is_first = false;
+ }
+ else if (r < result)
+ {
+ result = r;
+ }
+ return result > result_t(0);
+ }, collection);
+
+ return result;
+}
+
+template <typename GeometryCollection1, typename GeometryCollection2, typename Strategies>
+inline auto collection_to_collection(GeometryCollection1 const& collection1,
+ GeometryCollection2 const& collection2,
+ Strategies const& strategies)
+{
+ using result_t = typename geometry::distance_result<GeometryCollection1, GeometryCollection2, Strategies>::type;
+
+ using point1_t = typename geometry::point_type<GeometryCollection1>::type;
+ using box1_t = model::box<point1_t>;
+ using point2_t = typename geometry::point_type<GeometryCollection2>::type;
+ using box2_t = model::box<point2_t>;
+
+ using rtree_value_t = std::pair<box1_t, typename boost::range_iterator<GeometryCollection1 const>::type>;
+ using rtree_params_t = index::parameters<index::rstar<4>, Strategies>;
+ using rtree_t = index::rtree<rtree_value_t, rtree_params_t>;
+
+ rtree_params_t rtree_params(index::rstar<4>(), strategies);
+ rtree_t rtree(rtree_params);
+
+ // Build rtree of boxes and iterators of elements of GC1
+ // TODO: replace this with visit_breadth_first_iterator to avoid creating an unnecessary container?
+ {
+ std::vector<rtree_value_t> values;
+ visit_breadth_first_impl<true>::apply([&](auto & g1, auto it)
+ {
+ box1_t b1 = geometry::return_envelope<box1_t>(g1, strategies);
+ geometry::detail::expand_by_epsilon(b1);
+ values.emplace_back(b1, it);
+ return true;
+ }, collection1);
+ rtree_t rt(values.begin(), values.end(), rtree_params);
+ rtree = std::move(rt);
+ }
+
+ result_t const zero = 0;
+ auto const rtree_qend = rtree.qend();
+
+ result_t result = 0;
+ bool is_first = true;
+ visit_breadth_first([&](auto const& g2)
+ {
+ box2_t b2 = geometry::return_envelope<box2_t>(g2, strategies);
+ geometry::detail::expand_by_epsilon(b2);
+
+ for (auto it = rtree.qbegin(index::nearest(b2, rtree.size())) ; it != rtree_qend ; ++it)
+ {
+ // If the distance between boxes is greater than or equal to previously found
+ // distance between geometries then stop processing the current b2 because no
+ // closer b1 will be found
+ if (! is_first)
+ {
+ result_t const bd = dispatch::distance
+ <
+ box1_t, box2_t, Strategies
+ >::apply(it->first, b2, strategies);
+ if (bd >= result)
+ {
+ break;
+ }
+ }
+
+ // Boxes are closer than the previously found distance (or it's the first time),
+ // calculate the new distance between geometries and check if it's closer (or assign it).
+ traits::iter_visit<GeometryCollection1>::apply([&](auto const& g1)
+ {
+ result_t const d = dispatch::distance
+ <
+ util::remove_cref_t<decltype(g1)>, util::remove_cref_t<decltype(g2)>,
+ Strategies
+ >::apply(g1, g2, strategies);
+ if (is_first)
+ {
+ result = d;
+ is_first = false;
+ }
+ else if (d < result)
+ {
+ result = d;
+ }
+ }, it->second);
+
+ // The smallest possible distance found, end searching.
+ if (! is_first && result <= zero)
+ {
+ return false;
+ }
+ }
+
+ // Just in case
+ return is_first || result > zero;
+ }, collection2);
+
+ return result;
+}
+
+
+}} // namespace detail::distance
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Geometry, typename GeometryCollection, typename Strategies, typename Tag1
+>
+struct distance
+ <
+ Geometry, GeometryCollection, Strategies,
+ Tag1, geometry_collection_tag, void, false
+ >
+{
+ static inline auto apply(Geometry const& geometry,
+ GeometryCollection const& collection,
+ Strategies const& strategies)
+ {
+ assert_dimension_equal<Geometry, GeometryCollection>();
+
+ return detail::distance::geometry_to_collection(geometry, collection, strategies);
+ }
+};
+
+template
+<
+ typename GeometryCollection, typename Geometry, typename Strategies, typename Tag2
+>
+struct distance
+ <
+ GeometryCollection, Geometry, Strategies,
+ geometry_collection_tag, Tag2, void, false
+ >
+{
+ static inline auto apply(GeometryCollection const& collection,
+ Geometry const& geometry,
+ Strategies const& strategies)
+ {
+ assert_dimension_equal<Geometry, GeometryCollection>();
+
+ return detail::distance::geometry_to_collection(geometry, collection, strategies);
+ }
+};
+
+template
+<
+ typename GeometryCollection1, typename GeometryCollection2, typename Strategies
+>
+struct distance
+ <
+ GeometryCollection1, GeometryCollection2, Strategies,
+ geometry_collection_tag, geometry_collection_tag, void, false
+ >
+{
+ static inline auto apply(GeometryCollection1 const& collection1,
+ GeometryCollection2 const& collection2,
+ Strategies const& strategies)
+ {
+ assert_dimension_equal<GeometryCollection1, GeometryCollection2>();
+
+ // Build the rtree for the smaller GC (ignoring recursive GCs)
+ return boost::size(collection1) <= boost::size(collection2)
+ ? detail::distance::collection_to_collection(collection1, collection2, strategies)
+ : detail::distance::collection_to_collection(collection2, collection1, strategies);
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_SEGMENT_TO_BOX_HPP
diff --git a/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp b/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp
index 6a852ec43f..5af854f901 100644
--- a/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp
+++ b/boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp
@@ -54,7 +54,7 @@ template
>
struct segment_or_box_point_range_closure
: not_implemented<SegmentOrBox>
-{};
+{};
template <typename Segment>
struct segment_or_box_point_range_closure<Segment, segment_tag>
@@ -163,17 +163,11 @@ public:
Strategies const& strategies,
bool check_intersection = true)
{
- typedef geometry::point_iterator<Geometry const> point_iterator_type;
typedef geometry::segment_iterator
<
Geometry const
> segment_iterator_type;
- typedef typename boost::range_const_iterator
- <
- std::vector<segment_or_box_point>
- >::type seg_or_box_const_iterator;
-
typedef assign_new_min_iterator<SegmentOrBox> assign_new_value;
@@ -196,32 +190,27 @@ public:
assign_segment_or_box_points
<
- SegmentOrBox,
+ SegmentOrBox,
std::vector<segment_or_box_point>
>::apply(segment_or_box, seg_or_box_points);
// consider all distances of the points in the geometry to the
// segment or box
comparable_return_type cd_min1(0);
- point_iterator_type pit_min;
- seg_or_box_const_iterator it_min1 = boost::const_begin(seg_or_box_points);
- seg_or_box_const_iterator it_min2 = it_min1;
- ++it_min2;
+ auto pit_min = points_begin(geometry);
+ auto it_min1 = boost::const_begin(seg_or_box_points);
+ auto it_min2 = it_min1 + 1;
bool first = true;
- for (point_iterator_type pit = points_begin(geometry);
+ for (auto pit = pit_min;
pit != points_end(geometry); ++pit, first = false)
{
comparable_return_type cd;
- std::pair
- <
- seg_or_box_const_iterator, seg_or_box_const_iterator
- > it_pair
- = point_to_point_range::apply(*pit,
- boost::const_begin(seg_or_box_points),
- boost::const_end(seg_or_box_points),
- cstrategy,
- cd);
+ auto it_pair = point_to_point_range::apply(*pit,
+ boost::const_begin(seg_or_box_points),
+ boost::const_end(seg_or_box_points),
+ cstrategy,
+ cd);
if (first || cd < cd_min1)
{
@@ -236,10 +225,10 @@ public:
// segments of the geometry
comparable_return_type cd_min2(0);
segment_iterator_type sit_min;
- seg_or_box_const_iterator it_min;
+ auto it_min = boost::const_begin(seg_or_box_points);
first = true;
- for (seg_or_box_const_iterator it = boost::const_begin(seg_or_box_points);
+ for (auto it = boost::const_begin(seg_or_box_points);
it != boost::const_end(seg_or_box_points); ++it, first = false)
{
comparable_return_type cd;
@@ -282,7 +271,7 @@ public:
}
- static inline return_type apply(SegmentOrBox const& segment_or_box, Geometry const& geometry,
+ static inline return_type apply(SegmentOrBox const& segment_or_box, Geometry const& geometry,
Strategies const& strategies, bool check_intersection = true)
{
return apply(geometry, segment_or_box, strategies, check_intersection);
@@ -299,14 +288,7 @@ class geometry_to_segment_or_box
{
private:
typedef detail::closest_feature::geometry_to_range base_type;
-
- typedef typename boost::range_iterator
- <
- MultiPoint const
- >::type iterator_type;
-
typedef detail::closest_feature::geometry_to_range geometry_to_range;
-
typedef distance::strategy_t<MultiPoint, SegmentOrBox, Strategies> strategy_type;
public:
@@ -318,7 +300,7 @@ public:
{
distance::creturn_t<MultiPoint, SegmentOrBox, Strategies> cd_min;
- iterator_type it_min
+ auto const it_min
= geometry_to_range::apply(segment_or_box,
boost::begin(multipoint),
boost::end(multipoint),
diff --git a/boost/geometry/algorithms/detail/distance/implementation.hpp b/boost/geometry/algorithms/detail/distance/implementation.hpp
index 91b1d817b3..8dfe4fec7e 100644
--- a/boost/geometry/algorithms/detail/distance/implementation.hpp
+++ b/boost/geometry/algorithms/detail/distance/implementation.hpp
@@ -7,9 +7,9 @@
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
-
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -27,6 +27,7 @@
#include <boost/geometry/algorithms/detail/distance/linear_to_linear.hpp>
#include <boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp>
#include <boost/geometry/algorithms/detail/distance/linear_to_box.hpp>
+#include <boost/geometry/algorithms/detail/distance/geometry_collection.hpp>
#include <boost/geometry/algorithms/detail/distance/geometry_to_segment_or_box.hpp>
#include <boost/geometry/algorithms/detail/distance/segment_to_segment.hpp>
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
diff --git a/boost/geometry/algorithms/detail/distance/interface.hpp b/boost/geometry/algorithms/detail/distance/interface.hpp
index f39f505544..5fdb66beaf 100644
--- a/boost/geometry/algorithms/detail/distance/interface.hpp
+++ b/boost/geometry/algorithms/detail/distance/interface.hpp
@@ -8,7 +8,6 @@
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
-
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -28,6 +27,7 @@
#include <boost/geometry/algorithms/dispatch/distance.hpp>
#include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/core/visit.hpp>
#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -92,10 +92,9 @@ template
struct distance
{
template <typename Geometry1, typename Geometry2>
- static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
return dispatch::distance
<
@@ -123,11 +122,9 @@ struct distance<Strategy, false>
typename Geometry1, typename Geometry2, typename S,
std::enable_if_t<is_strategy_converter_specialized<S>::value, int> = 0
>
- static inline
- typename distance_result<Geometry1, Geometry2, S>::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- S const& strategy)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ S const& strategy)
{
typedef strategies::distance::services::strategy_converter<Strategy> converter;
typedef decltype(converter::get(strategy)) strategy_type;
@@ -143,11 +140,9 @@ struct distance<Strategy, false>
typename Geometry1, typename Geometry2, typename S,
std::enable_if_t<! is_strategy_converter_specialized<S>::value, int> = 0
>
- static inline
- typename distance_result<Geometry1, Geometry2, S>::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- S const& strategy)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ S const& strategy)
{
typedef strategies::distance::services::custom_strategy_converter
<
@@ -166,11 +161,9 @@ template <>
struct distance<default_strategy, false>
{
template <typename Geometry1, typename Geometry2>
- static inline
- typename distance_result<Geometry1, Geometry2, default_strategy>::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- default_strategy)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ default_strategy)
{
typedef typename strategies::distance::services::default_strategy
<
@@ -187,18 +180,22 @@ struct distance<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry1, typename Geometry2>
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct distance
{
template <typename Strategy>
- static inline typename distance_result<Geometry1, Geometry2, Strategy>::type
- apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
+ static inline auto apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
return resolve_strategy::distance
<
@@ -208,174 +205,72 @@ struct distance
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct distance<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
+struct distance<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Strategy>
- struct visitor: static_visitor
- <
- typename distance_result
- <
- variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Geometry2,
- Strategy
- >::type
- >
+ static inline auto apply(DynamicGeometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2,
- Strategy const& strategy)
- : m_geometry2(geometry2),
- m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- typename distance_result<Geometry1, Geometry2, Strategy>::type
- operator()(Geometry1 const& geometry1) const
+ using result_t = typename geometry::distance_result<DynamicGeometry1, Geometry2, Strategy>::type;
+ result_t result = 0;
+ traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
{
- return distance
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- Strategy
- >(geometry1, m_geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline typename distance_result
- <
- variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Geometry2,
- Strategy
- >::type
- apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
+ result = resolve_strategy::distance
+ <
+ Strategy
+ >::apply(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct distance<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
+struct distance<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: static_visitor
- <
- typename distance_result
- <
- Geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Strategy
- >::type
- >
+ static inline auto apply(Geometry1 const& geometry1,
+ DynamicGeometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1,
- Strategy const& strategy)
- : m_geometry1(geometry1),
- m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- typename distance_result<Geometry1, Geometry2, Strategy>::type
- operator()(Geometry2 const& geometry2) const
+ using result_t = typename geometry::distance_result<Geometry1, DynamicGeometry2, Strategy>::type;
+ result_t result = 0;
+ traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
{
- return distance
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- Strategy
- >(m_geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline typename distance_result
- <
- Geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(T)>,
- Strategy
- >::type
- apply(
- Geometry1 const& geometry1,
- const variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
+ result = resolve_strategy::distance
+ <
+ Strategy
+ >::apply(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
}
};
-template
-<
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
-struct distance
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
- >
+template <typename DynamicGeometry1, typename DynamicGeometry2>
+struct distance<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: static_visitor
- <
- typename distance_result
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
- Strategy
- >::type
- >
+ static inline auto apply(DynamicGeometry1 const& geometry1,
+ DynamicGeometry2 const& geometry2,
+ Strategy const& strategy)
{
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy)
- : m_strategy(strategy)
- {}
-
- template <typename Geometry1, typename Geometry2>
- typename distance_result<Geometry1, Geometry2, Strategy>::type
- operator()(Geometry1 const& geometry1, Geometry2 const& geometry2) const
+ using result_t = typename geometry::distance_result<DynamicGeometry1, DynamicGeometry2, Strategy>::type;
+ result_t result = 0;
+ traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
{
- return distance
- <
- Geometry1,
- Geometry2
- >::template apply
- <
- Strategy
- >(geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline typename distance_result
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>,
- Strategy
- >::type
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
+ result = resolve_strategy::distance
+ <
+ Strategy
+ >::apply(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -415,10 +310,9 @@ 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 distance_result<Geometry1, Geometry2, Strategy>::type
-distance(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
+inline auto distance(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
@@ -426,7 +320,7 @@ distance(Geometry1 const& geometry1,
detail::throw_on_empty_input(geometry1);
detail::throw_on_empty_input(geometry2);
- return resolve_variant::distance
+ return resolve_dynamic::distance
<
Geometry1,
Geometry2
@@ -448,13 +342,9 @@ distance(Geometry1 const& geometry1,
\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)
+inline auto distance(Geometry1 const& geometry1,
+ Geometry2 const& geometry2)
{
- concepts::check<Geometry1 const>();
- concepts::check<Geometry2 const>();
-
return geometry::distance(geometry1, geometry2, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp b/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp
index e4cb41a358..dc1f4786b5 100644
--- a/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp
+++ b/boost/geometry/algorithms/detail/distance/linear_or_areal_to_areal.hpp
@@ -91,7 +91,7 @@ template <typename Linear, typename Areal, typename Strategy>
struct distance
<
Linear, Areal, Strategy,
- linear_tag, areal_tag,
+ linear_tag, areal_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::linear_to_areal
@@ -104,7 +104,7 @@ template <typename Areal, typename Linear, typename Strategy>
struct distance
<
Areal, Linear, Strategy,
- areal_tag, linear_tag,
+ areal_tag, linear_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::linear_to_areal
@@ -118,7 +118,7 @@ template <typename Areal1, typename Areal2, typename Strategy>
struct distance
<
Areal1, Areal2, Strategy,
- areal_tag, areal_tag,
+ areal_tag, areal_tag,
strategy_tag_distance_point_segment, false
>
: detail::distance::areal_to_areal
diff --git a/boost/geometry/algorithms/detail/distance/linear_to_linear.hpp b/boost/geometry/algorithms/detail/distance/linear_to_linear.hpp
index eb81133f61..0c3e68051b 100644
--- a/boost/geometry/algorithms/detail/distance/linear_to_linear.hpp
+++ b/boost/geometry/algorithms/detail/distance/linear_to_linear.hpp
@@ -102,7 +102,7 @@ template <typename Linear1, typename Linear2, typename Strategy, typename Strate
struct distance
<
Linear1, Linear2, Strategy,
- linear_tag, linear_tag,
+ linear_tag, linear_tag,
StrategyTag, false
> : detail::distance::linear_to_linear
<
diff --git a/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp b/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp
index eabc9528db..58a9d5b283 100644
--- a/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp
+++ b/boost/geometry/algorithms/detail/distance/multipoint_to_geometry.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2021 Oracle and/or its affiliates.
+// Copyright (c) 2014-2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -16,7 +17,6 @@
#include <boost/range/size.hpp>
#include <boost/geometry/algorithms/covered_by.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp>
#include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
#include <boost/geometry/algorithms/dispatch/distance.hpp>
@@ -46,7 +46,6 @@ struct multipoint_to_multipoint
Strategies const& strategies)
{
if (boost::size(multipoint2) < boost::size(multipoint1))
-
{
return point_or_segment_range_to_geometry_rtree
<
@@ -103,16 +102,16 @@ template <typename MultiPoint, typename Areal, typename Strategies>
class multipoint_to_areal
{
private:
- struct not_covered_by_areal
+ struct covered_by_areal
{
- not_covered_by_areal(Areal const& areal, Strategies const& strategy)
+ covered_by_areal(Areal const& areal, Strategies const& strategy)
: m_areal(areal), m_strategy(strategy)
{}
template <typename Point>
- inline bool apply(Point const& point) const
+ inline bool operator()(Point const& point) const
{
- return !geometry::covered_by(point, m_areal, m_strategy);
+ return geometry::covered_by(point, m_areal, m_strategy);
}
Areal const& m_areal;
@@ -126,14 +125,10 @@ public:
Areal const& areal,
Strategies const& strategies)
{
- not_covered_by_areal predicate(areal, strategies);
+ covered_by_areal predicate(areal, strategies);
- if (check_iterator_range
- <
- not_covered_by_areal, false
- >::apply(boost::begin(multipoint),
- boost::end(multipoint),
- predicate))
+ if (! boost::empty(multipoint) &&
+ std::none_of(boost::begin(multipoint), boost::end(multipoint), predicate))
{
return detail::distance::point_or_segment_range_to_geometry_rtree
<
diff --git a/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp b/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp
index b76955cb63..cd7c46ce71 100644
--- a/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp
+++ b/boost/geometry/algorithms/detail/distance/range_to_geometry_rtree.hpp
@@ -95,7 +95,7 @@ public:
:
dispatch::distance
<
- point_or_segment_type,
+ point_or_segment_type,
typename std::iterator_traits
<
typename selector_type::iterator_type
diff --git a/boost/geometry/algorithms/detail/distance/segment_to_box.hpp b/boost/geometry/algorithms/detail/distance/segment_to_box.hpp
index 354d42bd01..09f3cc4f61 100644
--- a/boost/geometry/algorithms/detail/distance/segment_to_box.hpp
+++ b/boost/geometry/algorithms/detail/distance/segment_to_box.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2021 Oracle and/or its affiliates.
+// Copyright (c) 2014-2023 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -91,7 +91,7 @@ private:
std::vector<box_point>,
open
> point_to_point_range;
-
+
public:
// TODO: Or should the return type be defined by sb_strategy_type?
typedef distance::return_t<box_point, Segment, Strategies> return_type;
@@ -114,7 +114,7 @@ public:
// get box points
std::vector<box_point> box_points(4);
detail::assign_box_corners_oriented<true>(box, box_points);
-
+
ps_strategy_type const strategy = strategies.distance(dummy_point(), dummy_segment());
auto const cstrategy = strategy::distance::services::get_comparable
@@ -192,7 +192,7 @@ private:
public:
// TODO: Or should the return type be defined by sb_strategy_type?
typedef distance::return_t<box_point, Segment, Strategies> return_type;
-
+
static inline return_type apply(Segment const& segment,
Box const& box,
Strategies const& strategies,
@@ -658,7 +658,7 @@ public:
BoxPoint const& bottom_right,
Strategies const& strategies)
{
- BOOST_GEOMETRY_ASSERT( (geometry::less<SegmentPoint, -1, typename Strategies::cs_tag>()(p0, p1))
+ BOOST_GEOMETRY_ASSERT( (geometry::less<SegmentPoint, -1, Strategies>()(p0, p1))
|| geometry::has_nan_coordinate(p0)
|| geometry::has_nan_coordinate(p1) );
@@ -753,7 +753,7 @@ public:
bottom_left, bottom_right,
top_left, top_right);
- typedef geometry::less<segment_point, -1, typename Strategies::cs_tag> less_type;
+ typedef geometry::less<segment_point, -1, Strategies> less_type;
if (less_type()(p[0], p[1]))
{
return segment_to_box_2D
diff --git a/boost/geometry/algorithms/detail/envelope/areal.hpp b/boost/geometry/algorithms/detail/envelope/areal.hpp
index 3c9b5c576c..ece4d3d144 100644
--- a/boost/geometry/algorithms/detail/envelope/areal.hpp
+++ b/boost/geometry/algorithms/detail/envelope/areal.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2018 Oracle and/or its affiliates.
+// Copyright (c) 2018-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -22,6 +22,8 @@
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+#include <boost/geometry/views/reversible_view.hpp>
+
namespace boost { namespace geometry
{
@@ -29,6 +31,24 @@ namespace boost { namespace geometry
namespace detail { namespace envelope
{
+
+struct envelope_hole
+{
+ template <typename Range, typename Box, typename Strategies>
+ static inline void apply(Range const& range, Box& mbr, Strategies const& strategies)
+ {
+ // Reverse holes to avoid calculating the envelope for the outside
+ // in spherical and geographic coordinate systems
+ detail::clockwise_view
+ <
+ Range const,
+ geometry::point_order<Range>::value == counterclockwise
+ ? clockwise : counterclockwise
+ > view(range);
+ strategies.envelope(range, mbr).apply(view, mbr);
+ }
+};
+
struct envelope_polygon
{
template <typename Polygon, typename Box, typename Strategy>
@@ -39,11 +59,14 @@ struct envelope_polygon
if (geometry::is_empty(ext_ring))
{
+ // use dummy multi polygon to get the strategy because there is no multi ring concept
+ using strategy_t = decltype(strategy.envelope(detail::dummy_multi_polygon(),
+ detail::dummy_box()));
// if the exterior ring is empty, consider the interior rings
envelope_multi_range
<
- envelope_range
- >::apply(interior_rings(polygon), mbr, strategy);
+ envelope_hole
+ >::template apply<strategy_t>(interior_rings(polygon), mbr, strategy);
}
else
{
diff --git a/boost/geometry/algorithms/detail/envelope/geometry_collection.hpp b/boost/geometry/algorithms/detail/envelope/geometry_collection.hpp
new file mode 100644
index 0000000000..979513da7e
--- /dev/null
+++ b/boost/geometry/algorithms/detail/envelope/geometry_collection.hpp
@@ -0,0 +1,62 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Distributed under the Boost Software License, 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_ENVELOPE_GEOMETRY_COLLECTION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_GEOMETRY_COLLECTION_HPP
+
+
+#include <boost/geometry/algorithms/detail/visit.hpp>
+#include <boost/geometry/algorithms/dispatch/envelope.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
+
+#include <boost/geometry/core/tags.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Collection>
+struct envelope<Collection, geometry_collection_tag>
+{
+ template <typename Geometry, typename Box, typename Strategies>
+ static inline void apply(Geometry const& geometry,
+ Box& mbr,
+ Strategies const& strategies)
+ {
+ using strategy_t = decltype(strategies.envelope(geometry, mbr));
+
+ typename strategy_t::template state<Box> state;
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ if (! geometry::is_empty(g))
+ {
+ Box b;
+ envelope<util::remove_cref_t<decltype(g)>>::apply(g, b, strategies);
+ strategy_t::apply(state, b);
+ }
+ return true;
+ }, geometry);
+ strategy_t::result(state, mbr);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_GEOMETRY_COLLECTION_HPP
diff --git a/boost/geometry/algorithms/detail/envelope/implementation.hpp b/boost/geometry/algorithms/detail/envelope/implementation.hpp
index 569c77b036..cb4108d163 100644
--- a/boost/geometry/algorithms/detail/envelope/implementation.hpp
+++ b/boost/geometry/algorithms/detail/envelope/implementation.hpp
@@ -6,9 +6,9 @@
// This file was modified by Oracle on 2015-2021.
// Modifications copyright (c) 2015-2021, Oracle and/or its affiliates.
-
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -28,6 +28,7 @@
#include <boost/geometry/algorithms/detail/envelope/areal.hpp>
#include <boost/geometry/algorithms/detail/envelope/box.hpp>
+#include <boost/geometry/algorithms/detail/envelope/geometry_collection.hpp>
#include <boost/geometry/algorithms/detail/envelope/linear.hpp>
#include <boost/geometry/algorithms/detail/envelope/multipoint.hpp>
#include <boost/geometry/algorithms/detail/envelope/point.hpp>
diff --git a/boost/geometry/algorithms/detail/envelope/interface.hpp b/boost/geometry/algorithms/detail/envelope/interface.hpp
index 3f6dece384..70679dd918 100644
--- a/boost/geometry/algorithms/detail/envelope/interface.hpp
+++ b/boost/geometry/algorithms/detail/envelope/interface.hpp
@@ -22,16 +22,14 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_INTERFACE_HPP
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
#include <boost/geometry/algorithms/dispatch/envelope.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
@@ -39,6 +37,7 @@
#include <boost/geometry/strategies/envelope/services.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
+#include <boost/geometry/util/type_traits_std.hpp>
namespace boost { namespace geometry
@@ -98,10 +97,10 @@ struct envelope<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry>
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct envelope
{
template <typename Box, typename Strategy>
@@ -117,38 +116,22 @@ struct envelope
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct envelope<Geometry, dynamic_geometry_tag>
{
template <typename Box, typename Strategy>
- struct visitor: boost::static_visitor<void>
+ static inline void apply(Geometry const& geometry,
+ Box& box,
+ Strategy const& strategy)
{
- Box& m_box;
- Strategy const& m_strategy;
-
- visitor(Box& box, Strategy const& strategy)
- : m_box(box)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry>
- void operator()(Geometry const& geometry) const
+ traits::visit<Geometry>::apply([&](auto const& g)
{
- envelope<Geometry>::apply(geometry, m_box, m_strategy);
- }
- };
-
- template <typename Box, typename Strategy>
- static inline void
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- Box& box,
- Strategy const& strategy)
- {
- boost::apply_visitor(visitor<Box, Strategy>(box, strategy), geometry);
+ envelope<util::remove_cref_t<decltype(g)>>::apply(g, box, strategy);
+ }, geometry);
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -172,7 +155,7 @@ struct envelope<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template<typename Geometry, typename Box, typename Strategy>
inline void envelope(Geometry const& geometry, Box& mbr, Strategy const& strategy)
{
- resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy);
+ resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, strategy);
}
/*!
@@ -193,7 +176,7 @@ inline void envelope(Geometry const& geometry, Box& mbr, Strategy const& strateg
template<typename Geometry, typename Box>
inline void envelope(Geometry const& geometry, Box& mbr)
{
- resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy());
+ resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, default_strategy());
}
@@ -219,7 +202,7 @@ template<typename Box, typename Geometry, typename Strategy>
inline Box return_envelope(Geometry const& geometry, Strategy const& strategy)
{
Box mbr;
- resolve_variant::envelope<Geometry>::apply(geometry, mbr, strategy);
+ resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, strategy);
return mbr;
}
@@ -242,7 +225,7 @@ template<typename Box, typename Geometry>
inline Box return_envelope(Geometry const& geometry)
{
Box mbr;
- resolve_variant::envelope<Geometry>::apply(geometry, mbr, default_strategy());
+ resolve_dynamic::envelope<Geometry>::apply(geometry, mbr, default_strategy());
return mbr;
}
diff --git a/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp b/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp
index 47937bf740..05127e0d23 100644
--- a/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp
+++ b/boost/geometry/algorithms/detail/envelope/intersects_antimeridian.hpp
@@ -19,7 +19,7 @@
#include <boost/geometry/algorithms/detail/normalize.hpp>
-namespace boost { namespace geometry
+namespace boost { namespace geometry
{
namespace detail { namespace envelope
@@ -38,7 +38,7 @@ struct intersects_antimeridian
<
CoordinateType, Units
> constants;
-
+
return
math::equals(math::abs(lat1), constants::max_latitude())
||
diff --git a/boost/geometry/algorithms/detail/envelope/range.hpp b/boost/geometry/algorithms/detail/envelope/range.hpp
index 068685b0ef..4692341e06 100644
--- a/boost/geometry/algorithms/detail/envelope/range.hpp
+++ b/boost/geometry/algorithms/detail/envelope/range.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2015-2020.
-// Modifications copyright (c) 2015-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015-2021.
+// Modifications copyright (c) 2015-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -28,7 +28,7 @@
#include <boost/range/end.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
-
+#include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
#include <boost/geometry/algorithms/detail/expand/box.hpp>
#include <boost/geometry/algorithms/detail/expand/point.hpp>
@@ -47,42 +47,10 @@ namespace detail { namespace envelope
// implementation for simple ranges
struct envelope_range
{
- template <typename Iterator, typename Box, typename Strategy>
- static inline void apply(Iterator it,
- Iterator last,
- Box& mbr,
- Strategy const& strategy)
- {
- typedef typename std::iterator_traits<Iterator>::value_type value_type;
-
- // initialize MBR
- initialize<Box, 0, dimension<Box>::value>::apply(mbr);
-
- if (it != last)
- {
- // initialize box with first element in range
- dispatch::envelope
- <
- value_type
- >::apply(*it, mbr, strategy);
-
- // consider now the remaining elements in the range (if any)
- for (++it; it != last; ++it)
- {
- dispatch::expand
- <
- Box, value_type
- >::apply(mbr, *it, strategy);
- }
- }
- }
-
- template <typename Range, typename Box, typename Strategy>
- static inline void apply(Range const& range, Box& mbr, Strategy const& strategy)
+ template <typename Range, typename Box, typename Strategies>
+ static inline void apply(Range const& range, Box& mbr, Strategies const& strategies)
{
- using strategy_t = decltype(strategy.envelope(range, mbr));
- return apply(strategy_t::begin(range), strategy_t::end(range),
- mbr, strategy);
+ strategies.envelope(range, mbr).apply(range, mbr);
}
};
@@ -91,35 +59,32 @@ struct envelope_range
template <typename EnvelopePolicy>
struct envelope_multi_range
{
- template <typename MultiRange, typename Box, typename Strategy>
+ template <typename MultiRange, typename Box, typename Strategies>
static inline void apply(MultiRange const& multirange,
Box& mbr,
- Strategy const& strategy)
+ Strategies const& strategies)
{
- using range_t = typename boost::range_value<MultiRange>::type;
- using strategy_t = decltype(strategy.envelope(std::declval<range_t>(), mbr));
- using state_t = typename strategy_t::template multi_state<Box>;
- apply<state_t>(boost::begin(multirange), boost::end(multirange), mbr, strategy);
+ using strategy_t = decltype(strategies.envelope(multirange, mbr));
+ apply<strategy_t>(multirange, mbr, strategies);
}
-private:
- template <typename State, typename Iter, typename Box, typename Strategy>
- static inline void apply(Iter it,
- Iter last,
+ template <typename Strategy, typename MultiRange, typename Box, typename Strategies>
+ static inline void apply(MultiRange const& multirange,
Box& mbr,
- Strategy const& strategy)
+ Strategies const& strategies)
{
- State state;
- for (; it != last; ++it)
+ typename Strategy::template state<Box> state;
+ auto const end = boost::end(multirange);
+ for (auto it = boost::begin(multirange); it != end; ++it)
{
if (! geometry::is_empty(*it))
{
Box helper_mbr;
- EnvelopePolicy::apply(*it, helper_mbr, strategy);
- state.apply(helper_mbr);
+ EnvelopePolicy::apply(*it, helper_mbr, strategies);
+ Strategy::apply(state, helper_mbr);
}
}
- state.result(mbr);
+ Strategy::result(state, mbr);
}
};
diff --git a/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp b/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp
index c55be03435..04032c6237 100644
--- a/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp
+++ b/boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp
@@ -59,7 +59,7 @@ public:
longitude_interval(T const& left, T const& right)
{
m_end[0] = left;
- m_end[1] = right;
+ m_end[1] = right;
}
template <std::size_t Index>
@@ -162,11 +162,6 @@ struct envelope_range_of_boxes_by_expansion
{
typedef typename boost::range_value<RangeOfBoxes>::type box_type;
- typedef typename boost::range_iterator
- <
- RangeOfBoxes const
- >::type iterator_type;
-
// first initialize MBR
detail::indexed_point_view<Box, min_corner> mbr_min(mbr);
detail::indexed_point_view<Box, max_corner> mbr_max(mbr);
@@ -194,7 +189,7 @@ struct envelope_range_of_boxes_by_expansion
>::apply(first_box_max, mbr_max);
// now expand using the remaining boxes
- iterator_type it = boost::begin(range_of_boxes);
+ auto it = boost::begin(range_of_boxes);
for (++it; it != boost::end(range_of_boxes); ++it)
{
detail::expand::indexed_loop
@@ -237,10 +232,6 @@ struct envelope_range_of_boxes
typedef typename boost::range_value<RangeOfBoxes>::type box_type;
typedef typename coordinate_type<box_type>::type coordinate_type;
typedef typename detail::cs_angular_units<box_type>::type units_type;
- typedef typename boost::range_iterator
- <
- RangeOfBoxes const
- >::type iterator_type;
static const bool is_equatorial = ! std::is_same
<
@@ -258,39 +249,40 @@ struct envelope_range_of_boxes
BOOST_GEOMETRY_ASSERT(! boost::empty(range_of_boxes));
- iterator_type it_min = std::min_element(boost::begin(range_of_boxes),
- boost::end(range_of_boxes),
- latitude_less<min_corner>());
- iterator_type it_max = std::max_element(boost::begin(range_of_boxes),
- boost::end(range_of_boxes),
- latitude_less<max_corner>());
+ auto const it_min = std::min_element(boost::begin(range_of_boxes),
+ boost::end(range_of_boxes),
+ latitude_less<min_corner>());
+ auto const it_max = std::max_element(boost::begin(range_of_boxes),
+ boost::end(range_of_boxes),
+ latitude_less<max_corner>());
coordinate_type const min_longitude = constants::min_longitude();
coordinate_type const max_longitude = constants::max_longitude();
coordinate_type const period = constants::period();
interval_range_type intervals;
- for (iterator_type it = boost::begin(range_of_boxes);
+ for (auto it = boost::begin(range_of_boxes);
it != boost::end(range_of_boxes);
++it)
{
- if (is_inverse_spheroidal_coordinates(*it))
+ auto const& box = *it;
+ if (is_inverse_spheroidal_coordinates(box))
{
continue;
}
- coordinate_type lat_min = geometry::get<min_corner, 1>(*it);
- coordinate_type lat_max = geometry::get<max_corner, 1>(*it);
+ coordinate_type lat_min = geometry::get<min_corner, 1>(box);
+ coordinate_type lat_max = geometry::get<max_corner, 1>(box);
if (math::equals(lat_min, constants::max_latitude())
|| math::equals(lat_max, constants::min_latitude()))
{
// if the box degenerates to the south or north pole
// just ignore it
continue;
- }
+ }
- coordinate_type lon_left = geometry::get<min_corner, 0>(*it);
- coordinate_type lon_right = geometry::get<max_corner, 0>(*it);
+ coordinate_type lon_left = geometry::get<min_corner, 0>(box);
+ coordinate_type lon_right = geometry::get<max_corner, 0>(box);
if (math::larger(lon_right, max_longitude))
{
diff --git a/boost/geometry/algorithms/detail/equals/collect_vectors.hpp b/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
index f2e1c7eb49..b908c3e535 100644
--- a/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
+++ b/boost/geometry/algorithms/detail/equals/collect_vectors.hpp
@@ -22,7 +22,6 @@
#include <boost/numeric/conversion/cast.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/normalize.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
@@ -39,7 +38,6 @@
#include <boost/geometry/views/detail/closed_clockwise_view.hpp>
-#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
#include <boost/geometry/strategies/normalize.hpp>
@@ -47,34 +45,17 @@
namespace boost { namespace geometry
{
-// Since these vectors (though ray would be a better name) are used in the
-// implementation of equals() for Areal geometries the internal representation
-// should be consistent with the side strategy.
-template
-<
- typename T,
- typename Geometry,
- typename SideStrategy,
- typename CSTag = typename cs_tag<Geometry>::type
->
-struct collected_vector
- : nyi::not_implemented_tag
-{};
-// compatible with side_by_triangle cartesian strategy
-template <typename T, typename Geometry, typename CT, typename CSTag>
-struct collected_vector
- <
- T, Geometry, strategy::side::side_by_triangle<CT>, CSTag
- >
+template <typename T>
+struct collected_vector_cartesian
{
typedef T type;
-
- inline collected_vector()
+
+ inline collected_vector_cartesian()
{}
- inline collected_vector(T const& px, T const& py,
- T const& pdx, T const& pdy)
+ inline collected_vector_cartesian(T const& px, T const& py,
+ T const& pdx, T const& pdy)
: x(px)
, y(py)
, dx(pdx)
@@ -84,7 +65,7 @@ struct collected_vector
{}
template <typename Point>
- inline collected_vector(Point const& p1, Point const& p2)
+ inline collected_vector_cartesian(Point const& p1, Point const& p2)
: x(get<0>(p1))
, y(get<1>(p1))
, dx(get<0>(p2) - x)
@@ -95,8 +76,7 @@ struct collected_vector
bool normalize()
{
- T magnitude = math::sqrt(
- boost::numeric_cast<T>(dx * dx + dy * dy));
+ T magnitude = math::sqrt(boost::numeric_cast<T>(dx * dx + dy * dy));
// NOTE: shouldn't here math::equals() be called?
if (magnitude > 0)
@@ -110,7 +90,7 @@ struct collected_vector
}
// For sorting
- inline bool operator<(collected_vector const& other) const
+ inline bool operator<(collected_vector_cartesian const& other) const
{
if (math::equals(x, other.x))
{
@@ -127,13 +107,13 @@ struct collected_vector
return x < other.x;
}
- inline bool next_is_collinear(collected_vector const& other) const
+ inline bool next_is_collinear(collected_vector_cartesian const& other) const
{
return same_direction(other);
}
// For std::equals
- inline bool operator==(collected_vector const& other) const
+ inline bool operator==(collected_vector_cartesian const& other) const
{
return math::equals(x, other.x)
&& math::equals(y, other.y)
@@ -141,7 +121,7 @@ struct collected_vector
}
private:
- inline bool same_direction(collected_vector const& other) const
+ inline bool same_direction(collected_vector_cartesian const& other) const
{
// For high precision arithmetic, we have to be
// more relaxed then using ==
@@ -159,38 +139,32 @@ private:
// Compatible with spherical_side_formula which currently
// is the default spherical_equatorial and geographic strategy
// so CSTag is spherical_equatorial_tag or geographic_tag
-template <typename T, typename Geometry, typename CT, typename CSTag>
-struct collected_vector
- <
- T, Geometry, strategy::side::spherical_side_formula<CT>, CSTag
- >
+template <typename T, typename Point>
+struct collected_vector_spherical
{
typedef T type;
-
- typedef typename geometry::detail::cs_angular_units<Geometry>::type units_type;
- typedef model::point<T, 2, cs::spherical_equatorial<units_type> > point_type;
+
typedef model::point<T, 3, cs::cartesian> vector_type;
- collected_vector()
+ collected_vector_spherical()
{}
- template <typename Point>
- collected_vector(Point const& p1, Point const& p2)
+ collected_vector_spherical(Point const& p1, Point const& p2)
: origin(get<0>(p1), get<1>(p1))
{
- origin = detail::return_normalized<point_type>(
+ origin = detail::return_normalized<Point>(
origin,
strategy::normalize::spherical_point());
using namespace geometry::formula;
prev = sph_to_cart3d<vector_type>(p1);
next = sph_to_cart3d<vector_type>(p2);
- direction = cross_product(prev, next);
+ cross = direction = cross_product(prev, next);
}
bool normalize()
{
- T magnitude_sqr = dot_product(direction, direction);
+ T const magnitude_sqr = dot_product(direction, direction);
// NOTE: shouldn't here math::equals() be called?
if (magnitude_sqr > 0)
@@ -202,7 +176,7 @@ struct collected_vector
return false;
}
- bool operator<(collected_vector const& other) const
+ bool operator<(collected_vector_spherical const& other) const
{
if (math::equals(get<0>(origin), get<0>(other.origin)))
{
@@ -226,13 +200,13 @@ struct collected_vector
// For consistency with side and intersection strategies used by relops
// IMPORTANT: this method should be called for previous vector
// and next vector should be passed as parameter
- bool next_is_collinear(collected_vector const& other) const
+ bool next_is_collinear(collected_vector_spherical const& other) const
{
- return formula::sph_side_value(direction, other.next) == 0;
+ return formula::sph_side_value(cross, other.next) == 0;
}
// For std::equals
- bool operator==(collected_vector const& other) const
+ bool operator==(collected_vector_spherical const& other) const
{
return math::equals(get<0>(origin), get<0>(other.origin))
&& math::equals(get<1>(origin), get<1>(other.origin))
@@ -241,76 +215,57 @@ struct collected_vector
private:
// For consistency with side and intersection strategies used by relops
- bool is_collinear(collected_vector const& other) const
+ // NOTE: alternative would be to equal-compare direction's coordinates
+ // or to check if dot product of directions is equal to 1.
+ bool is_collinear(collected_vector_spherical const& other) const
{
- return formula::sph_side_value(direction, other.prev) == 0
- && formula::sph_side_value(direction, other.next) == 0;
+ return formula::sph_side_value(cross, other.prev) == 0
+ && formula::sph_side_value(cross, other.next) == 0;
}
-
- /*bool same_direction(collected_vector const& other) const
- {
- return math::equals_with_epsilon(get<0>(direction), get<0>(other.direction))
- && math::equals_with_epsilon(get<1>(direction), get<1>(other.direction))
- && math::equals_with_epsilon(get<2>(direction), get<2>(other.direction));
- }*/
- point_type origin; // used for sorting and equality check
+ Point origin; // used for sorting and equality check
vector_type direction; // used for sorting, only in operator<
+ vector_type cross; // used for sorting, used for collinearity check
vector_type prev; // used for collinearity check, only in operator==
vector_type next; // used for collinearity check
};
-// Specialization for spherical polar
-template <typename T, typename Geometry, typename CT>
-struct collected_vector
- <
- T, Geometry,
- strategy::side::spherical_side_formula<CT>,
- spherical_polar_tag
- >
- : public collected_vector
- <
- T, Geometry,
- strategy::side::spherical_side_formula<CT>,
- spherical_equatorial_tag
- >
+// Version for spherical polar
+template <typename T, typename Point>
+struct collected_vector_polar
+ : public collected_vector_spherical<T, Point>
{
- typedef collected_vector
- <
- T, Geometry,
- strategy::side::spherical_side_formula<CT>,
- spherical_equatorial_tag
- > base_type;
+ using type = T;
+ using base_point_type
+ = model::point<T, 2, cs::spherical_equatorial<geometry::degree>>;
+ using base_type = collected_vector_spherical<T, base_point_type>;
- collected_vector() {}
+ collected_vector_polar() {}
- template <typename Point>
- collected_vector(Point const& p1, Point const& p2)
+ collected_vector_polar(Point const& p1, Point const& p2)
: base_type(to_equatorial(p1), to_equatorial(p2))
{}
private:
- template <typename Point>
- Point to_equatorial(Point const& p)
+ static base_point_type to_equatorial(Point const& p)
{
- typedef typename coordinate_type<Point>::type coord_type;
-
- typedef math::detail::constants_on_spheroid
+ using coord_type = typename coordinate_type<Point>::type;
+ using constants = math::detail::constants_on_spheroid
<
coord_type,
typename coordinate_system<Point>::type::units
- > constants;
+ > ;
- coord_type const pi_2 = constants::half_period() / 2;
+ constexpr coord_type pi_2 = constants::half_period() / 2;
- Point res = p;
+ base_point_type res;
+ set<0>(res, get<0>(p));
set<1>(res, pi_2 - get<1>(p));
return res;
}
};
-
-// TODO: specialize collected_vector for geographic_tag
+// TODO: implement collected_vector type for geographic
#ifndef DOXYGEN_NO_DETAIL
@@ -339,15 +294,11 @@ private:
return;
}
- typedef typename boost::range_size<Collection>::type collection_size_t;
- collection_size_t c_old_size = boost::size(collection);
-
- typedef typename boost::range_iterator<ClosedClockwiseRange const>::type iterator;
-
+ auto c_old_size = boost::size(collection);
bool is_first = true;
- iterator it = boost::begin(range);
+ auto it = boost::begin(range);
- for (iterator prev = it++; it != boost::end(range); prev = it++)
+ for (auto prev = it++; it != boost::end(range); prev = it++)
{
typename boost::range_value<Collection>::type v(*prev, *it);
@@ -366,13 +317,10 @@ private:
}
// If first one has same direction as last one, remove first one
- collection_size_t collected_count = boost::size(collection) - c_old_size;
- if ( collected_count > 1 )
+ if (boost::size(collection) > c_old_size + 1)
{
- typedef typename boost::range_iterator<Collection>::type c_iterator;
- c_iterator first = range::pos(collection, c_old_size);
-
- if (collection.back().next_is_collinear(*first) )
+ auto first = range::pos(collection, c_old_size);
+ if (collection.back().next_is_collinear(*first))
{
//collection.erase(first);
// O(1) instead of O(N)
@@ -451,10 +399,8 @@ struct polygon_collect_vectors
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 (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ auto const& rings = interior_rings(polygon);
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
per_range::apply(collection, *it);
}
@@ -467,10 +413,7 @@ 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)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
SinglePolicy::apply(collection, *it);
}
diff --git a/boost/geometry/algorithms/detail/equals/implementation.hpp b/boost/geometry/algorithms/detail/equals/implementation.hpp
index e66a8a77ac..2f803f3658 100644
--- a/boost/geometry/algorithms/detail/equals/implementation.hpp
+++ b/boost/geometry/algorithms/detail/equals/implementation.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -36,8 +36,8 @@
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/equals/collect_vectors.hpp>
#include <boost/geometry/algorithms/detail/equals/interface.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
-#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/strategies/relate/cartesian.hpp>
#include <boost/geometry/strategies/relate/geographic.hpp>
@@ -160,26 +160,32 @@ struct length_check
*/
-template <typename Geometry1, typename Geometry2, typename Strategy>
-struct collected_vector
+// Small helper structure do decide to use collect_vectors, or not
+template <typename Strategy, typename CsTag>
+struct use_collect_vectors
{
- typedef typename geometry::select_most_precise
- <
- typename select_coordinate_type
- <
- Geometry1, Geometry2
- >::type,
- double
- >::type calculation_type;
+ static constexpr bool value = false;
+};
- typedef geometry::collected_vector
- <
- calculation_type,
- Geometry1,
- decltype(std::declval<Strategy>().side())
- > type;
+template <typename Strategy>
+struct use_collect_vectors<Strategy, cartesian_tag>
+{
+ static constexpr bool value = true;
+
+ template <typename T, typename Point>
+ using type = collected_vector_cartesian<T>;
};
+template <typename CV>
+struct use_collect_vectors<strategy::side::spherical_side_formula<CV>, spherical_tag>
+{
+ static constexpr bool value = true;
+
+ template <typename T, typename Point>
+ using type = collected_vector_spherical<T, Point>;
+};
+
+
template <typename TrivialCheck>
struct equals_by_collection
{
@@ -193,10 +199,24 @@ struct equals_by_collection
return false;
}
- typedef typename collected_vector
+ using calculation_type = typename geometry::select_most_precise
+ <
+ typename select_coordinate_type
+ <
+ Geometry1, Geometry2
+ >::type,
+ double
+ >::type;
+
+ using collected_vector_type = typename use_collect_vectors
<
- Geometry1, Geometry2, Strategy
- >::type collected_vector_type;
+ decltype(std::declval<Strategy>().side()),
+ typename Strategy::cs_tag
+ >::template type
+ <
+ calculation_type,
+ typename geometry::point_type<Geometry1>::type
+ >;
std::vector<collected_vector_type> c1, c2;
@@ -211,7 +231,7 @@ struct equals_by_collection
std::sort(c1.begin(), c1.end());
std::sort(c2.begin(), c2.end());
- // Just check if these vectors are equal.
+ // Check if these vectors are equal.
return std::equal(c1.begin(), c1.end(), c2.begin());
}
};
@@ -226,47 +246,40 @@ struct equals_by_relate
>
{};
-// If collect_vectors which is a SideStrategy-dispatched optimization
-// is implemented in a way consistent with the Intersection/Side Strategy
-// then collect_vectors is used, otherwise relate is used.
+// Use either collect_vectors or relate
// NOTE: the result could be conceptually different for invalid
// geometries in different coordinate systems because collect_vectors
// and relate treat invalid geometries differently.
template<typename TrivialCheck>
struct equals_by_collection_or_relate
{
- template <typename Geometry1, typename Geometry2, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- typedef std::is_base_of
- <
- nyi::not_implemented_tag,
- typename collected_vector
- <
- Geometry1, Geometry2, Strategy
- >::type
- > enable_relate_type;
-
- return apply(geometry1, geometry2, strategy, enable_relate_type());
- }
+ template <typename Strategy>
+ using use_vectors = use_collect_vectors
+ <
+ decltype(std::declval<Strategy>().side()),
+ typename Strategy::cs_tag
+ >;
-private:
- template <typename Geometry1, typename Geometry2, typename Strategy>
+ template
+ <
+ typename Geometry1, typename Geometry2, typename Strategy,
+ std::enable_if_t<use_vectors<Strategy>::value, int> = 0
+ >
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
- Strategy const& strategy,
- std::false_type /*enable_relate*/)
+ Strategy const& strategy)
{
return equals_by_collection<TrivialCheck>::apply(geometry1, geometry2, strategy);
}
- template <typename Geometry1, typename Geometry2, typename Strategy>
+ template
+ <
+ typename Geometry1, typename Geometry2, typename Strategy,
+ std::enable_if_t<! use_vectors<Strategy>::value, int> = 0
+ >
static inline bool apply(Geometry1 const& geometry1,
Geometry2 const& geometry2,
- Strategy const& strategy,
- std::true_type /*enable_relate*/)
+ Strategy const& strategy)
{
return equals_by_relate<Geometry1, Geometry2>::apply(geometry1, geometry2, strategy);
}
@@ -376,7 +389,7 @@ struct equals
<
MultiPolygon1, MultiPolygon2,
multi_polygon_tag, multi_polygon_tag,
- areal_tag, areal_tag,
+ areal_tag, areal_tag,
2,
Reverse
>
@@ -389,7 +402,7 @@ struct equals
<
Polygon, MultiPolygon,
polygon_tag, multi_polygon_tag,
- areal_tag, areal_tag,
+ areal_tag, areal_tag,
2,
Reverse
>
@@ -401,7 +414,7 @@ struct equals
<
MultiPolygon, Ring,
multi_polygon_tag, ring_tag,
- areal_tag, areal_tag,
+ areal_tag, areal_tag,
2,
Reverse
>
diff --git a/boost/geometry/algorithms/detail/equals/implementation_gc.hpp b/boost/geometry/algorithms/detail/equals/implementation_gc.hpp
new file mode 100644
index 0000000000..81424e0468
--- /dev/null
+++ b/boost/geometry/algorithms/detail/equals/implementation_gc.hpp
@@ -0,0 +1,114 @@
+// Boost.Geometry
+
+// Copyright (c) 2022 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// 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_IMPLEMENTATION_GC_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_GC_HPP
+
+
+#include <boost/geometry/algorithms/detail/equals/implementation.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation_gc.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Geometry1, typename Geometry2, std::size_t DimensionCount>
+struct equals
+ <
+ Geometry1, Geometry2,
+ geometry_collection_tag, geometry_collection_tag,
+ geometry_collection_tag, geometry_collection_tag,
+ DimensionCount, false
+ >
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ return detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_equals_type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
+ }
+};
+
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1, typename CastedTag1,
+ std::size_t DimensionCount
+>
+struct equals
+ <
+ Geometry1, Geometry2,
+ Tag1, geometry_collection_tag,
+ CastedTag1, geometry_collection_tag,
+ DimensionCount, false
+ >
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ using gc1_view_t = detail::geometry_collection_view<Geometry1>;
+ return equals
+ <
+ gc1_view_t, Geometry2
+ >::apply(gc1_view_t(geometry1), geometry2, strategy);
+ }
+};
+
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag2, typename CastedTag2,
+ std::size_t DimensionCount
+>
+struct equals
+ <
+ Geometry1, Geometry2,
+ geometry_collection_tag, Tag2,
+ geometry_collection_tag, CastedTag2,
+ DimensionCount, false
+ >
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ using gc2_view_t = detail::geometry_collection_view<Geometry2>;
+ return equals
+ <
+ Geometry1, gc2_view_t
+ >::apply(geometry1, gc2_view_t(geometry2), strategy);
+ }
+};
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_EQUALS_IMPLEMENTATION_GC_HPP
diff --git a/boost/geometry/algorithms/detail/equals/interface.hpp b/boost/geometry/algorithms/detail/equals/interface.hpp
index bd31e8c2c4..f0c4438430 100644
--- a/boost/geometry/algorithms/detail/equals/interface.hpp
+++ b/boost/geometry/algorithms/detail/equals/interface.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -23,15 +23,12 @@
#include <cstddef>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
@@ -157,9 +154,14 @@ struct equals<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant {
+namespace resolve_dynamic {
-template <typename Geometry1, typename Geometry2>
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct equals
{
template <typename Strategy>
@@ -180,114 +182,67 @@ struct equals
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct equals<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct equals<Geometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Strategy>
- struct visitor: static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Strategy const& strategy)
- : m_geometry2(geometry2)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- inline bool operator()(Geometry1 const& geometry1) const
+ bool result = false;
+ traits::visit<Geometry1>::apply([&](auto const& g1)
{
- return equals<Geometry1, Geometry2>
- ::apply(geometry1, m_geometry2, m_strategy);
- }
-
- };
-
- template <typename Strategy>
- static inline bool apply(
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy
- )
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
+ result = equals
+ <
+ util::remove_cref_t<decltype(g1)>,
+ Geometry2
+ >::apply(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct equals<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct equals<Geometry1, Geometry2, Tag1, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Strategy const& strategy)
- : m_geometry1(geometry1)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- inline bool operator()(Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry2>::apply([&](auto const& g2)
{
- return equals<Geometry1, Geometry2>
- ::apply(m_geometry1, geometry2, m_strategy);
- }
-
- };
-
- template <typename Strategy>
- static inline bool apply(
- Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy
- )
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
+ result = equals
+ <
+ Geometry1,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
}
};
-template <
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
-struct equals<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
->
+template <typename Geometry1, typename Geometry2>
+struct equals<Geometry1, Geometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy)
- : m_strategy(strategy)
- {}
-
- template <typename Geometry1, typename Geometry2>
- inline bool operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry1, Geometry2>::apply([&](auto const& g1, auto const& g2)
{
- return equals<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, m_strategy);
- }
-
- };
-
- template <typename Strategy>
- static inline bool apply(
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy
- )
- {
- return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
+ result = equals
+ <
+ util::remove_cref_t<decltype(g1)>,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -314,10 +269,10 @@ inline bool equals(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
- return resolve_variant::equals
- <
- Geometry1, Geometry2
- >::apply(geometry1, geometry2, strategy);
+ return resolve_dynamic::equals
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, strategy);
}
@@ -340,8 +295,10 @@ inline bool equals(Geometry1 const& geometry1,
template <typename Geometry1, typename Geometry2>
inline bool equals(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- return resolve_variant::equals<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, default_strategy());
+ return resolve_dynamic::equals
+ <
+ Geometry1, Geometry2
+ >::apply(geometry1, geometry2, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/expand/indexed.hpp b/boost/geometry/algorithms/detail/expand/indexed.hpp
index 08463689de..92d701d16e 100644
--- a/boost/geometry/algorithms/detail/expand/indexed.hpp
+++ b/boost/geometry/algorithms/detail/expand/indexed.hpp
@@ -61,7 +61,7 @@ struct indexed_loop
std::less<coordinate_type> less;
std::greater<coordinate_type> greater;
-
+
if (less(coord, get<min_corner, Dimension>(box)))
{
set<min_corner, Dimension>(box, coord);
diff --git a/boost/geometry/algorithms/detail/expand/interface.hpp b/boost/geometry/algorithms/detail/expand/interface.hpp
index 442a4e011f..6552c266e4 100644
--- a/boost/geometry/algorithms/detail/expand/interface.hpp
+++ b/boost/geometry/algorithms/detail/expand/interface.hpp
@@ -22,22 +22,23 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_EXPAND_INTERFACE_HPP
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/dispatch/expand.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/expand/services.hpp>
+#include <boost/geometry/util/type_traits_std.hpp>
+
namespace boost { namespace geometry
{
@@ -97,10 +98,10 @@ struct expand<default_strategy, false>
} //namespace resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-
-template <typename Geometry>
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct expand
{
template <typename Box, typename Strategy>
@@ -111,72 +112,28 @@ struct expand
concepts::check<Box>();
concepts::check<Geometry const>();
concepts::check_concepts_and_equal_dimensions<Box, Geometry const>();
-
+
resolve_strategy::expand<Strategy>::apply(box, geometry, strategy);
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct expand<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct expand<Geometry, dynamic_geometry_tag>
{
- template <typename Box, typename Strategy>
- struct visitor: boost::static_visitor<void>
- {
- Box& m_box;
- Strategy const& m_strategy;
-
- visitor(Box& box, Strategy const& strategy)
- : m_box(box)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry>
- void operator()(Geometry const& geometry) const
- {
- return expand<Geometry>::apply(m_box, geometry, m_strategy);
- }
- };
-
template <class Box, typename Strategy>
- static inline void
- apply(Box& box,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- Strategy const& strategy)
+ static inline void apply(Box& box,
+ Geometry const& geometry,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Box, Strategy>(box, strategy),
- geometry);
+ traits::visit<Geometry>::apply([&](auto const& g)
+ {
+ expand<util::remove_cref_t<decltype(g)>>::apply(box, g, strategy);
+ }, geometry);
}
};
-
-} // namespace resolve_variant
-
-
-/***
-*!
-\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)
-{
- concepts::check_concepts_and_equal_dimensions<Box, Geometry const>();
- dispatch::expand<Box, Geometry>::apply(box, geometry);
-}
-***/
+} // namespace resolve_dynamic
+
/*!
\brief Expands (with strategy)
@@ -195,7 +152,7 @@ will be added to the box
template <typename Box, typename Geometry, typename Strategy>
inline void expand(Box& box, Geometry const& geometry, Strategy const& strategy)
{
- resolve_variant::expand<Geometry>::apply(box, geometry, strategy);
+ resolve_dynamic::expand<Geometry>::apply(box, geometry, strategy);
}
/*!
@@ -213,7 +170,7 @@ added to the box
template <typename Box, typename Geometry>
inline void expand(Box& box, Geometry const& geometry)
{
- resolve_variant::expand<Geometry>::apply(box, geometry, default_strategy());
+ resolve_dynamic::expand<Geometry>::apply(box, geometry, default_strategy());
}
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/expand_by_epsilon.hpp b/boost/geometry/algorithms/detail/expand_by_epsilon.hpp
index 3e41b71ff9..ae07f5bb0a 100644
--- a/boost/geometry/algorithms/detail/expand_by_epsilon.hpp
+++ b/boost/geometry/algorithms/detail/expand_by_epsilon.hpp
@@ -44,7 +44,7 @@ struct corner_by_epsilon
typedef typename coordinate_type<Point>::type coord_type;
coord_type const coord = get<I>(point);
coord_type const seps = math::scaled_epsilon(coord);
-
+
set<I>(point, PlusOrMinus<coord_type>()(coord, seps));
corner_by_epsilon<Point, PlusOrMinus, I+1>::apply(point);
diff --git a/boost/geometry/algorithms/detail/extreme_points.hpp b/boost/geometry/algorithms/detail/extreme_points.hpp
index a6605fd45d..2ac13fc1ed 100644
--- a/boost/geometry/algorithms/detail/extreme_points.hpp
+++ b/boost/geometry/algorithms/detail/extreme_points.hpp
@@ -26,7 +26,6 @@
#include <boost/range/value_type.hpp>
#include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/arithmetic/arithmetic.hpp>
@@ -124,7 +123,6 @@ struct extreme_points_on_ring
{
typedef typename geometry::coordinate_type<Ring>::type coordinate_type;
- typedef typename boost::range_iterator<Ring const>::type range_iterator;
typedef typename geometry::point_type<Ring>::type point_type;
template <typename CirclingIterator, typename Points>
@@ -288,8 +286,7 @@ struct extreme_points_on_ring
template <typename Iterator, typename SideStrategy>
static inline bool right_turn(Ring const& ring, Iterator it, SideStrategy const& strategy)
{
- typename std::iterator_traits<Iterator>::difference_type const index
- = std::distance(boost::begin(ring), it);
+ auto const index = std::distance(boost::begin(ring), it);
geometry::ever_circling_range_iterator<Ring const> left(ring);
geometry::ever_circling_range_iterator<Ring const> right(ring);
left += index;
@@ -326,9 +323,9 @@ struct extreme_points_on_ring
// Get all maxima, usually one. In case of self-tangencies, or self-crossings,
// the max might be is not valid. A valid max should make a right turn
- range_iterator max_it = boost::begin(ring);
+ auto max_it = boost::begin(ring);
compare<Dimension> smaller;
- for (range_iterator it = max_it + 1; it != boost::end(ring); ++it)
+ for (auto it = max_it + 1; it != boost::end(ring); ++it)
{
if (smaller(*max_it, *it) && right_turn(ring, it, strategy))
{
@@ -341,8 +338,7 @@ struct extreme_points_on_ring
return false;
}
- typename std::iterator_traits<range_iterator>::difference_type const
- index = std::distance(boost::begin(ring), max_it);
+ auto const index = std::distance(boost::begin(ring), max_it);
//std::cout << "Extreme point lies at " << index << " having " << geometry::wkt(*max_it) << std::endl;
geometry::ever_circling_range_iterator<Ring const> left(ring);
@@ -429,10 +425,8 @@ struct extreme_points<Polygon, Dimension, polygon_tag>
}
// For a polygon, its interior rings can contain intruders
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(polygon);
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ auto const& rings = interior_rings(polygon);
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
ring_implementation::get_intruders(*it, extremes, intruders, strategy);
}
diff --git a/boost/geometry/algorithms/detail/gc_group_elements.hpp b/boost/geometry/algorithms/detail/gc_group_elements.hpp
new file mode 100644
index 0000000000..c1c26ec9c6
--- /dev/null
+++ b/boost/geometry/algorithms/detail/gc_group_elements.hpp
@@ -0,0 +1,196 @@
+// Boost.Geometry
+
+// Copyright (c) 2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_GROUP_ELEMENTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_GROUP_ELEMENTS_HPP
+
+
+#include <array>
+#include <deque>
+#include <map>
+#include <set>
+#include <vector>
+
+#include <boost/range/begin.hpp>
+#include <boost/range/size.hpp>
+
+#include <boost/geometry/algorithms/detail/gc_make_rtree.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
+#include <boost/geometry/core/topological_dimension.hpp>
+#include <boost/geometry/views/detail/random_access_view.hpp>
+
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+struct gc_element_id
+{
+ gc_element_id(unsigned int source_id_, std::size_t gc_id_)
+ : source_id(source_id_), gc_id(gc_id_)
+ {}
+
+ unsigned int source_id;
+ std::size_t gc_id;
+
+ friend bool operator<(gc_element_id const& left, gc_element_id const& right)
+ {
+ return left.source_id < right.source_id
+ || (left.source_id == right.source_id && left.gc_id < right.gc_id);
+ }
+};
+
+template <typename GC1View, typename GC2View, typename Strategy, typename IntersectingFun, typename DisjointFun>
+inline void gc_group_elements(GC1View const& gc1_view, GC2View const& gc2_view, Strategy const& strategy,
+ IntersectingFun&& intersecting_fun,
+ DisjointFun&& disjoint_fun,
+ bool const group_self = false)
+{
+ // NOTE: gc_make_rtree_indexes() already checks for random-access,
+ // non-recursive geometry collections.
+
+ // NOTE: could be replaced with unordered_map and unordered_set
+ std::map<gc_element_id, std::set<gc_element_id>> adjacent;
+
+ // Create adjacency list based on intersecting envelopes of GC elements
+ auto const rtree2 = gc_make_rtree_indexes(gc2_view, strategy);
+ if (! group_self) // group only elements from the other GC?
+ {
+ for (std::size_t i = 0; i < boost::size(gc1_view); ++i)
+ {
+ traits::iter_visit<GC1View>::apply([&](auto const& g1)
+ {
+ using g1_t = util::remove_cref_t<decltype(g1)>;
+ using box1_t = gc_make_rtree_box_t<g1_t>;
+ box1_t b1 = geometry::return_envelope<box1_t>(g1, strategy);
+ detail::expand_by_epsilon(b1);
+
+ gc_element_id id1 = {0, i};
+ for (auto qit = rtree2.qbegin(index::intersects(b1)); qit != rtree2.qend(); ++qit)
+ {
+ gc_element_id id2 = {1, qit->second};
+ adjacent[id1].insert(id2);
+ adjacent[id2].insert(id1);
+ }
+ }, boost::begin(gc1_view) + i);
+ }
+ }
+ else // group elements from the same GCs and the other GC
+ {
+ auto const rtree1 = gc_make_rtree_indexes(gc1_view, strategy);
+ for (auto it1 = rtree1.begin() ; it1 != rtree1.end() ; ++it1)
+ {
+ auto const b1 = it1->first;
+ gc_element_id id1 = {0, it1->second};
+ for (auto qit2 = rtree2.qbegin(index::intersects(b1)); qit2 != rtree2.qend(); ++qit2)
+ {
+ gc_element_id id2 = {1, qit2->second};
+ adjacent[id1].insert(id2);
+ adjacent[id2].insert(id1);
+ }
+ for (auto qit1 = rtree1.qbegin(index::intersects(b1)); qit1 != rtree1.qend(); ++qit1)
+ {
+ if (id1.gc_id != qit1->second)
+ {
+ gc_element_id id11 = {0, qit1->second};
+ adjacent[id1].insert(id11);
+ adjacent[id11].insert(id1);
+ }
+ }
+ }
+ for (auto it2 = rtree2.begin(); it2 != rtree2.end(); ++it2)
+ {
+ auto const b2 = it2->first;
+ gc_element_id id2 = {1, it2->second};
+ for (auto qit2 = rtree2.qbegin(index::intersects(b2)); qit2 != rtree2.qend(); ++qit2)
+ {
+ if (id2.gc_id != qit2->second)
+ {
+ gc_element_id id22 = {1, qit2->second};
+ adjacent[id2].insert(id22);
+ adjacent[id22].insert(id2);
+ }
+ }
+ }
+ }
+
+ // Traverse the graph and build connected groups i.e. groups of intersecting envelopes
+ std::deque<gc_element_id> queue;
+ std::array<std::vector<bool>, 2> visited = {
+ std::vector<bool>(boost::size(gc1_view), false),
+ std::vector<bool>(boost::size(gc2_view), false)
+ };
+ for (auto const& elem : adjacent)
+ {
+ std::vector<gc_element_id> group;
+ if (! visited[elem.first.source_id][elem.first.gc_id])
+ {
+ queue.push_back(elem.first);
+ visited[elem.first.source_id][elem.first.gc_id] = true;
+ group.push_back(elem.first);
+ while (! queue.empty())
+ {
+ gc_element_id e = queue.front();
+ queue.pop_front();
+ for (auto const& n : adjacent[e])
+ {
+ if (! visited[n.source_id][n.gc_id])
+ {
+ queue.push_back(n);
+ visited[n.source_id][n.gc_id] = true;
+ group.push_back(n);
+ }
+ }
+ }
+ }
+ if (! group.empty())
+ {
+ if (! intersecting_fun(group))
+ {
+ return;
+ }
+ }
+ }
+
+ {
+ std::vector<gc_element_id> group;
+ for (std::size_t i = 0; i < visited[0].size(); ++i)
+ {
+ if (! visited[0][i])
+ {
+ group.emplace_back(0, i);
+ }
+ }
+ for (std::size_t i = 0; i < visited[1].size(); ++i)
+ {
+ if (! visited[1][i])
+ {
+ group.emplace_back(1, i);
+ }
+ }
+ if (! group.empty())
+ {
+ disjoint_fun(group);
+ }
+ }
+}
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_GROUP_ELEMENTS_HPP
diff --git a/boost/geometry/algorithms/detail/gc_make_rtree.hpp b/boost/geometry/algorithms/detail/gc_make_rtree.hpp
new file mode 100644
index 0000000000..c1c00d4692
--- /dev/null
+++ b/boost/geometry/algorithms/detail/gc_make_rtree.hpp
@@ -0,0 +1,118 @@
+// Boost.Geometry
+
+// Copyright (c) 2022, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_MAKE_RTREE_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_MAKE_RTREE_HPP
+
+#include <vector>
+
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/size.hpp>
+
+#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
+#include <boost/geometry/algorithms/envelope.hpp>
+#include <boost/geometry/index/rtree.hpp>
+#include <boost/geometry/strategies/index/services.hpp>
+#include <boost/geometry/views/detail/random_access_view.hpp>
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template <typename GC>
+using gc_make_rtree_box_t = geometry::model::box
+ <
+ geometry::model::point
+ <
+ typename geometry::coordinate_type<GC>::type,
+ geometry::dimension<GC>::value,
+ typename geometry::coordinate_system<GC>::type
+ >
+ >;
+
+
+template <typename GC, typename Strategy>
+inline auto gc_make_rtree_iterators(GC& gc, Strategy const& strategy)
+{
+ using box_t = gc_make_rtree_box_t<GC>;
+ using iter_t = typename boost::range_iterator<GC>::type;
+
+ using rtree_param_t = index::rstar<4>;
+ using rtree_parameters_t = index::parameters<rtree_param_t, Strategy>;
+ using value_t = std::pair<box_t, iter_t>;
+ using rtree_t = index::rtree<value_t, rtree_parameters_t>;
+
+ // TODO: get rid of the temporary vector
+ auto const size = boost::size(gc);
+ std::vector<value_t> values;
+ values.reserve(size);
+
+ visit_breadth_first_impl<true>::apply([&](auto const& g, auto iter)
+ {
+ box_t b = geometry::return_envelope<box_t>(g, strategy);
+ detail::expand_by_epsilon(b);
+ values.emplace_back(b, iter);
+ return true;
+ }, gc);
+
+ return rtree_t(values.begin(), values.end(), rtree_parameters_t(rtree_param_t(), strategy));
+}
+
+
+template <typename GCView, typename Strategy>
+inline auto gc_make_rtree_indexes(GCView const& gc, Strategy const& strategy)
+{
+ // Alternatively only take random_access_view<GC>
+ static const bool is_random_access = is_random_access_range<GCView>::value;
+ static const bool is_not_recursive = ! is_geometry_collection_recursive<GCView>::value;
+ BOOST_GEOMETRY_STATIC_ASSERT((is_random_access && is_not_recursive),
+ "This algorithm requires random-access, non-recursive geometry collection or view.",
+ GCView);
+
+ using box_t = gc_make_rtree_box_t<GCView>;
+
+ using rtree_param_t = index::rstar<4>;
+ using rtree_parameters_t = index::parameters<rtree_param_t, Strategy>;
+ using value_t = std::pair<box_t, std::size_t>;
+ using rtree_t = index::rtree<value_t, rtree_parameters_t>;
+
+ // TODO: get rid of the temporary vector
+ std::size_t const size = boost::size(gc);
+ std::vector<value_t> values;
+ values.reserve(size);
+
+ auto const begin = boost::begin(gc);
+ for (std::size_t i = 0; i < size; ++i)
+ {
+ traits::iter_visit<GCView>::apply([&](auto const& g)
+ {
+ box_t b = geometry::return_envelope<box_t>(g, strategy);
+ detail::expand_by_epsilon(b);
+ values.emplace_back(b, i);
+ }, begin + i);
+ }
+
+ return rtree_t(values.begin(), values.end(), rtree_parameters_t(rtree_param_t(), strategy));
+}
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_MAKE_RTREE_HPP
diff --git a/boost/geometry/algorithms/detail/gc_topological_dimension.hpp b/boost/geometry/algorithms/detail/gc_topological_dimension.hpp
new file mode 100644
index 0000000000..49f017945c
--- /dev/null
+++ b/boost/geometry/algorithms/detail/gc_topological_dimension.hpp
@@ -0,0 +1,51 @@
+// Boost.Geometry
+
+// Copyright (c) 2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_TOPOLOGICAL_DIMENSION_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_TOPOLOGICAL_DIMENSION_HPP
+
+
+#include <algorithm>
+
+#include <boost/geometry/algorithms/detail/visit.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
+#include <boost/geometry/core/topological_dimension.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template <typename GeometryCollection>
+inline int gc_topological_dimension(GeometryCollection const& geometry)
+{
+ int result = -1;
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ if (! geometry::is_empty(g))
+ {
+ static const int d = geometry::topological_dimension<decltype(g)>::value;
+ result = (std::max)(result, d);
+ }
+ return result >= 2;
+ }, geometry);
+ return result;
+}
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_GC_TOPOLOGICAL_DIMENSION_HPP
diff --git a/boost/geometry/algorithms/detail/has_self_intersections.hpp b/boost/geometry/algorithms/detail/has_self_intersections.hpp
index 805ab6754a..0b13eb7bda 100644
--- a/boost/geometry/algorithms/detail/has_self_intersections.hpp
+++ b/boost/geometry/algorithms/detail/has_self_intersections.hpp
@@ -91,10 +91,8 @@ inline bool has_self_intersections(Geometry const& geometry,
#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)
+ for (auto const& info : turns)
{
- 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;
diff --git a/boost/geometry/algorithms/detail/interior_iterator.hpp b/boost/geometry/algorithms/detail/interior_iterator.hpp
index 3582773c3d..1a9d4f1922 100644
--- a/boost/geometry/algorithms/detail/interior_iterator.hpp
+++ b/boost/geometry/algorithms/detail/interior_iterator.hpp
@@ -31,7 +31,7 @@ struct interior_iterator
{
typedef typename boost::range_iterator
<
- typename geometry::interior_type<Geometry>::type
+ typename geometry::interior_type<Geometry>::type
>::type type;
};
diff --git a/boost/geometry/algorithms/detail/intersection/areal_areal.hpp b/boost/geometry/algorithms/detail/intersection/areal_areal.hpp
index 9faa1df55c..e657f825f2 100644
--- a/boost/geometry/algorithms/detail/intersection/areal_areal.hpp
+++ b/boost/geometry/algorithms/detail/intersection/areal_areal.hpp
@@ -155,7 +155,7 @@ struct intersection_areal_areal_<TupledOut, tupled_output_tag>
pointlike::get(geometry_out),
strategy);
}
-
+
return;
}
diff --git a/boost/geometry/algorithms/detail/intersection/gc.hpp b/boost/geometry/algorithms/detail/intersection/gc.hpp
new file mode 100644
index 0000000000..fa492c0f34
--- /dev/null
+++ b/boost/geometry/algorithms/detail/intersection/gc.hpp
@@ -0,0 +1,329 @@
+// Boost.Geometry
+
+// Copyright (c) 2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_GC_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_GC_HPP
+
+
+#include <tuple>
+
+#include <boost/geometry/algorithms/detail/gc_make_rtree.hpp>
+#include <boost/geometry/algorithms/detail/intersection/interface.hpp>
+#include <boost/geometry/views/detail/geometry_collection_view.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace intersection
+{
+
+
+template <typename GC, typename Multi>
+struct gc_can_move_element
+{
+ template <typename G>
+ using is_same_as_single = std::is_same<G, typename boost::range_value<Multi>::type>;
+ using gc_types = typename traits::geometry_types<GC>::type;
+ using found_type = typename util::sequence_find_if<gc_types, is_same_as_single>::type;
+ static const bool value = ! std::is_void<found_type>::value;
+};
+
+template <typename GC, typename Multi>
+struct gc_can_convert_element
+{
+ template <typename G>
+ using has_same_tag_as_single = std::is_same
+ <
+ typename geometry::tag<G>::type,
+ typename geometry::tag<typename boost::range_value<Multi>::type>::type
+ >;
+ using gc_types = typename traits::geometry_types<GC>::type;
+ using found_type = typename util::sequence_find_if<gc_types, has_same_tag_as_single>::type;
+ static const bool value = ! std::is_void<found_type>::value;
+};
+
+template
+<
+ typename GC, typename Multi,
+ std::enable_if_t<gc_can_move_element<GC, Multi>::value, int> = 0
+>
+inline void gc_move_one_elem_multi_back(GC& gc, Multi&& multi)
+{
+ range::emplace_back(gc, std::move(*boost::begin(multi)));
+}
+
+template
+<
+ typename GC, typename Multi,
+ std::enable_if_t<! gc_can_move_element<GC, Multi>::value && gc_can_convert_element<GC, Multi>::value, int> = 0
+>
+inline void gc_move_one_elem_multi_back(GC& gc, Multi&& multi)
+{
+ typename gc_can_convert_element<GC, Multi>::found_type single_out;
+ geometry::convert(*boost::begin(multi), single_out);
+ range::emplace_back(gc, std::move(single_out));
+}
+
+template
+<
+ typename GC, typename Multi,
+ std::enable_if_t<! gc_can_move_element<GC, Multi>::value && ! gc_can_convert_element<GC, Multi>::value, int> = 0
+>
+inline void gc_move_one_elem_multi_back(GC& gc, Multi&& multi)
+{
+ range::emplace_back(gc, std::move(multi));
+}
+
+template <typename GC, typename Multi>
+inline void gc_move_multi_back(GC& gc, Multi&& multi)
+{
+ if (! boost::empty(multi))
+ {
+ if (boost::size(multi) == 1)
+ {
+ gc_move_one_elem_multi_back(gc, std::move(multi));
+ }
+ else
+ {
+ range::emplace_back(gc, std::move(multi));
+ }
+ }
+}
+
+
+}} // namespace detail::intersection
+#endif // DOXYGEN_NO_DETAIL
+
+
+namespace resolve_collection
+{
+
+
+template
+<
+ typename Geometry1, typename Geometry2, typename GeometryOut
+>
+struct intersection
+ <
+ Geometry1, Geometry2, GeometryOut,
+ geometry_collection_tag, geometry_collection_tag, geometry_collection_tag
+ >
+{
+ // NOTE: for now require all of the possible output types
+ // technically only a subset could be needed.
+ using multi_point_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<GeometryOut>::type,
+ util::is_multi_point
+ >::type;
+ using multi_linestring_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<GeometryOut>::type,
+ util::is_multi_linestring
+ >::type;
+ using multi_polygon_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<GeometryOut>::type,
+ util::is_multi_polygon
+ >::type;
+ using tuple_out_t = boost::tuple<multi_point_t, multi_linestring_t, multi_polygon_t>;
+
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
+ {
+ bool result = false;
+ tuple_out_t out;
+
+ auto const rtree2 = detail::gc_make_rtree_iterators(geometry2, strategy);
+ detail::visit_breadth_first([&](auto const& g1)
+ {
+ bool r = g1_prod_gc2(g1, rtree2, out, strategy);
+ result = result || r;
+ return true;
+ }, geometry1);
+
+ detail::intersection::gc_move_multi_back(geometry_out, boost::get<0>(out));
+ detail::intersection::gc_move_multi_back(geometry_out, boost::get<1>(out));
+ detail::intersection::gc_move_multi_back(geometry_out, boost::get<2>(out));
+
+ return result;
+ }
+
+private:
+ // Implemented as separate function because msvc is unable to do nested lambda capture
+ template <typename G1, typename Rtree2, typename TupleOut, typename Strategy>
+ static bool g1_prod_gc2(G1 const& g1, Rtree2 const& rtree2, TupleOut& out, Strategy const& strategy)
+ {
+ bool result = false;
+
+ using box1_t = detail::gc_make_rtree_box_t<G1>;
+ box1_t b1 = geometry::return_envelope<box1_t>(g1, strategy);
+ detail::expand_by_epsilon(b1);
+
+ for (auto qit = rtree2.qbegin(index::intersects(b1)); qit != rtree2.qend(); ++qit)
+ {
+ traits::iter_visit<Geometry2>::apply([&](auto const& g2)
+ {
+ TupleOut inters_result;
+ using g2_t = util::remove_cref_t<decltype(g2)>;
+ intersection<G1, g2_t, TupleOut>::apply(g1, g2, inters_result, strategy);
+
+ // TODO: If possible merge based on adjacency lists, i.e. merge
+ // only the intersections of elements that intersect each other
+ // as subgroups. So the result could contain merged intersections
+ // of several groups, not only one.
+ // TODO: It'd probably be better to gather all of the parts first
+ // and then merge them with merge_elements.
+ // NOTE: template explicitly called because gcc-6 doesn't compile it
+ // otherwise.
+ bool const r0 = intersection::template merge_result<0>(inters_result, out, strategy);
+ bool const r1 = intersection::template merge_result<1>(inters_result, out, strategy);
+ bool const r2 = intersection::template merge_result<2>(inters_result, out, strategy);
+ result = result || r0 || r1 || r2;
+ }, qit->second);
+ }
+
+ return result;
+ }
+
+ template <std::size_t Index, typename Out, typename Strategy>
+ static bool merge_result(Out const& inters_result, Out& out, Strategy const& strategy)
+ {
+ auto const& multi_result = boost::get<Index>(inters_result);
+ auto& multi_out = boost::get<Index>(out);
+ if (! boost::empty(multi_result))
+ {
+ std::remove_reference_t<decltype(multi_out)> temp_result;
+ merge_two(multi_out, multi_result, temp_result, strategy);
+ multi_out = std::move(temp_result);
+ return true;
+ }
+ return false;
+ }
+
+ template <typename Out, typename Strategy, std::enable_if_t<! util::is_pointlike<Out>::value, int> = 0>
+ static void merge_two(Out const& g1, Out const& g2, Out& out, Strategy const& strategy)
+ {
+ using rescale_policy_type = typename geometry::rescale_overlay_policy_type
+ <
+ Out, Out, typename Strategy::cs_tag
+ >::type;
+
+ rescale_policy_type robust_policy
+ = geometry::get_rescale_policy<rescale_policy_type>(
+ g1, g2, strategy);
+
+ geometry::dispatch::intersection_insert
+ <
+ Out, Out, typename boost::range_value<Out>::type,
+ overlay_union
+ >::apply(g1,
+ g2,
+ robust_policy,
+ geometry::range::back_inserter(out),
+ strategy);
+ }
+
+ template <typename Out, typename Strategy, std::enable_if_t<util::is_pointlike<Out>::value, int> = 0>
+ static void merge_two(Out const& g1, Out const& g2, Out& out, Strategy const& strategy)
+ {
+ detail::overlay::union_pointlike_pointlike_point
+ <
+ Out, Out, typename boost::range_value<Out>::type
+ >::apply(g1,
+ g2,
+ 0, // dummy robust policy
+ geometry::range::back_inserter(out),
+ strategy);
+ }
+};
+
+template
+<
+ typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag1
+>
+struct intersection
+ <
+ Geometry1, Geometry2, GeometryOut,
+ Tag1, geometry_collection_tag, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
+ {
+ using gc_view_t = geometry::detail::geometry_collection_view<Geometry1>;
+ return intersection
+ <
+ gc_view_t, Geometry2, GeometryOut
+ >::apply(gc_view_t(geometry1), geometry2, geometry_out, strategy);
+ }
+};
+
+template
+<
+ typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag2
+>
+struct intersection
+ <
+ Geometry1, Geometry2, GeometryOut,
+ geometry_collection_tag, Tag2, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
+ {
+ using gc_view_t = geometry::detail::geometry_collection_view<Geometry2>;
+ return intersection
+ <
+ Geometry1, gc_view_t, GeometryOut
+ >::apply(geometry1, gc_view_t(geometry2), geometry_out, strategy);
+ }
+};
+
+template
+<
+ typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag1, typename Tag2
+>
+struct intersection
+ <
+ Geometry1, Geometry2, GeometryOut,
+ Tag1, Tag2, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
+ {
+ using gc1_view_t = geometry::detail::geometry_collection_view<Geometry1>;
+ using gc2_view_t = geometry::detail::geometry_collection_view<Geometry2>;
+ return intersection
+ <
+ gc1_view_t, gc2_view_t, GeometryOut
+ >::apply(gc1_view_t(geometry1), gc2_view_t(geometry2), geometry_out, strategy);
+ }
+};
+
+
+} // namespace resolve_collection
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_GC_HPP
diff --git a/boost/geometry/algorithms/detail/intersection/implementation.hpp b/boost/geometry/algorithms/detail/intersection/implementation.hpp
index eee3f25f91..199a05d015 100644
--- a/boost/geometry/algorithms/detail/intersection/implementation.hpp
+++ b/boost/geometry/algorithms/detail/intersection/implementation.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -17,6 +17,7 @@
#include <boost/geometry/algorithms/detail/intersection/areal_areal.hpp>
#include <boost/geometry/algorithms/detail/intersection/box_box.hpp>
+#include <boost/geometry/algorithms/detail/intersection/gc.hpp>
#include <boost/geometry/algorithms/detail/intersection/multi.hpp>
#include <boost/geometry/strategies/relate/cartesian.hpp>
diff --git a/boost/geometry/algorithms/detail/intersection/interface.hpp b/boost/geometry/algorithms/detail/intersection/interface.hpp
index fcd7e959e7..84a9a57cc1 100644
--- a/boost/geometry/algorithms/detail/intersection/interface.hpp
+++ b/boost/geometry/algorithms/detail/intersection/interface.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014-2020.
-// Modifications copyright (c) 2014-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -14,17 +14,15 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_INTERSECTION_INTERFACE_HPP
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
#include <boost/geometry/algorithms/detail/tupled_output.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/services.hpp>
#include <boost/geometry/util/range.hpp>
+#include <boost/geometry/util/type_traits_std.hpp>
namespace boost { namespace geometry
@@ -107,25 +105,21 @@ struct intersection
#endif // DOXYGEN_NO_DISPATCH
-namespace resolve_strategy {
+namespace resolve_collection
+{
template
<
- typename Strategy,
- bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
+ typename Geometry1, typename Geometry2, typename GeometryOut,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type,
+ typename TagOut = typename geometry::tag<GeometryOut>::type
>
struct intersection
{
- template
- <
- typename Geometry1,
- typename Geometry2,
- typename GeometryOut
- >
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- GeometryOut & geometry_out,
- Strategy const& strategy)
+ template <typename Strategy>
+ static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ GeometryOut & geometry_out, Strategy const& strategy)
{
typedef typename geometry::rescale_overlay_policy_type
<
@@ -133,7 +127,7 @@ struct intersection
Geometry2,
typename Strategy::cs_tag
>::type rescale_policy_type;
-
+
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(
geometry1, geometry2, strategy);
@@ -147,6 +141,36 @@ struct intersection
}
};
+} // namespace resolve_collection
+
+
+namespace resolve_strategy {
+
+template
+<
+ typename Strategy,
+ bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
+>
+struct intersection
+{
+ template
+ <
+ typename Geometry1,
+ typename Geometry2,
+ typename GeometryOut
+ >
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut & geometry_out,
+ Strategy const& strategy)
+ {
+ return resolve_collection::intersection
+ <
+ Geometry1, Geometry2, GeometryOut
+ >::apply(geometry1, geometry2, geometry_out, strategy);
+ }
+};
+
template <typename Strategy>
struct intersection<Strategy, false>
{
@@ -199,21 +223,24 @@ struct intersection<default_strategy, false>
} // resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-
-template <typename Geometry1, typename Geometry2>
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct intersection
{
template <typename GeometryOut, typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- GeometryOut& geometry_out,
- Strategy const& strategy)
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ GeometryOut& geometry_out, Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
-
+
return resolve_strategy::intersection
<
Strategy
@@ -222,135 +249,70 @@ struct intersection
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
+struct intersection<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename GeometryOut, typename Strategy>
- struct visitor: static_visitor<bool>
+ static inline bool apply(DynamicGeometry1 const& geometry1, Geometry2 const& geometry2,
+ GeometryOut& geometry_out, Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- GeometryOut& m_geometry_out;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2,
- GeometryOut& geometry_out,
- Strategy const& strategy)
- : m_geometry2(geometry2)
- , m_geometry_out(geometry_out)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- bool operator()(Geometry1 const& geometry1) const
+ bool result = false;
+ traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
{
- return intersection
+ result = intersection
<
- Geometry1,
+ util::remove_cref_t<decltype(g1)>,
Geometry2
- >::apply(geometry1, m_geometry2, m_geometry_out, m_strategy);
- }
- };
-
- template <typename GeometryOut, typename Strategy>
- static inline bool
- apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- GeometryOut& geometry_out,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry2,
- geometry_out,
- strategy),
- geometry1);
+ >::apply(g1, geometry2, geometry_out, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct intersection<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
+struct intersection<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
{
template <typename GeometryOut, typename Strategy>
- struct visitor: static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1, DynamicGeometry2 const& geometry2,
+ GeometryOut& geometry_out, Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- GeometryOut& m_geometry_out;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1,
- GeometryOut& geometry_out,
- Strategy const& strategy)
- : m_geometry1(geometry1)
- , m_geometry_out(geometry_out)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- bool operator()(Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
{
- return intersection
+ result = intersection
<
Geometry1,
- Geometry2
- >::apply(m_geometry1, geometry2, m_geometry_out, m_strategy);
- }
- };
-
- template <typename GeometryOut, typename Strategy>
- static inline bool
- apply(Geometry1 const& geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- GeometryOut& geometry_out,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry1,
- geometry_out,
- strategy),
- geometry2);
+ util::remove_cref_t<decltype(g2)>
+ >::apply(geometry1, g2, geometry_out, strategy);
+ }, geometry2);
+ return result;
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
-struct intersection<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
+template <typename DynamicGeometry1, typename DynamicGeometry2>
+struct intersection<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename GeometryOut, typename Strategy>
- struct visitor: static_visitor<bool>
+ static inline bool apply(DynamicGeometry1 const& geometry1, DynamicGeometry2 const& geometry2,
+ GeometryOut& geometry_out, Strategy const& strategy)
{
- GeometryOut& m_geometry_out;
- Strategy const& m_strategy;
-
- visitor(GeometryOut& geometry_out, Strategy const& strategy)
- : m_geometry_out(geometry_out)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1, typename Geometry2>
- bool operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
{
- return intersection
+ result = intersection
<
- Geometry1,
- Geometry2
- >::apply(geometry1, geometry2, m_geometry_out, m_strategy);
- }
- };
-
- template <typename GeometryOut, typename Strategy>
- static inline bool
- apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- GeometryOut& geometry_out,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<GeometryOut, Strategy>(geometry_out,
- strategy),
- geometry1, geometry2);
+ util::remove_cref_t<decltype(g1)>,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(g1, g2, geometry_out, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
-
-} // namespace resolve_variant
-
+
+} // namespace resolve_dynamic
+
/*!
\brief \brief_calc2{intersection}
@@ -382,7 +344,7 @@ inline bool intersection(Geometry1 const& geometry1,
GeometryOut& geometry_out,
Strategy const& strategy)
{
- return resolve_variant::intersection
+ return resolve_dynamic::intersection
<
Geometry1,
Geometry2
@@ -415,7 +377,7 @@ inline bool intersection(Geometry1 const& geometry1,
Geometry2 const& geometry2,
GeometryOut& geometry_out)
{
- return resolve_variant::intersection
+ return resolve_dynamic::intersection
<
Geometry1,
Geometry2
diff --git a/boost/geometry/algorithms/detail/intersection/multi.hpp b/boost/geometry/algorithms/detail/intersection/multi.hpp
index 42b9997fd0..7810abab50 100644
--- a/boost/geometry/algorithms/detail/intersection/multi.hpp
+++ b/boost/geometry/algorithms/detail/intersection/multi.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014, 2020.
-// Modifications copyright (c) 2014-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -22,6 +22,8 @@
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
+
// TODO: those headers probably may be removed
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
@@ -33,7 +35,6 @@
#include <boost/geometry/algorithms/detail/intersection/interface.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
@@ -63,19 +64,9 @@ struct intersection_multi_linestring_multi_linestring_point
{
// 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 (auto 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)
+ for (auto it2 = boost::begin(ml2); it2 != boost::end(ml2); ++it2)
{
out = intersection_linestring_linestring_point<PointOut>
::apply(*it1, *it2, robust_policy, out, strategy);
@@ -102,12 +93,7 @@ struct intersection_linestring_multi_linestring_point
OutputIterator out,
Strategy const& strategy)
{
- for (typename boost::range_iterator
- <
- MultiLinestring const
- >::type it = boost::begin(ml);
- it != boost::end(ml);
- ++it)
+ for (auto it = boost::begin(ml); it != boost::end(ml); ++it)
{
out = intersection_linestring_linestring_point<PointOut>
::apply(linestring, *it, robust_policy, out, strategy);
@@ -140,12 +126,7 @@ struct intersection_of_multi_linestring_with_areal
OutputIterator out,
Strategy const& strategy)
{
- for (typename boost::range_iterator
- <
- MultiLinestring const
- >::type it = boost::begin(ml);
- it != boost::end(ml);
- ++it)
+ for (auto it = boost::begin(ml); it != boost::end(ml); ++it)
{
out = intersection_of_linestring_with_areal
<
@@ -204,9 +185,7 @@ struct clip_multi_linestring
{
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)
+ for (auto it = boost::begin(multi_linestring); it != boost::end(multi_linestring); ++it)
{
out = detail::intersection::clip_range_with_box
<LinestringOut>(box, *it, robust_policy, out, lb_strategy);
@@ -537,6 +516,40 @@ struct intersection_insert
template
<
+ typename Linestring, typename MultiPolygon,
+ typename TupledOut,
+ overlay_type OverlayType,
+ bool ReverseMultiLinestring, bool ReverseMultiPolygon
+>
+struct intersection_insert
+ <
+ Linestring, MultiPolygon,
+ TupledOut,
+ OverlayType,
+ ReverseMultiLinestring, ReverseMultiPolygon,
+ linestring_tag, multi_polygon_tag, detail::tupled_output_tag,
+ linear_tag, areal_tag, detail::tupled_output_tag
+ > : detail::intersection::intersection_of_linestring_with_areal
+ <
+ ReverseMultiPolygon, TupledOut, OverlayType, true
+ >
+ , detail::expect_output
+ <
+ Linestring, MultiPolygon, TupledOut,
+ // NOTE: points can be the result only in case of intersection.
+ // TODO: union should require L and A
+ std::conditional_t
+ <
+ (OverlayType == overlay_intersection),
+ point_tag,
+ void
+ >,
+ linestring_tag
+ >
+{};
+
+template
+<
typename MultiLinestring, typename MultiPolygon,
typename TupledOut,
overlay_type OverlayType,
diff --git a/boost/geometry/algorithms/detail/is_simple/areal.hpp b/boost/geometry/algorithms/detail/is_simple/areal.hpp
index 4fc3fa26e5..952aa4e549 100644
--- a/boost/geometry/algorithms/detail/is_simple/areal.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/areal.hpp
@@ -49,12 +49,12 @@ template <typename InteriorRings, typename Strategy>
inline bool are_simple_interior_rings(InteriorRings const& interior_rings,
Strategy const& strategy)
{
- auto const end = boost::end(interior_rings);
- return std::find_if(boost::begin(interior_rings), end,
- [&](auto const& r)
- {
- return ! is_simple_ring(r, strategy);
- }) == end; // non-simple ring not found
+ return std::all_of(boost::begin(interior_rings),
+ boost::end(interior_rings),
+ [&](auto const& r)
+ {
+ return is_simple_ring(r, strategy);
+ }); // non-simple ring not found
// allow empty ring
}
@@ -116,12 +116,11 @@ struct is_simple<MultiPolygon, multi_polygon_tag>
template <typename Strategy>
static inline bool apply(MultiPolygon const& multipolygon, Strategy const& strategy)
{
- auto const end = boost::end(multipolygon);
- return std::find_if(boost::begin(multipolygon), end,
- [&](auto const& po) {
- return ! detail::is_simple::is_simple_polygon(po, strategy);
- }) == end; // non-simple polygon not found
- // allow empty multi-polygon
+ return std::none_of(boost::begin(multipolygon), boost::end(multipolygon),
+ [&](auto const& po) {
+ return ! detail::is_simple::is_simple_polygon(po, strategy);
+ }); // non-simple polygon not found
+ // allow empty multi-polygon
}
};
diff --git a/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp b/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp
index b336d44f67..7136e5167e 100644
--- a/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/debug_print_boundary_points.hpp
@@ -69,9 +69,7 @@ struct debug_boundary_points_printer<MultiLinestring, multi_linestring_tag>
typedef std::vector<point_type> point_vector;
point_vector boundary_points;
- for (typename boost::range_iterator<MultiLinestring const>::type it
- = boost::begin(multilinestring);
- it != boost::end(multilinestring); ++it)
+ for (auto it = boost::begin(multilinestring); it != boost::end(multilinestring); ++it)
{
if ( boost::size(*it) > 1
&& !geometry::equals(range::front(*it), range::back(*it)) )
@@ -85,11 +83,9 @@ struct debug_boundary_points_printer<MultiLinestring, multi_linestring_tag>
geometry::less<point_type>());
std::cout << "boundary points: ";
- for (typename point_vector::const_iterator
- pit = boundary_points.begin();
- pit != boundary_points.end(); ++pit)
+ for (auto const& p : boundary_points)
{
- std::cout << " " << geometry::dsv(*pit);
+ std::cout << " " << geometry::dsv(p);
}
std::cout << std::endl << std::endl;
}
diff --git a/boost/geometry/algorithms/detail/is_simple/linear.hpp b/boost/geometry/algorithms/detail/is_simple/linear.hpp
index 090824c25e..e2ac77ad56 100644
--- a/boost/geometry/algorithms/detail/is_simple/linear.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/linear.hpp
@@ -2,6 +2,7 @@
// Copyright (c) 2014-2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -36,7 +37,6 @@
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/algorithms/detail/disjoint/linear_linear.hpp>
@@ -158,7 +158,7 @@ public:
inline bool apply(Turn const& turn) const
{
typedef typename boost::range_value<MultiLinestring>::type linestring_type;
-
+
linestring_type const& ls1 =
range::at(m_multilinestring, turn.operations[0].seg_id.multi_index);
@@ -261,16 +261,16 @@ struct is_simple_multilinestring
{
private:
template <typename Strategy>
- struct per_linestring
+ struct not_simple
{
- per_linestring(Strategy const& strategy)
+ not_simple(Strategy const& strategy)
: m_strategy(strategy)
{}
template <typename Linestring>
- inline bool apply(Linestring const& linestring) const
+ inline bool operator()(Linestring const& linestring) const
{
- return detail::is_simple::is_simple_linestring
+ return ! detail::is_simple::is_simple_linestring
<
Linestring,
false // do not compute self-intersections
@@ -285,19 +285,16 @@ public:
static inline bool apply(MultiLinestring const& multilinestring,
Strategy const& strategy)
{
- typedef per_linestring<Strategy> per_ls;
-
// check each of the linestrings for simplicity
// but do not compute self-intersections yet; these will be
// computed for the entire multilinestring
- if ( ! detail::check_iterator_range
- <
- per_ls, // do not compute self-intersections
- true // allow empty multilinestring
- >::apply(boost::begin(multilinestring),
- boost::end(multilinestring),
- per_ls(strategy))
- )
+ // return true for empty multilinestring
+
+ using not_simple = not_simple<Strategy>; // do not compute self-intersections
+
+ if (std::any_of(boost::begin(multilinestring),
+ boost::end(multilinestring),
+ not_simple(strategy)))
{
return false;
}
diff --git a/boost/geometry/algorithms/detail/is_simple/multipoint.hpp b/boost/geometry/algorithms/detail/is_simple/multipoint.hpp
index 2d2e52130f..2eba68f97e 100644
--- a/boost/geometry/algorithms/detail/is_simple/multipoint.hpp
+++ b/boost/geometry/algorithms/detail/is_simple/multipoint.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2021, Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -44,12 +45,11 @@ struct is_simple_multipoint
template <typename Strategy>
static inline bool apply(MultiPoint const& multipoint, Strategy const& strategy)
{
- typedef typename Strategy::cs_tag cs_tag;
typedef geometry::less
<
typename point_type<MultiPoint>::type,
-1,
- cs_tag
+ Strategy
> less_type;
if (boost::empty(multipoint))
diff --git a/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp b/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp
index 67a94f1016..9a51d30eb4 100644
--- a/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/complement_graph.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, 2018, 2019, Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -32,7 +33,7 @@ namespace detail { namespace is_valid
{
-template <typename TurnPoint, typename CSTag>
+template <typename TurnPoint, typename Strategy>
class complement_graph_vertex
{
public:
@@ -55,7 +56,7 @@ public:
{
return geometry::less
<
- TurnPoint, -1, CSTag
+ TurnPoint, -1, Strategy
>()(*m_turn_point, *other.m_turn_point);
}
if ( m_turn_point == NULL && other.m_turn_point == NULL )
@@ -77,11 +78,11 @@ private:
-template <typename TurnPoint, typename CSTag>
+template <typename TurnPoint, typename Strategy>
class complement_graph
{
private:
- typedef complement_graph_vertex<TurnPoint, CSTag> vertex;
+ typedef complement_graph_vertex<TurnPoint, Strategy> vertex;
typedef std::set<vertex> vertex_container;
public:
@@ -224,9 +225,10 @@ public:
}
#ifdef BOOST_GEOMETRY_TEST_DEBUG
- template <typename OStream, typename TP>
+ template <typename OutputStream>
friend inline
- void debug_print_complement_graph(OStream&, complement_graph<TP> const&);
+ void debug_print_complement_graph(OutputStream&,
+ complement_graph<TurnPoint, Strategy> const&);
#endif // BOOST_GEOMETRY_TEST_DEBUG
private:
diff --git a/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp b/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp
index 5d16e2ea3c..4e4b978b53 100644
--- a/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/debug_complement_graph.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, 2018, 2019, Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -25,12 +26,12 @@ namespace detail { namespace is_valid
#ifdef BOOST_GEOMETRY_TEST_DEBUG
-template <typename OutputStream, typename TurnPoint, typename CSTag>
+template <typename OutputStream, typename TurnPoint, typename Strategy>
inline void
debug_print_complement_graph(OutputStream& os,
- complement_graph<TurnPoint, CSTag> const& graph)
+ complement_graph<TurnPoint, Strategy> const& graph)
{
- typedef typename complement_graph<TurnPoint>::vertex_handle vertex_handle;
+ typedef typename complement_graph<TurnPoint, Strategy>::vertex_handle vertex_handle;
os << "num rings: " << graph.m_num_rings << std::endl;
os << "vertex ids: {";
@@ -39,7 +40,7 @@ debug_print_complement_graph(OutputStream& os,
{
os << " " << it->id();
}
- os << " }" << std::endl;
+ os << " }" << std::endl;
for (vertex_handle it = graph.m_vertices.begin();
it != graph.m_vertices.end(); ++it)
@@ -47,20 +48,20 @@ debug_print_complement_graph(OutputStream& os,
os << "neighbors of " << it->id() << ": {";
for (typename complement_graph
<
- TurnPoint
+ TurnPoint, Strategy
>::neighbor_container::const_iterator
nit = graph.m_neighbors[it->id()].begin();
nit != graph.m_neighbors[it->id()].end(); ++nit)
{
os << " " << (*nit)->id();
}
- os << "}" << std::endl;
+ os << "}" << std::endl;
}
}
#else
-template <typename OutputStream, typename TurnPoint, typename CSTag>
+template <typename OutputStream, typename TurnPoint, typename Strategy>
inline void debug_print_complement_graph(OutputStream&,
- complement_graph<TurnPoint, CSTag> const&)
+ complement_graph<TurnPoint, Strategy> const&)
{
}
#endif
diff --git a/boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp b/boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp
index ce0853d20c..82a1f5f4cd 100644
--- a/boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -14,7 +15,6 @@
#include <cstddef>
#include <type_traits>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
@@ -28,7 +28,7 @@
namespace boost { namespace geometry
{
-
+
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace is_valid
{
@@ -80,26 +80,19 @@ struct indexed_has_invalid_coordinate
struct range_has_invalid_coordinate
{
- struct point_has_valid_coordinates
- {
- template <typename Point>
- static inline bool apply(Point const& point)
- {
- return ! point_has_invalid_coordinate::apply(point);
- }
- };
-
template <typename Geometry, typename VisitPolicy>
static inline bool apply(Geometry const& geometry, VisitPolicy& visitor)
{
boost::ignore_unused(visitor);
- bool const has_valid_coordinates = detail::check_iterator_range
- <
- point_has_valid_coordinates,
- true // do not consider an empty range as problematic
- >::apply(geometry::points_begin(geometry),
- geometry::points_end(geometry));
+ auto const points_end = geometry::points_end(geometry);
+ bool const has_valid_coordinates = std::none_of
+ (
+ geometry::points_begin(geometry), points_end,
+ []( auto const& point ){
+ return point_has_invalid_coordinate::apply(point);
+ }
+ );
return has_valid_coordinates
?
diff --git a/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp b/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
index 6dbaa49bc7..08e9ab43d2 100644
--- a/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/has_spikes.hpp
@@ -56,7 +56,9 @@ struct has_spikes
Strategy const& strategy)
{
if (first == last)
+ {
return last;
+ }
auto const& front = *first;
++first;
return std::find_if(first, last, [&](auto const& pt) {
@@ -71,18 +73,12 @@ struct has_spikes
{
boost::ignore_unused(visitor);
- typedef typename boost::range_iterator<View const>::type iterator;
+ auto cur = boost::begin(view);
+ auto prev = find_different_from_first(boost::rbegin(view),
+ boost::rend(view),
+ strategy);
- iterator cur = boost::begin(view);
- typename boost::range_reverse_iterator
- <
- View const
- >::type prev = find_different_from_first(boost::rbegin(view),
- boost::rend(view),
- strategy);
-
- iterator next = find_different_from_first(cur, boost::end(view),
- strategy);
+ auto next = find_different_from_first(cur, boost::end(view), strategy);
if (detail::is_spike_or_equal(*next, *cur, *prev, strategy.side()))
{
return ! visitor.template apply<failure_spikes>(is_linear, *cur);
@@ -131,8 +127,7 @@ struct has_spikes
// also in geographic cases going over the pole
if (detail::is_spike_or_equal(*next, *cur, *prev, strategy.side()))
{
- return
- ! visitor.template apply<failure_spikes>(is_linestring, *cur);
+ return ! visitor.template apply<failure_spikes>(is_linestring, *cur);
}
prev = cur;
cur = next;
diff --git a/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp b/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp
index 6c33961b3b..b12c42c8e9 100644
--- a/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -54,11 +54,6 @@ private:
CSTag
>::type rescale_policy_type;
- typedef detail::overlay::get_turn_info
- <
- detail::overlay::assign_null_policy
- > turn_policy;
-
public:
typedef detail::overlay::turn_info
<
@@ -88,12 +83,11 @@ public:
> interrupt_policy;
// Calculate self-turns, skipping adjacent segments
- detail::self_get_turn_points::self_turns<false, turn_policy>(geometry,
- strategy,
- robust_policy,
- turns,
- interrupt_policy,
- 0, true);
+ detail::self_get_turn_points::self_turns
+ <
+ false, detail::overlay::assign_null_policy
+ >(geometry, strategy, robust_policy, turns, interrupt_policy,
+ 0, true);
if (interrupt_policy.has_intersections)
{
diff --git a/boost/geometry/algorithms/detail/is_valid/interface.hpp b/boost/geometry/algorithms/detail/is_valid/interface.hpp
index 4f8d1f5435..53576d20cb 100644
--- a/boost/geometry/algorithms/detail/is_valid/interface.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/interface.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -14,12 +14,11 @@
#include <sstream>
#include <string>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
+#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/algorithms/dispatch/is_valid.hpp>
#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/policies/is_valid/default_policy.hpp>
#include <boost/geometry/policies/is_valid/failing_reason_policy.hpp>
@@ -31,7 +30,7 @@
namespace boost { namespace geometry
{
-
+
namespace resolve_strategy
{
@@ -90,10 +89,10 @@ struct is_valid<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry>
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct is_valid
{
template <typename VisitPolicy, typename Strategy>
@@ -110,39 +109,42 @@ struct is_valid
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct is_valid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct is_valid<Geometry, dynamic_geometry_tag>
{
template <typename VisitPolicy, typename Strategy>
- struct visitor : boost::static_visitor<bool>
+ static inline bool apply(Geometry const& geometry,
+ VisitPolicy& policy_visitor,
+ Strategy const& strategy)
{
- visitor(VisitPolicy& policy, Strategy const& strategy)
- : m_policy(policy)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry>
- bool operator()(Geometry const& geometry) const
+ bool result = true;
+ traits::visit<Geometry>::apply([&](auto const& g)
{
- return is_valid<Geometry>::apply(geometry, m_policy, m_strategy);
- }
-
- VisitPolicy& m_policy;
- Strategy const& m_strategy;
- };
+ result = is_valid<util::remove_cref_t<decltype(g)>>::apply(g, policy_visitor, strategy);
+ }, geometry);
+ return result;
+ }
+};
+template <typename Geometry>
+struct is_valid<Geometry, geometry_collection_tag>
+{
template <typename VisitPolicy, typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- VisitPolicy& policy_visitor,
- Strategy const& strategy)
+ static inline bool apply(Geometry const& geometry,
+ VisitPolicy& policy_visitor,
+ Strategy const& strategy)
{
- return boost::apply_visitor(visitor<VisitPolicy, Strategy>(policy_visitor, strategy),
- geometry);
+ bool result = true;
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ result = is_valid<util::remove_cref_t<decltype(g)>>::apply(g, policy_visitor, strategy);
+ return result;
+ }, geometry);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
// Undocumented for now
@@ -151,7 +153,7 @@ inline bool is_valid(Geometry const& geometry,
VisitPolicy& visitor,
Strategy const& strategy)
{
- return resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
+ return resolve_dynamic::is_valid<Geometry>::apply(geometry, visitor, strategy);
}
@@ -175,7 +177,7 @@ template <typename Geometry, typename Strategy>
inline bool is_valid(Geometry const& geometry, Strategy const& strategy)
{
is_valid_default_policy<> visitor;
- return resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
+ return resolve_dynamic::is_valid<Geometry>::apply(geometry, visitor, strategy);
}
/*!
@@ -220,7 +222,7 @@ template <typename Geometry, typename Strategy>
inline bool is_valid(Geometry const& geometry, validity_failure_type& failure, Strategy const& strategy)
{
failure_type_policy<> visitor;
- bool result = resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
+ bool result = resolve_dynamic::is_valid<Geometry>::apply(geometry, visitor, strategy);
failure = visitor.failure();
return result;
}
@@ -271,7 +273,7 @@ inline bool is_valid(Geometry const& geometry, std::string& message, Strategy co
{
std::ostringstream stream;
failing_reason_policy<> visitor(stream);
- bool result = resolve_variant::is_valid<Geometry>::apply(geometry, visitor, strategy);
+ bool result = resolve_dynamic::is_valid<Geometry>::apply(geometry, visitor, strategy);
message = stream.str();
return result;
}
diff --git a/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp b/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp
index 9ca82b1071..4aad18881d 100644
--- a/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/is_acceptable_turn.hpp
@@ -151,7 +151,7 @@ public:
|| turn.method == method_touch_interior)
&& turn.touch_only;
}
-};
+};
}} // namespace detail::is_valid
diff --git a/boost/geometry/algorithms/detail/is_valid/linear.hpp b/boost/geometry/algorithms/detail/is_valid/linear.hpp
index 69cb76e5d5..3753c87a42 100644
--- a/boost/geometry/algorithms/detail/is_valid/linear.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/linear.hpp
@@ -1,7 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2021, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -20,7 +22,6 @@
#include <boost/geometry/algorithms/equals.hpp>
#include <boost/geometry/algorithms/validity_failure_type.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/is_valid/has_invalid_coordinate.hpp>
#include <boost/geometry/algorithms/detail/is_valid/has_spikes.hpp>
#include <boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp>
@@ -31,7 +32,7 @@
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tags.hpp>
-#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/constexpr.hpp>
namespace boost { namespace geometry
@@ -105,7 +106,7 @@ namespace dispatch
// A curve is simple if it does not pass through the same point twice,
// with the possible exception of its two endpoints
//
-// There is an option here as to whether spikes are allowed for linestrings;
+// There is an option here as to whether spikes are allowed for linestrings;
// here we pass this as an additional template parameter: allow_spikes
// If allow_spikes is set to true, spikes are allowed, false otherwise.
// By default, spikes are disallowed
@@ -131,7 +132,6 @@ class is_valid
MultiLinestring, multi_linestring_tag, AllowEmptyMultiGeometries
>
{
-private:
template <typename VisitPolicy, typename Strategy>
struct per_linestring
{
@@ -141,7 +141,7 @@ private:
{}
template <typename Linestring>
- inline bool apply(Linestring const& linestring) const
+ inline bool operator()(Linestring const& linestring) const
{
return detail::is_valid::is_valid_linestring
<
@@ -159,21 +159,19 @@ public:
VisitPolicy& visitor,
Strategy const& strategy)
{
- if (BOOST_GEOMETRY_CONDITION(
- AllowEmptyMultiGeometries && boost::empty(multilinestring)))
+ if BOOST_GEOMETRY_CONSTEXPR (AllowEmptyMultiGeometries)
{
- return visitor.template apply<no_failure>();
+ if (boost::empty(multilinestring))
+ {
+ return visitor.template apply<no_failure>();
+ }
}
- typedef per_linestring<VisitPolicy, Strategy> per_ls;
+ using per_ls = per_linestring<VisitPolicy, Strategy>;
- return detail::check_iterator_range
- <
- per_ls,
- false // do not check for empty multilinestring (done above)
- >::apply(boost::begin(multilinestring),
- boost::end(multilinestring),
- per_ls(visitor, strategy));
+ return std::all_of(boost::begin(multilinestring),
+ boost::end(multilinestring),
+ per_ls(visitor, strategy));
}
};
diff --git a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
index 0b3b4c4a74..5af933de85 100644
--- a/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/multipolygon.hpp
@@ -1,7 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -26,7 +28,7 @@
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tags.hpp>
-#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/constexpr.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/geometries/box.hpp>
@@ -34,7 +36,6 @@
#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/algorithms/within.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/is_valid/has_valid_self_turns.hpp>
@@ -257,55 +258,56 @@ private:
template <typename VisitPolicy, typename Strategy>
- struct per_polygon
+ struct is_invalid_polygon
{
- per_polygon(VisitPolicy& policy, Strategy const& strategy)
+ is_invalid_polygon(VisitPolicy& policy, Strategy const& strategy)
: m_policy(policy)
, m_strategy(strategy)
{}
template <typename Polygon>
- inline bool apply(Polygon const& polygon) const
+ inline bool operator()(Polygon const& polygon) const
{
- return base::apply(polygon, m_policy, m_strategy);
+ return ! base::apply(polygon, m_policy, m_strategy);
}
VisitPolicy& m_policy;
Strategy const& m_strategy;
};
+
public:
template <typename VisitPolicy, typename Strategy>
static inline bool apply(MultiPolygon const& multipolygon,
VisitPolicy& visitor,
Strategy const& strategy)
{
- typedef debug_validity_phase<MultiPolygon> debug_phase;
+ using debug_phase = debug_validity_phase<MultiPolygon>;
- if (BOOST_GEOMETRY_CONDITION(AllowEmptyMultiGeometries)
- && boost::empty(multipolygon))
+ if BOOST_GEOMETRY_CONSTEXPR (AllowEmptyMultiGeometries)
{
- return visitor.template apply<no_failure>();
+ if (boost::empty(multipolygon))
+ {
+ return visitor.template apply<no_failure>();
+ }
}
// check validity of all polygons ring
debug_phase::apply(1);
- if (! detail::check_iterator_range
- <
- per_polygon<VisitPolicy, Strategy>,
- false // do not check for empty multipolygon (done above)
- >::apply(boost::begin(multipolygon),
- boost::end(multipolygon),
- per_polygon<VisitPolicy, Strategy>(visitor, strategy)))
+ if (std::any_of(boost::begin(multipolygon), boost::end(multipolygon),
+ is_invalid_polygon<VisitPolicy, Strategy>(visitor, strategy)))
{
return false;
}
-
// compute turns and check if all are acceptable
debug_phase::apply(2);
- typedef has_valid_self_turns<MultiPolygon, typename Strategy::cs_tag> has_valid_turns;
+ using has_valid_turns = has_valid_self_turns
+ <
+ MultiPolygon,
+ typename Strategy::cs_tag
+ >;
std::deque<typename has_valid_turns::turn_type> turns;
bool has_invalid_turns =
diff --git a/boost/geometry/algorithms/detail/is_valid/polygon.hpp b/boost/geometry/algorithms/detail/is_valid/polygon.hpp
index 72ae593f8e..39512ad154 100644
--- a/boost/geometry/algorithms/detail/is_valid/polygon.hpp
+++ b/boost/geometry/algorithms/detail/is_valid/polygon.hpp
@@ -1,9 +1,9 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2017-2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -34,7 +34,7 @@
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tags.hpp>
-#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/constexpr.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/util/sequence.hpp>
@@ -50,7 +50,6 @@
#include <boost/geometry/algorithms/detail/point_on_border.hpp>
#include <boost/geometry/algorithms/within.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/is_valid/complement_graph.hpp>
@@ -86,17 +85,17 @@ class is_valid_polygon
protected:
template <typename VisitPolicy, typename Strategy>
- struct per_ring
+ struct is_invalid_ring
{
- per_ring(VisitPolicy& policy, Strategy const& strategy)
+ is_invalid_ring(VisitPolicy& policy, Strategy const& strategy)
: m_policy(policy)
, m_strategy(strategy)
{}
template <typename Ring>
- inline bool apply(Ring const& ring) const
+ inline bool operator()(Ring const& ring) const
{
- return detail::is_valid::is_valid_ring
+ return ! detail::is_valid::is_valid_ring
<
Ring, false, true
>::apply(ring, m_policy, m_strategy);
@@ -111,14 +110,9 @@ protected:
VisitPolicy& visitor,
Strategy const& strategy)
{
- return
- detail::check_iterator_range
- <
- per_ring<VisitPolicy, Strategy>,
- true // allow for empty interior ring range
- >::apply(boost::begin(interior_rings),
- boost::end(interior_rings),
- per_ring<VisitPolicy, Strategy>(visitor, strategy));
+ return std::none_of(boost::begin(interior_rings),
+ boost::end(interior_rings),
+ is_invalid_ring<VisitPolicy, Strategy>(visitor, strategy));
}
struct has_valid_rings
@@ -372,7 +366,7 @@ protected:
}
struct has_holes_inside
- {
+ {
template <typename TurnIterator, typename VisitPolicy, typename Strategy>
static inline bool apply(Polygon const& polygon,
TurnIterator first,
@@ -410,7 +404,7 @@ protected:
typedef complement_graph
<
typename turn_type::point_type,
- typename Strategy::cs_tag
+ Strategy
> graph;
graph g(geometry::num_interior_rings(polygon) + 1);
@@ -452,7 +446,7 @@ public:
return false;
}
- if (BOOST_GEOMETRY_CONDITION(CheckRingValidityOnly))
+ if BOOST_GEOMETRY_CONSTEXPR (CheckRingValidityOnly)
{
return true;
}
diff --git a/boost/geometry/algorithms/detail/make/make.hpp b/boost/geometry/algorithms/detail/make/make.hpp
index 566936b86a..45aa6ed473 100644
--- a/boost/geometry/algorithms/detail/make/make.hpp
+++ b/boost/geometry/algorithms/detail/make/make.hpp
@@ -19,10 +19,10 @@ namespace boost { namespace geometry
namespace detail { namespace make
{
-template <typename Type, typename Coordinate>
+template <typename Type, typename Coordinate1, typename Coordinate2>
inline
-model::infinite_line<Type> make_infinite_line(Coordinate const& x1,
- Coordinate const& y1, Coordinate const& x2, Coordinate const& y2)
+model::infinite_line<Type> make_infinite_line(Coordinate1 const& x1,
+ Coordinate1 const& y1, Coordinate2 const& x2, Coordinate2 const& y2)
{
model::infinite_line<Type> result;
result.a = y1 - y2;
@@ -31,9 +31,9 @@ model::infinite_line<Type> make_infinite_line(Coordinate const& x1,
return result;
}
-template <typename Type, typename Point>
+template <typename Type, typename PointA, typename PointB>
inline
-model::infinite_line<Type> make_infinite_line(Point const& a, Point const& b)
+model::infinite_line<Type> make_infinite_line(PointA const& a, PointB const& b)
{
return make_infinite_line<Type>(geometry::get<0>(a), geometry::get<1>(a),
geometry::get<0>(b), geometry::get<1>(b));
@@ -49,9 +49,9 @@ model::infinite_line<Type> make_infinite_line(Segment const& segment)
geometry::get<1, 1>(segment));
}
-template <typename Type, typename Point>
+template <typename Type, typename PointA, typename PointB, typename PointC>
inline
-model::infinite_line<Type> make_perpendicular_line(Point const& a, Point const& b, Point const& c)
+model::infinite_line<Type> make_perpendicular_line(PointA const& a, PointB const& b, PointC const& c)
{
// https://www.math-only-math.com/equation-of-a-line-perpendicular-to-a-line.html
model::infinite_line<Type> const line = make_infinite_line<Type>(a, b);
diff --git a/boost/geometry/algorithms/detail/max_interval_gap.hpp b/boost/geometry/algorithms/detail/max_interval_gap.hpp
index f71efc9aa6..905491ef36 100644
--- a/boost/geometry/algorithms/detail/max_interval_gap.hpp
+++ b/boost/geometry/algorithms/detail/max_interval_gap.hpp
@@ -225,7 +225,7 @@ maximum_gap(RangeOfIntervals const& range_of_intervals,
std::priority_queue
<
event_type,
- std::vector<event_type>,
+ std::vector<event_type>,
detail::max_interval_gap::event_greater<event_type>
> queue;
diff --git a/boost/geometry/algorithms/detail/multi_modify.hpp b/boost/geometry/algorithms/detail/multi_modify.hpp
index 9c2f180067..58597ed6f3 100644
--- a/boost/geometry/algorithms/detail/multi_modify.hpp
+++ b/boost/geometry/algorithms/detail/multi_modify.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2017-2020.
-// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2021.
+// Modifications copyright (c) 2017-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -32,27 +32,24 @@ namespace detail
{
-template <typename MultiGeometry, typename Policy>
+template <typename Policy>
struct multi_modify
{
+ template <typename MultiGeometry>
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)
+ auto const end = boost::end(multi);
+ for (auto it = boost::begin(multi); it != end; ++it)
{
Policy::apply(*it);
}
}
- template <typename Strategy>
+ template <typename MultiGeometry, typename Strategy>
static inline void apply(MultiGeometry& multi, Strategy const& strategy)
{
- typedef typename boost::range_iterator<MultiGeometry>::type iterator_type;
- for (iterator_type it = boost::begin(multi);
- it != boost::end(multi);
- ++it)
+ auto const end = boost::end(multi);
+ for (auto it = boost::begin(multi); it != end; ++it)
{
Policy::apply(*it, strategy);
}
diff --git a/boost/geometry/algorithms/detail/multi_modify_with_predicate.hpp b/boost/geometry/algorithms/detail/multi_modify_with_predicate.hpp
index 4dcc919e98..8d0ec2cb51 100644
--- a/boost/geometry/algorithms/detail/multi_modify_with_predicate.hpp
+++ b/boost/geometry/algorithms/detail/multi_modify_with_predicate.hpp
@@ -36,10 +36,7 @@ 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)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
Policy::apply(*it, predicate);
}
diff --git a/boost/geometry/algorithms/detail/multi_sum.hpp b/boost/geometry/algorithms/detail/multi_sum.hpp
index d41a3689fd..1c5ad6bf51 100644
--- a/boost/geometry/algorithms/detail/multi_sum.hpp
+++ b/boost/geometry/algorithms/detail/multi_sum.hpp
@@ -31,15 +31,10 @@ namespace detail
struct multi_sum
{
template <typename ReturnType, typename Policy, typename MultiGeometry, typename Strategy>
- static inline ReturnType apply(MultiGeometry const& geometry, Strategy const& strategy)
+ static inline ReturnType apply(MultiGeometry const& multi, Strategy const& strategy)
{
ReturnType sum = ReturnType();
- for (typename boost::range_iterator
- <
- MultiGeometry const
- >::type it = boost::begin(geometry);
- it != boost::end(geometry);
- ++it)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
sum += Policy::apply(*it, strategy);
}
diff --git a/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp b/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp
index 5acc531d32..4b94ed4c4f 100644
--- a/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp
+++ b/boost/geometry/algorithms/detail/num_distinct_consecutive_points.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -19,6 +20,8 @@
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
+
namespace boost { namespace geometry
{
@@ -48,8 +51,6 @@ struct num_distinct_consecutive_points
template <typename Strategy>
static inline std::size_t apply(Range const& range, Strategy const& strategy)
{
- typedef typename boost::range_iterator<Range const>::type iterator;
-
std::size_t const size = boost::size(range);
if ( size < 2u )
@@ -57,13 +58,13 @@ struct num_distinct_consecutive_points
return (size < MaximumNumber) ? size : MaximumNumber;
}
- iterator current = boost::begin(range);
- iterator const end = boost::end(range);
+ auto current = boost::begin(range);
+ auto const end = boost::end(range);
std::size_t counter(0);
do
{
++counter;
- iterator next = std::find_if(current, end, [&](auto const& pt) {
+ auto next = std::find_if(current, end, [&](auto const& pt) {
return ! equals::equals_point_point(pt, *current, strategy);
});
current = next;
diff --git a/boost/geometry/algorithms/detail/overlaps/implementation.hpp b/boost/geometry/algorithms/detail/overlaps/implementation.hpp
index e056cbbdaf..5ab1b6ba7b 100644
--- a/boost/geometry/algorithms/detail/overlaps/implementation.hpp
+++ b/boost/geometry/algorithms/detail/overlaps/implementation.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -24,9 +24,11 @@
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/algorithms/detail/gc_topological_dimension.hpp>
#include <boost/geometry/algorithms/detail/overlaps/interface.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation_gc.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
-#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -34,6 +36,8 @@
#include <boost/geometry/strategies/relate/geographic.hpp>
#include <boost/geometry/strategies/relate/spherical.hpp>
+#include <boost/geometry/views/detail/geometry_collection_view.hpp>
+
namespace boost { namespace geometry
{
@@ -150,6 +154,74 @@ struct overlaps<Box1, Box2, box_tag, box_tag>
: detail::overlaps::box_box
{};
+
+template <typename Geometry1, typename Geometry2>
+struct overlaps<Geometry1, Geometry2, geometry_collection_tag, geometry_collection_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ int dimension1 = detail::gc_topological_dimension(geometry1);
+ int dimension2 = detail::gc_topological_dimension(geometry2);
+
+ if (dimension1 >= 0 && dimension2 >= 0)
+ {
+ if (dimension1 == 1 && dimension2 == 1)
+ {
+ return detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_overlaps_d1_1_d2_1_type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
+ }
+ else if (dimension1 == dimension2)
+ {
+ return detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_overlaps_d1_eq_d2_type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
+ }
+ }
+
+ return false;
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct overlaps<Geometry1, Geometry2, Tag1, geometry_collection_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ using gc1_view_t = detail::geometry_collection_view<Geometry1>;
+ return overlaps
+ <
+ gc1_view_t, Geometry2
+ >::apply(gc1_view_t(geometry1), geometry2, strategy);
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct overlaps<Geometry1, Geometry2, geometry_collection_tag, Tag2>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ using gc2_view_t = detail::geometry_collection_view<Geometry2>;
+ return overlaps
+ <
+ Geometry1, gc2_view_t
+ >::apply(geometry1, gc2_view_t(geometry2), strategy);
+ }
+};
+
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/detail/overlaps/interface.hpp b/boost/geometry/algorithms/detail/overlaps/interface.hpp
index fbe0ffdae8..bc2cfb517b 100644
--- a/boost/geometry/algorithms/detail/overlaps/interface.hpp
+++ b/boost/geometry/algorithms/detail/overlaps/interface.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -24,6 +24,7 @@
#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
@@ -124,6 +125,96 @@ struct overlaps<default_strategy, false>
} // namespace resolve_strategy
+namespace resolve_dynamic
+{
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
+struct overlaps
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ return resolve_strategy::overlaps
+ <
+ Strategy
+ >::apply(geometry1, geometry2, strategy);
+ }
+};
+
+
+template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
+struct overlaps<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
+{
+ template <typename Strategy>
+ static inline bool apply(DynamicGeometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ bool result = false;
+ traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
+ {
+ result = resolve_strategy::overlaps
+ <
+ Strategy
+ >::apply(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
+ }
+};
+
+
+template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
+struct overlaps<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1,
+ DynamicGeometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ bool result = false;
+ traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
+ {
+ result = resolve_strategy::overlaps
+ <
+ Strategy
+ >::apply(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
+ }
+};
+
+
+template <typename DynamicGeometry1, typename DynamicGeometry2>
+struct overlaps<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
+{
+ template <typename Strategy>
+ static inline bool apply(DynamicGeometry1 const& geometry1,
+ DynamicGeometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ bool result = false;
+ traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
+ {
+ result = resolve_strategy::overlaps
+ <
+ Strategy
+ >::apply(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
+ }
+};
+
+
+} // namespace resolve_dynamic
+
+
/*!
\brief \brief_check2{overlap}
\ingroup overlaps
@@ -146,9 +237,9 @@ inline bool overlaps(Geometry1 const& geometry1,
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
- return resolve_strategy::overlaps
+ return resolve_dynamic::overlaps
<
- Strategy
+ Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
}
@@ -174,9 +265,9 @@ inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2)
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
- return resolve_strategy::overlaps
+ return resolve_dynamic::overlaps
<
- default_strategy
+ Geometry1, Geometry2
>::apply(geometry1, geometry2, default_strategy());
}
diff --git a/boost/geometry/algorithms/detail/overlay/add_rings.hpp b/boost/geometry/algorithms/detail/overlay/add_rings.hpp
index 45f2e7f12f..026906b496 100644
--- a/boost/geometry/algorithms/detail/overlay/add_rings.hpp
+++ b/boost/geometry/algorithms/detail/overlay/add_rings.hpp
@@ -96,8 +96,6 @@ inline OutputIterator add_rings(SelectionMap const& map,
Strategy const& strategy,
add_rings_error_handling error_handling = add_rings_ignore_unordered)
{
- typedef typename SelectionMap::const_iterator iterator;
-
std::size_t const min_num_points = core_detail::closure::minimum_ring_size
<
geometry::closure
@@ -110,29 +108,23 @@ inline OutputIterator add_rings(SelectionMap const& map,
>::value;
- for (iterator it = boost::begin(map);
- it != boost::end(map);
- ++it)
+ for (auto const& pair : map)
{
- if (! it->second.discarded
- && it->second.parent.source_index == -1)
+ if (! pair.second.discarded
+ && pair.second.parent.source_index == -1)
{
GeometryOut result;
convert_and_add(result, geometry1, geometry2, collection,
- it->first, it->second.reversed, false);
+ pair.first, pair.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)
+ for (auto const& child : pair.second.children)
{
- iterator mit = map.find(*child_it);
- if (mit != map.end()
- && ! mit->second.discarded)
+ auto mit = map.find(child);
+ if (mit != map.end() && ! mit->second.discarded)
{
convert_and_add(result, geometry1, geometry2, collection,
- *child_it, mit->second.reversed, true);
+ child, mit->second.reversed, true);
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp b/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp
index f304600c00..a21ee9832b 100644
--- a/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp
+++ b/boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp
@@ -23,6 +23,7 @@
#include <boost/static_assert.hpp>
#include <boost/geometry/algorithms/append.hpp>
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
@@ -99,7 +100,16 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point,
return;
}
- traits::push_back<Range>::apply(range, point);
+ auto append = [](auto& r, const auto& p)
+ {
+ using point_t = typename boost::range_value<Range>::type;
+ point_t rp;
+ geometry::detail::conversion::convert_point_to_point(p, rp);
+ traits::push_back<Range>::apply(r, std::move(rp));
+ };
+
+ append(range, point);
+
// If a point is equal, or forming a spike, remove the pen-ultimate point
// because this one caused the spike.
@@ -115,7 +125,7 @@ inline void append_no_dups_or_spikes(Range& range, Point const& point,
{
// Use the Concept/traits, so resize and append again
traits::resize<Range>::apply(range, boost::size(range) - 2);
- traits::push_back<Range>::apply(range, point);
+ append(range, point);
}
}
@@ -174,7 +184,6 @@ inline void clean_closing_dups_and_spikes(Range& range,
return;
}
- typedef typename boost::range_iterator<Range>::type iterator_type;
static bool const closed = geometry::closure<Range>::value == geometry::closed;
// TODO: the following algorithm could be rewritten to first look for spikes
@@ -184,9 +193,9 @@ inline void clean_closing_dups_and_spikes(Range& range,
do
{
found = false;
- iterator_type first = boost::begin(range);
- iterator_type second = first + 1;
- iterator_type ultimate = boost::end(range) - 1;
+ auto first = boost::begin(range);
+ auto second = first + 1;
+ auto ultimate = boost::end(range) - 1;
if (BOOST_GEOMETRY_CONDITION(closed))
{
ultimate--;
diff --git a/boost/geometry/algorithms/detail/overlay/approximately_equals.hpp b/boost/geometry/algorithms/detail/overlay/approximately_equals.hpp
index d28a04ee8f..1f41085dc1 100644
--- a/boost/geometry/algorithms/detail/overlay/approximately_equals.hpp
+++ b/boost/geometry/algorithms/detail/overlay/approximately_equals.hpp
@@ -23,7 +23,7 @@ namespace detail { namespace overlay
template <typename Point1, typename Point2, typename E>
inline bool approximately_equals(Point1 const& a, Point2 const& b,
- E const& multiplier)
+ E const& epsilon_multiplier)
{
using coor_t = typename select_coordinate_type<Point1, Point2>::type;
using calc_t = typename geometry::select_most_precise<coor_t, E>::type;
@@ -34,7 +34,7 @@ inline bool approximately_equals(Point1 const& a, Point2 const& b,
calc_t const& b1 = geometry::get<1>(b);
math::detail::equals_factor_policy<calc_t> policy(a0, b0, a1, b1);
- policy.factor *= multiplier;
+ policy.multiply_epsilon(epsilon_multiplier);
return math::detail::equals_by_policy(a0, b0, policy)
&& math::detail::equals_by_policy(a1, b1, policy);
diff --git a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
index a4cfac4dc1..fb3ee1bef2 100644
--- a/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
+++ b/boost/geometry/algorithms/detail/overlay/assign_parents.hpp
@@ -3,8 +3,9 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017-2020.
-// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2023.
+// Modifications copyright (c) 2017-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -18,15 +19,19 @@
#include <boost/range/end.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
+
+#include <boost/geometry/algorithms/area_result.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/expand.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/geometry/algorithms/detail/partition.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
#include <boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/geometries/box.hpp>
+#include <boost/geometry/util/for_each_with_index.hpp>
+
namespace boost { namespace geometry
{
@@ -260,38 +265,31 @@ inline void assign_parents(Geometry1 const& geometry1,
point_type, Strategy // TODO: point_type is technically incorrect
>::type area_result_type;
- typedef typename RingMap::iterator map_iterator_type;
-
{
- typedef ring_info_helper<point_type, area_result_type> helper;
- typedef std::vector<helper> vector_type;
- typedef typename boost::range_iterator<vector_type const>::type vector_iterator_type;
-
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);
+ // Copy to vector (this might be obsolete, using the map directly)
+ using helper = ring_info_helper<point_type, area_result_type>;
+ std::vector<helper> vector(count_total);
- for (map_iterator_type it = boost::begin(ring_map);
- it != boost::end(ring_map); ++it, ++index)
+ for_each_with_index(ring_map, [&](std::size_t index, auto const& pair)
{
- vector[index] = helper(it->first, it->second.get_area());
+ vector[index] = helper(pair.first, pair.second.get_area());
helper& item = vector[index];
- switch(it->first.source_index)
+ switch(pair.first.source_index)
{
case 0 :
- geometry::envelope(get_ring<tag1>::apply(it->first, geometry1),
+ geometry::envelope(get_ring<tag1>::apply(pair.first, geometry1),
item.envelope, strategy);
break;
case 1 :
- geometry::envelope(get_ring<tag2>::apply(it->first, geometry2),
+ geometry::envelope(get_ring<tag2>::apply(pair.first, geometry2),
item.envelope, strategy);
break;
case 2 :
- geometry::envelope(get_ring<void>::apply(it->first, collection),
+ geometry::envelope(get_ring<void>::apply(pair.first, collection),
item.envelope, strategy);
break;
}
@@ -304,7 +302,7 @@ inline void assign_parents(Geometry1 const& geometry1,
count_positive++;
index_positive = index;
}
- }
+ });
if (! check_for_orientation)
{
@@ -325,17 +323,15 @@ inline void assign_parents(Geometry1 const& geometry1,
// located outside the outer ring, this cannot be done
ring_identifier id_of_positive = vector[index_positive].id;
ring_info_type& outer = ring_map[id_of_positive];
- index = 0;
- for (vector_iterator_type it = boost::begin(vector);
- it != boost::end(vector); ++it, ++index)
+ for_each_with_index(vector, [&](std::size_t index, auto const& item)
{
if (index != index_positive)
{
- ring_info_type& inner = ring_map[it->id];
+ ring_info_type& inner = ring_map[item.id];
inner.parent = id_of_positive;
- outer.children.push_back(it->id);
+ outer.children.push_back(item.id);
}
- }
+ });
return;
}
}
@@ -357,10 +353,9 @@ inline void assign_parents(Geometry1 const& geometry1,
if (check_for_orientation)
{
- for (map_iterator_type it = boost::begin(ring_map);
- it != boost::end(ring_map); ++it)
+ for (auto& pair : ring_map)
{
- ring_info_type& info = it->second;
+ ring_info_type& info = pair.second;
if (geometry::math::equals(info.get_area(), 0))
{
info.discarded = true;
@@ -397,12 +392,11 @@ inline void assign_parents(Geometry1 const& geometry1,
}
// Assign childlist
- for (map_iterator_type it = boost::begin(ring_map);
- it != boost::end(ring_map); ++it)
+ for (auto& pair : ring_map)
{
- if (it->second.parent.source_index >= 0)
+ if (pair.second.parent.source_index >= 0)
{
- ring_map[it->second.parent].children.push_back(it->first);
+ ring_map[pair.second.parent].children.push_back(pair.first);
}
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp b/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp
index 14be63a554..49d190bd0c 100644
--- a/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp
+++ b/boost/geometry/algorithms/detail/overlay/backtrack_check_si.hpp
@@ -38,21 +38,11 @@ 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 (auto& turn : turns)
{
- 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)
+ for (auto& op : turn.operations)
{
- op_it->visited.clear();
+ op.visited.clear();
}
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/check_enrich.hpp b/boost/geometry/algorithms/detail/overlay/check_enrich.hpp
index 843e120a18..ad3bd6bda9 100644
--- a/boost/geometry/algorithms/detail/overlay/check_enrich.hpp
+++ b/boost/geometry/algorithms/detail/overlay/check_enrich.hpp
@@ -127,37 +127,30 @@ 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)
+ for_each_with_index(turn_points, [&](std::size_t index, auto const& point)
{
- meta_turns.push_back(meta_turn<turn_point_type>(index, *it));
- }
+ meta_turns.push_back(meta_turn<turn_point_type>(index, point));
+ });
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)
+ for (auto& meta_turn : meta_turns)
{
- if (! (it->turn->blocked() || it->turn->discarded))
+ if (! (meta_turn.turn->blocked() || meta_turn.turn->discarded))
{
for (int i = 0 ; i < 2; i++)
{
- if (! it->handled[i]
- && it->turn->operations[i].operation == for_operation)
+ if (! meta_turn.handled[i]
+ && meta_turn.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);
+ meta_turn.handled[i] = true;
+ check_detailed(meta_turns, meta_turn, i, cycle++, meta_turn.index, for_operation, error);
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
- std::cout <<" END CYCLE " << it->index << std::endl;
+ std::cout <<" END CYCLE " << meta_turn.index << std::endl;
#endif
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp b/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp
index f99140dcd0..2eb70aa7d8 100644
--- a/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp
+++ b/boost/geometry/algorithms/detail/overlay/clip_linestring.hpp
@@ -197,9 +197,8 @@ OutputIterator clip_range_with_box(Box const& b, Range const& range,
OutputLinestring line_out;
- typedef typename boost::range_iterator<Range const>::type iterator_type;
- iterator_type vertex = boost::begin(range);
- for(iterator_type previous = vertex++;
+ auto vertex = boost::begin(range);
+ for (auto previous = vertex++;
vertex != boost::end(range);
++previous, ++vertex)
{
diff --git a/boost/geometry/algorithms/detail/overlay/cluster_exits.hpp b/boost/geometry/algorithms/detail/overlay/cluster_exits.hpp
index c4d01b1c14..8c4f4c7f31 100644
--- a/boost/geometry/algorithms/detail/overlay/cluster_exits.hpp
+++ b/boost/geometry/algorithms/detail/overlay/cluster_exits.hpp
@@ -2,8 +2,9 @@
// Copyright (c) 2020 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2023.
+// Modifications copyright (c) 2020-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -22,6 +23,7 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
+#include <boost/geometry/algorithms/detail/overlay/sort_by_side.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
#include <boost/geometry/util/condition.hpp>
@@ -67,16 +69,11 @@ private :
signed_size_type rank_index;
};
- typedef typename std::vector<linked_turn_op_info>::const_iterator const_it_type;
- typedef typename std::vector<linked_turn_op_info>::iterator it_type;
- typedef typename std::set<signed_size_type>::const_iterator sit_type;
-
inline signed_size_type get_rank(Sbs const& sbs,
linked_turn_op_info const& info) const
{
- for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
+ for (auto const& rp : sbs.m_ranked_points)
{
- typename Sbs::rp const& rp = sbs.m_ranked_points[i];
if (rp.turn_index == info.turn_index
&& rp.operation_index == info.op_index
&& rp.direction == sort_by_side::dir_to)
@@ -95,9 +92,8 @@ private :
bool collect(Turns const& turns)
{
- for (sit_type it = m_ids.begin(); it != m_ids.end(); ++it)
+ for (auto cluster_turn_index : m_ids)
{
- signed_size_type cluster_turn_index = *it;
turn_type const& cluster_turn = turns[cluster_turn_index];
if (cluster_turn.discarded)
{
@@ -148,23 +144,19 @@ private :
return true;
}
- for (it_type it = possibilities.begin(); it != possibilities.end(); ++it)
+ for (auto& info : possibilities)
{
- linked_turn_op_info& info = *it;
info.rank_index = get_rank(sbs, info);
}
- for (it_type it = blocked.begin(); it != blocked.end(); ++it)
+ for (auto& info : blocked)
{
- linked_turn_op_info& info = *it;
info.rank_index = get_rank(sbs, info);
}
- for (const_it_type it = possibilities.begin(); it != possibilities.end(); ++it)
+ for (auto const& lti : possibilities)
{
- linked_turn_op_info const& lti = *it;
- for (const_it_type bit = blocked.begin(); bit != blocked.end(); ++bit)
+ for (auto const& blti : blocked)
{
- linked_turn_op_info const& blti = *bit;
if (blti.next_turn_index == lti.next_turn_index
&& blti.rank_index == lti.rank_index)
{
@@ -198,10 +190,8 @@ public :
// If there is one (and only one) possibility pointing outside
// the cluster, take that one.
linked_turn_op_info target;
- for (const_it_type it = possibilities.begin();
- it != possibilities.end(); ++it)
+ for (auto const& lti : possibilities)
{
- linked_turn_op_info const& lti = *it;
if (m_ids.count(lti.next_turn_index) == 0)
{
if (target.turn_index >= 0
diff --git a/boost/geometry/algorithms/detail/overlay/colocate_clusters.hpp b/boost/geometry/algorithms/detail/overlay/colocate_clusters.hpp
new file mode 100644
index 0000000000..06d6e7bd61
--- /dev/null
+++ b/boost/geometry/algorithms/detail/overlay/colocate_clusters.hpp
@@ -0,0 +1,107 @@
+// Boost.Geometry
+
+// Copyright (c) 2023 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_COLOCATE_CLUSTERS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COLOCATE_CLUSTERS_HPP
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace overlay
+{
+
+// Default implementation, using the first point for all turns in the cluster.
+template
+<
+ typename Point,
+ typename CoordinateType = typename geometry::coordinate_type<Point>::type,
+ typename CsTag = typename geometry::cs_tag<Point>::type,
+ bool IsIntegral = std::is_integral<CoordinateType>::value
+>
+struct cluster_colocator
+{
+ template <typename TurnIndices, typename Turns>
+ static inline void apply(TurnIndices const& indices, Turns& turns)
+ {
+ // This approach works for all but one testcase (rt_p13)
+ // The problem is fill_sbs, which uses sides and these sides might change slightly
+ // depending on the exact location of the cluster.
+ // Using the centroid is, on the average, a safer choice for sides.
+ // Alternatively fill_sbs could be revised, but that requires a lot of work
+ // and is outside current scope.
+ // Integer coordinates are always colocated already and do not need centroid calculation.
+ // Geographic/spherical coordinates might (in extremely rare cases) cross the date line
+ // and therefore the first point is taken for them as well.
+ auto it = indices.begin();
+ auto const& first_point = turns[*it].point;
+ for (++it; it != indices.end(); ++it)
+ {
+ turns[*it].point = first_point;
+ }
+ }
+};
+
+// Specialization for non-integral cartesian coordinates, calculating
+// the centroid of the points of the turns in the cluster.
+template <typename Point, typename CoordinateType>
+struct cluster_colocator<Point, CoordinateType, geometry::cartesian_tag, false>
+{
+ template <typename TurnIndices, typename Turns>
+ static inline void apply(TurnIndices const& indices, Turns& turns)
+ {
+ CoordinateType centroid_0 = 0;
+ CoordinateType centroid_1 = 0;
+ for (const auto& index : indices)
+ {
+ centroid_0 += geometry::get<0>(turns[index].point);
+ centroid_1 += geometry::get<1>(turns[index].point);
+ }
+ centroid_0 /= indices.size();
+ centroid_1 /= indices.size();
+ for (const auto& index : indices)
+ {
+ geometry::set<0>(turns[index].point, centroid_0);
+ geometry::set<1>(turns[index].point, centroid_1);
+ }
+ }
+};
+
+// Moves intersection points per cluster such that they are identical.
+// Because clusters are intersection close together, and
+// handled as one location. Then they should also have one location.
+// It is necessary to avoid artefacts and invalidities.
+template <typename Clusters, typename Turns>
+inline void colocate_clusters(Clusters const& clusters, Turns& turns)
+{
+ for (auto const& pair : clusters)
+ {
+ auto const& indices = pair.second.turn_indices;
+ if (indices.size() < 2)
+ {
+ // Defensive check
+ continue;
+ }
+ using point_t = decltype(turns[*indices.begin()].point);
+ cluster_colocator<point_t>::apply(indices, turns);
+ }
+}
+
+
+}} // namespace detail::overlay
+#endif //DOXYGEN_NO_DETAIL
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COLOCATE_CLUSTERS_HPP
diff --git a/boost/geometry/algorithms/detail/overlay/convert_ring.hpp b/boost/geometry/algorithms/detail/overlay/convert_ring.hpp
index becaaafc37..c7c1cf7030 100644
--- a/boost/geometry/algorithms/detail/overlay/convert_ring.hpp
+++ b/boost/geometry/algorithms/detail/overlay/convert_ring.hpp
@@ -86,6 +86,7 @@ struct convert_ring<polygon_tag>
if (geometry::num_points(source) >= min_num_points)
{
+ // TODO: resize and .size() and .back() should not be called here
interior_rings(destination).resize(
interior_rings(destination).size() + 1);
geometry::convert(source, interior_rings(destination).back());
diff --git a/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
index 30a0a25095..8280a25018 100644
--- a/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
+++ b/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2020-2021.
// Modifications copyright (c) 2020-2021, Oracle and/or its affiliates.
@@ -14,7 +15,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP
-#include <boost/array.hpp>
+#include <array>
+
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
@@ -113,7 +115,7 @@ struct copy_segment_point_box
SegmentIdentifier const& seg_id, signed_size_type offset,
PointOut& point)
{
- boost::array<typename point_type<Box>::type, 4> bp;
+ std::array<typename point_type<Box>::type, 4> bp;
assign_box_corners_oriented<Reverse>(box, bp);
signed_size_type const target = circular_offset(4, seg_id.segment_index, offset);
diff --git a/boost/geometry/algorithms/detail/overlay/copy_segments.hpp b/boost/geometry/algorithms/detail/overlay/copy_segments.hpp
index 8af9ea4c1f..545bdc0314 100644
--- a/boost/geometry/algorithms/detail/overlay/copy_segments.hpp
+++ b/boost/geometry/algorithms/detail/overlay/copy_segments.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
@@ -15,10 +16,10 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP
+#include <array>
#include <type_traits>
#include <vector>
-#include <boost/array.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
@@ -167,10 +168,7 @@ public:
}
signed_size_type const count = to_index - from_index + 1;
-
- typename boost::range_iterator<LineString const>::type
- it = boost::begin(ls) + from_index;
-
+ auto it = boost::begin(ls) + from_index;
for (signed_size_type i = 0; i < count; ++i, ++it)
{
append_to_output(current_output, *it, strategy, robust_policy,
@@ -238,7 +236,7 @@ struct copy_segments_box
: 5 - index + to_index + 1;
// Create array of points, the fifth one closes it
- boost::array<typename point_type<Box>::type, 5> bp;
+ std::array<typename point_type<Box>::type, 5> bp;
assign_box_corners_oriented<Reverse>(box, bp);
bp[4] = bp[0];
diff --git a/boost/geometry/algorithms/detail/overlay/discard_duplicate_turns.hpp b/boost/geometry/algorithms/detail/overlay/discard_duplicate_turns.hpp
index f5a4a82656..258a815f09 100644
--- a/boost/geometry/algorithms/detail/overlay/discard_duplicate_turns.hpp
+++ b/boost/geometry/algorithms/detail/overlay/discard_duplicate_turns.hpp
@@ -2,6 +2,10 @@
// Copyright (c) 2021 Barend Gehrels, Amsterdam, the Netherlands.
+// This file was modified by Oracle on 2023.
+// Modifications copyright (c) 2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -9,6 +13,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DISCARD_DUPLICATE_TURNS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_DISCARD_DUPLICATE_TURNS_HPP
+#include <map>
+
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
diff --git a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
index 58ab4fcdda..b94bba6c5a 100644
--- a/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp
@@ -3,9 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017-2020.
+// This file was modified by Oracle on 2017-2021.
// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates.
-
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -42,6 +41,7 @@
#include <boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
#include <boost/geometry/policies/robustness/robust_type.hpp>
+#include <boost/geometry/util/for_each_with_index.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
# include <boost/geometry/algorithms/detail/overlay/check_enrich.hpp>
@@ -83,24 +83,24 @@ template
typename Turns,
typename Geometry1, typename Geometry2,
typename RobustPolicy,
- typename SideStrategy
+ typename Strategy
>
inline void enrich_sort(Operations& operations,
Turns const& turns,
Geometry1 const& geometry1,
Geometry2 const& geometry2,
RobustPolicy const& robust_policy,
- SideStrategy const& strategy)
+ Strategy const& strategy)
{
- std::sort(boost::begin(operations),
- boost::end(operations),
- less_by_segment_ratio
+ std::sort(std::begin(operations),
+ std::end(operations),
+ less_by_segment_ratio
<
Turns,
typename boost::range_value<Operations>::type,
Geometry1, Geometry2,
RobustPolicy,
- SideStrategy,
+ Strategy,
Reverse1, Reverse2
>(turns, geometry1, geometry2, robust_policy, strategy));
}
@@ -110,93 +110,83 @@ template <typename Operations, typename Turns>
inline void enrich_assign(Operations& operations, Turns& turns,
bool check_turns)
{
- typedef typename boost::range_value<Turns>::type turn_type;
- typedef typename turn_type::turn_operation_type op_type;
- typedef typename boost::range_iterator<Operations>::type iterator_type;
+ if (operations.empty())
+ {
+ return;
+ }
+ // Assign travel-to-vertex/ip index for each turning point.
+ // Iterator "next" is circular
- if (operations.size() > 0)
- {
- // Assign travel-to-vertex/ip index for each turning point.
- // Iterator "next" is circular
+ geometry::ever_circling_range_iterator<Operations const> next(operations);
+ ++next;
- geometry::ever_circling_range_iterator<Operations const> next(operations);
- ++next;
+ for (auto const& indexed : operations)
+ {
+ auto& turn = turns[indexed.turn_index];
+ auto& op = turn.operations[indexed.operation_index];
- for (iterator_type it = boost::begin(operations);
- it != boost::end(operations); ++it)
+ if (check_turns && indexed.turn_index == next->turn_index)
{
- turn_type& turn = turns[it->turn_index];
- op_type& op = turn.operations[it->operation_index];
-
- if (check_turns && it->turn_index == next->turn_index)
- {
- // Normal behaviour: next points at next turn, increase next.
- // For dissolve this should not be done, turn_index is often
- // the same for two consecutive operations
- ++next;
- }
+ // Normal behaviour: next points at next turn, increase next.
+ // For dissolve this should not be done, turn_index is often
+ // the same for two consecutive operations
+ ++next;
+ }
- // Cluster behaviour: next should point after cluster, unless
- // their seg_ids are not the same
- // (For dissolve, this is still to be examined - TODO)
- while (turn.is_clustered()
- && it->turn_index != next->turn_index
- && turn.cluster_id == turns[next->turn_index].cluster_id
- && op.seg_id == turns[next->turn_index].operations[next->operation_index].seg_id)
- {
- ++next;
- }
+ // Cluster behaviour: next should point after cluster, unless
+ // their seg_ids are not the same
+ // (For dissolve, this is still to be examined - TODO)
+ while (turn.is_clustered()
+ && indexed.turn_index != next->turn_index
+ && turn.cluster_id == turns[next->turn_index].cluster_id
+ && op.seg_id == turns[next->turn_index].operations[next->operation_index].seg_id)
+ {
+ ++next;
+ }
- turn_type const& next_turn = turns[next->turn_index];
- op_type const& next_op = next_turn.operations[next->operation_index];
+ auto const& next_turn = turns[next->turn_index];
+ auto const& next_op = next_turn.operations[next->operation_index];
- op.enriched.travels_to_ip_index
- = static_cast<signed_size_type>(next->turn_index);
- op.enriched.travels_to_vertex_index
- = next->subject->seg_id.segment_index;
+ op.enriched.travels_to_ip_index
+ = static_cast<signed_size_type>(next->turn_index);
+ op.enriched.travels_to_vertex_index
+ = next->subject->seg_id.segment_index;
- if (op.seg_id.segment_index == next_op.seg_id.segment_index
- && op.fraction < next_op.fraction)
- {
- // Next turn is located further on same segment
- // assign next_ip_index
- // (this is one not circular therefore fraction is considered)
- op.enriched.next_ip_index = static_cast<signed_size_type>(next->turn_index);
- }
+ if (op.seg_id.segment_index == next_op.seg_id.segment_index
+ && op.fraction < next_op.fraction)
+ {
+ // Next turn is located further on same segment
+ // assign next_ip_index
+ // (this is one not circular therefore fraction is considered)
+ op.enriched.next_ip_index = static_cast<signed_size_type>(next->turn_index);
+ }
- if (! check_turns)
- {
- ++next;
- }
+ if (! check_turns)
+ {
+ ++next;
}
}
// DEBUG
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
+ for (auto const& indexed_op : operations)
{
- for (iterator_type it = boost::begin(operations);
- it != boost::end(operations);
- ++it)
- {
- op_type const& op = turns[it->turn_index]
- .operations[it->operation_index];
-
- std::cout << it->turn_index
- << " cl=" << turns[it->turn_index].cluster_id
- << " meth=" << method_char(turns[it->turn_index].method)
- << " seg=" << op.seg_id
- << " dst=" << op.fraction // needs define
- << " op=" << operation_char(turns[it->turn_index].operations[0].operation)
- << operation_char(turns[it->turn_index].operations[1].operation)
- << " (" << operation_char(op.operation) << ")"
- << " nxt=" << op.enriched.next_ip_index
- << " / " << op.enriched.travels_to_ip_index
- << " [vx " << op.enriched.travels_to_vertex_index << "]"
- << (turns[it->turn_index].discarded ? " discarded" : "")
- << std::endl;
- ;
- }
+ auto const& op = turns[indexed_op.turn_index].operations[indexed_op.operation_index];
+
+ std::cout << indexed_op.turn_index
+ << " cl=" << turns[indexed_op.turn_index].cluster_id
+ << " meth=" << method_char(turns[indexed_op.turn_index].method)
+ << " seg=" << op.seg_id
+ << " dst=" << op.fraction // needs define
+ << " op=" << operation_char(turns[indexed_op.turn_index].operations[0].operation)
+ << operation_char(turns[indexed_op.turn_index].operations[1].operation)
+ << " (" << operation_char(op.operation) << ")"
+ << " nxt=" << op.enriched.next_ip_index
+ << " / " << op.enriched.travels_to_ip_index
+ << " [vx " << op.enriched.travels_to_vertex_index << "]"
+ << (turns[indexed_op.turn_index].discarded ? " discarded" : "")
+ << std::endl;
}
#endif
// END DEBUG
@@ -206,47 +196,37 @@ inline void enrich_assign(Operations& operations, Turns& turns,
template <typename Operations, typename Turns>
inline void enrich_adapt(Operations& operations, Turns& turns)
{
- typedef typename boost::range_value<Turns>::type turn_type;
- typedef typename turn_type::turn_operation_type op_type;
- typedef typename boost::range_value<Operations>::type indexed_turn_type;
-
+ // Operations is a vector of indexed_turn_operation<>
+ // If it is empty, or contains one or two items, it makes no sense
if (operations.size() < 3)
{
- // If it is empty, or contains one or two turns, it makes no sense
return;
}
- // Operations is a vector of indexed_turn_operation<>
-
- // Last index:
- std::size_t const x = operations.size() - 1;
bool next_phase = false;
+ std::size_t previous_index = operations.size() - 1;
- for (std::size_t i = 0; i < operations.size(); i++)
+ for_each_with_index(operations, [&](std::size_t index, auto const& indexed)
{
- indexed_turn_type const& indexed = operations[i];
-
- turn_type& turn = turns[indexed.turn_index];
- op_type& op = turn.operations[indexed.operation_index];
-
- // Previous/next index
- std::size_t const p = i > 0 ? i - 1 : x;
- std::size_t const n = i < x ? i + 1 : 0;
+ auto& turn = turns[indexed.turn_index];
+ auto& op = turn.operations[indexed.operation_index];
- turn_type const& next_turn = turns[operations[n].turn_index];
- op_type const& next_op = next_turn.operations[operations[n].operation_index];
+ std::size_t const next_index = index + 1 < operations.size() ? index + 1 : 0;
+ auto const& next_turn = turns[operations[next_index].turn_index];
+ auto const& next_op = next_turn.operations[operations[next_index].operation_index];
if (op.seg_id.segment_index == next_op.seg_id.segment_index)
{
- turn_type const& prev_turn = turns[operations[p].turn_index];
- op_type const& prev_op = prev_turn.operations[operations[p].operation_index];
+ auto const& prev_turn = turns[operations[previous_index].turn_index];
+ auto const& prev_op = prev_turn.operations[operations[previous_index].operation_index];
if (op.seg_id.segment_index == prev_op.seg_id.segment_index)
{
op.enriched.startable = false;
next_phase = true;
}
}
- }
+ previous_index = index;
+ });
if (! next_phase)
{
@@ -255,12 +235,8 @@ inline void enrich_adapt(Operations& operations, Turns& turns)
// Discard turns which are both non-startable
next_phase = false;
- for (typename boost::range_iterator<Turns>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it)
+ for (auto& turn : turns)
{
- turn_type& turn = *it;
if (! turn.operations[0].enriched.startable
&& ! turn.operations[1].enriched.startable)
{
@@ -276,8 +252,8 @@ inline void enrich_adapt(Operations& operations, Turns& turns)
// Remove discarded turns from operations to avoid having them as next turn
discarded_indexed_turn<Turns> const predicate(turns);
- operations.erase(std::remove_if(boost::begin(operations),
- boost::end(operations), predicate), boost::end(operations));
+ operations.erase(std::remove_if(std::begin(operations),
+ std::end(operations), predicate), std::end(operations));
}
struct enriched_map_default_include_policy
@@ -290,52 +266,35 @@ struct enriched_map_default_include_policy
}
};
+// Add all (non discarded) operations on this ring
+// Blocked operations or uu on clusters (for intersection)
+// should be included, to block potential paths in clusters
template <typename Turns, typename MappedVector, typename IncludePolicy>
inline void create_map(Turns const& turns, MappedVector& mapped_vector,
IncludePolicy const& include_policy)
{
- typedef typename boost::range_value<Turns>::type turn_type;
- typedef typename turn_type::container_type container_type;
- typedef typename MappedVector::mapped_type mapped_type;
- typedef typename boost::range_value<mapped_type>::type indexed_type;
-
- std::size_t index = 0;
- for (typename boost::range_iterator<Turns const>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it, ++index)
+ for_each_with_index(turns, [&](std::size_t index, auto const& turn)
{
- // Add all (non discarded) operations on this ring
- // Blocked operations or uu on clusters (for intersection)
- // should be included, to block potential paths in clusters
- turn_type const& turn = *it;
- if (turn.discarded)
- {
- continue;
- }
-
- std::size_t op_index = 0;
- for (typename boost::range_iterator<container_type const>::type
- op_it = boost::begin(turn.operations);
- op_it != boost::end(turn.operations);
- ++op_it, ++op_index)
+ if (! turn.discarded)
{
- if (include_policy.include(op_it->operation))
+ for_each_with_index(turn.operations, [&](std::size_t op_index, auto const& op)
{
- ring_identifier const ring_id
- (
- op_it->seg_id.source_index,
- op_it->seg_id.multi_index,
- op_it->seg_id.ring_index
- );
- mapped_vector[ring_id].push_back
- (
- indexed_type(index, op_index, *op_it,
- it->operations[1 - op_index].seg_id)
- );
- }
+ if (include_policy.include(op.operation))
+ {
+ ring_identifier const ring_id
+ (
+ op.seg_id.source_index,
+ op.seg_id.multi_index,
+ op.seg_id.ring_index
+ );
+ mapped_vector[ring_id].emplace_back
+ (
+ index, op_index, op, turn.operations[1 - op_index].seg_id
+ );
+ }
+ });
}
- }
+ });
}
template <typename Point1, typename Point2>
@@ -344,7 +303,7 @@ inline typename geometry::coordinate_type<Point1>::type
{
// TODO: use comparable distance for point-point instead - but that
// causes currently cycling include problems
- typedef typename geometry::coordinate_type<Point1>::type ctype;
+ using ctype = typename geometry::coordinate_type<Point1>::type;
ctype const dx = get<0>(a) - get<0>(b);
ctype const dy = get<1>(a) - get<1>(b);
return dx * dx + dy * dy;
@@ -353,30 +312,24 @@ inline typename geometry::coordinate_type<Point1>::type
template <typename Turns>
inline void calculate_remaining_distance(Turns& turns)
{
- typedef typename boost::range_value<Turns>::type turn_type;
- typedef typename turn_type::turn_operation_type op_type;
-
- for (typename boost::range_iterator<Turns>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it)
+ for (auto& turn : turns)
{
- turn_type& turn = *it;
+ auto& op0 = turn.operations[0];
+ auto& op1 = turn.operations[1];
- op_type& op0 = turn.operations[0];
- op_type& op1 = turn.operations[1];
+ static decltype(op0.remaining_distance) const zero_distance = 0;
- if (op0.remaining_distance != 0
- || op1.remaining_distance != 0)
+ if (op0.remaining_distance != zero_distance
+ || op1.remaining_distance != zero_distance)
{
continue;
}
- signed_size_type const to_index0 = op0.enriched.get_next_turn_index();
- signed_size_type const to_index1 = op1.enriched.get_next_turn_index();
+ auto const to_index0 = op0.enriched.get_next_turn_index();
+ auto const to_index1 = op1.enriched.get_next_turn_index();
if (to_index0 >= 0
- && to_index1 >= 0
- && to_index0 != to_index1)
+ && to_index1 >= 0
+ && to_index0 != to_index1)
{
op0.remaining_distance = distance_measure(turn.point, turns[to_index0].point);
op1.remaining_distance = distance_measure(turn.point, turns[to_index1].point);
@@ -422,29 +375,28 @@ inline void enrich_intersection_points(Turns& turns,
RobustPolicy const& robust_policy,
IntersectionStrategy const& strategy)
{
- static const detail::overlay::operation_type target_operation
+ constexpr detail::overlay::operation_type target_operation
= detail::overlay::operation_from_overlay<OverlayType>::value;
- static const detail::overlay::operation_type opposite_operation
+ constexpr detail::overlay::operation_type opposite_operation
= target_operation == detail::overlay::operation_union
? detail::overlay::operation_intersection
: detail::overlay::operation_union;
- static const bool is_dissolve = OverlayType == overlay_dissolve;
+ constexpr bool is_dissolve = OverlayType == overlay_dissolve;
- typedef typename boost::range_value<Turns>::type turn_type;
- typedef typename turn_type::turn_operation_type op_type;
- typedef detail::overlay::indexed_turn_operation
+ using turn_type = typename boost::range_value<Turns>::type;
+ using indexed_turn_operation = detail::overlay::indexed_turn_operation
<
- op_type
- > indexed_turn_operation;
+ typename turn_type::turn_operation_type
+ > ;
- typedef std::map
+ using mapped_vector_type = std::map
<
ring_identifier,
std::vector<indexed_turn_operation>
- > mapped_vector_type;
+ >;
// From here on, turn indexes are used (in clusters, next_index, etc)
- // and may not be DELETED - they may only be flagged as discarded
+ // and turns may not be DELETED - they may only be flagged as discarded
discard_duplicate_start_turns(turns, geometry1, geometry2);
bool has_cc = false;
@@ -455,13 +407,8 @@ inline void enrich_intersection_points(Turns& turns,
>(turns, clusters, robust_policy);
// Discard turns not part of target overlay
- for (typename boost::range_iterator<Turns>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it)
+ for (auto& turn : turns)
{
- turn_type& turn = *it;
-
if (turn.both(detail::overlay::operation_none)
|| turn.both(opposite_operation)
|| turn.both(detail::overlay::operation_blocked)
@@ -514,20 +461,15 @@ inline void enrich_intersection_points(Turns& turns,
detail::overlay::create_map(turns, mapped_vector,
detail::overlay::enriched_map_default_include_policy());
- // 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)
+ for (auto& pair : mapped_vector)
{
detail::overlay::enrich_sort<Reverse1, Reverse2>(
- mit->second, turns,
+ pair.second, turns,
geometry1, geometry2,
- robust_policy, strategy.side()); // TODO: pass strategy
+ robust_policy, strategy);
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
- std::cout << "ENRICH-sort Ring " << mit->first << std::endl;
- for (auto const& op : mit->second)
+ std::cout << "ENRICH-sort Ring " << pair.first << std::endl;
+ for (auto const& op : pair.second)
{
std::cout << op.turn_index << " " << op.operation_index << std::endl;
}
@@ -551,20 +493,17 @@ inline void enrich_intersection_points(Turns& turns,
// After cleaning up clusters assign the next turns
- for (typename mapped_vector_type::iterator mit
- = mapped_vector.begin();
- mit != mapped_vector.end();
- ++mit)
+ for (auto& pair : mapped_vector)
{
#ifdef BOOST_GEOMETRY_DEBUG_ENRICH
- std::cout << "ENRICH-assign Ring " << mit->first << std::endl;
+ std::cout << "ENRICH-assign Ring " << pair.first << std::endl;
#endif
if (is_dissolve)
{
- detail::overlay::enrich_adapt(mit->second, turns);
+ detail::overlay::enrich_adapt(pair.second, turns);
}
- detail::overlay::enrich_assign(mit->second, turns, ! is_dissolve);
+ detail::overlay::enrich_assign(pair.second, turns, ! is_dissolve);
}
if (has_cc)
diff --git a/boost/geometry/algorithms/detail/overlay/follow.hpp b/boost/geometry/algorithms/detail/overlay/follow.hpp
index afcd2bd82e..d945605413 100644
--- a/boost/geometry/algorithms/detail/overlay/follow.hpp
+++ b/boost/geometry/algorithms/detail/overlay/follow.hpp
@@ -3,8 +3,8 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014-2020.
-// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -23,8 +23,8 @@
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.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>
@@ -422,13 +422,6 @@ public :
OutputIterator out,
Strategy const& strategy)
{
- 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, RemoveSpikes> action;
// Sort intersection points on segments-along-linestring, and distance
@@ -438,8 +431,7 @@ public :
// for different ring id: c, i, u, x
typedef relate::turns::less
<
- 0, relate::turns::less_op_linear_areal_single<0>,
- typename Strategy::cs_tag
+ 0, relate::turns::less_op_linear_areal_single<0>, Strategy
> turn_less;
std::sort(boost::begin(turns), boost::end(turns), turn_less());
@@ -449,51 +441,51 @@ public :
// 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)
+ for (auto const& turn : turns)
{
- turn_operation_iterator_type iit = boost::begin(it->operations);
+ auto const& op = turn.operations[0];
- if (following::was_entered(*it, *iit, first, linestring, polygon, strategy))
+ if (following::was_entered(turn, op, first, linestring, polygon, strategy))
{
- debug_traverse(*it, *iit, "-> Was entered");
+ debug_traverse(turn, op, "-> Was entered");
entered = true;
}
- if (following::is_staying_inside(*it, *iit, entered, first, linestring, polygon, strategy))
+ if (following::is_staying_inside(turn, op, entered, first, linestring, polygon, strategy))
{
- debug_traverse(*it, *iit, "-> Staying inside");
+ debug_traverse(turn, op, "-> Staying inside");
entered = true;
}
- else if (following::is_entering(*it, *iit))
+ else if (following::is_entering(turn, op))
{
- debug_traverse(*it, *iit, "-> Entering");
+ debug_traverse(turn, op, "-> Entering");
entered = true;
action::enter(current_piece, linestring, current_segment_id,
- iit->seg_id.segment_index, it->point, *iit,
+ op.seg_id.segment_index, turn.point, op,
strategy, robust_policy,
linear::get(out));
}
- else if (following::is_leaving(*it, *iit, entered, first, linestring, polygon, strategy))
+ else if (following::is_leaving(turn, op, entered, first, linestring, polygon, strategy))
{
- debug_traverse(*it, *iit, "-> Leaving");
+ debug_traverse(turn, op, "-> Leaving");
entered = false;
action::leave(current_piece, linestring, current_segment_id,
- iit->seg_id.segment_index, it->point, *iit,
+ op.seg_id.segment_index, turn.point, op,
strategy, robust_policy,
linear::get(out));
}
else if (BOOST_GEOMETRY_CONDITION(FollowIsolatedPoints)
- && following::is_touching(*it, *iit, entered))
+ && following::is_touching(turn, op, entered))
{
- debug_traverse(*it, *iit, "-> Isolated point");
+ debug_traverse(turn, op, "-> Isolated point");
action::template isolated_point
<
typename pointlike::type
- >(it->point, pointlike::get(out));
+ >(turn.point, pointlike::get(out));
}
first = false;
diff --git a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
index a3ad620162..5d1577c481 100644
--- a/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/follow_linear_linear.hpp
@@ -74,7 +74,7 @@ static inline bool is_entering(Turn const& turn,
template <typename Turn, typename Operation>
static inline bool is_staying_inside(Turn const& turn,
- Operation const& operation,
+ Operation const& operation,
bool entered)
{
if ( !entered )
@@ -327,21 +327,17 @@ public:
for (TurnIterator it = first; it != beyond; ++it)
{
oit = process_turn(it, boost::begin(it->operations),
- entered, enter_count,
+ entered, enter_count,
linestring,
current_piece, current_segment_id,
oit,
strategy);
}
-#if ! defined(BOOST_GEOMETRY_OVERLAY_NO_THROW)
if (enter_count != 0)
{
- BOOST_THROW_EXCEPTION(inconsistent_turns_exception());
+ return oit;
}
-#else
- BOOST_GEOMETRY_ASSERT(enter_count == 0);
-#endif
return process_end(entered, linestring,
current_segment_id, current_piece,
diff --git a/boost/geometry/algorithms/detail/overlay/get_clusters.hpp b/boost/geometry/algorithms/detail/overlay/get_clusters.hpp
index 1e612d6577..2747fa68ba 100644
--- a/boost/geometry/algorithms/detail/overlay/get_clusters.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_clusters.hpp
@@ -35,19 +35,29 @@ namespace detail { namespace overlay
template <typename Tag = no_rescale_policy_tag, bool Integral = false>
struct sweep_equal_policy
{
+private:
+ template <typename T>
+ static inline T threshold()
+ {
+ // Points within some epsilons are considered as equal.
+ return T(100);
+ }
+public:
+ // Returns true if point are considered equal (within an epsilon)
template <typename P>
static inline bool equals(P const& p1, P const& p2)
{
- // Points within a kilo epsilon are considered as equal
- return approximately_equals(p1, p2, 1000.0);
+ using coor_t = typename coordinate_type<P>::type;
+ return approximately_equals(p1, p2, threshold<coor_t>());
}
template <typename T>
static inline bool exceeds(T value)
{
// This threshold is an arbitrary value
- // as long as it is than the used kilo-epsilon
- return value > 1.0e-3;
+ // as long as it is bigger than the used value above
+ T const limit = T(1) / threshold<T>();
+ return value > limit;
}
};
diff --git a/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp b/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp
index 82ab3d5d04..d462bb524d 100644
--- a/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp
@@ -1,6 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2019 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2019-2021 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2022.
+// Modifications copyright (c) 2022 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -61,53 +65,48 @@ namespace detail_dispatch
template <typename CalculationType, typename CsTag>
struct get_distance_measure
- : not_implemented<CsTag>
+ : not_implemented<CsTag>
{};
template <typename CalculationType>
-struct get_distance_measure<CalculationType, cartesian_tag>
+struct get_distance_measure<CalculationType, spherical_tag>
{
- typedef detail::distance_measure<CalculationType> result_type;
+ // By default the distance measure is zero, no side difference
+ using result_type = detail::distance_measure<CalculationType>;
template <typename SegmentPoint, typename Point>
- static result_type apply(SegmentPoint const& p1, SegmentPoint const& p2,
- Point const& p)
+ static result_type apply(SegmentPoint const& , SegmentPoint const& ,
+ Point const& )
{
- // Get the distance measure / side value
- // It is not a real distance and purpose is
- // to detect small differences in collinearity
-
- typedef model::infinite_line<CalculationType> line_type;
- line_type const line = detail::make::make_infinite_line<CalculationType>(p1, p2);
- result_type result;
- result.measure = arithmetic::side_value(line, p);
+ const result_type result;
return result;
}
};
template <typename CalculationType>
-struct get_distance_measure<CalculationType, spherical_tag>
+struct get_distance_measure<CalculationType, geographic_tag>
+ : get_distance_measure<CalculationType, spherical_tag>
+{};
+
+template <typename CalculationType>
+struct get_distance_measure<CalculationType, cartesian_tag>
{
- typedef detail::distance_measure<CalculationType> result_type;
+ using result_type = detail::distance_measure<CalculationType>;
template <typename SegmentPoint, typename Point>
- static result_type apply(SegmentPoint const& , SegmentPoint const& ,
- Point const& )
+ static result_type apply(SegmentPoint const& p1, SegmentPoint const& p2,
+ Point const& p)
{
- // TODO, optional
+ // Get the distance measure / side value
+ // It is not a real distance and purpose is
+ // to detect small differences in collinearity
+ auto const line = detail::make::make_infinite_line<CalculationType>(p1, p2);
result_type result;
+ result.measure = arithmetic::side_value(line, p);
return result;
}
};
-template <typename CalculationType>
-struct get_distance_measure<CalculationType, geographic_tag>
- : get_distance_measure<CalculationType, spherical_tag> {};
-
-template <typename CalculationType>
-struct get_distance_measure<CalculationType, spherical_equatorial_tag>
- : get_distance_measure<CalculationType, spherical_tag> {};
-
} // namespace detail_dispatch
namespace detail
@@ -117,18 +116,32 @@ namespace detail
// 0 (absolutely 0, not even an epsilon) means collinear. Like side,
// a negative means that p is to the right of p1-p2. And a positive value
// means that p is to the left of p1-p2.
-
-template <typename SegmentPoint, typename Point>
-static distance_measure<typename select_coordinate_type<SegmentPoint, Point>::type>
-get_distance_measure(SegmentPoint const& p1, SegmentPoint const& p2, Point const& p)
+template <typename SegmentPoint, typename Point, typename Strategies>
+inline auto get_distance_measure(SegmentPoint const& p1, SegmentPoint const& p2, Point const& p,
+ Strategies const&)
{
- typedef typename geometry::cs_tag<Point>::type cs_tag;
- return detail_dispatch::get_distance_measure
- <
- typename select_coordinate_type<SegmentPoint, Point>::type,
- cs_tag
- >::apply(p1, p2, p);
+ using calc_t = typename select_coordinate_type<SegmentPoint, Point>::type;
+
+ // Verify equality, without using a tolerance
+ // (so don't use equals or equals_point_point)
+ // because it is about very tiny differences.
+ auto identical = [](const auto& point1, const auto& point2)
+ {
+ return geometry::get<0>(point1) == geometry::get<0>(point2)
+ && geometry::get<1>(point1) == geometry::get<1>(point2);
+ };
+ if (identical(p1, p) || identical(p2, p))
+ {
+ detail::distance_measure<calc_t> const result;
+ return result;
+ }
+
+ return detail_dispatch::get_distance_measure
+ <
+ calc_t,
+ typename Strategies::cs_tag
+ >::apply(p1, p2, p);
}
} // namespace detail
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
index fcd3635fd6..4e10c07bde 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp
@@ -1,11 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2007-2021 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2015-2020.
-// Modifications copyright (c) 2015-2020 Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2015-2022.
+// Modifications copyright (c) 2015-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -26,14 +25,9 @@
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_distance_measure.hpp>
#include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
-
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp>
-// Silence warning C4127: conditional expression is constant
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4127)
-#endif
+#include <boost/geometry/util/condition.hpp>
namespace boost { namespace geometry
@@ -66,6 +60,36 @@ public:
namespace detail { namespace overlay
{
+
+struct policy_verify_nothing
+{
+ static bool const use_side_verification = false;
+ static bool const use_start_turn = false;
+ static bool const use_handle_as_touch = false;
+ static bool const use_handle_as_equal = false;
+ static bool const use_handle_imperfect_touch = false;
+};
+
+struct policy_verify_all
+{
+ static bool const use_side_verification = true;
+ static bool const use_start_turn = true;
+ static bool const use_handle_as_touch = true;
+ static bool const use_handle_as_equal = true;
+ static bool const use_handle_imperfect_touch = true;
+};
+
+
+#if defined(BOOST_GEOMETRY_USE_RESCALING)
+using verify_policy_aa = policy_verify_nothing;
+#else
+using verify_policy_aa = policy_verify_all;
+#endif
+
+using verify_policy_ll = policy_verify_nothing;
+using verify_policy_la = policy_verify_nothing;
+
+
struct base_turn_handler
{
// Returns true if both sides are opposite
@@ -107,52 +131,6 @@ struct base_turn_handler
both(ti, condition ? operation_union : operation_intersection);
}
-
-#if ! defined(BOOST_GEOMETRY_USE_RESCALING)
- template
- <
- typename UniqueSubRange1,
- typename UniqueSubRange2
- >
- static inline int side_with_distance_measure(UniqueSubRange1 const& range_p,
- UniqueSubRange2 const& range_q,
- int range_index, int point_index)
- {
- if (range_index >= 1 && range_p.is_last_segment())
- {
- return 0;
- }
- if (point_index >= 2 && range_q.is_last_segment())
- {
- return 0;
- }
-
- auto const dm = get_distance_measure(range_p.at(range_index), range_p.at(range_index + 1), range_q.at(point_index));
- return dm.measure == 0 ? 0 : dm.measure > 0 ? 1 : -1;
- }
-
- template
- <
- typename UniqueSubRange1,
- typename UniqueSubRange2
- >
- static inline int verified_side(int side,
- UniqueSubRange1 const& range_p,
- UniqueSubRange2 const& range_q,
- int range_index,
- int point_index)
- {
- return side == 0 ? side_with_distance_measure(range_p, range_q, range_index, point_index) : side;
- }
-#else
- template <typename T1, typename T2>
- static inline int verified_side(int side, T1 const& , T2 const& , int , int)
- {
- return side;
- }
-#endif
-
-
template <typename TurnInfo, typename IntersectionInfo>
static inline void assign_point(TurnInfo& ti,
method_type method,
@@ -208,14 +186,22 @@ struct base_turn_handler
? 1 : 0;
}
+};
+
+template<typename VerifyPolicy>
+struct turn_info_verification_functions
+{
template <typename Point1, typename Point2>
- static inline typename geometry::coordinate_type<Point1>::type
- distance_measure(Point1 const& a, Point2 const& b)
+ static inline
+ typename select_coordinate_type<Point1, Point2>::type
+ distance_measure(Point1 const& a, Point2 const& b)
{
- // TODO: use comparable distance for point-point instead - but that
- // causes currently cycling include problems
- auto const dx = get<0>(a) - get<0>(b);
- auto const dy = get<1>(a) - get<1>(b);
+ // TODO: revise this using comparable distance for various
+ // coordinate systems
+ using coor_t = typename select_coordinate_type<Point1, Point2>::type;
+
+ coor_t const dx = get<0>(a) - get<0>(b);
+ coor_t const dy = get<1>(a) - get<1>(b);
return dx * dx + dy * dy;
}
@@ -228,50 +214,127 @@ struct base_turn_handler
typename UmbrellaStrategy,
typename TurnInfo
>
- static inline void both_collinear(
+ static inline void set_both_verified(
UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
- UmbrellaStrategy const&,
+ UmbrellaStrategy const& umbrella_strategy,
std::size_t index_p, std::size_t index_q,
TurnInfo& ti)
{
- boost::ignore_unused(range_p, range_q);
BOOST_GEOMETRY_ASSERT(IndexP + IndexQ == 1);
BOOST_GEOMETRY_ASSERT(index_p > 0 && index_p <= 2);
BOOST_GEOMETRY_ASSERT(index_q > 0 && index_q <= 2);
-#if ! defined(BOOST_GEOMETRY_USE_RESCALING)
- ti.operations[IndexP].remaining_distance = distance_measure(ti.point, range_p.at(index_p));
- ti.operations[IndexQ].remaining_distance = distance_measure(ti.point, range_q.at(index_q));
-
- // pk/q2 is considered as collinear, but there might be
- // a tiny measurable difference. If so, use that.
- // Calculate pk // qj-qk
- bool const p_closer =
- ti.operations[IndexP].remaining_distance
- < ti.operations[IndexQ].remaining_distance;
- auto const dm
+ using distance_measure_result_type = typename geometry::coordinate_type<decltype(ti.point)>::type;
+
+ bool const p_in_range = index_p < range_p.size();
+ bool const q_in_range = index_q < range_q.size();
+ ti.operations[IndexP].remaining_distance
+ = p_in_range
+ ? distance_measure(ti.point, range_p.at(index_p))
+ : distance_measure_result_type{0};
+ ti.operations[IndexQ].remaining_distance
+ = q_in_range
+ ? distance_measure(ti.point, range_q.at(index_q))
+ : distance_measure_result_type{0};
+
+ if (p_in_range && q_in_range)
+ {
+ // pk/q2 is considered as collinear, but there might be
+ // a tiny measurable difference. If so, use that.
+ // Calculate pk // qj-qk
+ bool const p_closer
+ = ti.operations[IndexP].remaining_distance
+ < ti.operations[IndexQ].remaining_distance;
+ auto const dm
= p_closer
? get_distance_measure(range_q.at(index_q - 1),
- range_q.at(index_q), range_p.at(index_p))
+ range_q.at(index_q), range_p.at(index_p),
+ umbrella_strategy)
: get_distance_measure(range_p.at(index_p - 1),
- range_p.at(index_p), range_q.at(index_q));
+ range_p.at(index_p), range_q.at(index_q),
+ umbrella_strategy);
+
+ if (! dm.is_zero())
+ {
+ // Not truely collinear, distinguish for union/intersection
+ // If p goes left (positive), take that for a union
+ bool const p_left
+ = p_closer ? dm.is_positive() : dm.is_negative();
+
+ ti.operations[IndexP].operation = p_left
+ ? operation_union : operation_intersection;
+ ti.operations[IndexQ].operation = p_left
+ ? operation_intersection : operation_union;
+ return;
+ }
+ }
+
+ base_turn_handler::both(ti, operation_continue);
+ }
- if (! dm.is_zero())
+ template
+ <
+ std::size_t IndexP,
+ std::size_t IndexQ,
+ typename UniqueSubRange1,
+ typename UniqueSubRange2,
+ typename UmbrellaStrategy,
+ typename TurnInfo
+ >
+ static inline void both_collinear(
+ UniqueSubRange1 const& range_p,
+ UniqueSubRange2 const& range_q,
+ UmbrellaStrategy const& umbrella_strategy,
+ std::size_t index_p, std::size_t index_q,
+ TurnInfo& ti)
+ {
+ if (BOOST_GEOMETRY_CONDITION(VerifyPolicy::use_side_verification))
{
- // Not truely collinear, distinguish for union/intersection
- // If p goes left (positive), take that for a union
- bool const p_left = p_closer ? dm.is_positive() : dm.is_negative();
-
- ti.operations[IndexP].operation = p_left
- ? operation_union : operation_intersection;
- ti.operations[IndexQ].operation = p_left
- ? operation_intersection : operation_union;
- return;
+ set_both_verified<IndexP, IndexQ>(range_p, range_q, umbrella_strategy,
+ index_p, index_q, ti);
}
-#endif
+ else
+ {
+ base_turn_handler::both(ti, operation_continue);
+ }
+ }
- both(ti, operation_continue);
+ template
+ <
+ typename UniqueSubRange1,
+ typename UniqueSubRange2,
+ typename UmbrellaStrategy
+ >
+ static inline int verified_side(int side,
+ UniqueSubRange1 const& range_p,
+ UniqueSubRange2 const& range_q,
+ UmbrellaStrategy const& umbrella_strategy,
+ int index_p, int index_q)
+ {
+ if (side == 0
+ && BOOST_GEOMETRY_CONDITION(VerifyPolicy::use_side_verification))
+ {
+ if (index_p >= 1 && range_p.is_last_segment())
+ {
+ return 0;
+ }
+ if (index_q >= 2 && range_q.is_last_segment())
+ {
+ return 0;
+ }
+
+ auto const dm = get_distance_measure(range_p.at(index_p),
+ range_p.at(index_p + 1),
+ range_q.at(index_q),
+ umbrella_strategy);
+ static decltype(dm.measure) const zero = 0;
+ return dm.measure == zero ? 0 : dm.measure > zero ? 1 : -1;
+ }
+ else
+ {
+ return side;
+ }
}
};
@@ -279,10 +342,12 @@ struct base_turn_handler
template
<
- typename TurnInfo
+ typename TurnInfo,
+ typename VerifyPolicy
>
struct touch_interior : public base_turn_handler
{
+ using fun = turn_info_verification_functions<VerifyPolicy>;
template
<
@@ -292,9 +357,11 @@ struct touch_interior : public base_turn_handler
static bool handle_as_touch(IntersectionInfo const& info,
UniqueSubRange const& non_touching_range)
{
-#if defined(BOOST_GEOMETRY_USE_RESCALING)
- return false;
-#endif
+ if (! BOOST_GEOMETRY_CONDITION(VerifyPolicy::use_handle_as_touch))
+ {
+ return false;
+ }
+
//
//
// ^ Q(i) ^ P(i)
@@ -325,7 +392,7 @@ struct touch_interior : public base_turn_handler
// Therefore handle it as a normal touch (two segments arrive at the
// intersection point). It currently checks for zero, but even a
// distance a little bit larger would do.
- auto const dm = distance_measure(info.intersections[0], non_touching_range.at(1));
+ auto const dm = fun::distance_measure(info.intersections[0], non_touching_range.at(1));
decltype(dm) const zero = 0;
bool const result = math::equals(dm, zero);
return result;
@@ -448,7 +515,8 @@ struct touch_interior : public base_turn_handler
// Q intersects on interior of P and continues collinearly
if (side_qk_q == side_qi_p)
{
- both_collinear<index_p, index_q>(range_p, range_q, umbrella_strategy, 1, 2, ti);
+ fun::template both_collinear<index_p, index_q>(range_p, range_q, umbrella_strategy,
+ 1, 2, ti);
}
else
{
@@ -472,24 +540,35 @@ struct touch_interior : public base_turn_handler
template
<
- typename TurnInfo
+ typename TurnInfo,
+ typename VerifyPolicy
>
struct touch : public base_turn_handler
{
+ using fun = turn_info_verification_functions<VerifyPolicy>;
+
static inline bool between(int side1, int side2, int turn)
{
return side1 == side2 && ! opposite(side1, turn);
}
-#if ! defined(BOOST_GEOMETRY_USE_RESCALING)
template
<
typename UniqueSubRange1,
- typename UniqueSubRange2
+ typename UniqueSubRange2,
+ typename UmbrellaStrategy
>
static inline bool handle_imperfect_touch(UniqueSubRange1 const& range_p,
- UniqueSubRange2 const& range_q, TurnInfo& ti)
+ UniqueSubRange2 const& range_q,
+ int side_pk_q2,
+ UmbrellaStrategy const& umbrella_strategy,
+ TurnInfo& ti)
{
+ if (! BOOST_GEOMETRY_CONDITION(VerifyPolicy::use_handle_imperfect_touch))
+ {
+ return false;
+ }
+
// Q
// ^
// ||
@@ -513,13 +592,18 @@ struct touch : public base_turn_handler
// >----->P qj is LEFT of P1 and pi is LEFT of Q2
// (the other way round is also possible)
- auto const dm_qj_p1 = get_distance_measure(range_p.at(0), range_p.at(1), range_q.at(1));
- auto const dm_pi_q2 = get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(0));
+ auto has_distance = [&](const auto& r1, const auto& r2) -> bool
+ {
+ auto const d1 = get_distance_measure(r1.at(0), r1.at(1), r2.at(1), umbrella_strategy);
+ auto const d2 = get_distance_measure(r2.at(1), r2.at(2), r1.at(0), umbrella_strategy);
+ return d1.measure > 0 && d2.measure > 0;
+ };
- if (dm_qj_p1.measure > 0 && dm_pi_q2.measure > 0)
+ if (side_pk_q2 == -1 && has_distance(range_p, range_q))
{
// Even though there is a touch, Q(j) is left of P1
// and P(i) is still left from Q2.
+ // Q continues to the right.
// It can continue.
ti.operations[0].operation = operation_blocked;
// Q turns right -> union (both independent),
@@ -529,24 +613,17 @@ struct touch : public base_turn_handler
return true;
}
- auto const dm_pj_q1 = get_distance_measure(range_q.at(0), range_q.at(1), range_p.at(1));
- auto const dm_qi_p2 = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(0));
-
- if (dm_pj_q1.measure > 0 && dm_qi_p2.measure > 0)
+ if (side_pk_q2 == 1 && has_distance(range_q, range_p))
{
- // Even though there is a touch, Q(j) is left of P1
- // and P(i) is still left from Q2.
- // It can continue.
+ // Similarly, but the other way round.
+ // Q continues to the left.
ti.operations[0].operation = operation_union;
- // Q turns right -> union (both independent),
- // Q turns left -> intersection
ti.operations[1].operation = operation_blocked;
ti.touch_only = true;
return true;
}
return false;
}
-#endif
template
<
@@ -572,8 +649,12 @@ struct touch : public base_turn_handler
int const side_pk_q1 = has_pk ? side.pk_wrt_q1() : 0;
- int const side_qi_p1 = verified_side(dir_info.sides.template get<1, 0>(), range_p, range_q, 0, 0);
- int const side_qk_p1 = has_qk ? verified_side(side.qk_wrt_p1(), range_p, range_q, 0, 2) : 0;
+ int const side_qi_p1 = fun::verified_side(dir_info.sides.template get<1, 0>(),
+ range_p, range_q, umbrella_strategy, 0, 0);
+ int const side_qk_p1 = has_qk
+ ? fun::verified_side(side.qk_wrt_p1(), range_p, range_q,
+ umbrella_strategy, 0, 2)
+ : 0;
// If Qi and Qk are both at same side of Pi-Pj,
// or collinear (so: not opposite sides)
@@ -596,21 +677,20 @@ struct touch : public base_turn_handler
|| side_pk_p == side_qk_p1
|| (side_qi_p1 == 0 && side_qk_p1 == 0 && side_pk_p != -1))
{
-#if ! defined(BOOST_GEOMETRY_USE_RESCALING)
if (side_qk_p1 == 0 && side_pk_q1 == 0
- && has_qk && has_qk
- && handle_imperfect_touch(range_p, range_q, ti))
+ && has_pk && has_qk
+ && handle_imperfect_touch(range_p, range_q, side_pk_q2, umbrella_strategy, ti))
{
// If q continues collinearly (opposite) with p, it should be blocked
// but (FP) not if there is just a tiny space in between
return;
}
-#endif
// Collinear -> lines join, continue
// (#BRL2)
if (side_pk_q2 == 0 && ! block_q)
{
- both_collinear<0, 1>(range_p, range_q, umbrella_strategy, 2, 2, ti);
+ fun::template both_collinear<0, 1>(range_p, range_q, umbrella_strategy,
+ 2, 2, ti);
return;
}
@@ -687,7 +767,10 @@ struct touch : public base_turn_handler
{
// The qi/qk are opposite to each other, w.r.t. p1
// From left to right or from right to left
- int const side_pk_p = has_pk ? verified_side(side.pk_wrt_p1(), range_p, range_p, 0, 2) : 0;
+ int const side_pk_p = has_pk
+ ? fun::verified_side(side.pk_wrt_p1(), range_p, range_p,
+ umbrella_strategy, 0, 2)
+ : 0;
bool const right_to_left = side_qk_p1 == 1;
// If p turns into direction of qi (1,2)
@@ -738,10 +821,13 @@ struct touch : public base_turn_handler
template
<
- typename TurnInfo
+ typename TurnInfo,
+ typename VerifyPolicy
>
struct equal : public base_turn_handler
{
+ using fun = turn_info_verification_functions<VerifyPolicy>;
+
template
<
typename UniqueSubRange1,
@@ -769,17 +855,18 @@ struct equal : public base_turn_handler
int const side_pk_p = has_pk ? side.pk_wrt_p1() : 0;
int const side_qk_p = has_qk ? side.qk_wrt_p1() : 0;
-#if ! defined(BOOST_GEOMETRY_USE_RESCALING)
-
- if (has_pk && has_qk && side_pk_p == side_qk_p)
+ if (BOOST_GEOMETRY_CONDITION(VerifyPolicy::use_side_verification)
+ && has_pk && has_qk && side_pk_p == side_qk_p)
{
// They turn to the same side, or continue both collinearly
// Without rescaling, to check for union/intersection,
// try to check side values (without any thresholds)
auto const dm_pk_q2
- = get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(2));
+ = get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(2),
+ umbrella_strategy);
auto const dm_qk_p2
- = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(2));
+ = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(2),
+ umbrella_strategy);
if (dm_qk_p2.measure != dm_pk_q2.measure)
{
@@ -789,7 +876,6 @@ struct equal : public base_turn_handler
return;
}
}
-#endif
// If pk is collinear with qj-qk, they continue collinearly.
// This can be on either side of p1 (== q1), or collinear
@@ -797,7 +883,7 @@ struct equal : public base_turn_handler
// oppositely
if (side_pk_q2 == 0 && side_pk_p == side_qk_p)
{
- both_collinear<0, 1>(range_p, range_q, umbrella_strategy, 2, 2, ti);
+ fun::template both_collinear<0, 1>(range_p, range_q, umbrella_strategy, 2, 2, ti);
return;
}
@@ -819,7 +905,8 @@ struct equal : public base_turn_handler
template
<
- typename TurnInfo
+ typename TurnInfo,
+ typename VerifyPolicy
>
struct start : public base_turn_handler
{
@@ -840,10 +927,10 @@ struct start : public base_turn_handler
SideCalculator const& side,
UmbrellaStrategy const& )
{
-#if defined(BOOST_GEOMETRY_USE_RESCALING)
- // With rescaling, start turns are not needed.
- return false;
-#endif
+ if (! BOOST_GEOMETRY_CONDITION(VerifyPolicy::use_start_turn))
+ {
+ return false;
+ }
// Start turns have either how_a = -1, or how_b = -1 (either p leaves or q leaves)
BOOST_GEOMETRY_ASSERT(dir_info.how_a != dir_info.how_b);
@@ -898,7 +985,7 @@ struct equal_opposite : public base_turn_handler
IntersectionInfo const& intersection_info)
{
// For equal-opposite segments, normally don't do anything.
- if (AssignPolicy::include_opposite)
+ if (BOOST_GEOMETRY_CONDITION(AssignPolicy::include_opposite))
{
tp.method = method_equal;
for (unsigned int i = 0; i < 2; i++)
@@ -916,10 +1003,13 @@ struct equal_opposite : public base_turn_handler
template
<
- typename TurnInfo
+ typename TurnInfo,
+ typename VerifyPolicy
>
struct collinear : public base_turn_handler
{
+ using fun = turn_info_verification_functions<VerifyPolicy>;
+
template
<
typename IntersectionInfo,
@@ -932,9 +1022,11 @@ struct collinear : public base_turn_handler
UniqueSubRange2 const& range_q,
DirInfo const& dir_info)
{
-#if defined(BOOST_GEOMETRY_USE_RESCALING)
- return false;
-#endif
+ if (! BOOST_GEOMETRY_CONDITION(VerifyPolicy::use_handle_as_equal))
+ {
+ return false;
+ }
+
int const arrival_p = dir_info.arrival[0];
int const arrival_q = dir_info.arrival[1];
if (arrival_p * arrival_q != -1 || info.count != 2)
@@ -943,8 +1035,9 @@ struct collinear : public base_turn_handler
return false;
}
- auto const dm = distance_measure(info.intersections[1],
- arrival_p == 1 ? range_q.at(1) : range_p.at(1));
+ auto const dm = arrival_p == 1
+ ? fun::distance_measure(info.intersections[1], range_q.at(1))
+ : fun::distance_measure(info.intersections[1], range_p.at(1));
decltype(dm) const zero = 0;
return math::equals(dm, zero);
}
@@ -1046,12 +1139,12 @@ struct collinear : public base_turn_handler
// measured until the end of the next segment
ti.operations[0].remaining_distance
= side_p == 0 && has_pk
- ? distance_measure(ti.point, range_p.at(2))
- : distance_measure(ti.point, range_p.at(1));
+ ? fun::distance_measure(ti.point, range_p.at(2))
+ : fun::distance_measure(ti.point, range_p.at(1));
ti.operations[1].remaining_distance
= side_q == 0 && has_qk
- ? distance_measure(ti.point, range_q.at(2))
- : distance_measure(ti.point, range_q.at(1));
+ ? fun::distance_measure(ti.point, range_q.at(2))
+ : fun::distance_measure(ti.point, range_q.at(1));
}
};
@@ -1110,7 +1203,7 @@ private :
// 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)
+ if (BOOST_GEOMETRY_CONDITION(AssignPolicy::include_opposite))
{
tp.operations[Index].operation = operation_opposite;
blocked = operation_opposite;
@@ -1204,7 +1297,7 @@ public:
*out++ = tp;
}
- if (AssignPolicy::include_opposite)
+ if (BOOST_GEOMETRY_CONDITION(AssignPolicy::include_opposite))
{
// Handle cases not yet handled above
if ((arrival_q == -1 && arrival_p == 0)
@@ -1352,8 +1445,11 @@ struct get_turn_info
if (handle_as_start)
{
// It is in some cases necessary to handle a start turn
- if (AssignPolicy::include_start_turn
- && start<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides(), umbrella_strategy))
+ using handler = start<TurnInfo, verify_policy_aa>;
+ if (BOOST_GEOMETRY_CONDITION(AssignPolicy::include_start_turn)
+ && handler::apply(range_p, range_q, tp,
+ inters.i_info(), inters.d_info(), inters.sides(),
+ umbrella_strategy))
{
*out++ = tp;
}
@@ -1365,7 +1461,7 @@ struct get_turn_info
if (handle_as_touch_interior)
{
- typedef touch_interior<TurnInfo> handler;
+ using handler = touch_interior<TurnInfo, verify_policy_aa>;
if ( inters.d_info().arrival[1] == 1 )
{
@@ -1406,7 +1502,9 @@ struct get_turn_info
if (handle_as_touch)
{
// Touch: both segments arrive at the intersection point
- touch<TurnInfo>::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides(), umbrella_strategy);
+ using handler = touch<TurnInfo, verify_policy_aa>;
+ handler::apply(range_p, range_q, tp, inters.i_info(), inters.d_info(), inters.sides(),
+ umbrella_strategy);
*out++ = tp;
}
@@ -1415,16 +1513,17 @@ struct get_turn_info
// Collinear
if ( ! inters.d_info().opposite )
{
+ using handler = collinear<TurnInfo, verify_policy_aa>;
if (inters.d_info().arrival[0] == 0
- || collinear<TurnInfo>::handle_as_equal(inters.i_info(), range_p, range_q, inters.d_info()))
+ || handler::handle_as_equal(inters.i_info(), range_p, range_q, inters.d_info()))
{
// Both segments arrive at the second intersection point
handle_as_equal = true;
}
else
{
- collinear<TurnInfo>::apply(range_p, range_q, tp,
- inters.i_info(), inters.d_info(), inters.sides());
+ handler::apply(range_p, range_q, tp, inters.i_info(),
+ inters.d_info(), inters.sides());
*out++ = tp;
}
}
@@ -1445,7 +1544,8 @@ struct get_turn_info
{
// Both equal
// or collinear-and-ending at intersection point
- equal<TurnInfo>::apply(range_p, range_q, tp,
+ using handler = equal<TurnInfo, verify_policy_aa>;
+ handler::apply(range_p, range_q, tp,
inters.i_info(), inters.d_info(), inters.sides(),
umbrella_strategy);
if (handle_as_collinear)
@@ -1467,8 +1567,10 @@ struct get_turn_info
}
}
- if ((handle_as_degenerate && AssignPolicy::include_degenerate)
- || (do_only_convert && AssignPolicy::include_no_turn))
+ if ((handle_as_degenerate
+ && BOOST_GEOMETRY_CONDITION(AssignPolicy::include_degenerate))
+ || (do_only_convert
+ && BOOST_GEOMETRY_CONDITION(AssignPolicy::include_no_turn)))
{
if (inters.i_info().count > 0)
{
@@ -1489,8 +1591,4 @@ struct get_turn_info
}} // 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_turn_info_for_endpoint.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp
index 2b56d7dd57..007ada0f2f 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp
@@ -201,7 +201,7 @@ public:
BOOST_STATIC_ASSERT(I < 2);
return ips[I];
}
-
+
private:
// only if collinear (same_dirs)
@@ -287,7 +287,7 @@ struct get_turn_info_for_endpoint
if ( intersections.template get<1>().p_operation == operation_none )
return result_ignore_ip0;
-
+
bool append1_last
= analyse_segment_and_assign_ip(range_p, range_q,
intersections.template get<1>(),
@@ -436,7 +436,7 @@ struct get_turn_info_for_endpoint
if ( operations_both(operations, operation_continue) )
{
- if ( op1 != operation_union
+ if ( op1 != operation_union
|| op2 != operation_union
|| ! ( G1Index == 0 ? inters.is_spike_q() : inters.is_spike_p() ) )
{
@@ -544,7 +544,7 @@ struct get_turn_info_for_endpoint
OutputIterator out)
{
TurnInfo tp = tp_model;
-
+
//geometry::convert(ip, tp.point);
//tp.method = method;
base_turn_handler::assign_point(tp, method, result.intersection_points, ip_index);
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
index b82528fa4d..00a6004f2d 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_helpers.hpp
@@ -50,8 +50,6 @@ template
>
struct side_calculator
{
- typedef typename UniqueSubRange1::point_type point1_type;
- typedef typename UniqueSubRange2::point_type point2_type;
typedef decltype(std::declval<Strategy>().side()) side_strategy_type;
inline side_calculator(UniqueSubRange1 const& range_p,
@@ -76,13 +74,13 @@ struct side_calculator
inline int pj_wrt_q1() const { return m_side_strategy.apply(get_qi(), get_qj(), get_pj()); }
inline int pj_wrt_q2() const { return m_side_strategy.apply(get_qj(), get_qk(), get_pj()); }
- inline point1_type const& get_pi() const { return m_range_p.at(0); }
- inline point1_type const& get_pj() const { return m_range_p.at(1); }
- inline point1_type const& get_pk() const { return m_range_p.at(2); }
+ inline auto const& get_pi() const { return m_range_p.at(0); }
+ inline auto const& get_pj() const { return m_range_p.at(1); }
+ inline auto const& get_pk() const { return m_range_p.at(2); }
- inline point2_type const& get_qi() const { return m_range_q.at(0); }
- inline point2_type const& get_qj() const { return m_range_q.at(1); }
- inline point2_type const& get_qk() const { return m_range_q.at(2); }
+ inline auto const& get_qi() const { return m_range_q.at(0); }
+ inline auto const& get_qj() const { return m_range_q.at(1); }
+ inline auto const& get_qk() const { return m_range_q.at(2); }
// Used side-strategy, owned by the calculator
side_strategy_type m_side_strategy;
@@ -338,9 +336,6 @@ public:
typedef typename intersection_policy_type::return_type result_type;
- typedef typename UniqueSubRange1::point_type point1_type;
- typedef typename UniqueSubRange2::point_type point2_type;
-
typedef side_calculator
<
UniqueSubRange1, UniqueSubRange2, UmbrellaStrategy
@@ -350,7 +345,7 @@ public:
<
UniqueSubRange2, UniqueSubRange1, UmbrellaStrategy
> swapped_side_calculator_type;
-
+
intersection_info_base(UniqueSubRange1 const& range_p,
UniqueSubRange2 const& range_q,
UmbrellaStrategy const& umbrella_strategy,
@@ -366,13 +361,13 @@ public:
inline bool p_is_last_segment() const { return m_range_p.is_last_segment(); }
inline bool q_is_last_segment() const { return m_range_q.is_last_segment(); }
- inline point1_type const& rpi() const { return m_side_calc.get_pi(); }
- inline point1_type const& rpj() const { return m_side_calc.get_pj(); }
- inline point1_type const& rpk() const { return m_side_calc.get_pk(); }
+ inline auto const& rpi() const { return m_side_calc.get_pi(); }
+ inline auto const& rpj() const { return m_side_calc.get_pj(); }
+ inline auto const& rpk() const { return m_side_calc.get_pk(); }
- inline point2_type const& rqi() const { return m_side_calc.get_qi(); }
- inline point2_type const& rqj() const { return m_side_calc.get_qj(); }
- inline point2_type const& rqk() const { return m_side_calc.get_qk(); }
+ inline auto const& rqi() const { return m_side_calc.get_qi(); }
+ inline auto const& rqj() const { return m_side_calc.get_qj(); }
+ inline auto const& rqk() const { return m_side_calc.get_qk(); }
inline side_calculator_type const& sides() const { return m_side_calc; }
inline swapped_side_calculator_type const& swapped_sides() const
@@ -410,14 +405,11 @@ class intersection_info
public:
- typedef typename UniqueSubRange1::point_type point1_type;
- typedef typename UniqueSubRange2::point_type point2_type;
-
typedef typename UmbrellaStrategy::cs_tag cs_tag;
typedef typename base::side_calculator_type side_calculator_type;
typedef typename base::result_type result_type;
-
+
typedef typename result_type::intersection_points_type i_info_type;
typedef typename result_type::direction_type d_info_type;
@@ -470,7 +462,7 @@ public:
return true;
}
}
-
+
return false;
}
@@ -493,18 +485,18 @@ public:
bool const has_pk = ! base::p_is_last_segment();
int const pk_q1 = has_pk ? base::sides().pk_wrt_q1() : 0;
int const pk_q2 = has_pk ? base::sides().pk_wrt_q2() : 0;
-
+
if (pk_q1 == -pk_q2)
{
if (pk_q1 == 0)
{
return direction_code<cs_tag>(base::rqi(), base::rqj(), base::rqk()) == -1;
}
-
+
return true;
}
}
-
+
return false;
}
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
index 20aaa6a434..76d7faf6de 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp
@@ -95,7 +95,7 @@ struct get_turn_info_linear_areal
}
else
{
- typedef touch_interior<TurnInfo> handler;
+ using handler = touch_interior<TurnInfo, verify_policy_la>;
// If Q (1) arrives (1)
if ( inters.d_info().arrival[1] == 1 )
@@ -120,12 +120,12 @@ struct get_turn_info_linear_areal
replace_method_and_operations_tm(tp.method,
tp.operations[0].operation,
tp.operations[1].operation);
-
+
// this function assumes that 'u' must be set for a spike
calculate_spike_operation(tp.operations[0].operation,
inters,
umbrella_strategy);
-
+
*out++ = tp;
}
}
@@ -148,9 +148,10 @@ struct get_turn_info_linear_areal
{
// do nothing
}
- else
+ else
{
- touch<TurnInfo>::apply(range_p, range_q, tp,
+ using handler = touch<TurnInfo, verify_policy_la>;
+ handler::apply(range_p, range_q, tp,
inters.i_info(), inters.d_info(), inters.sides(),
umbrella_strategy);
@@ -177,7 +178,7 @@ struct get_turn_info_linear_areal
}
else
{
- tp.operations[0].operation = operation_union;
+ tp.operations[0].operation = operation_union;
}
}
}
@@ -246,7 +247,8 @@ struct get_turn_info_linear_areal
{
// Both equal
// or collinear-and-ending at intersection point
- equal<TurnInfo>::apply(range_p, range_q, tp,
+ using handler = equal<TurnInfo, verify_policy_la>;
+ handler::apply(range_p, range_q, tp,
inters.i_info(), inters.d_info(), inters.sides(),
umbrella_strategy);
@@ -295,7 +297,8 @@ struct get_turn_info_linear_areal
if ( inters.d_info().arrival[0] == 0 )
{
// Collinear, but similar thus handled as equal
- equal<TurnInfo>::apply(range_p, range_q, tp,
+ using handler = equal<TurnInfo, verify_policy_la>;
+ handler::apply(range_p, range_q, tp,
inters.i_info(), inters.d_info(), inters.sides(),
umbrella_strategy);
@@ -304,8 +307,9 @@ struct get_turn_info_linear_areal
}
else
{
- collinear<TurnInfo>::apply(range_p, range_q, tp,
- inters.i_info(), inters.d_info(), inters.sides());
+ using handler = collinear<TurnInfo, verify_policy_la>;
+ handler::apply(range_p, range_q, tp, inters.i_info(),
+ inters.d_info(), inters.sides());
//method_replace = method_touch_interior;
//version = append_collinear;
@@ -403,7 +407,7 @@ struct get_turn_info_linear_areal
if ( is_p_spike )
{
int const pk_q1 = inters.sides().pk_wrt_q1();
-
+
bool going_in = pk_q1 < 0; // Pk on the right
bool going_out = pk_q1 > 0; // Pk on the left
@@ -411,7 +415,7 @@ struct get_turn_info_linear_areal
// special cases
if ( qk_q1 < 0 ) // Q turning R
- {
+ {
// spike on the edge point
// if it's already known that the spike is going out this musn't be checked
if ( ! going_out
@@ -524,7 +528,7 @@ struct get_turn_info_linear_areal
|| tp.operations[0].operation == operation_intersection ) : // i ???
true )
&& inters.is_spike_p();
-
+
// TODO: throw an exception for spike in Areal?
/*bool is_q_spike = ( ( Version == append_touches
&& tp.operations[1].operation == operation_continue )
@@ -671,7 +675,7 @@ struct get_turn_info_linear_areal
// possible to define a spike on an endpoint. Areal geometries must
// NOT have spikes at all. One thing that could be done is to throw
// an exception when spike is detected in Areal geometry.
-
+
template <bool EnableFirst,
bool EnableLast,
typename UniqueSubRange1,
@@ -797,7 +801,7 @@ struct get_turn_info_linear_areal
&& ( ip_count > 1 ? (ip1.is_pj && !ip1.is_qi) : (ip0.is_pj && !ip0.is_qi) ) ) // prevents duplication
{
TurnInfo tp = tp_model;
-
+
if ( inters.i_info().count > 1 )
{
//BOOST_GEOMETRY_ASSERT( result.template get<1>().dir_a == 0 && result.template get<1>().dir_b == 0 );
@@ -823,7 +827,7 @@ struct get_turn_info_linear_areal
{
side_pi_y = sides.apply(range_q.at(1), range_q.at(2), range_p.at(0)); // pi wrt q2
side_pi_x = sides.apply(range_q.at(0), range_q.at(1), range_p.at(0)); // pi wrt q1
- side_qz_x = sides.apply(range_q.at(0), range_q.at(1), range_q.at(2)); // qk wrt q1
+ side_qz_x = sides.apply(range_q.at(0), range_q.at(1), range_q.at(2)); // qk wrt q1
}
// 2. ip0 or pj in the middle of q1
else
@@ -849,7 +853,7 @@ struct get_turn_info_linear_areal
tp.operations[0].operation = operation_blocked;
tp.operations[0].position = position_back;
tp.operations[1].position = position_middle;
-
+
// equals<> or collinear<> will assign the second point,
// we'd like to assign the first one
unsigned int ip_index = ip_count > 1 ? 1 : 0;
diff --git a/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp b/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
index ccb5e668ae..6dbd6d682c 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp
@@ -83,6 +83,8 @@ struct get_turn_info_linear_linear
case 'm' :
{
+ using handler = touch_interior<TurnInfo, verify_policy_ll>;
+
if ( get_turn_info_for_endpoint<false, true>
::apply(range_p, range_q,
tp_model, inters, method_touch_interior, out,
@@ -92,15 +94,10 @@ struct get_turn_info_linear_linear
}
else
{
- typedef touch_interior
- <
- TurnInfo
- > policy;
-
// If Q (1) arrives (1)
if ( inters.d_info().arrival[1] == 1)
{
- policy::template apply<0>(range_p, range_q, tp,
+ handler::template apply<0>(range_p, range_q, tp,
inters.i_info(), inters.d_info(),
inters.sides(),
umbrella_strategy);
@@ -108,12 +105,12 @@ struct get_turn_info_linear_linear
else
{
// Swap p/q
- policy::template apply<1>(range_q, range_p, tp,
+ handler::template apply<1>(range_q, range_p, tp,
inters.i_info(), inters.d_info(),
inters.swapped_sides(),
umbrella_strategy);
}
-
+
if ( tp.operations[0].operation == operation_blocked )
{
tp.operations[1].is_collinear = true;
@@ -126,7 +123,7 @@ struct get_turn_info_linear_linear
replace_method_and_operations_tm(tp.method,
tp.operations[0].operation,
tp.operations[1].operation);
-
+
*out++ = tp;
}
}
@@ -142,6 +139,8 @@ struct get_turn_info_linear_linear
break;
case 't' :
{
+ using handler = touch<TurnInfo, verify_policy_ll>;
+
// Both touch (both arrive there)
if ( get_turn_info_for_endpoint<false, true>
::apply(range_p, range_q,
@@ -150,12 +149,12 @@ struct get_turn_info_linear_linear
{
// do nothing
}
- else
+ else
{
- touch<TurnInfo>::apply(range_p, range_q, tp,
- inters.i_info(), inters.d_info(),
- inters.sides(),
- umbrella_strategy);
+ handler::apply(range_p, range_q, tp,
+ inters.i_info(), inters.d_info(),
+ inters.sides(),
+ umbrella_strategy);
// workarounds for touch<> not taking spikes into account starts here
// those was discovered empirically
@@ -170,7 +169,7 @@ struct get_turn_info_linear_linear
if ( inters.is_spike_p() && inters.is_spike_q() )
{
tp.operations[0].operation = operation_union;
- tp.operations[1].operation = operation_union;
+ tp.operations[1].operation = operation_union;
}
else
{
@@ -189,7 +188,7 @@ struct get_turn_info_linear_linear
}
else
{
- tp.operations[0].operation = operation_union;
+ tp.operations[0].operation = operation_union;
}
}
else
@@ -208,7 +207,7 @@ struct get_turn_info_linear_linear
}
else
{
- tp.operations[1].operation = operation_union;
+ tp.operations[1].operation = operation_union;
}
}
else
@@ -224,7 +223,7 @@ struct get_turn_info_linear_linear
&& inters.is_spike_p() )
{
tp.operations[0].operation = operation_union;
- tp.operations[1].operation = operation_union;
+ tp.operations[1].operation = operation_union;
}
}
else if ( tp.operations[0].operation == operation_none
@@ -275,6 +274,8 @@ struct get_turn_info_linear_linear
break;
case 'e':
{
+ using handler = equal<TurnInfo, verify_policy_ll>;
+
if ( get_turn_info_for_endpoint<true, true>
::apply(range_p, range_q,
tp_model, inters, method_equal, out,
@@ -291,7 +292,7 @@ struct get_turn_info_linear_linear
{
// Both equal
// or collinear-and-ending at intersection point
- equal<TurnInfo>::apply(range_p, range_q, tp,
+ handler::apply(range_p, range_q, tp,
inters.i_info(), inters.d_info(), inters.sides(),
umbrella_strategy);
@@ -351,7 +352,9 @@ struct get_turn_info_linear_linear
if ( inters.d_info().arrival[0] == 0 )
{
// Collinear, but similar thus handled as equal
- equal<TurnInfo>::apply(range_p, range_q, tp,
+ using handler = equal<TurnInfo, verify_policy_ll>;
+
+ handler::apply(range_p, range_q, tp,
inters.i_info(), inters.d_info(), inters.sides(),
umbrella_strategy);
@@ -364,8 +367,10 @@ struct get_turn_info_linear_linear
}
else
{
- collinear<TurnInfo>::apply(range_p, range_q,
- tp, inters.i_info(), inters.d_info(), inters.sides());
+ using handler = collinear<TurnInfo, verify_policy_ll>;
+ handler::apply(range_p, range_q, tp,
+ inters.i_info(), inters.d_info(),
+ inters.sides());
//method_replace = method_touch_interior;
//spike_op = operation_continue;
@@ -374,7 +379,7 @@ struct get_turn_info_linear_linear
// transform turn
turn_transformer_ec transformer(method_replace);
transformer(tp);
-
+
// conditionally handle spikes
if ( ! BOOST_GEOMETRY_CONDITION(handle_spikes)
|| ! append_collinear_spikes(tp, inters,
@@ -519,7 +524,7 @@ struct get_turn_info_linear_linear
return true;
}
-
+
return false;
}
@@ -562,9 +567,9 @@ struct get_turn_info_linear_linear
{
tp.operations[0].is_collinear = true;
tp.operations[1].is_collinear = false;
-
+
BOOST_GEOMETRY_ASSERT(inters.i_info().count > 1);
-
+
base_turn_handler::assign_point(tp, method_touch_interior,
inters.i_info(), 1);
}
@@ -593,7 +598,7 @@ struct get_turn_info_linear_linear
{
tp.operations[0].is_collinear = false;
tp.operations[1].is_collinear = true;
-
+
BOOST_GEOMETRY_ASSERT(inters.i_info().count > 0);
base_turn_handler::assign_point(tp, method_touch_interior, inters.i_info(), 0);
@@ -608,7 +613,7 @@ struct get_turn_info_linear_linear
res = true;
}
-
+
return res;
}
diff --git a/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/boost/geometry/algorithms/detail/overlay/get_turns.hpp
index 35ca5157de..326c883b39 100644
--- a/boost/geometry/algorithms/detail/overlay/get_turns.hpp
+++ b/boost/geometry/algorithms/detail/overlay/get_turns.hpp
@@ -1,11 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
-
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -16,10 +15,10 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_TURNS_HPP
+#include <array>
#include <cstddef>
#include <map>
-#include <boost/array.hpp>
#include <boost/concept_check.hpp>
#include <boost/core/ignore_unused.hpp>
#include <boost/range/begin.hpp>
@@ -29,7 +28,6 @@
#include <boost/geometry/algorithms/detail/disjoint/box_box.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_ll.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info_la.hpp>
@@ -111,7 +109,7 @@ template
>
struct unique_sub_range_from_section
{
- typedef Point point_type;
+ using point_type = Point;
unique_sub_range_from_section(Section const& section, signed_size_type index,
CircularIterator circular_iterator,
@@ -123,7 +121,7 @@ struct unique_sub_range_from_section
, m_previous_point(previous)
, m_current_point(current)
, m_circular_iterator(circular_iterator)
- , m_point_retrieved(false)
+ , m_next_point_retrieved(false)
, m_strategy(strategy)
, m_robust_policy(robust_policy)
{}
@@ -158,18 +156,18 @@ struct unique_sub_range_from_section
private :
inline Point const& get_next_point() const
{
- if (! m_point_retrieved)
+ if (! m_next_point_retrieved)
{
advance_to_non_duplicate_next(m_current_point, m_circular_iterator);
- m_point = *m_circular_iterator;
- m_point_retrieved = true;
+ m_next_point_retrieved = true;
}
- return m_point;
+ return *m_circular_iterator;
}
inline void advance_to_non_duplicate_next(Point const& current, CircularIterator& circular_iterator) const
{
- typedef typename robust_point_type<Point, RobustPolicy>::type robust_point_type;
+ using box_point_type = typename geometry::point_type<typename Section::box_type>::type;
+ using robust_point_type = typename robust_point_type<box_point_type, RobustPolicy>::type;
robust_point_type current_robust_point;
robust_point_type next_robust_point;
geometry::recalculate(current_robust_point, current, m_robust_policy);
@@ -199,8 +197,7 @@ private :
Point const& m_previous_point;
Point const& m_current_point;
mutable CircularIterator m_circular_iterator;
- mutable Point m_point;
- mutable bool m_point_retrieved;
+ mutable bool m_next_point_retrieved;
Strategy m_strategy;
RobustPolicy m_robust_policy;
};
@@ -571,7 +568,7 @@ struct get_turns_cs
{
typedef typename geometry::point_type<Range>::type range_point_type;
typedef typename geometry::point_type<Box>::type box_point_type;
- typedef boost::array<box_point_type, 4> box_array;
+ typedef std::array<box_point_type, 4> box_array;
using view_type = detail::closed_clockwise_view
<
@@ -843,10 +840,8 @@ struct get_turns_polygon_cs
signed_size_type i = 0;
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(polygon);
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it, ++i)
+ auto const& rings = interior_rings(polygon);
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it, ++i)
{
intersector_type::apply(
source_id1, *it,
@@ -878,15 +873,8 @@ struct get_turns_multi_polygon_cs
Turns& turns,
InterruptPolicy& interrupt_policy)
{
- typedef typename boost::range_iterator
- <
- Multi const
- >::type iterator_type;
-
signed_size_type i = 0;
- for (iterator_type it = boost::begin(multi);
- it != boost::end(multi);
- ++it, ++i)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it, ++i)
{
// Call its single version
get_turns_polygon_cs
@@ -927,24 +915,24 @@ struct get_turn_info_type<Geometry1, Geometry2, AssignPolicy, Tag1, Tag2, linear
: overlay::get_turn_info_linear_areal<AssignPolicy>
{};
-template <typename Geometry1, typename Geometry2, typename SegmentRatio,
+template <typename Geometry1, typename Geometry2, typename Point, typename SegmentRatio,
typename Tag1 = typename tag<Geometry1>::type, typename Tag2 = typename tag<Geometry2>::type,
typename TagBase1 = typename topological_tag_base<Geometry1>::type, typename TagBase2 = typename topological_tag_base<Geometry2>::type>
struct turn_operation_type
{
- typedef overlay::turn_operation<typename point_type<Geometry1>::type, SegmentRatio> type;
+ using type = overlay::turn_operation<Point, SegmentRatio>;
};
-template <typename Geometry1, typename Geometry2, typename SegmentRatio, typename Tag1, typename Tag2>
-struct turn_operation_type<Geometry1, Geometry2, SegmentRatio, Tag1, Tag2, linear_tag, linear_tag>
+template <typename Geometry1, typename Geometry2, typename Point, typename SegmentRatio, typename Tag1, typename Tag2>
+struct turn_operation_type<Geometry1, Geometry2, Point, SegmentRatio, Tag1, Tag2, linear_tag, linear_tag>
{
- typedef overlay::turn_operation_linear<typename point_type<Geometry1>::type, SegmentRatio> type;
+ using type = overlay::turn_operation_linear<Point, SegmentRatio>;
};
-template <typename Geometry1, typename Geometry2, typename SegmentRatio, typename Tag1, typename Tag2>
-struct turn_operation_type<Geometry1, Geometry2, SegmentRatio, Tag1, Tag2, linear_tag, areal_tag>
+template <typename Geometry1, typename Geometry2, typename Point, typename SegmentRatio, typename Tag1, typename Tag2>
+struct turn_operation_type<Geometry1, Geometry2, Point, SegmentRatio, Tag1, Tag2, linear_tag, areal_tag>
{
- typedef overlay::turn_operation_linear<typename point_type<Geometry1>::type, SegmentRatio> type;
+ using type = overlay::turn_operation_linear<Point, SegmentRatio>;
};
}} // namespace detail::get_turns
diff --git a/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp b/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
index 9afea24c2b..aaabb4a4df 100644
--- a/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
+++ b/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp
@@ -29,6 +29,7 @@
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/do_reverse.hpp>
+#include <boost/geometry/algorithms/detail/overlay/colocate_clusters.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_clusters.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp>
@@ -52,22 +53,22 @@ namespace boost { namespace geometry
namespace detail { namespace overlay
{
+// Removes clusters which have only one point left, or are empty.
template <typename Turns, typename Clusters>
inline void remove_clusters(Turns& turns, Clusters& clusters)
{
- typename Clusters::iterator it = clusters.begin();
+ auto it = clusters.begin();
while (it != clusters.end())
{
// Hold iterator and increase. We can erase cit, this keeps the
// iterator valid (cf The standard associative-container erase idiom)
- typename Clusters::iterator current_it = it;
+ auto current_it = it;
++it;
- std::set<signed_size_type> const& turn_indices
- = current_it->second.turn_indices;
+ auto const& turn_indices = current_it->second.turn_indices;
if (turn_indices.size() == 1)
{
- signed_size_type const turn_index = *turn_indices.begin();
+ auto const turn_index = *turn_indices.begin();
turns[turn_index].cluster_id = -1;
clusters.erase(current_it);
}
@@ -78,36 +79,35 @@ template <typename Turns, typename Clusters>
inline void cleanup_clusters(Turns& turns, Clusters& clusters)
{
// Removes discarded turns from clusters
- for (typename Clusters::iterator mit = clusters.begin();
- mit != clusters.end(); ++mit)
+ for (auto& pair : clusters)
{
- cluster_info& cinfo = mit->second;
- std::set<signed_size_type>& ids = cinfo.turn_indices;
- for (std::set<signed_size_type>::iterator sit = ids.begin();
- sit != ids.end(); /* no increment */)
+ auto& cinfo = pair.second;
+ auto& indices = cinfo.turn_indices;
+ for (auto sit = indices.begin(); sit != indices.end(); /* no increment */)
{
- std::set<signed_size_type>::iterator current_it = sit;
+ auto current_it = sit;
++sit;
- signed_size_type const turn_index = *current_it;
+ auto const turn_index = *current_it;
if (turns[turn_index].discarded)
{
- ids.erase(current_it);
+ indices.erase(current_it);
}
}
}
remove_clusters(turns, clusters);
+ colocate_clusters(clusters, turns);
}
-template <typename Turn, typename IdSet>
-inline void discard_colocated_turn(Turn& turn, IdSet& ids, signed_size_type id)
+template <typename Turn, typename IndexSet>
+inline void discard_colocated_turn(Turn& turn, IndexSet& indices, signed_size_type index)
{
turn.discarded = true;
// Set cluster id to -1, but don't clear colocated flags
turn.cluster_id = -1;
// To remove it later from clusters
- ids.insert(id);
+ indices.insert(index);
}
template <bool Reverse>
@@ -167,22 +167,17 @@ template
>
inline void discard_interior_exterior_turns(Turns& turns, Clusters& clusters)
{
- typedef std::set<signed_size_type>::const_iterator set_iterator;
- typedef typename boost::range_value<Turns>::type turn_type;
-
- std::set<signed_size_type> ids_to_remove;
+ std::set<signed_size_type> indices_to_remove;
- for (typename Clusters::iterator cit = clusters.begin();
- cit != clusters.end(); ++cit)
+ for (auto& pair : clusters)
{
- cluster_info& cinfo = cit->second;
- std::set<signed_size_type>& ids = cinfo.turn_indices;
+ cluster_info& cinfo = pair.second;
- ids_to_remove.clear();
+ indices_to_remove.clear();
- for (set_iterator it = ids.begin(); it != ids.end(); ++it)
+ for (auto index : cinfo.turn_indices)
{
- turn_type& turn = turns[*it];
+ auto& turn = turns[index];
segment_identifier const& seg_0 = turn.operations[0].seg_id;
segment_identifier const& seg_1 = turn.operations[1].seg_id;
@@ -193,34 +188,33 @@ inline void discard_interior_exterior_turns(Turns& turns, Clusters& clusters)
continue;
}
- for (set_iterator int_it = ids.begin(); int_it != ids.end(); ++int_it)
+ for (auto interior_index : cinfo.turn_indices)
{
- if (*it == *int_it)
+ if (index == interior_index)
{
continue;
}
// Turn with, possibly, an interior ring involved
- turn_type& int_turn = turns[*int_it];
- segment_identifier const& int_seg_0 = int_turn.operations[0].seg_id;
- segment_identifier const& int_seg_1 = int_turn.operations[1].seg_id;
+ auto& interior_turn = turns[interior_index];
+ segment_identifier const& int_seg_0 = interior_turn.operations[0].seg_id;
+ segment_identifier const& int_seg_1 = interior_turn.operations[1].seg_id;
if (is_ie_turn<Reverse0, Reverse1>(seg_0, seg_1, int_seg_0, int_seg_1))
{
- discard_colocated_turn(int_turn, ids_to_remove, *int_it);
+ discard_colocated_turn(interior_turn, indices_to_remove, interior_index);
}
if (is_ie_turn<Reverse1, Reverse0>(seg_1, seg_0, int_seg_1, int_seg_0))
{
- discard_colocated_turn(int_turn, ids_to_remove, *int_it);
+ discard_colocated_turn(interior_turn, indices_to_remove, interior_index);
}
}
}
- // Erase from the ids (which cannot be done above)
- for (set_iterator sit = ids_to_remove.begin();
- sit != ids_to_remove.end(); ++sit)
+ // Erase from the indices (which cannot be done above)
+ for (auto index : indices_to_remove)
{
- ids.erase(*sit);
+ cinfo.turn_indices.erase(index);
}
}
}
@@ -233,19 +227,14 @@ template
>
inline void set_colocation(Turns& turns, Clusters const& clusters)
{
- typedef std::set<signed_size_type>::const_iterator set_iterator;
- typedef typename boost::range_value<Turns>::type turn_type;
-
- for (typename Clusters::const_iterator cit = clusters.begin();
- cit != clusters.end(); ++cit)
+ for (auto const& pair : clusters)
{
- cluster_info const& cinfo = cit->second;
- std::set<signed_size_type> const& ids = cinfo.turn_indices;
+ cluster_info const& cinfo = pair.second;
bool both_target = false;
- for (set_iterator it = ids.begin(); it != ids.end(); ++it)
+ for (auto index : cinfo.turn_indices)
{
- turn_type const& turn = turns[*it];
+ auto const& turn = turns[index];
if (turn.both(operation_from_overlay<OverlayType>::value))
{
both_target = true;
@@ -255,9 +244,9 @@ inline void set_colocation(Turns& turns, Clusters const& clusters)
if (both_target)
{
- for (set_iterator it = ids.begin(); it != ids.end(); ++it)
+ for (auto index : cinfo.turn_indices)
{
- turn_type& turn = turns[*it];
+ auto& turn = turns[index];
turn.has_colocated_both = true;
}
}
@@ -276,7 +265,7 @@ inline void check_colocation(bool& has_blocked,
has_blocked = false;
- typename Clusters::const_iterator mit = clusters.find(cluster_id);
+ auto mit = clusters.find(cluster_id);
if (mit == clusters.end())
{
return;
@@ -284,11 +273,9 @@ inline void check_colocation(bool& has_blocked,
cluster_info const& cinfo = mit->second;
- for (std::set<signed_size_type>::const_iterator it
- = cinfo.turn_indices.begin();
- it != cinfo.turn_indices.end(); ++it)
+ for (auto index : cinfo.turn_indices)
{
- turn_type const& turn = turns[*it];
+ turn_type const& turn = turns[index];
if (turn.any_blocked())
{
has_blocked = true;
@@ -410,21 +397,15 @@ inline bool fill_sbs(Sbs& sbs, Point& turn_point,
Turns const& turns,
Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- typedef typename boost::range_value<Turns>::type turn_type;
-
- std::set<signed_size_type> const& ids = cinfo.turn_indices;
-
- if (ids.empty())
+ if (cinfo.turn_indices.empty())
{
return false;
}
bool first = true;
- for (std::set<signed_size_type>::const_iterator sit = ids.begin();
- sit != ids.end(); ++sit)
+ for (auto turn_index : cinfo.turn_indices)
{
- signed_size_type turn_index = *sit;
- turn_type const& turn = turns[turn_index];
+ auto const& turn = turns[turn_index];
if (first)
{
turn_point = turn.point;
@@ -464,10 +445,9 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
Reverse1, Reverse2, OverlayType, point_type, SideStrategy, std::less<int>
> sbs_type;
- for (typename Clusters::iterator mit = clusters.begin();
- mit != clusters.end(); ++mit)
+ for (auto& pair : clusters)
{
- cluster_info& cinfo = mit->second;
+ cluster_info& cinfo = pair.second;
sbs_type sbs(strategy);
point_type turn_point; // should be all the same for all turns in cluster
@@ -515,10 +495,10 @@ inline void gather_cluster_properties(Clusters& clusters, Turns& turns,
continue;
}
- if (BOOST_GEOMETRY_CONDITION(OverlayType != overlay_difference)
+ if (BOOST_GEOMETRY_CONDITION(OverlayType == overlay_difference)
&& is_self_turn<OverlayType>(turn))
{
- // Difference needs the self-turns, TODO: investigate
+ // TODO: investigate
continue;
}
diff --git a/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp b/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp
index aec43548d4..435a80c272 100644
--- a/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp
+++ b/boost/geometry/algorithms/detail/overlay/handle_self_turns.hpp
@@ -1,10 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2017 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2017-2023 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2019-2020.
-// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2022.
+// Modifications copyright (c) 2019-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -19,11 +19,11 @@
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/geometry/algorithms/detail/overlay/cluster_info.hpp>
#include <boost/geometry/algorithms/detail/overlay/is_self_turn.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
-#include <boost/geometry/algorithms/within.hpp>
+#include <boost/geometry/algorithms/detail/within/implementation.hpp>
namespace boost { namespace geometry
{
@@ -106,15 +106,8 @@ struct discard_closed_turns<overlay_union, operation_union>
Geometry0 const& geometry0, Geometry1 const& geometry1,
Strategy const& strategy)
{
- typedef typename boost::range_value<Turns>::type turn_type;
-
- for (typename boost::range_iterator<Turns>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it)
+ for (auto& turn : turns)
{
- turn_type& turn = *it;
-
if (! turn.discarded
&& is_self_turn<overlay_union>(turn)
&& check_within<overlay_union>::apply(turn, geometry0,
@@ -137,18 +130,16 @@ private :
bool is_self_cluster(signed_size_type cluster_id,
const Turns& turns, Clusters const& clusters)
{
- typename Clusters::const_iterator cit = clusters.find(cluster_id);
+ auto cit = clusters.find(cluster_id);
if (cit == clusters.end())
{
return false;
}
cluster_info const& cinfo = cit->second;
- for (std::set<signed_size_type>::const_iterator it
- = cinfo.turn_indices.begin();
- it != cinfo.turn_indices.end(); ++it)
+ for (auto index : cinfo.turn_indices)
{
- if (! is_self_turn<OverlayType>(turns[*it]))
+ if (! is_self_turn<OverlayType>(turns[index]))
{
return false;
}
@@ -164,28 +155,25 @@ private :
Geometry0 const& geometry0, Geometry1 const& geometry1,
Strategy const& strategy)
{
- for (typename Clusters::const_iterator cit = clusters.begin();
- cit != clusters.end(); ++cit)
+ for (auto const& pair : clusters)
{
- signed_size_type const cluster_id = cit->first;
+ signed_size_type const cluster_id = pair.first;
+ cluster_info const& cinfo = pair.second;
// If there are only self-turns in the cluster, the cluster should
// be located within the other geometry, for intersection
- if (! cit->second.turn_indices.empty()
+ if (! cinfo.turn_indices.empty()
&& is_self_cluster(cluster_id, turns, clusters))
{
- cluster_info const& cinfo = cit->second;
- signed_size_type const index = *cinfo.turn_indices.begin();
- if (! check_within<OverlayType>::apply(turns[index],
+ signed_size_type const first_index = *cinfo.turn_indices.begin();
+ if (! check_within<OverlayType>::apply(turns[first_index],
geometry0, geometry1,
strategy))
{
// Discard all turns in cluster
- for (std::set<signed_size_type>::const_iterator sit
- = cinfo.turn_indices.begin();
- sit != cinfo.turn_indices.end(); ++sit)
+ for (auto index : cinfo.turn_indices)
{
- turns[*sit].discarded = true;
+ turns[index].discarded = true;
}
}
}
@@ -203,15 +191,8 @@ public :
{
discard_clusters(turns, clusters, geometry0, geometry1, strategy);
- typedef typename boost::range_value<Turns>::type turn_type;
-
- for (typename boost::range_iterator<Turns>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it)
+ for (auto& turn : turns)
{
- turn_type& turn = *it;
-
// It is a ii self-turn
// Check if it is within the other geometry
if (! turn.discarded
diff --git a/boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp b/boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp
index c62b7d2834..31db94dd95 100644
--- a/boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp
+++ b/boost/geometry/algorithms/detail/overlay/intersection_box_box.hpp
@@ -63,7 +63,7 @@ struct intersection_box_box
// 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, robust_policy, box_out, strategy);
}
diff --git a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
index 153fb1cf4b..df3b70a456 100644
--- a/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
+++ b/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp
@@ -2,9 +2,10 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014-2020.
-// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2021.
+// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -25,7 +26,6 @@
#include <boost/range/size.hpp>
#include <boost/geometry/algorithms/convert.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.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/follow.hpp>
@@ -59,6 +59,7 @@
#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
+#include <boost/geometry/util/for_each_with_index.hpp>
#endif
namespace boost { namespace geometry
@@ -145,11 +146,10 @@ struct intersection_linestring_linestring_point
geometry::get_intersection_points(linestring1, linestring2,
robust_policy, turns, strategy);
- for (typename boost::range_iterator<std::deque<turn_info> const>::type
- it = boost::begin(turns); it != boost::end(turns); ++it)
+ for (auto const& turn : turns)
{
PointOut p;
- geometry::convert(it->point, p);
+ geometry::convert(turn.point, p);
*out++ = p;
}
return out;
@@ -212,11 +212,10 @@ struct intersection_of_linestring_with_areal
bool found_union = false;
bool found_front = false;
- for (typename Turns::const_iterator it = turns.begin();
- it != turns.end(); ++it)
+ for (auto const& turn : turns)
{
- method_type const method = it->method;
- operation_type const op = it->operations[0].operation;
+ method_type const method = turn.method;
+ operation_type const op = turn.operations[0].operation;
if (method == method_crosses)
{
@@ -240,7 +239,7 @@ struct intersection_of_linestring_with_areal
return false;
}
- if (it->operations[0].position == position_front)
+ if (turn.operations[0].position == position_front)
{
found_front = true;
}
@@ -378,14 +377,12 @@ struct intersection_of_linestring_with_areal
return out;
}
-
+
#if defined(BOOST_GEOMETRY_DEBUG_FOLLOW)
- int index = 0;
- for(typename std::deque<turn_info>::const_iterator
- it = turns.begin(); it != turns.end(); ++it)
+ for_each_with_index(turns, [](auto index, auto const& turn)
{
- debug_follow(*it, it->operations[0], index++);
- }
+ debug_follow(turn, turn.operations[0], index);
+ });
#endif
return follower::apply
@@ -402,10 +399,9 @@ template <typename Turns, typename OutputIterator>
inline OutputIterator intersection_output_turn_points(Turns const& turns,
OutputIterator out)
{
- for (typename Turns::const_iterator
- it = turns.begin(); it != turns.end(); ++it)
+ for (auto const& turn : turns)
{
- *out++ = it->point;
+ *out++ = turn.point;
}
return out;
@@ -1543,7 +1539,7 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1,
<
Geometry1, Geometry2
>::type strategy_type;
-
+
return intersection_insert<GeometryOut>(geometry1, geometry2, out,
strategy_type());
}
diff --git a/boost/geometry/algorithms/detail/overlay/is_self_turn.hpp b/boost/geometry/algorithms/detail/overlay/is_self_turn.hpp
index 448c04404f..1606c31e90 100644
--- a/boost/geometry/algorithms/detail/overlay/is_self_turn.hpp
+++ b/boost/geometry/algorithms/detail/overlay/is_self_turn.hpp
@@ -26,8 +26,7 @@ struct is_self_turn_check
template <typename Turn>
static inline bool apply(Turn const& turn)
{
- return turn.operations[0].seg_id.source_index
- == turn.operations[1].seg_id.source_index;
+ return turn.is_self();
}
};
diff --git a/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp b/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp
index 06ce0a7f0d..1ce97d261e 100644
--- a/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp
+++ b/boost/geometry/algorithms/detail/overlay/less_by_segment_ratio.hpp
@@ -66,7 +66,7 @@ template
typename Indexed,
typename Geometry1, typename Geometry2,
typename RobustPolicy,
- typename SideStrategy,
+ typename Strategy,
bool Reverse1, bool Reverse2
>
struct less_by_segment_ratio
@@ -75,7 +75,7 @@ struct less_by_segment_ratio
, Geometry1 const& geometry1
, Geometry2 const& geometry2
, RobustPolicy const& robust_policy
- , SideStrategy const& strategy)
+ , Strategy const& strategy)
: m_turns(turns)
, m_geometry1(geometry1)
, m_geometry2(geometry2)
@@ -90,7 +90,7 @@ private :
Geometry1 const& m_geometry1;
Geometry2 const& m_geometry2;
RobustPolicy const& m_robust_policy;
- SideStrategy const& m_strategy;
+ Strategy const& m_strategy;
typedef typename geometry::point_type<Geometry1>::type point_type;
@@ -115,8 +115,9 @@ private :
*right.other_seg_id,
si, sj);
- int const side_rj_p = m_strategy.apply(pi, pj, rj);
- int const side_sj_p = m_strategy.apply(pi, pj, sj);
+ auto side_strategy = m_strategy.side();
+ int const side_rj_p = side_strategy.apply(pi, pj, rj);
+ int const side_sj_p = side_strategy.apply(pi, pj, sj);
// Put the one turning left (1; right == -1) as last
if (side_rj_p != side_sj_p)
@@ -124,8 +125,8 @@ private :
return side_rj_p < side_sj_p;
}
- int const side_sj_r = m_strategy.apply(ri, rj, sj);
- int const side_rj_s = m_strategy.apply(si, sj, rj);
+ int const side_sj_r = side_strategy.apply(ri, rj, sj);
+ int const side_rj_s = side_strategy.apply(si, sj, rj);
// If they both turn left: the most left as last
// If they both turn right: this is not relevant, but take also here most left
@@ -156,10 +157,8 @@ public :
return left.subject->fraction < right.subject->fraction;
}
-
- typedef typename boost::range_value<Turns>::type turn_type;
- turn_type const& left_turn = m_turns[left.turn_index];
- turn_type const& right_turn = m_turns[right.turn_index];
+ auto const& left_turn = m_turns[left.turn_index];
+ auto const& right_turn = m_turns[right.turn_index];
// First check "real" intersection (crosses)
// -> distance zero due to precision, solve it by sorting
diff --git a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
index f5d5f7bf4d..f67a06b0bb 100644
--- a/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/linear_linear.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -30,7 +30,7 @@
#include <boost/geometry/algorithms/convert.hpp>
-
+#include <boost/geometry/geometries/helper_geometry.hpp>
namespace boost { namespace geometry
{
@@ -82,9 +82,7 @@ struct linear_linear_no_intersections
static inline OutputIterator apply(MultiLineString const& multilinestring,
OutputIterator oit)
{
- for (typename boost::range_iterator<MultiLineString const>::type
- it = boost::begin(multilinestring);
- it != boost::end(multilinestring); ++it)
+ for (auto it = boost::begin(multilinestring); it != boost::end(multilinestring); ++it)
{
LineStringOut ls_out;
geometry::convert(*it, ls_out);
@@ -206,7 +204,7 @@ protected:
turns::remove_duplicate_turns
<
Turns, EnableRemoveDuplicateTurns
- >::apply(turns);
+ >::apply(turns, strategy);
return detail::overlay::following::linear::follow
<
diff --git a/boost/geometry/algorithms/detail/overlay/overlay.hpp b/boost/geometry/algorithms/detail/overlay/overlay.hpp
index 7d960987d4..e0451f9dd6 100644
--- a/boost/geometry/algorithms/detail/overlay/overlay.hpp
+++ b/boost/geometry/algorithms/detail/overlay/overlay.hpp
@@ -103,10 +103,6 @@ template
>
inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns, Clusters const& clusters)
{
- typedef typename boost::range_value<Turns>::type turn_type;
- typedef typename turn_type::turn_operation_type turn_operation_type;
- typedef typename turn_type::container_type container_type;
-
static const operation_type target_operation
= operation_from_overlay<OverlayType>::value;
static const operation_type opposite_operation
@@ -114,13 +110,8 @@ inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns, C
? operation_intersection
: operation_union;
- for (typename boost::range_iterator<Turns const>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it)
+ for (auto const& turn : turns)
{
- turn_type const& turn = *it;
-
bool cluster_checked = false;
bool has_blocked = false;
@@ -130,12 +121,8 @@ inline void get_ring_turn_info(TurnInfoMap& turn_info_map, Turns const& turns, C
continue;
}
- for (typename boost::range_iterator<container_type const>::type
- op_it = boost::begin(turn.operations);
- op_it != boost::end(turn.operations);
- ++op_it)
+ for (auto const& op : turn.operations)
{
- turn_operation_type const& op = *op_it;
ring_identifier const ring_id = ring_id_by_seg_id(op.seg_id);
if (! is_self_turn<OverlayType>(turn)
@@ -369,12 +356,9 @@ std::cout << "traverse" << std::endl;
// 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)
+ for (auto const& ring : rings)
{
- selected_ring_properties[id] = properties(*it, strategy);
+ selected_ring_properties[id] = properties(ring, strategy);
selected_ring_properties[id].reversed = ReverseOut;
id.multi_index++;
}
@@ -392,15 +376,18 @@ std::cout << "traverse" << std::endl;
// it can be returned or an exception can be thrown.
return add_rings<GeometryOut>(selected_ring_properties, geometry1, geometry2, rings, out,
strategy,
- OverlayType == overlay_union ?
#if defined(BOOST_GEOMETRY_UNION_THROW_INVALID_OUTPUT_EXCEPTION)
+ OverlayType == overlay_union ?
add_rings_throw_if_reversed
+ : add_rings_ignore_unordered
#elif defined(BOOST_GEOMETRY_UNION_RETURN_INVALID)
+ OverlayType == overlay_union ?
add_rings_add_unordered
+ : add_rings_ignore_unordered
#else
add_rings_ignore_unordered
#endif
- : add_rings_ignore_unordered);
+ );
}
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp
index 8b62b0752b..503d656478 100644
--- a/boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp
+++ b/boost/geometry/algorithms/detail/overlay/pointlike_areal.hpp
@@ -157,7 +157,7 @@ private:
private:
MultiPolygon const& m_multipolygon;
- OutputIterator& m_oit;
+ OutputIterator& m_oit;
Strategy const& m_strategy;
};
diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
index bbf62b3633..19045b250a 100644
--- a/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
+++ b/boost/geometry/algorithms/detail/overlay/pointlike_linear.hpp
@@ -98,10 +98,7 @@ struct multipoint_single_point
OutputIterator oit,
Strategy const& strategy)
{
- for (typename boost::range_iterator<MultiPoint const>::type
- it = boost::begin(multipoint);
- it != boost::end(multipoint);
- ++it)
+ for (auto it = boost::begin(multipoint); it != boost::end(multipoint); ++it)
{
action_selector_pl
<
diff --git a/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp b/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp
index a46fc8b5f7..4ad311277a 100644
--- a/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp
+++ b/boost/geometry/algorithms/detail/overlay/pointlike_pointlike.hpp
@@ -1,7 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -33,6 +36,8 @@
#include <boost/geometry/policies/compare.hpp>
+#include <boost/geometry/util/condition.hpp>
+
namespace boost { namespace geometry
{
@@ -75,9 +80,7 @@ struct copy_points<PointOut, MultiPointIn, multi_point_tag>
static inline void apply(MultiPointIn const& multi_point_in,
OutputIterator& oit)
{
- for (typename boost::range_iterator<MultiPointIn const>::type
- it = boost::begin(multi_point_in);
- it != boost::end(multi_point_in); ++it)
+ for (auto it = boost::begin(multi_point_in); it != boost::end(multi_point_in); ++it)
{
PointOut point_out;
geometry::convert(*it, point_out);
@@ -189,9 +192,7 @@ struct multipoint_point_point
{
BOOST_GEOMETRY_ASSERT( OverlayType == overlay_difference );
- for (typename boost::range_iterator<MultiPoint const>::type
- it = boost::begin(multipoint);
- it != boost::end(multipoint); ++it)
+ for (auto it = boost::begin(multipoint); it != boost::end(multipoint); ++it)
{
action_selector_pl
<
@@ -225,9 +226,7 @@ struct point_multipoint_point
{
typedef action_selector_pl<PointOut, OverlayType> action;
- for (typename boost::range_iterator<MultiPoint const>::type
- it = boost::begin(multipoint);
- it != boost::end(multipoint); ++it)
+ for (auto it = boost::begin(multipoint); it != boost::end(multipoint); ++it)
{
if ( detail::equals::equals_point_point(*it, point, strategy) )
{
@@ -260,10 +259,10 @@ struct multipoint_multipoint_point
OutputIterator oit,
Strategy const& strategy)
{
- typedef geometry::less<void, -1, typename Strategy::cs_tag> less_type;
+ typedef geometry::less<void, -1, Strategy> less_type;
- if ( OverlayType != overlay_difference
- && boost::size(multipoint1) > boost::size(multipoint2) )
+ if (BOOST_GEOMETRY_CONDITION(OverlayType != overlay_difference)
+ && boost::size(multipoint1) > boost::size(multipoint2))
{
return multipoint_multipoint_point
<
@@ -279,9 +278,7 @@ struct multipoint_multipoint_point
less_type const less = less_type();
std::sort(points2.begin(), points2.end(), less);
- for (typename boost::range_iterator<MultiPoint1 const>::type
- it1 = boost::begin(multipoint1);
- it1 != boost::end(multipoint1); ++it1)
+ for (auto it1 = boost::begin(multipoint1); it1 != boost::end(multipoint1); ++it1)
{
bool found = std::binary_search(points2.begin(), points2.end(),
*it1, less);
diff --git a/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp b/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp
index 6f49f5168d..e41ee8238c 100644
--- a/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp
+++ b/boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2017-2020 Oracle and/or its affiliates.
+// Copyright (c) 2017-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -12,7 +12,7 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_RANGE_IN_GEOMETRY_HPP
-#include <boost/geometry/algorithms/covered_by.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/iterators/point_iterator.hpp>
@@ -154,7 +154,7 @@ inline int range_in_geometry(Point1 const& first_point1,
// check points of geometry1 until point inside/outside is found
// NOTE: skip first point because it should be already tested above
result = range_in_geometry(geometry1, geometry2, strategy, true);
- }
+ }
return result;
}
diff --git a/boost/geometry/algorithms/detail/overlay/ring_properties.hpp b/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
index c5341832bc..4039891f74 100644
--- a/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
+++ b/boost/geometry/algorithms/detail/overlay/ring_properties.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2017.
-// Modifications copyright (c) 2017 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2022.
+// Modifications copyright (c) 2017-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,8 +15,8 @@
#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/within/implementation.hpp>
namespace boost { namespace geometry
diff --git a/boost/geometry/algorithms/detail/overlay/select_rings.hpp b/boost/geometry/algorithms/detail/overlay/select_rings.hpp
index 1f43133367..58371606e2 100644
--- a/boost/geometry/algorithms/detail/overlay/select_rings.hpp
+++ b/boost/geometry/algorithms/detail/overlay/select_rings.hpp
@@ -3,8 +3,8 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017-2021.
-// Modifications copyright (c) 2017-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2022.
+// Modifications copyright (c) 2017-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -23,12 +23,11 @@
#include <boost/geometry/core/tags.hpp>
-#include <boost/geometry/algorithms/covered_by.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
-#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/implementation.hpp>
#include <boost/geometry/algorithms/detail/overlay/range_in_geometry.hpp>
#include <boost/geometry/algorithms/detail/overlay/ring_properties.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay_type.hpp>
+#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
namespace boost { namespace geometry
@@ -119,10 +118,8 @@ namespace dispatch
per_ring::apply(exterior_ring(polygon), geometry, id, ring_properties, strategy);
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(polygon);
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ auto const& rings = interior_rings(polygon);
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
id.ring_index++;
per_ring::apply(*it, geometry, id, ring_properties, strategy);
@@ -139,10 +136,8 @@ namespace dispatch
per_ring::apply(exterior_ring(polygon), id, ring_properties, strategy);
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(polygon);
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ auto const& rings = interior_rings(polygon);
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
id.ring_index++;
per_ring::apply(*it, id, ring_properties, strategy);
@@ -158,15 +153,10 @@ namespace dispatch
ring_identifier id, RingPropertyMap& ring_properties,
Strategy const& strategy)
{
- 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)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
id.ring_index = -1;
per_polygon::apply(*it, geometry, id, ring_properties, strategy);
@@ -254,15 +244,13 @@ inline void update_ring_selection(Geometry1 const& geometry1,
{
selected_ring_properties.clear();
- for (typename RingPropertyMap::const_iterator it = boost::begin(all_ring_properties);
- it != boost::end(all_ring_properties);
- ++it)
+ for (auto const& pair : all_ring_properties)
{
- ring_identifier const& id = it->first;
+ ring_identifier const& id = pair.first;
ring_turn_info info;
- typename TurnInfoMap::const_iterator tcit = turn_info_map.find(id);
+ auto tcit = turn_info_map.find(id);
if (tcit != turn_info_map.end())
{
info = tcit->second; // Copy by value
@@ -281,12 +269,12 @@ inline void update_ring_selection(Geometry1 const& geometry1,
{
// within
case 0 :
- info.within_other = range_in_geometry(it->second.point,
+ info.within_other = range_in_geometry(pair.second.point,
geometry1, geometry2,
strategy) > 0;
break;
case 1 :
- info.within_other = range_in_geometry(it->second.point,
+ info.within_other = range_in_geometry(pair.second.point,
geometry2, geometry1,
strategy) > 0;
break;
@@ -294,7 +282,7 @@ inline void update_ring_selection(Geometry1 const& geometry1,
if (decide<OverlayType>::include(id, info))
{
- typename RingPropertyMap::mapped_type properties = it->second; // Copy by value
+ auto properties = pair.second; // Copy by value
properties.reversed = decide<OverlayType>::reversed(id, info);
selected_ring_properties[id] = properties;
}
@@ -321,7 +309,7 @@ inline void select_rings(Geometry1 const& geometry1, Geometry2 const& geometry2,
{
typedef typename geometry::tag<Geometry1>::type tag1;
typedef typename geometry::tag<Geometry2>::type tag2;
-
+
RingPropertyMap all_ring_properties;
dispatch::select_rings<tag1, Geometry1>::apply(geometry1, geometry2,
ring_identifier(0, -1, -1), all_ring_properties,
diff --git a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
index 0845390a90..20369fa95a 100644
--- a/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
+++ b/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp
@@ -3,9 +3,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017-2020.
-// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2017-2021.
+// Modifications copyright (c) 2017-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -33,6 +32,9 @@
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/strategies/detail.hpp>
+#include <boost/geometry/strategies/relate/services.hpp>
+
#include <boost/geometry/util/condition.hpp>
@@ -271,24 +273,103 @@ struct self_get_turn_points
#endif // DOXYGEN_NO_DISPATCH
+namespace resolve_strategy
+{
+
+template
+<
+ bool Reverse,
+ typename AssignPolicy,
+ typename Strategies,
+ bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
+>
+struct self_get_turn_points
+{
+ template
+ <
+ typename Geometry,
+ typename RobustPolicy,
+ typename Turns,
+ typename InterruptPolicy
+ >
+ static inline void apply(Geometry const& geometry,
+ Strategies const& strategies,
+ RobustPolicy const& robust_policy,
+ Turns& turns,
+ InterruptPolicy& interrupt_policy,
+ int source_index,
+ bool skip_adjacent)
+ {
+ using turn_policy = detail::overlay::get_turn_info<AssignPolicy>;
+
+ dispatch::self_get_turn_points
+ <
+ Reverse,
+ typename tag<Geometry>::type,
+ Geometry,
+ turn_policy
+ >::apply(geometry, strategies, robust_policy, turns, interrupt_policy,
+ source_index, skip_adjacent);
+ }
+};
+
+template <bool Reverse, typename AssignPolicy, typename Strategy>
+struct self_get_turn_points<Reverse, AssignPolicy, Strategy, false>
+{
+ template
+ <
+ typename Geometry,
+ typename RobustPolicy,
+ typename Turns,
+ typename InterruptPolicy
+ >
+ static inline void apply(Geometry const& geometry,
+ Strategy const& strategy,
+ RobustPolicy const& robust_policy,
+ Turns& turns,
+ InterruptPolicy& interrupt_policy,
+ int source_index,
+ bool skip_adjacent)
+ {
+ using strategies::relate::services::strategy_converter;
+
+ self_get_turn_points
+ <
+ Reverse,
+ AssignPolicy,
+ decltype(strategy_converter<Strategy>::get(strategy))
+ >::apply(geometry,
+ strategy_converter<Strategy>::get(strategy),
+ robust_policy,
+ turns,
+ interrupt_policy,
+ source_index,
+ skip_adjacent);
+ }
+};
+
+
+} // namespace resolve_strategy
+
+
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace self_get_turn_points
{
-// Version where Reverse can be specified manually. TODO:
+// Version where Reverse can be specified manually. TODO:
// can most probably be merged with self_get_turn_points::get_turn
template
<
bool Reverse,
typename AssignPolicy,
typename Geometry,
- typename IntersectionStrategy,
+ typename Strategy,
typename RobustPolicy,
typename Turns,
typename InterruptPolicy
>
inline void self_turns(Geometry const& geometry,
- IntersectionStrategy const& strategy,
+ Strategy const& strategy,
RobustPolicy const& robust_policy,
Turns& turns,
InterruptPolicy& interrupt_policy,
@@ -297,14 +378,9 @@ inline void self_turns(Geometry const& geometry,
{
concepts::check<Geometry const>();
- typedef detail::overlay::get_turn_info<detail::overlay::assign_null_policy> turn_policy;
-
- dispatch::self_get_turn_points
+ resolve_strategy::self_get_turn_points
<
- Reverse,
- typename tag<Geometry>::type,
- Geometry,
- turn_policy
+ Reverse, AssignPolicy, Strategy
>::apply(geometry, strategy, robust_policy, turns, interrupt_policy,
source_index, skip_adjacent);
}
@@ -351,12 +427,11 @@ inline void self_turns(Geometry const& geometry,
geometry::point_order<Geometry>::value
>::value;
- detail::self_get_turn_points::self_turns
+ resolve_strategy::self_get_turn_points
<
- reverse,
- AssignPolicy
- >(geometry, strategy, robust_policy, turns, interrupt_policy,
- source_index, skip_adjacent);
+ reverse, AssignPolicy, Strategy
+ >::apply(geometry, strategy, robust_policy, turns, interrupt_policy,
+ source_index, skip_adjacent);
}
diff --git a/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp b/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
index 49e6761860..503b36720a 100644
--- a/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
+++ b/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp
@@ -3,9 +3,10 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017, 2019.
-// Modifications copyright (c) 2017, 2019 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2023.
+// Modifications copyright (c) 2017-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -17,6 +18,7 @@
#include <algorithm>
#include <map>
+#include <set>
#include <vector>
#include <boost/geometry/algorithms/detail/overlay/approximately_equals.hpp>
@@ -127,10 +129,10 @@ struct less_false
}
};
-template <typename Point, typename SideStrategy, typename LessOnSame, typename Compare>
+template <typename PointOrigin, typename PointTurn, typename SideStrategy, typename LessOnSame, typename Compare>
struct less_by_side
{
- less_by_side(const Point& p1, const Point& p2, SideStrategy const& strategy)
+ less_by_side(const PointOrigin& p1, const PointTurn& p2, SideStrategy const& strategy)
: m_origin(p1)
, m_turn_point(p2)
, m_strategy(strategy)
@@ -209,8 +211,8 @@ struct less_by_side
}
private :
- Point const& m_origin;
- Point const& m_turn_point;
+ PointOrigin const& m_origin;
+ PointTurn const& m_turn_point;
SideStrategy const& m_strategy;
};
@@ -316,7 +318,15 @@ public :
// then take a point (or more) further back.
// The limit of offset avoids theoretical infinite loops.
// In practice it currently walks max 1 point back in all cases.
- double const tolerance = 1.0e9;
+ // Use the coordinate type, but if it is too small (e.g. std::int16), use a double
+ using ct_type = typename geometry::select_most_precise
+ <
+ typename geometry::coordinate_type<Point>::type,
+ double
+ >::type;
+
+ ct_type const tolerance = 1000000000;
+
int offset = 0;
while (approximately_equals(point_from, turn.point, tolerance)
&& offset > -10)
@@ -371,7 +381,8 @@ public :
}
}
- void apply(Point const& turn_point)
+ template <typename PointTurn>
+ void apply(PointTurn const& turn_point)
{
// We need three compare functors:
// 1) to order clockwise (union) or counter clockwise (intersection)
@@ -380,8 +391,8 @@ public :
// to give colinear points
// Sort by side and assign rank
- less_by_side<Point, SideStrategy, less_by_index, Compare> less_unique(m_origin, turn_point, m_strategy);
- less_by_side<Point, SideStrategy, less_false, Compare> less_non_unique(m_origin, turn_point, m_strategy);
+ less_by_side<Point, PointTurn, SideStrategy, less_by_index, Compare> less_unique(m_origin, turn_point, m_strategy);
+ less_by_side<Point, PointTurn, SideStrategy, less_false, Compare> less_non_unique(m_origin, turn_point, m_strategy);
std::sort(m_ranked_points.begin(), m_ranked_points.end(), less_unique);
@@ -467,7 +478,7 @@ public :
// Move iterator after rank==0
bool has_first = false;
- typename container_type::iterator it = m_ranked_points.begin() + 1;
+ auto it = m_ranked_points.begin() + 1;
for (; it != m_ranked_points.end() && it->rank == 0; ++it)
{
has_first = true;
@@ -478,8 +489,7 @@ public :
// Reverse first part (having rank == 0), if any,
// but skip the very first row
std::reverse(m_ranked_points.begin() + 1, it);
- for (typename container_type::iterator fit = m_ranked_points.begin();
- fit != it; ++fit)
+ for (auto fit = m_ranked_points.begin(); fit != it; ++fit)
{
BOOST_ASSERT(fit->rank == 0);
}
diff --git a/boost/geometry/algorithms/detail/overlay/traversal.hpp b/boost/geometry/algorithms/detail/overlay/traversal.hpp
index a0149789c6..22ae1a2de8 100644
--- a/boost/geometry/algorithms/detail/overlay/traversal.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traversal.hpp
@@ -123,12 +123,8 @@ public :
template <typename TurnInfoMap>
inline void finalize_visit_info(TurnInfoMap& turn_info_map)
{
- for (typename boost::range_iterator<Turns>::type
- it = boost::begin(m_turns);
- it != boost::end(m_turns);
- ++it)
+ for (auto& turn : m_turns)
{
- turn_type& turn = *it;
for (int i = 0; i < 2; i++)
{
turn_operation_type& op = turn.operations[i];
@@ -158,23 +154,18 @@ public :
inline void set_visited_in_cluster(signed_size_type cluster_id,
signed_size_type rank)
{
- typename Clusters::const_iterator mit = m_clusters.find(cluster_id);
+ auto mit = m_clusters.find(cluster_id);
BOOST_ASSERT(mit != m_clusters.end());
cluster_info const& cinfo = mit->second;
- std::set<signed_size_type> const& ids = cinfo.turn_indices;
- for (typename std::set<signed_size_type>::const_iterator it = ids.begin();
- it != ids.end(); ++it)
+ for (auto turn_index : cinfo.turn_indices)
{
- signed_size_type const turn_index = *it;
turn_type& turn = m_turns[turn_index];
- for (int i = 0; i < 2; i++)
+ for (auto& op : turn.operations)
{
- turn_operation_type& op = turn.operations[i];
- if (op.visited.none()
- && op.enriched.rank == rank)
+ if (op.visited.none() && op.enriched.rank == rank)
{
op.visited.set_visited();
}
@@ -621,31 +612,32 @@ public :
return m_turns[rp.turn_index].operations[rp.operation_index];
}
- inline sort_by_side::rank_type select_rank(sbs_type const& sbs,
- bool skip_isolated) const
+ inline sort_by_side::rank_type select_rank(sbs_type const& sbs) const
{
+ static bool const is_intersection
+ = target_operation == operation_intersection;
+
// Take the first outgoing rank corresponding to incoming region,
// or take another region if it is not isolated
- turn_operation_type const& incoming_op
- = operation_from_rank(sbs.m_ranked_points.front());
+ auto const& in_op = operation_from_rank(sbs.m_ranked_points.front());
for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
{
- typename sbs_type::rp const& rp = sbs.m_ranked_points[i];
+ auto const& rp = sbs.m_ranked_points[i];
if (rp.rank == 0 || rp.direction == sort_by_side::dir_from)
{
continue;
}
- turn_operation_type const& op = operation_from_rank(rp);
+ auto const& out_op = operation_from_rank(rp);
- if (op.operation != target_operation
- && op.operation != operation_continue)
+ if (out_op.operation != target_operation
+ && out_op.operation != operation_continue)
{
continue;
}
- if (op.enriched.region_id == incoming_op.enriched.region_id
- || (skip_isolated && ! op.enriched.isolated))
+ if (in_op.enriched.region_id == out_op.enriched.region_id
+ || (is_intersection && ! out_op.enriched.isolated))
{
// Region corresponds to incoming region, or (for intersection)
// there is a non-isolated other region which should be taken
@@ -660,7 +652,7 @@ public :
int& op_index, sbs_type const& sbs,
signed_size_type start_turn_index, int start_op_index) const
{
- sort_by_side::rank_type const selected_rank = select_rank(sbs, false);
+ sort_by_side::rank_type const selected_rank = select_rank(sbs);
int current_priority = 0;
for (std::size_t i = 1; i < sbs.m_ranked_points.size(); i++)
@@ -688,49 +680,59 @@ public :
inline bool analyze_cluster_intersection(signed_size_type& turn_index,
int& op_index, sbs_type const& sbs) const
{
- sort_by_side::rank_type const selected_rank = select_rank(sbs, true);
+ // Select the rank based on regions and isolation
+ sort_by_side::rank_type const selected_rank = select_rank(sbs);
- if (selected_rank > 0)
+ if (selected_rank <= 0)
{
- typename turn_operation_type::comparable_distance_type
- min_remaining_distance = 0;
+ return false;
+ }
- std::size_t selected_index = sbs.m_ranked_points.size();
- for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
+ // From these ranks, select the index: the first, or the one with
+ // the smallest remaining distance
+ typename turn_operation_type::comparable_distance_type
+ min_remaining_distance = 0;
+
+ std::size_t selected_index = sbs.m_ranked_points.size();
+ for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++)
+ {
+ auto const& ranked_point = sbs.m_ranked_points[i];
+
+ if (ranked_point.rank > selected_rank)
{
- typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[i];
+ break;
+ }
+ else if (ranked_point.rank == selected_rank)
+ {
+ auto const& op = operation_from_rank(ranked_point);
- if (ranked_point.rank == selected_rank)
+ if (op.visited.finalized())
{
- turn_operation_type const& op = operation_from_rank(ranked_point);
-
- if (op.visited.finalized())
- {
- // This direction is already traveled before, the same
- // cannot be traveled again
- continue;
- }
-
- // Take turn with the smallest remaining distance
- if (selected_index == sbs.m_ranked_points.size()
- || op.remaining_distance < min_remaining_distance)
- {
- selected_index = i;
- min_remaining_distance = op.remaining_distance;
- }
+ // This direction is already traveled,
+ // it cannot be traveled again
+ continue;
}
- }
- if (selected_index < sbs.m_ranked_points.size())
- {
- typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[selected_index];
- turn_index = ranked_point.turn_index;
- op_index = ranked_point.operation_index;
- return true;
+ if (selected_index == sbs.m_ranked_points.size()
+ || op.remaining_distance < min_remaining_distance)
+ {
+ // It was unassigned or it is better
+ selected_index = i;
+ min_remaining_distance = op.remaining_distance;
+ }
}
}
- return false;
+ if (selected_index == sbs.m_ranked_points.size())
+ {
+ // Should not happen, there must be points with the selected rank
+ return false;
+ }
+
+ auto const& ranked_point = sbs.m_ranked_points[selected_index];
+ turn_index = ranked_point.turn_index;
+ op_index = ranked_point.operation_index;
+ return true;
}
inline bool fill_sbs(sbs_type& sbs,
@@ -778,21 +780,19 @@ public :
turn_type const& turn = m_turns[turn_index];
BOOST_ASSERT(turn.is_clustered());
- typename Clusters::const_iterator mit = m_clusters.find(turn.cluster_id);
+ auto mit = m_clusters.find(turn.cluster_id);
BOOST_ASSERT(mit != m_clusters.end());
cluster_info const& cinfo = mit->second;
- std::set<signed_size_type> const& cluster_indices = cinfo.turn_indices;
sbs_type sbs(m_strategy);
-
- if (! fill_sbs(sbs, turn_index, cluster_indices, previous_seg_id))
+ if (! fill_sbs(sbs, turn_index, cinfo.turn_indices, previous_seg_id))
{
return false;
}
- cluster_exits<OverlayType, Turns, sbs_type> exits(m_turns, cluster_indices, sbs);
+ cluster_exits<OverlayType, Turns, sbs_type> exits(m_turns, cinfo.turn_indices, sbs);
if (exits.apply(turn_index, op_index))
{
@@ -803,7 +803,7 @@ public :
if (is_union)
{
- result = select_from_cluster_union(turn_index, cluster_indices,
+ result = select_from_cluster_union(turn_index, cinfo.turn_indices,
op_index, sbs,
start_turn_index, start_op_index);
if (! result)
@@ -819,6 +819,7 @@ public :
return result;
}
+ // Analyzes a non-clustered "ii" intersection, as if it is clustered.
inline bool analyze_ii_intersection(signed_size_type& turn_index, int& op_index,
turn_type const& current_turn,
segment_identifier const& previous_seg_id)
@@ -956,31 +957,43 @@ public :
{
turn_type const& current_turn = m_turns[turn_index];
+ bool const back_at_start_cluster
+ = has_points
+ && current_turn.is_clustered()
+ && m_turns[start_turn_index].cluster_id == current_turn.cluster_id;
if (BOOST_GEOMETRY_CONDITION(target_operation == operation_intersection))
{
- if (has_points)
- {
- bool const back_at_start_cluster
- = current_turn.is_clustered()
- && m_turns[start_turn_index].cluster_id == current_turn.cluster_id;
+ // Intersection or difference
- if (turn_index == start_turn_index || back_at_start_cluster)
- {
- // Intersection can always be finished if returning
- turn_index = start_turn_index;
- op_index = start_op_index;
- return true;
- }
+ if (has_points && (turn_index == start_turn_index || back_at_start_cluster))
+ {
+ // Intersection can always be finished if returning
+ turn_index = start_turn_index;
+ op_index = start_op_index;
+ return true;
}
if (! current_turn.is_clustered()
- && current_turn.both(operation_intersection))
- {
- if (analyze_ii_intersection(turn_index, op_index,
+ && current_turn.both(operation_intersection)
+ && analyze_ii_intersection(turn_index, op_index,
current_turn, previous_seg_id))
- {
- return true;
- }
+ {
+ return true;
+ }
+ }
+ else if (turn_index == start_turn_index || back_at_start_cluster)
+ {
+ // Union or buffer: cannot return immediately to starting turn, because it then
+ // might miss a formed multi polygon with a touching point.
+ auto const& current_op = current_turn.operations[op_index];
+ signed_size_type const next_turn_index = current_op.enriched.get_next_turn_index();
+ bool const to_other_turn = next_turn_index >= 0 && m_turns[next_turn_index].cluster_id != current_turn.cluster_id;
+ if (! to_other_turn)
+ {
+ // Return to starting point
+ turn_index = start_turn_index;
+ op_index = start_op_index;
+ return true;
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp b/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp
index ad248826dd..be0f2bcd87 100644
--- a/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp
@@ -89,7 +89,6 @@ struct traversal_switch_detector
enum isolation_type
{
- isolation_unknown = -1,
isolation_no = 0,
isolation_yes = 1,
isolation_multiple = 2
@@ -121,7 +120,7 @@ struct traversal_switch_detector
struct region_properties
{
signed_size_type region_id = -1;
- isolation_type isolated = isolation_unknown;
+ isolation_type isolated = isolation_no;
set_type unique_turn_ids;
connection_map connected_region_counts;
};
@@ -374,7 +373,7 @@ struct traversal_switch_detector
{
region_properties& properties = key_val.second;
- if (properties.isolated == isolation_unknown
+ if (properties.isolated == isolation_no
&& has_only_isolated_children(properties))
{
properties.isolated = isolation_yes;
@@ -388,13 +387,36 @@ struct traversal_switch_detector
{
for (turn_type& turn : m_turns)
{
+ // For difference, for the input walked through in reverse,
+ // the meaning is reversed: what is isolated is actually not,
+ // and vice versa.
+ bool const reverseMeaningInTurn
+ = (Reverse1 || Reverse2)
+ && ! turn.is_self()
+ && ! turn.is_clustered()
+ && uu_or_ii(turn)
+ && turn.operations[0].enriched.region_id
+ != turn.operations[1].enriched.region_id;
+
for (auto& op : turn.operations)
{
auto mit = m_connected_regions.find(op.enriched.region_id);
if (mit != m_connected_regions.end())
{
+ bool const reverseMeaningInOp
+ = reverseMeaningInTurn
+ && ((op.seg_id.source_index == 0 && Reverse1)
+ || (op.seg_id.source_index == 1 && Reverse2));
+
+ // It is assigned to isolated if it's property is "Yes",
+ // (one connected interior, or chained).
+ // "Multiple" doesn't count for isolation,
+ // neither for intersection, neither for difference.
region_properties const& prop = mit->second;
- op.enriched.isolated = prop.isolated == isolation_yes;
+ op.enriched.isolated
+ = reverseMeaningInOp
+ ? false
+ : prop.isolated == isolation_yes;
}
}
}
@@ -478,8 +500,12 @@ struct traversal_switch_detector
// Discarded turns don't connect rings to the same region
// Also xx are not relevant
// (otherwise discarded colocated uu turn could make a connection)
- return ! turn.discarded
- && ! turn.both(operation_blocked);
+ return ! turn.discarded && ! turn.both(operation_blocked);
+ }
+
+ inline bool uu_or_ii(turn_type const& turn) const
+ {
+ return turn.both(operation_union) || turn.both(operation_intersection);
}
inline bool connects_same_region(turn_type const& turn) const
@@ -492,7 +518,7 @@ struct traversal_switch_detector
if (! turn.is_clustered())
{
// If it is a uu/ii-turn (non clustered), it is never same region
- return ! (turn.both(operation_union) || turn.both(operation_intersection));
+ return ! uu_or_ii(turn);
}
if (BOOST_GEOMETRY_CONDITION(target_operation == operation_union))
@@ -565,10 +591,83 @@ struct traversal_switch_detector
}
}
+#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
+ void debug_show_results()
+ {
+ auto isolation_to_string = [](isolation_type const& iso) -> std::string
+ {
+ switch(iso)
+ {
+ case isolation_no : return "no";
+ case isolation_yes : return "yes";
+ case isolation_multiple : return "multiple";
+ }
+ return "error";
+ };
+ auto set_to_string = [](auto const& s) -> std::string
+ {
+ std::ostringstream result;
+ for (auto item : s) { result << " " << item; }
+ return result.str();
+ };
+
+ for (auto const& kv : m_connected_regions)
+ {
+ auto const& prop = kv.second;
+
+ std::ostringstream sub;
+ sub << "[turns" << set_to_string(prop.unique_turn_ids)
+ << "] regions";
+ for (auto const& kvs : prop.connected_region_counts)
+ {
+ sub << " { " << kvs.first
+ << " : via [" << set_to_string(kvs.second.unique_turn_ids)
+ << " ] }";
+ }
+
+ std::cout << "REGION " << prop.region_id
+ << " " << isolation_to_string(prop.isolated)
+ << " " << sub.str()
+ << std::endl;
+ }
+
+ for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)
+ {
+ turn_type const& turn = m_turns[turn_index];
+
+ if (uu_or_ii(turn) && ! turn.is_clustered())
+ {
+ std::cout << (turn.both(operation_union) ? "UU" : "II")
+ << " " << turn_index
+ << " (" << geometry::get<0>(turn.point)
+ << ", " << geometry::get<1>(turn.point) << ")"
+ << " -> " << std::boolalpha
+ << " [" << turn.operations[0].seg_id.source_index
+ << "/" << turn.operations[1].seg_id.source_index << "] "
+ << "(" << turn.operations[0].enriched.region_id
+ << " " << turn.operations[0].enriched.isolated
+ << ") / (" << turn.operations[1].enriched.region_id
+ << " " << turn.operations[1].enriched.isolated << ")"
+ << std::endl;
+ }
+ }
+
+ for (auto const& key_val : m_clusters)
+ {
+ cluster_info const& cinfo = key_val.second;
+ std::cout << "CL RESULT " << key_val.first
+ << " -> " << cinfo.open_count << std::endl;
+ }
+ }
+#endif
+
void iterate()
{
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
- std::cout << "BEGIN SWITCH DETECTOR (region_ids and isolation)" << std::endl;
+ std::cout << "BEGIN SWITCH DETECTOR (region_ids and isolation)"
+ << (Reverse1 ? " REVERSE_1" : "")
+ << (Reverse2 ? " REVERSE_2" : "")
+ << std::endl;
#endif
// Collect turns per ring
@@ -608,33 +707,7 @@ struct traversal_switch_detector
#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR)
std::cout << "END SWITCH DETECTOR" << std::endl;
-
- for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index)
- {
- turn_type const& turn = m_turns[turn_index];
-
- if ((turn.both(operation_union) || turn.both(operation_intersection))
- && ! turn.is_clustered())
- {
- std::cout << (turn.both(operation_union) ? "UU" : "II")
- << " " << turn_index
- << " (" << geometry::get<0>(turn.point)
- << ", " << geometry::get<1>(turn.point) << ")"
- << " -> " << std::boolalpha
- << "(" << turn.operations[0].enriched.region_id
- << " " << turn.operations[0].enriched.isolated
- << ") / (" << turn.operations[1].enriched.region_id
- << " " << turn.operations[1].enriched.isolated << ")"
- << std::endl;
- }
- }
-
- for (auto const& key_val : m_clusters)
- {
- cluster_info const& cinfo = key_val.second;
- std::cout << "CL RESULT " << key_val.first
- << " -> " << cinfo.open_count << std::endl;
- }
+ debug_show_results();
#endif
}
diff --git a/boost/geometry/algorithms/detail/overlay/traverse.hpp b/boost/geometry/algorithms/detail/overlay/traverse.hpp
index b9cbea3127..710cea09e9 100644
--- a/boost/geometry/algorithms/detail/overlay/traverse.hpp
+++ b/boost/geometry/algorithms/detail/overlay/traverse.hpp
@@ -42,14 +42,11 @@ class traverse
template <typename Turns>
static void reset_visits(Turns& turns)
{
- for (typename boost::range_iterator<Turns>::type
- it = boost::begin(turns);
- it != boost::end(turns);
- ++it)
+ for (auto& turn : turns)
{
- for (int i = 0; i < 2; i++)
+ for (auto& op : turn.operations)
{
- it->operations[i].visited.reset();
+ op.visited.reset();
}
}
}
diff --git a/boost/geometry/algorithms/detail/overlay/turn_info.hpp b/boost/geometry/algorithms/detail/overlay/turn_info.hpp
index 7dcbf4c8ef..8f1d22c8c0 100644
--- a/boost/geometry/algorithms/detail/overlay/turn_info.hpp
+++ b/boost/geometry/algorithms/detail/overlay/turn_info.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 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
@@ -10,7 +11,7 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TURN_INFO_HPP
-#include <boost/array.hpp>
+#include <array>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
@@ -80,7 +81,7 @@ template
typename Point,
typename SegmentRatio = geometry::segment_ratio<typename coordinate_type<Point>::type>,
typename Operation = turn_operation<Point, SegmentRatio>,
- typename Container = boost::array<Operation, 2>
+ typename Container = std::array<Operation, 2>
>
struct turn_info
{
@@ -138,6 +139,11 @@ struct turn_info
{
return cluster_id > 0;
}
+ inline bool is_self() const
+ {
+ return operations[0].seg_id.source_index
+ == operations[1].seg_id.source_index;
+ }
private :
inline bool has12(operation_type type1, operation_type type2) const
diff --git a/boost/geometry/algorithms/detail/partition.hpp b/boost/geometry/algorithms/detail/partition.hpp
index 2a47eb2b64..e3c4208e3e 100644
--- a/boost/geometry/algorithms/detail/partition.hpp
+++ b/boost/geometry/algorithms/detail/partition.hpp
@@ -52,20 +52,39 @@ struct divide_interval<T, true>
{
static inline T apply(T const& mi, T const& ma)
{
- // avoid overflow
+ // Avoid overflow
return mi / 2 + ma / 2 + (mi % 2 + ma % 2) / 2;
}
};
-template <int Dimension, typename Box>
+struct visit_no_policy
+{
+ template <typename Box>
+ static inline void apply(Box const&, std::size_t )
+ {}
+};
+
+struct include_all_policy
+{
+ template <typename Item>
+ static inline bool apply(Item const&)
+ {
+ return true;
+ }
+};
+
+
+template <std::size_t Dimension, typename Box>
inline void divide_box(Box const& box, Box& lower_box, Box& upper_box)
{
- typedef typename coordinate_type<Box>::type ctype;
+ using coor_t = typename coordinate_type<Box>::type;
- // Divide input box into two parts, e.g. left/right
- ctype mid = divide_interval<ctype>::apply(
- geometry::get<min_corner, Dimension>(box),
- geometry::get<max_corner, Dimension>(box));
+ // Divide input box into two halves
+ // either left/right (Dimension 0)
+ // or top/bottom (Dimension 1)
+ coor_t const mid
+ = divide_interval<coor_t>::apply(geometry::get<min_corner, Dimension>(box),
+ geometry::get<max_corner, Dimension>(box));
lower_box = box;
upper_box = box;
@@ -85,12 +104,7 @@ inline void divide_into_subsets(Box const& lower_box,
IteratorVector& exceeding,
OverlapsPolicy const& overlaps_policy)
{
- typedef typename boost::range_iterator
- <
- IteratorVector const
- >::type it_type;
-
- for(it_type it = boost::begin(input); it != boost::end(input); ++it)
+ for (auto it = boost::begin(input); it != boost::end(input); ++it)
{
bool const lower_overlapping = overlaps_policy.apply(lower_box, **it);
bool const upper_overlapping = overlaps_policy.apply(upper_box, **it);
@@ -124,10 +138,9 @@ template
inline void expand_with_elements(Box& total, IteratorVector const& input,
ExpandPolicy const& expand_policy)
{
- typedef typename boost::range_iterator<IteratorVector const>::type it_type;
- for(it_type it = boost::begin(input); it != boost::end(input); ++it)
+ for (auto const& it : input)
{
- expand_policy.apply(total, **it);
+ expand_policy.apply(total, *it);
}
}
@@ -141,17 +154,15 @@ inline bool handle_one(IteratorVector const& input, VisitPolicy& visitor)
return true;
}
- typedef typename boost::range_iterator<IteratorVector const>::type it_type;
-
// Quadratic behaviour at lowest level (lowest quad, or all exceeding)
- for (it_type it1 = boost::begin(input); it1 != boost::end(input); ++it1)
+ for (auto it1 = boost::begin(input); it1 != boost::end(input); ++it1)
{
- it_type it2 = it1;
+ auto it2 = it1;
for (++it2; it2 != boost::end(input); ++it2)
{
if (! visitor.apply(**it1, **it2))
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
}
@@ -170,32 +181,19 @@ inline bool handle_two(IteratorVector1 const& input1,
IteratorVector2 const& input2,
VisitPolicy& visitor)
{
- typedef typename boost::range_iterator
- <
- IteratorVector1 const
- >::type iterator_type1;
-
- typedef typename boost::range_iterator
- <
- IteratorVector2 const
- >::type iterator_type2;
if (boost::empty(input1) || boost::empty(input2))
{
return true;
}
- for(iterator_type1 it1 = boost::begin(input1);
- it1 != boost::end(input1);
- ++it1)
+ for (auto const& it1 : input1)
{
- for(iterator_type2 it2 = boost::begin(input2);
- it2 != boost::end(input2);
- ++it2)
+ for (auto const& it2 : input2)
{
- if (! visitor.apply(**it1, **it2))
+ if (! visitor.apply(*it1, *it2))
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
}
@@ -236,11 +234,11 @@ inline bool recurse_ok(IteratorVector1 const& input1,
}
-template <int Dimension, typename Box>
+template <std::size_t Dimension, typename Box>
class partition_two_ranges;
-template <int Dimension, typename Box>
+template <std::size_t Dimension, typename Box>
class partition_one_range
{
template <typename IteratorVector, typename ExpandPolicy>
@@ -349,10 +347,10 @@ public :
if (! boost::empty(exceeding))
{
// Get the box of exceeding-only
- Box exceeding_box = get_new_box(exceeding, expand_policy);
+ Box const exceeding_box = get_new_box(exceeding, expand_policy);
- // Recursively do exceeding elements only, in next dimension they
- // will probably be less exceeding within the new box
+ // Recursively do exceeding elements only, in next dimension they
+ // will probably be less exceeding within the new box
if (! (next_level(exceeding_box, exceeding, level, min_elements,
visitor, expand_policy, overlaps_policy, box_policy)
// Switch to two forward ranges, combine exceeding with
@@ -362,7 +360,7 @@ public :
&& next_level2(exceeding_box, exceeding, upper, level, min_elements,
visitor, expand_policy, overlaps_policy, box_policy)) )
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
@@ -376,7 +374,7 @@ public :
template
<
- int Dimension,
+ std::size_t Dimension,
typename Box
>
class partition_two_ranges
@@ -480,20 +478,20 @@ public :
if (recurse_ok(exceeding1, exceeding2, min_elements, level))
{
- Box exceeding_box = get_new_box(exceeding1, exceeding2,
- expand_policy1, expand_policy2);
+ Box const exceeding_box = get_new_box(exceeding1, exceeding2,
+ expand_policy1, expand_policy2);
if (! next_level(exceeding_box, exceeding1, exceeding2, level,
min_elements, visitor, expand_policy1, overlaps_policy1,
expand_policy2, overlaps_policy2, box_policy))
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
else
{
if (! handle_two(exceeding1, exceeding2, visitor))
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
@@ -503,7 +501,7 @@ public :
// the same combinations again and again)
if (recurse_ok(lower2, upper2, exceeding1, min_elements, level))
{
- Box exceeding_box = get_new_box(exceeding1, expand_policy1);
+ Box const exceeding_box = get_new_box(exceeding1, expand_policy1);
if (! (next_level(exceeding_box, exceeding1, lower2, level,
min_elements, visitor, expand_policy1, overlaps_policy1,
expand_policy2, overlaps_policy2, box_policy)
@@ -511,7 +509,7 @@ public :
min_elements, visitor, expand_policy1, overlaps_policy1,
expand_policy2, overlaps_policy2, box_policy)) )
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
else
@@ -519,7 +517,7 @@ public :
if (! (handle_two(exceeding1, lower2, visitor)
&& handle_two(exceeding1, upper2, visitor)) )
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
}
@@ -529,7 +527,7 @@ public :
// All exceeding from 2 with lower and upper of 1:
if (recurse_ok(lower1, upper1, exceeding2, min_elements, level))
{
- Box exceeding_box = get_new_box(exceeding2, expand_policy2);
+ Box const exceeding_box = get_new_box(exceeding2, expand_policy2);
if (! (next_level(exceeding_box, lower1, exceeding2, level,
min_elements, visitor, expand_policy1, overlaps_policy1,
expand_policy2, overlaps_policy2, box_policy)
@@ -537,7 +535,7 @@ public :
min_elements, visitor, expand_policy1, overlaps_policy1,
expand_policy2, overlaps_policy2, box_policy)) )
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
else
@@ -545,7 +543,7 @@ public :
if (! (handle_two(lower1, exceeding2, visitor)
&& handle_two(upper1, exceeding2, visitor)) )
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
}
@@ -556,14 +554,14 @@ public :
min_elements, visitor, expand_policy1, overlaps_policy1,
expand_policy2, overlaps_policy2, box_policy) )
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
else
{
if (! handle_two(lower1, lower2, visitor))
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
@@ -573,14 +571,14 @@ public :
min_elements, visitor, expand_policy1, overlaps_policy1,
expand_policy2, overlaps_policy2, box_policy) )
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
else
{
if (! handle_two(upper1, upper2, visitor))
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
@@ -588,22 +586,6 @@ public :
}
};
-struct visit_no_policy
-{
- template <typename Box>
- static inline void apply(Box const&, std::size_t )
- {}
-};
-
-struct include_all_policy
-{
- template <typename Item>
- static inline bool apply(Item const&)
- {
- return true;
- }
-};
-
}} // namespace detail::partition
@@ -629,10 +611,7 @@ class partition
IteratorVector& iterator_vector,
ExpandPolicy const& expand_policy)
{
- for(typename boost::range_iterator<ForwardRange const>::type
- it = boost::begin(forward_range);
- it != boost::end(forward_range);
- ++it)
+ for (auto it = boost::begin(forward_range); it != boost::end(forward_range); ++it)
{
if (IncludePolicy::apply(*it))
{
@@ -691,14 +670,14 @@ public:
std::size_t min_elements,
VisitBoxPolicy box_visitor)
{
- typedef typename boost::range_iterator
+ using iterator_t = typename boost::range_iterator
<
ForwardRange const
- >::type iterator_type;
+ >::type;
if (std::size_t(boost::size(forward_range)) > min_elements)
{
- std::vector<iterator_type> iterator_vector;
+ std::vector<iterator_t> iterator_vector;
Box total;
assign_inverse(total);
expand_to_range<IncludePolicy1>(forward_range, total,
@@ -712,16 +691,16 @@ public:
}
else
{
- for(iterator_type it1 = boost::begin(forward_range);
+ for (auto it1 = boost::begin(forward_range);
it1 != boost::end(forward_range);
++it1)
{
- iterator_type it2 = it1;
- for(++it2; it2 != boost::end(forward_range); ++it2)
+ auto it2 = it1;
+ for (++it2; it2 != boost::end(forward_range); ++it2)
{
if (! visitor.apply(*it1, *it2))
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
}
@@ -817,21 +796,21 @@ public:
std::size_t min_elements,
VisitBoxPolicy box_visitor)
{
- typedef typename boost::range_iterator
+ using iterator1_t = typename boost::range_iterator
<
ForwardRange1 const
- >::type iterator_type1;
+ >::type;
- typedef typename boost::range_iterator
+ using iterator2_t = typename boost::range_iterator
<
ForwardRange2 const
- >::type iterator_type2;
+ >::type;
if (std::size_t(boost::size(forward_range1)) > min_elements
&& std::size_t(boost::size(forward_range2)) > min_elements)
{
- std::vector<iterator_type1> iterator_vector1;
- std::vector<iterator_type2> iterator_vector2;
+ std::vector<iterator1_t> iterator_vector1;
+ std::vector<iterator2_t> iterator_vector2;
Box total;
assign_inverse(total);
expand_to_range<IncludePolicy1>(forward_range1, total,
@@ -849,17 +828,17 @@ public:
}
else
{
- for(iterator_type1 it1 = boost::begin(forward_range1);
+ for (auto it1 = boost::begin(forward_range1);
it1 != boost::end(forward_range1);
++it1)
{
- for(iterator_type2 it2 = boost::begin(forward_range2);
+ for (auto it2 = boost::begin(forward_range2);
it2 != boost::end(forward_range2);
++it2)
{
if (! visitor.apply(*it1, *it2))
{
- return false; // interrupt
+ return false; // Bail out if visitor returns false
}
}
}
diff --git a/boost/geometry/algorithms/detail/point_on_border.hpp b/boost/geometry/algorithms/detail/point_on_border.hpp
index 3969939b4e..8b3a20a16f 100644
--- a/boost/geometry/algorithms/detail/point_on_border.hpp
+++ b/boost/geometry/algorithms/detail/point_on_border.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2017-2020.
-// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2022.
+// Modifications copyright (c) 2017-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -25,17 +25,15 @@
#include <boost/range/end.hpp>
#include <boost/static_assert.hpp>
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/core/tags.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/equals/point_point.hpp>
-
#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/views/detail/indexed_point_view.hpp>
namespace boost { namespace geometry
@@ -49,10 +47,10 @@ namespace detail { namespace point_on_border
struct get_point
{
- template <typename Point>
- static inline bool apply(Point& destination, Point const& source)
+ template <typename Destination, typename Source>
+ static inline bool apply(Destination& destination, Source const& source)
{
- destination = source;
+ detail::conversion::convert_point_to_point(source, destination);
return true;
}
};
@@ -69,7 +67,7 @@ struct point_on_range
return false;
}
- geometry::detail::conversion::convert_point_to_point(*begin, point);
+ detail::conversion::convert_point_to_point(*begin, point);
return true;
}
@@ -92,12 +90,13 @@ struct point_on_polygon
};
-struct point_on_box
+struct point_on_segment_or_box
{
- template<typename Point, typename Box>
- static inline bool apply(Point& point, Box const& box)
+ template<typename Point, typename SegmentOrBox>
+ static inline bool apply(Point& point, SegmentOrBox const& segment_or_box)
{
- detail::assign::assign_box_2d_corner<min_corner, min_corner>(box, point);
+ detail::indexed_point_view<SegmentOrBox const, 0> view(segment_or_box);
+ detail::conversion::convert_point_to_point(view, point);
return true;
}
};
@@ -111,12 +110,7 @@ struct point_on_multi
{
// 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)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
if (Policy::apply(point, *it))
{
@@ -147,6 +141,11 @@ struct point_on_border<point_tag>
{};
template <>
+struct point_on_border<segment_tag>
+ : detail::point_on_border::point_on_segment_or_box
+{};
+
+template <>
struct point_on_border<linestring_tag>
: detail::point_on_border::point_on_range
{};
@@ -163,11 +162,16 @@ struct point_on_border<polygon_tag>
template <>
struct point_on_border<box_tag>
- : detail::point_on_border::point_on_box
+ : detail::point_on_border::point_on_segment_or_box
{};
template <>
+struct point_on_border<multi_point_tag>
+ : detail::point_on_border::point_on_range
+{};
+
+template <>
struct point_on_border<multi_polygon_tag>
: detail::point_on_border::point_on_multi
<
@@ -189,6 +193,9 @@ struct point_on_border<multi_linestring_tag>
#endif // DOXYGEN_NO_DISPATCH
+// TODO: We should probably rename this utility because it can return point
+// which is in the interior of a geometry (for PointLike and LinearRings).
+
/*!
\brief Take point on a border
\ingroup overlay
diff --git a/boost/geometry/algorithms/detail/recalculate.hpp b/boost/geometry/algorithms/detail/recalculate.hpp
index 688d49237d..eb633c9c2f 100644
--- a/boost/geometry/algorithms/detail/recalculate.hpp
+++ b/boost/geometry/algorithms/detail/recalculate.hpp
@@ -106,13 +106,10 @@ struct range_to_range
typedef recalculate_point<geometry::dimension<point_type>::value> per_point;
geometry::clear(destination);
- for (typename boost::range_iterator<Range2 const>::type it
- = boost::begin(source);
- it != boost::end(source);
- ++it)
+ for (auto const& source_point : source)
{
point_type p;
- per_point::apply(p, *it, strategy);
+ per_point::apply(p, source_point, strategy);
geometry::append(destination, p);
}
}
diff --git a/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/boost/geometry/algorithms/detail/relate/areal_areal.hpp
index 99df598da8..41366e3167 100644
--- a/boost/geometry/algorithms/detail/relate/areal_areal.hpp
+++ b/boost/geometry/algorithms/detail/relate/areal_areal.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018, 2019.
-// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -29,12 +29,14 @@
#include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp>
#include <boost/geometry/algorithms/detail/relate/follow_helpers.hpp>
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail { namespace relate {
-
+
// WARNING!
// TODO: In the worst case calling this Pred in a loop for MultiPolygon/MultiPolygon may take O(NM)
// Use the rtree in this case!
@@ -85,9 +87,9 @@ public:
return false;
}
- typedef typename geometry::point_type<Areal>::type point_type;
- point_type pt;
- bool const ok = boost::geometry::point_on_border(pt, areal);
+ using point_type = typename geometry::point_type<Areal>::type;
+ typename helper_geometry<point_type>::type pt;
+ bool const ok = geometry::point_on_border(pt, areal);
// TODO: for now ignore, later throw an exception?
if ( !ok )
@@ -102,7 +104,7 @@ public:
m_other_areal,
m_point_in_areal_strategy);
//BOOST_GEOMETRY_ASSERT( pig != 0 );
-
+
// inside
if ( pig > 0 )
{
@@ -185,7 +187,7 @@ public:
}
}
}
-
+
return m_flags != 3 && !m_result.interrupt;
}
@@ -206,9 +208,6 @@ struct areal_areal
static const bool interruption_enabled = true;
- typedef typename geometry::point_type<Geometry1>::type point1_type;
- typedef typename geometry::point_type<Geometry2>::type point2_type;
-
template <typename Result, typename Strategy>
static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
Result & result,
@@ -216,17 +215,16 @@ struct areal_areal
{
// TODO: If Areal geometry may have infinite size, change the following line:
- // The result should be FFFFFFFFF
- relate::set<exterior, exterior, result_dimension<Geometry2>::value>(result);// FFFFFFFFd, d in [1,9] or T
+ update<exterior, exterior, result_dimension<Geometry2>::value>(result);// FFFFFFFFd, d in [1,9] or T
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
// get and analyse turns
- typedef typename turns::get_turns
+ using turn_type = typename turns::get_turns
<
Geometry1, Geometry2
- >::template turn_info_type<Strategy>::type turn_type;
+ >::template turn_info_type<Strategy>::type;
std::vector<turn_type> turns;
interrupt_policy_areal_areal<Result> interrupt_policy(geometry1, geometry2, result);
@@ -235,8 +233,6 @@ struct areal_areal
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
- typedef typename Strategy::cs_tag cs_tag;
-
no_turns_aa_pred<Geometry2, Result, Strategy, false>
pred1(geometry2, result, strategy);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
@@ -248,7 +244,7 @@ struct areal_areal
for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
-
+
if ( turns.empty() )
return;
@@ -259,8 +255,8 @@ struct areal_areal
|| may_update<exterior, interior, '2'>(result) )
{
// sort turns
- typedef turns::less<0, turns::less_op_areal_areal<0>, cs_tag> less;
- std::sort(turns.begin(), turns.end(), less());
+ using less_t = turns::less<0, turns::less_op_areal_areal<0>, Strategy>;
+ std::sort(turns.begin(), turns.end(), less_t());
/*if ( may_update<interior, exterior, '2'>(result)
|| may_update<boundary, exterior, '1'>(result)
@@ -299,8 +295,8 @@ struct areal_areal
|| may_update<exterior, interior, '2', true>(result) )
{
// sort turns
- typedef turns::less<1, turns::less_op_areal_areal<1>, cs_tag> less;
- std::sort(turns.begin(), turns.end(), less());
+ using less_t = turns::less<1, turns::less_op_areal_areal<1>, Strategy>;
+ std::sort(turns.begin(), turns.end(), less_t());
/*if ( may_update<interior, exterior, '2', true>(result)
|| may_update<boundary, exterior, '1', true>(result)
@@ -352,9 +348,7 @@ struct areal_areal
template <typename Range>
inline bool apply(Range const& turns)
{
- typedef typename boost::range_iterator<Range const>::type iterator;
-
- for (iterator it = boost::begin(turns) ; it != boost::end(turns) ; ++it)
+ for (auto it = boost::begin(turns) ; it != boost::end(turns) ; ++it)
{
per_turn<0>(*it);
per_turn<1>(*it);
@@ -469,7 +463,7 @@ struct areal_areal
{
m_exit_detected = false;
}
- }
+ }
/*else*/
if ( m_enter_detected /*m_previous_operation == overlay::operation_intersection*/ )
{
@@ -652,15 +646,14 @@ struct areal_areal
return;
}
- typename detail::sub_range_return_type<Geometry const>::type
- range_ref = detail::sub_range(geometry, seg_id);
+ auto const& sub_range = detail::sub_range(geometry, seg_id);
- if ( boost::empty(range_ref) )
+ if ( boost::empty(sub_range) )
{
// TODO: throw an exception?
return; // ignore
}
-
+
// TODO: possible optimization
// if the range is an interior ring we may use other IPs generated for this single geometry
// to know which other single geometries should be checked
@@ -668,7 +661,7 @@ struct areal_areal
// TODO: optimize! e.g. use spatial index
// O(N) - running it in a loop gives O(NM)
using detail::within::point_in_geometry;
- int const pig = point_in_geometry(range::front(range_ref),
+ int const pig = point_in_geometry(range::front(sub_range),
other_geometry,
m_point_in_areal_strategy);
@@ -713,12 +706,12 @@ struct areal_areal
for ( TurnIt it = first ; it != last ; ++it )
{
- if ( it->operations[0].operation == overlay::operation_intersection
+ if ( it->operations[0].operation == overlay::operation_intersection
&& it->operations[1].operation == overlay::operation_intersection )
{
found_ii = true;
}
- else if ( it->operations[0].operation == overlay::operation_union
+ else if ( it->operations[0].operation == overlay::operation_union
&& it->operations[1].operation == overlay::operation_union )
{
found_uu = true;
@@ -735,7 +728,7 @@ struct areal_areal
update<interior, interior, '2', transpose_result>(m_result);
m_flags |= 1;
- //update<boundary, boundary, '0', transpose_result>(m_result);
+ //update<boundary, boundary, '0', transpose_result>(m_result);
update<boundary, interior, '1', transpose_result>(m_result);
update<exterior, interior, '2', transpose_result>(m_result);
@@ -846,7 +839,7 @@ struct areal_areal
count = boost::numeric_cast<signed_size_type>(
geometry::num_interior_rings(
detail::single_geometry(analyser.geometry, seg_id)));
-
+
for_no_turns_rings(analyser, turn, seg_id.ring_index + 1, count);
}
diff --git a/boost/geometry/algorithms/detail/relate/boundary_checker.hpp b/boost/geometry/algorithms/detail/relate/boundary_checker.hpp
index 487c706e9f..0d95aabac1 100644
--- a/boost/geometry/algorithms/detail/relate/boundary_checker.hpp
+++ b/boost/geometry/algorithms/detail/relate/boundary_checker.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020 Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -17,8 +18,14 @@
#include <boost/geometry/algorithms/detail/sub_range.hpp>
#include <boost/geometry/algorithms/num_points.hpp>
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
#include <boost/geometry/policies/compare.hpp>
+#include <boost/geometry/strategies/relate/cartesian.hpp>
+#include <boost/geometry/strategies/relate/geographic.hpp>
+#include <boost/geometry/strategies/relate/spherical.hpp>
+
#include <boost/geometry/util/has_nan_coordinate.hpp>
#include <boost/geometry/util/range.hpp>
@@ -26,9 +33,9 @@ namespace boost { namespace geometry
{
#ifndef DOXYGEN_NO_DETAIL
-namespace detail { namespace relate {
+namespace detail { namespace relate
+{
-enum boundary_query { boundary_front, boundary_back, boundary_any };
template
<
@@ -41,30 +48,26 @@ class boundary_checker {};
template <typename Geometry, typename Strategy>
class boundary_checker<Geometry, Strategy, linestring_tag>
{
- typedef typename point_type<Geometry>::type point_type;
-
public:
boundary_checker(Geometry const& g, Strategy const& s)
- : m_has_boundary( boost::size(g) >= 2
- && ! detail::equals::equals_point_point(range::front(g),
- range::back(g),
- s) )
+ : m_has_boundary(
+ boost::size(g) >= 2
+ && ! detail::equals::equals_point_point(range::front(g), range::back(g), s))
#ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER
, m_geometry(g)
#endif
, m_strategy(s)
{}
- template <boundary_query BoundaryQuery>
- bool is_endpoint_boundary(point_type const& pt) const
+ template <typename Point>
+ bool is_endpoint_boundary(Point const& pt) const
{
boost::ignore_unused(pt);
#ifdef BOOST_GEOMETRY_DEBUG_RELATE_BOUNDARY_CHECKER
// may give false positives for INT
- BOOST_GEOMETRY_ASSERT( (BoundaryQuery == boundary_front || BoundaryQuery == boundary_any)
- && detail::equals::equals_point_point(pt, range::front(m_geometry), m_strategy)
- || (BoundaryQuery == boundary_back || BoundaryQuery == boundary_any)
- && detail::equals::equals_point_point(pt, range::back(m_geometry), m_strategy) );
+ BOOST_GEOMETRY_ASSERT(
+ detail::equals::equals_point_point(pt, range::front(m_geometry), m_strategy)
+ || detail::equals::equals_point_point(pt, range::back(m_geometry), m_strategy));
#endif
return m_has_boundary;
}
@@ -82,10 +85,72 @@ private:
Strategy const& m_strategy;
};
+
+template <typename Point, typename Strategy, typename Out>
+inline void copy_boundary_points(Point const& front_pt, Point const& back_pt,
+ Strategy const& strategy, Out & boundary_points)
+{
+ using mutable_point_type = typename Out::value_type;
+ // linear ring or point - no boundary
+ if (! equals::equals_point_point(front_pt, back_pt, strategy))
+ {
+ // do not add points containing NaN coordinates
+ // because they cannot be reasonably compared, e.g. with MSVC
+ // an assertion failure is reported in std::equal_range()
+ if (! geometry::has_nan_coordinate(front_pt))
+ {
+ mutable_point_type pt;
+ geometry::convert(front_pt, pt);
+ boundary_points.push_back(pt);
+ }
+ if (! geometry::has_nan_coordinate(back_pt))
+ {
+ mutable_point_type pt;
+ geometry::convert(back_pt, pt);
+ boundary_points.push_back(pt);
+ }
+ }
+}
+
+template <typename Segment, typename Strategy, typename Out>
+inline void copy_boundary_points_of_seg(Segment const& seg, Strategy const& strategy,
+ Out & boundary_points)
+{
+ typename Out::value_type front_pt, back_pt;
+ assign_point_from_index<0>(seg, front_pt);
+ assign_point_from_index<1>(seg, back_pt);
+ copy_boundary_points(front_pt, back_pt, strategy, boundary_points);
+}
+
+template <typename Linestring, typename Strategy, typename Out>
+inline void copy_boundary_points_of_ls(Linestring const& ls, Strategy const& strategy,
+ Out & boundary_points)
+{
+ // empty or point - no boundary
+ if (boost::size(ls) >= 2)
+ {
+ auto const& front_pt = range::front(ls);
+ auto const& back_pt = range::back(ls);
+ copy_boundary_points(front_pt, back_pt, strategy, boundary_points);
+ }
+}
+
+template <typename MultiLinestring, typename Strategy, typename Out>
+inline void copy_boundary_points_of_mls(MultiLinestring const& mls, Strategy const& strategy,
+ Out & boundary_points)
+{
+ for (auto it = boost::begin(mls); it != boost::end(mls); ++it)
+ {
+ copy_boundary_points_of_ls(*it, strategy, boundary_points);
+ }
+}
+
+
template <typename Geometry, typename Strategy>
class boundary_checker<Geometry, Strategy, multi_linestring_tag>
{
- typedef typename point_type<Geometry>::type point_type;
+ using point_type = typename point_type<Geometry>::type;
+ using mutable_point_type = typename helper_geometry<point_type>::type;
public:
boundary_checker(Geometry const& g, Strategy const& s)
@@ -94,75 +159,38 @@ public:
// First call O(NlogN)
// Each next call O(logN)
- template <boundary_query BoundaryQuery>
- bool is_endpoint_boundary(point_type const& pt) const
+ template <typename Point>
+ bool is_endpoint_boundary(Point const& pt) const
{
- typedef geometry::less<point_type, -1, typename Strategy::cs_tag> less_type;
+ using less_type = geometry::less<mutable_point_type, -1, Strategy>;
- typedef typename boost::range_size<Geometry>::type size_type;
- size_type multi_count = boost::size(m_geometry);
+ auto const multi_count = boost::size(m_geometry);
- if ( multi_count < 1 )
+ if (multi_count < 1)
+ {
return false;
+ }
- if ( ! m_is_filled )
+ if (! m_is_filled)
{
//boundary_points.clear();
m_boundary_points.reserve(multi_count * 2);
- typedef typename boost::range_iterator<Geometry const>::type multi_iterator;
- for ( multi_iterator it = boost::begin(m_geometry) ;
- it != boost::end(m_geometry) ; ++ it )
- {
- typename boost::range_reference<Geometry const>::type
- ls = *it;
-
- // empty or point - no boundary
- if (boost::size(ls) < 2)
- {
- continue;
- }
-
- typedef typename boost::range_reference
- <
- typename boost::range_value<Geometry const>::type const
- >::type point_reference;
-
- point_reference front_pt = range::front(ls);
- point_reference back_pt = range::back(ls);
-
- // linear ring or point - no boundary
- if (! equals::equals_point_point(front_pt, back_pt, m_strategy))
- {
- // do not add points containing NaN coordinates
- // because they cannot be reasonably compared, e.g. with MSVC
- // an assertion failure is reported in std::equal_range()
- if (! geometry::has_nan_coordinate(front_pt))
- {
- m_boundary_points.push_back(front_pt);
- }
- if (! geometry::has_nan_coordinate(back_pt))
- {
- m_boundary_points.push_back(back_pt);
- }
- }
- }
-
- std::sort(m_boundary_points.begin(),
- m_boundary_points.end(),
- less_type());
+ copy_boundary_points_of_mls(m_geometry, m_strategy, m_boundary_points);
+
+ std::sort(m_boundary_points.begin(), m_boundary_points.end(), less_type());
m_is_filled = true;
}
- std::size_t equal_points_count
- = boost::size(
- std::equal_range(m_boundary_points.begin(),
- m_boundary_points.end(),
- pt,
- less_type())
- );
+ mutable_point_type mpt;
+ geometry::convert(pt, mpt);
+ auto const equal_range = std::equal_range(m_boundary_points.begin(),
+ m_boundary_points.end(),
+ mpt,
+ less_type());
+ std::size_t const equal_points_count = boost::size(equal_range);
return equal_points_count % 2 != 0;// && equal_points_count > 0; // the number is odd and > 0
}
@@ -173,13 +201,14 @@ public:
private:
mutable bool m_is_filled;
- // TODO: store references/pointers instead of points?
- mutable std::vector<point_type> m_boundary_points;
+ // TODO: store references/pointers instead of converted points?
+ mutable std::vector<mutable_point_type> m_boundary_points;
Geometry const& m_geometry;
Strategy const& m_strategy;
};
+
}} // namespace detail::relate
#endif // DOXYGEN_NO_DETAIL
diff --git a/boost/geometry/algorithms/detail/relate/box_areal.hpp b/boost/geometry/algorithms/detail/relate/box_areal.hpp
new file mode 100644
index 0000000000..a9e749fdb2
--- /dev/null
+++ b/boost/geometry/algorithms/detail/relate/box_areal.hpp
@@ -0,0 +1,70 @@
+// Boost.Geometry
+
+// Copyright (c) 2022, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOX_AREAL_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOX_AREAL_HPP
+
+#include <boost/geometry/algorithms/detail/relate/areal_areal.hpp>
+#include <boost/geometry/views/box_view.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace relate {
+
+
+// The implementation of an algorithm calculating relate() for B/A
+template <typename Box, typename Areal>
+struct box_areal
+{
+ static const bool interruption_enabled = true;
+
+ template <typename Result, typename Strategy>
+ static inline void apply(Box const& box, Areal const& areal,
+ Result& result,
+ Strategy const& strategy)
+ {
+ using is_cartesian = std::is_same
+ <
+ typename Strategy::cs_tag,
+ cartesian_tag
+ >;
+ apply(box, areal, result, strategy, is_cartesian());
+ }
+
+ template <typename Result, typename Strategy>
+ static inline void apply(Box const& box, Areal const& areal,
+ Result& result,
+ Strategy const& strategy,
+ std::true_type /*is_cartesian*/)
+ {
+ using box_view = boost::geometry::box_view<Box>;
+ box_view view(box);
+ areal_areal<box_view, Areal>::apply(view, areal, result, strategy);
+ }
+
+ template <typename Result, typename Strategy>
+ static inline void apply(Box const& box, Areal const& areal,
+ Result& result,
+ Strategy const& strategy,
+ std::false_type /*is_cartesian*/)
+ {
+ BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
+ "Not implemented for this coordinate system.",
+ typename Strategy::cs_tag());
+ }
+};
+
+}} // namespace detail::relate
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_BOX_AREAL_HPP
diff --git a/boost/geometry/algorithms/detail/relate/de9im.hpp b/boost/geometry/algorithms/detail/relate/de9im.hpp
index a89d46100a..a9d6ea5792 100644
--- a/boost/geometry/algorithms/detail/relate/de9im.hpp
+++ b/boost/geometry/algorithms/detail/relate/de9im.hpp
@@ -1,9 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2022 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -25,7 +26,7 @@
namespace boost { namespace geometry
{
-
+
namespace de9im
{
@@ -103,7 +104,7 @@ public:
inline explicit mask(const char* code)
: base_type(code)
{}
-
+
/*!
\brief The constructor.
\param code The mask pattern.
@@ -275,6 +276,11 @@ struct static_mask_touches_impl<Geometry1, Geometry2, 0, 0>
};
template <typename Geometry1, typename Geometry2>
+struct static_mask_touches_not_pp_type
+ : static_mask_touches_impl<Geometry1, Geometry2, 2, 2> // dummy dimensions
+{};
+
+template <typename Geometry1, typename Geometry2>
struct static_mask_touches_type
: static_mask_touches_impl<Geometry1, Geometry2>
{};
@@ -344,6 +350,21 @@ struct static_mask_crosses_type
: static_mask_crosses_impl<Geometry1, Geometry2>
{};
+template <typename Geometry1, typename Geometry2>
+struct static_mask_crosses_d1_le_d2_type // specific dimensions are not important here
+ : static_mask_crosses_impl<Geometry1, Geometry2, 0, 1>
+{};
+
+template <typename Geometry1, typename Geometry2>
+struct static_mask_crosses_d2_le_d1_type // specific dimensions are not important here
+ : static_mask_crosses_impl<Geometry1, Geometry2, 1, 0>
+{};
+
+template <typename Geometry1, typename Geometry2>
+struct static_mask_crosses_d1_1_d2_1_type
+ : static_mask_crosses_impl<Geometry1, Geometry2, 1, 1>
+{};
+
// OVERLAPS
// dim(G1) != dim(G2) - NOT P/P, L/L, A/A
@@ -376,6 +397,16 @@ struct static_mask_overlaps_type
: static_mask_overlaps_impl<Geometry1, Geometry2>
{};
+template <typename Geometry1, typename Geometry2>
+struct static_mask_overlaps_d1_eq_d2_type
+ : static_mask_overlaps_impl<Geometry1, Geometry2, 2, 2>
+{};
+
+template <typename Geometry1, typename Geometry2>
+struct static_mask_overlaps_d1_1_d2_1_type
+ : static_mask_overlaps_impl<Geometry1, Geometry2, 1, 1>
+{};
+
}} // namespace detail::de9im
#endif // DOXYGEN_NO_DETAIL
diff --git a/boost/geometry/algorithms/detail/relate/follow_helpers.hpp b/boost/geometry/algorithms/detail/relate/follow_helpers.hpp
index d584e81e5c..cb1f0f40c9 100644
--- a/boost/geometry/algorithms/detail/relate/follow_helpers.hpp
+++ b/boost/geometry/algorithms/detail/relate/follow_helpers.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2018.
-// Modifications copyright (c) 2013-2018 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -30,6 +30,8 @@
#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
+#include <type_traits>
+
namespace boost { namespace geometry
{
@@ -42,7 +44,7 @@ namespace detail { namespace relate {
template <std::size_t OpId,
typename Geometry,
typename Tag = typename geometry::tag<Geometry>::type,
- bool IsMulti = boost::is_base_of<multi_tag, Tag>::value
+ bool IsMulti = std::is_base_of<multi_tag, Tag>::value
>
struct for_each_disjoint_geometry_if
: public not_implemented<Tag>
@@ -52,14 +54,12 @@ template <std::size_t OpId, typename Geometry, typename Tag>
struct for_each_disjoint_geometry_if<OpId, Geometry, Tag, false>
{
template <typename TurnIt, typename Pred>
- static inline bool apply(TurnIt first, TurnIt last,
- Geometry const& geometry,
- Pred & pred)
+ static void apply(TurnIt first, TurnIt last, Geometry const& geometry, Pred & pred)
{
- if ( first != last )
- return false;
- pred(geometry);
- return true;
+ if (first == last)
+ {
+ pred(geometry);
+ }
}
};
@@ -67,49 +67,43 @@ template <std::size_t OpId, typename Geometry, typename Tag>
struct for_each_disjoint_geometry_if<OpId, Geometry, Tag, true>
{
template <typename TurnIt, typename Pred>
- static inline bool apply(TurnIt first, TurnIt last,
- Geometry const& geometry,
- Pred & pred)
+ static void apply(TurnIt first, TurnIt last, Geometry const& geometry, Pred & pred)
{
- if ( first != last )
- return for_turns(first, last, geometry, pred);
+ if (first == last)
+ {
+ for_empty(geometry, pred);
+ }
else
- return for_empty(geometry, pred);
+ {
+ for_turns(first, last, geometry, pred);
+ }
}
template <typename Pred>
- static inline bool for_empty(Geometry const& geometry,
- Pred & pred)
+ static void for_empty(Geometry const& geometry, Pred & pred)
{
- typedef typename boost::range_iterator<Geometry const>::type iterator;
-
// O(N)
// check predicate for each contained geometry without generated turn
- for ( iterator it = boost::begin(geometry) ;
- it != boost::end(geometry) ; ++it )
+ for (auto it = boost::begin(geometry); it != boost::end(geometry) ; ++it)
{
- bool cont = pred(*it);
- if ( !cont )
+ if (! pred(*it))
+ {
break;
+ }
}
-
- return !boost::empty(geometry);
}
template <typename TurnIt, typename Pred>
- static inline bool for_turns(TurnIt first, TurnIt last,
- Geometry const& geometry,
- Pred & pred)
+ static void for_turns(TurnIt first, TurnIt last, Geometry const& geometry, Pred & pred)
{
BOOST_GEOMETRY_ASSERT(first != last);
const std::size_t count = boost::size(geometry);
- boost::ignore_unused(count);
// O(I)
// gather info about turns generated for contained geometries
std::vector<bool> detected_intersections(count, false);
- for ( TurnIt it = first ; it != last ; ++it )
+ for (TurnIt it = first; it != last; ++it)
{
signed_size_type multi_index = it->operations[OpId].seg_id.multi_index;
BOOST_GEOMETRY_ASSERT(multi_index >= 0);
@@ -118,28 +112,23 @@ struct for_each_disjoint_geometry_if<OpId, Geometry, Tag, true>
detected_intersections[index] = true;
}
- bool found = false;
-
// O(N)
// check predicate for each contained geometry without generated turn
- for ( std::vector<bool>::iterator it = detected_intersections.begin() ;
- it != detected_intersections.end() ; ++it )
+ for (std::size_t index = 0; index < detected_intersections.size(); ++index)
{
// if there were no intersections for this multi_index
- if ( *it == false )
+ if (detected_intersections[index] == false)
{
- found = true;
- std::size_t const index = std::size_t(std::distance(detected_intersections.begin(), it));
- bool cont = pred(range::at(geometry, index));
- if ( !cont )
+ if (! pred(range::at(geometry, index)))
+ {
break;
+ }
}
}
-
- return found;
}
};
+
// WARNING! This class stores pointers!
// Passing a reference to local variable will result in undefined behavior!
template <typename Point>
@@ -184,7 +173,7 @@ public:
bool operator()(segment_identifier const& sid) const
{
- return sid.multi_index == sid_ptr->multi_index;
+ return sid.multi_index == sid_ptr->multi_index;
}
template <typename Point>
@@ -267,11 +256,10 @@ public:
segment_identifier const& other_id = turn.operations[other_op_id].seg_id;
overlay::operation_type exit_op = turn.operations[op_id].operation;
- typedef typename std::vector<point_info>::iterator point_iterator;
// search for the entry point in the same range of other geometry
- point_iterator entry_it = std::find_if(m_other_entry_points.begin(),
- m_other_entry_points.end(),
- same_single(other_id));
+ auto entry_it = std::find_if(m_other_entry_points.begin(),
+ m_other_entry_points.end(),
+ same_single(other_id));
// this end point has corresponding entry point
if ( entry_it != m_other_entry_points.end() )
@@ -298,11 +286,10 @@ public:
bool is_outside(TurnInfo const& turn) const
{
return m_other_entry_points.empty()
- || std::find_if(m_other_entry_points.begin(),
+ || std::none_of(m_other_entry_points.begin(),
m_other_entry_points.end(),
same_single(
- turn.operations[other_op_id].seg_id))
- == m_other_entry_points.end();
+ turn.operations[other_op_id].seg_id));
}
overlay::operation_type get_exit_operation() const
@@ -366,44 +353,17 @@ inline bool turn_on_the_same_ip(Turn const& prev_turn, Turn const& curr_turn,
return detail::equals::equals_point_point(prev_turn.point, curr_turn.point, strategy);
}
-template <boundary_query BoundaryQuery,
- typename Point,
- typename BoundaryChecker>
-static inline bool is_endpoint_on_boundary(Point const& pt,
- BoundaryChecker & boundary_checker)
-{
- return boundary_checker.template is_endpoint_boundary<BoundaryQuery>(pt);
-}
-
-template <boundary_query BoundaryQuery,
- typename IntersectionPoint,
- typename OperationInfo,
- typename BoundaryChecker>
+template <typename IntersectionPoint, typename OperationInfo, typename BoundaryChecker>
static inline bool is_ip_on_boundary(IntersectionPoint const& ip,
OperationInfo const& operation_info,
- BoundaryChecker & boundary_checker,
- segment_identifier const& seg_id)
+ BoundaryChecker const& boundary_checker)
{
- boost::ignore_unused(seg_id);
-
- bool res = false;
-
- // IP on the last point of the linestring
- if ( BOOST_GEOMETRY_CONDITION(BoundaryQuery == boundary_back || BoundaryQuery == boundary_any)
- && operation_info.position == overlay::position_back )
- {
- // check if this point is a boundary
- res = boundary_checker.template is_endpoint_boundary<boundary_back>(ip);
- }
- // IP on the last point of the linestring
- else if ( BOOST_GEOMETRY_CONDITION(BoundaryQuery == boundary_front || BoundaryQuery == boundary_any)
- && operation_info.position == overlay::position_front )
- {
- // check if this point is a boundary
- res = boundary_checker.template is_endpoint_boundary<boundary_front>(ip);
- }
-
- return res;
+ // IP on the first or the last point of the linestring
+ return (operation_info.position == overlay::position_back
+ || operation_info.position == overlay::position_front)
+ // check if this point is a boundary
+ ? boundary_checker.is_endpoint_boundary(ip)
+ : false;
}
diff --git a/boost/geometry/algorithms/detail/relate/implementation.hpp b/boost/geometry/algorithms/detail/relate/implementation.hpp
index 190a5e3d6b..458bfdba3f 100644
--- a/boost/geometry/algorithms/detail/relate/implementation.hpp
+++ b/boost/geometry/algorithms/detail/relate/implementation.hpp
@@ -2,9 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013-2021.
-// Modifications copyright (c) 2013-2021 Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,16 +14,16 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_HPP
-#include <boost/geometry/core/tags.hpp>
-
+#include <boost/geometry/algorithms/detail/relate/areal_areal.hpp>
+#include <boost/geometry/algorithms/detail/relate/box_areal.hpp>
#include <boost/geometry/algorithms/detail/relate/interface.hpp>
-
-#include <boost/geometry/algorithms/detail/relate/point_point.hpp>
-#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>
-#include <boost/geometry/algorithms/detail/relate/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/relate/linear_areal.hpp>
+#include <boost/geometry/algorithms/detail/relate/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp>
-#include <boost/geometry/algorithms/detail/relate/areal_areal.hpp>
+#include <boost/geometry/algorithms/detail/relate/point_geometry.hpp>
+#include <boost/geometry/algorithms/detail/relate/point_point.hpp>
+
+#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/strategies/relate/cartesian.hpp>
#include <boost/geometry/strategies/relate/geographic.hpp>
@@ -116,6 +115,23 @@ struct relate<Areal1, Areal2, Tag1, Tag2, 2, 2, true>
: detail::relate::areal_areal<Areal1, Areal2>
{};
+
+template <typename Box, typename Ring>
+struct relate<Box, Ring, box_tag, ring_tag, 2, 2, false>
+ : detail::relate::box_areal<Box, Ring>
+{};
+
+template <typename Box, typename Polygon>
+struct relate<Box, Polygon, box_tag, polygon_tag, 2, 2, false>
+ : detail::relate::box_areal<Box, Polygon>
+{};
+
+template <typename Box, typename MultiPolygon>
+struct relate<Box, MultiPolygon, box_tag, multi_polygon_tag, 2, 2, false>
+ : detail::relate::box_areal<Box, MultiPolygon>
+{};
+
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/detail/relate/implementation_gc.hpp b/boost/geometry/algorithms/detail/relate/implementation_gc.hpp
new file mode 100644
index 0000000000..f0fa11d2af
--- /dev/null
+++ b/boost/geometry/algorithms/detail/relate/implementation_gc.hpp
@@ -0,0 +1,696 @@
+// Boost.Geometry
+
+// Copyright (c) 2022-2023 Adam Wulkiewicz, Lodz, Poland.
+
+// Copyright (c) 2022 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// 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_RELATE_IMPLEMENTATION_GC_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_GC_HPP
+
+
+#include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp>
+#include <boost/geometry/algorithms/detail/relate/interface.hpp>
+#include <boost/geometry/algorithms/difference.hpp>
+#include <boost/geometry/algorithms/intersection.hpp>
+#include <boost/geometry/algorithms/is_empty.hpp>
+#include <boost/geometry/algorithms/union.hpp>
+#include <boost/geometry/geometries/linestring.hpp>
+#include <boost/geometry/geometries/multi_linestring.hpp>
+#include <boost/geometry/geometries/multi_point.hpp>
+#include <boost/geometry/geometries/multi_polygon.hpp>
+#include <boost/geometry/geometries/polygon.hpp>
+#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/views/detail/geometry_collection_view.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace relate
+{
+
+// For fields II IE and EI this handler behaves like matrix_handler.
+// It has to be created at the beginning of processing because it relies on the
+// fact that all of the fields are set to F and no geometry was handled yet.
+// This way it can check which fields are required for any mask and matrix
+// without accessing the internals.
+// An alternative would be to remove this wrapper and always set the matrix
+// in static_mask_handler even if this is not required.
+template <typename Handler>
+struct aa_handler_wrapper
+{
+ bool interrupt = false;
+
+ explicit aa_handler_wrapper(Handler& handler)
+ : m_handler(handler)
+ , m_overwrite_ii(! handler.template may_update<interior, interior, '2'>())
+ , m_overwrite_ie(! handler.template may_update<interior, exterior, '2'>())
+ , m_overwrite_ei(! handler.template may_update<exterior, interior, '2'>())
+ {}
+
+ template <field F1, field F2, char D>
+ inline bool may_update() const
+ {
+ if ((BOOST_GEOMETRY_CONDITION(F1 == interior && F2 == interior) && m_overwrite_ii)
+ || (BOOST_GEOMETRY_CONDITION(F1 == interior && F2 == exterior) && m_overwrite_ie)
+ || (BOOST_GEOMETRY_CONDITION(F1 == exterior && F2 == interior) && m_overwrite_ei))
+ {
+ char const c = m_handler.template get<F1, F2>();
+ return D > c || c > '9';
+ }
+ else
+ {
+ return m_handler.template may_update<F1, F2, D>();
+ }
+ }
+
+ template <field F1, field F2, char V>
+ inline void update()
+ {
+ if ((BOOST_GEOMETRY_CONDITION(F1 == interior && F2 == interior) && m_overwrite_ii)
+ || (BOOST_GEOMETRY_CONDITION(F1 == interior && F2 == exterior) && m_overwrite_ie)
+ || (BOOST_GEOMETRY_CONDITION(F1 == exterior && F2 == interior) && m_overwrite_ei))
+ {
+ // NOTE: Other handlers first check for potential interruption
+ // and only after that checks update condition.
+ char const c = m_handler.template get<F1, F2>();
+ // If c == T and V == T it will be set anyway but that's fine.
+ if (V > c || c > '9')
+ {
+ // set may set interrupt flag
+ m_handler.template set<F1, F2, V>();
+ }
+ }
+ else
+ {
+ m_handler.template update<F1, F2, V>();
+ }
+ interrupt = interrupt || m_handler.interrupt;
+ }
+
+private:
+ Handler & m_handler;
+ bool const m_overwrite_ii;
+ bool const m_overwrite_ie;
+ bool const m_overwrite_ei;
+};
+
+
+template <typename Geometry1, typename Geometry2>
+struct gc_gc
+{
+ static const bool interruption_enabled = true;
+
+ using mpt1_found_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Geometry1>::type,
+ util::is_multi_point
+ >::type;
+ using mls1_found_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Geometry1>::type,
+ util::is_multi_linestring
+ >::type;
+ using mpo1_found_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Geometry1>::type,
+ util::is_multi_polygon
+ >::type;
+ using pt1_t = typename geometry::point_type<Geometry1>::type;
+ using mpt1_t = std::conditional_t
+ <
+ std::is_void<mpt1_found_t>::value,
+ geometry::model::multi_point<pt1_t>,
+ mpt1_found_t
+ >;
+ using mls1_t = std::conditional_t
+ <
+ std::is_void<mls1_found_t>::value,
+ geometry::model::multi_linestring<geometry::model::linestring<pt1_t>>,
+ mls1_found_t
+ >;
+ using mpo1_t = std::conditional_t
+ <
+ std::is_void<mpo1_found_t>::value,
+ geometry::model::multi_polygon<geometry::model::polygon<pt1_t>>,
+ mpo1_found_t
+ >;
+ using tuple1_t = boost::tuple<mpt1_t, mls1_t, mpo1_t>;
+
+ using mpt2_found_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Geometry2>::type,
+ util::is_multi_point
+ >::type;
+ using mls2_found_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Geometry2>::type,
+ util::is_multi_linestring
+ >::type;
+ using mpo2_found_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Geometry2>::type,
+ util::is_multi_polygon
+ >::type;
+ using pt2_t = typename geometry::point_type<Geometry2>::type;
+ using mpt2_t = std::conditional_t
+ <
+ std::is_void<mpt2_found_t>::value,
+ geometry::model::multi_point<pt2_t>,
+ mpt2_found_t
+ >;
+ using mls2_t = std::conditional_t
+ <
+ std::is_void<mls2_found_t>::value,
+ geometry::model::multi_linestring<geometry::model::linestring<pt2_t>>,
+ mls2_found_t
+ >;
+ using mpo2_t = std::conditional_t
+ <
+ std::is_void<mpo2_found_t>::value,
+ geometry::model::multi_polygon<geometry::model::polygon<pt2_t>>,
+ mpo2_found_t
+ >;
+ using tuple2_t = boost::tuple<mpt2_t, mls2_t, mpo2_t>;
+
+ template <typename Geometry>
+ using kind_id = util::index_constant
+ <
+ util::is_areal<Geometry>::value ? 2
+ : util::is_linear<Geometry>::value ? 1
+ : 0
+ >;
+
+ template <typename Result, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Result & result,
+ Strategy const& strategy)
+ {
+ using gc1_view_t = random_access_view<Geometry1 const>;
+ using gc2_view_t = random_access_view<Geometry2 const>;
+ gc1_view_t const gc1_view(geometry1);
+ gc2_view_t const gc2_view(geometry2);
+
+ bool inters_found[2][3] = {{false, false, false}, {false, false, false}};
+ bool disjoint_found[2][3] = {{false, false, false}, {false, false, false}};
+ bool disjoint_linear_boundary_found[2] = {false, false};
+ bool has_disjoint = false;
+
+ gc_group_elements(gc1_view, gc2_view, strategy,
+ [&](auto const& inters_group)
+ {
+ tuple1_t tuple1;
+ tuple2_t tuple2;
+
+ // Create MPts, MLss and MPos containing all gc elements from this group
+ // They may potentially intersect each other
+ for (auto const& id : inters_group)
+ {
+ BOOST_GEOMETRY_ASSERT(id.source_id == 0 || id.source_id == 1);
+ if (id.source_id == 0)
+ {
+ traits::iter_visit<gc1_view_t>::apply([&](auto const& g1)
+ {
+ merge_geometry(tuple1, g1, strategy);
+ }, boost::begin(gc1_view) + id.gc_id);
+ }
+ else
+ {
+ traits::iter_visit<gc2_view_t>::apply([&](auto const& g2)
+ {
+ merge_geometry(tuple2, g2, strategy);
+ }, boost::begin(gc2_view) + id.gc_id);
+ }
+ }
+
+ // Subtract higher topo-dim elements from elements of lower topo-dim
+ // MPts do not intersect other geometries, MLss and MPos may touch
+ subtract_elements(tuple1, strategy);
+ subtract_elements(tuple2, strategy);
+
+ // Helpers
+ auto const& mpt1 = boost::get<0>(tuple1);
+ auto const& mls1 = boost::get<1>(tuple1);
+ auto const& mpo1 = boost::get<2>(tuple1);
+ auto const& mpt2 = boost::get<0>(tuple2);
+ auto const& mls2 = boost::get<1>(tuple2);
+ auto const& mpo2 = boost::get<2>(tuple2);
+
+ // A/A
+ if (! geometry::is_empty(mpo1) && ! geometry::is_empty(mpo2))
+ {
+ inters_found[0][2] = true;
+ inters_found[1][2] = true;
+ aa_handler_wrapper<Result> wrapper(result);
+ call_relate(mpo1, mpo2, wrapper, strategy);
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ bool is_aa_ii = result.template get<interior, interior>() != 'F';
+ bool is_aa_ie = result.template get<interior, exterior>() != 'F';
+ bool is_aa_ei = result.template get<exterior, interior>() != 'F';
+ // is_aa_ii implies is_aa_checked and non-empty Areal geometries
+ bool are_aa_equal = is_aa_ii && ! is_aa_ie && ! is_aa_ei;
+
+ // Boundary checkers are internally initialized lazily later if a point has to be checked
+ boundary_checker<mls1_t, Strategy> mls1_boundary(mls1, strategy);
+ boundary_checker<mls2_t, Strategy> mls2_boundary(mls2, strategy);
+
+ // If needed divide MLss into two parts:
+ // - inside Areal of other GC
+ // - outside of other GC Areal to check WRT Linear of other GC
+ mls2_t mls2_diff_mpo1, mls2_inters_mpo1;
+ bool is_mls2_divided = false;
+ mls1_t mls1_diff_mpo2, mls1_inters_mpo2;
+ bool is_mls1_divided = false;
+ // If Areal are equal then Linear are outside of both so there is no need to divide
+ if (! are_aa_equal && ! geometry::is_empty(mls1) && ! geometry::is_empty(mls2))
+ {
+ // LA/L
+ if (! geometry::is_empty(mpo1))
+ {
+ geometry::difference(mls2, mpo1, mls2_diff_mpo1);
+ geometry::intersection(mls2, mpo1, mls2_inters_mpo1);
+ is_mls2_divided = true;
+ }
+ // L/LA
+ if (! geometry::is_empty(mpo2))
+ {
+ geometry::difference(mls1, mpo2, mls1_diff_mpo2);
+ geometry::intersection(mls1, mpo2, mls1_inters_mpo2);
+ is_mls1_divided = true;
+ }
+ }
+
+ // A/L
+ if (! geometry::is_empty(mpo1) && ! geometry::is_empty(mls2))
+ {
+ inters_found[0][2] = true;
+ inters_found[1][1] = true;
+ if (is_aa_ii && ! is_aa_ie && ! is_aa_ei && ! geometry::is_empty(mls1))
+ {
+ // Equal Areal and both Linear non-empty, calculate only L/L below
+ }
+ else if (is_aa_ii && ! is_aa_ie && geometry::is_empty(mls1))
+ {
+ // An alternative would be to calculate L/L with one empty below
+ mpo1_t empty;
+ call_relate_al(empty, mls2, mls2_boundary, result, strategy);
+ }
+ else
+ {
+ if (is_mls2_divided)
+ {
+ if (! geometry::is_empty(mls2_inters_mpo1))
+ {
+ call_relate_al(mpo1, mls2_inters_mpo1, mls2_boundary, result, strategy);
+ }
+ }
+ else
+ {
+ call_relate_al(mpo1, mls2, mls2_boundary, result, strategy);
+ }
+ }
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ // L/A
+ if (! geometry::is_empty(mls1) && ! geometry::is_empty(mpo2))
+ {
+ inters_found[0][1] = true;
+ inters_found[1][2] = true;
+ if (is_aa_ii && ! is_aa_ei && ! is_aa_ie && ! geometry::is_empty(mls2))
+ {
+ // Equal Areal and both Linear non-empty, calculate only L/L below
+ }
+ else if (is_aa_ii && ! is_aa_ei && geometry::is_empty(mls2))
+ {
+ // An alternative would be to calculate L/L with one empty below
+ mpo2_t empty;
+ call_relate_la(mls1, empty, mls1_boundary, result, strategy);
+ }
+ else
+ {
+ if (is_mls1_divided)
+ {
+ if (! geometry::is_empty(mls1_inters_mpo2))
+ {
+ call_relate_la(mls1_inters_mpo2, mpo2, mls1_boundary, result, strategy);
+ }
+ }
+ else
+ {
+ call_relate_la(mls1, mpo2, mls1_boundary, result, strategy);
+ }
+ }
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ // L/L
+ if (! geometry::is_empty(mls1) && ! geometry::is_empty(mls2))
+ {
+ inters_found[0][1] = true;
+ inters_found[1][1] = true;
+ if (is_mls1_divided && is_mls2_divided)
+ {
+ if (! geometry::is_empty(mls1_diff_mpo2) && ! geometry::is_empty(mls2_diff_mpo1))
+ {
+ call_relate_ll(mls1_diff_mpo2, mls2_diff_mpo1, mls1_boundary, mls2_boundary, result, strategy);
+ }
+ }
+ else if (is_mls1_divided)
+ {
+ if (! geometry::is_empty(mls1_diff_mpo2))
+ {
+ call_relate_ll(mls1_diff_mpo2, mls2, mls1_boundary, mls2_boundary, result, strategy);
+ }
+ }
+ else if (is_mls2_divided)
+ {
+ if (! geometry::is_empty(mls2_diff_mpo1))
+ {
+ call_relate_ll(mls1, mls2_diff_mpo1, mls1_boundary, mls2_boundary, result, strategy);
+ }
+ }
+ else
+ {
+ call_relate_ll(mls1, mls2, mls1_boundary, mls2_boundary, result, strategy);
+ }
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ // A/P
+ if (! geometry::is_empty(mpo1) && ! geometry::is_empty(mpt2))
+ {
+ inters_found[0][2] = true;
+ inters_found[1][0] = true;
+ call_relate(mpo1, mpt2, result, strategy);
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ // P/A
+ if (! geometry::is_empty(mpt1) && ! geometry::is_empty(mpo2))
+ {
+ inters_found[0][0] = true;
+ inters_found[1][2] = true;
+ call_relate(mpt1, mpo2, result, strategy);
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ // L/P
+ if (! geometry::is_empty(mls1) && ! geometry::is_empty(mpt2))
+ {
+ inters_found[0][1] = true;
+ inters_found[1][0] = true;
+ call_relate(mls1, mpt2, result, strategy);
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ // P/L
+ if (! geometry::is_empty(mpt1) && ! geometry::is_empty(mls2))
+ {
+ inters_found[0][0] = true;
+ inters_found[1][1] = true;
+ call_relate(mpt1, mls2, result, strategy);
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ // P/P
+ if (! geometry::is_empty(mpt1) && ! geometry::is_empty(mpt2))
+ {
+ inters_found[0][0] = true;
+ inters_found[1][0] = true;
+ call_relate(mpt1, mpt2, result, strategy);
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(result.interrupt))
+ {
+ return false;
+ }
+
+ return true;
+ },
+ [&](auto const& disjoint_group)
+ {
+ for (auto const& id : disjoint_group)
+ {
+ BOOST_GEOMETRY_ASSERT(id.source_id == 0 || id.source_id == 1);
+ if (id.source_id == 0)
+ {
+ traits::iter_visit<gc1_view_t>::apply([&](auto const& g1)
+ {
+ if (! geometry::is_empty(g1))
+ {
+ static const std::size_t index = kind_id<util::remove_cref_t<decltype(g1)>>::value;
+ disjoint_found[0][index] = true;
+ disjoint_linear_boundary_found[0] = has_linear_boundary(g1, strategy);
+ has_disjoint = true;
+ }
+ }, boost::begin(gc1_view) + id.gc_id);
+ }
+ else
+ {
+ traits::iter_visit<gc2_view_t>::apply([&](auto const& g2)
+ {
+ if (! geometry::is_empty(g2))
+ {
+ static const std::size_t index = kind_id<util::remove_cref_t<decltype(g2)>>::value;
+ disjoint_found[1][index] = true;
+ disjoint_linear_boundary_found[1] = has_linear_boundary(g2, strategy);
+ has_disjoint = true;
+ }
+ }, boost::begin(gc2_view) + id.gc_id);
+ }
+ }
+ }, true);
+
+ // Based on found disjoint geometries as well as those intersecting set exteriors
+ if (has_disjoint)
+ {
+ if (disjoint_found[0][2] == true)
+ {
+ update<interior, exterior, '2'>(result);
+ update<boundary, exterior, '1'>(result);
+ }
+ else if (disjoint_found[0][1] == true)
+ {
+ update<interior, exterior, '1'>(result);
+ if (disjoint_linear_boundary_found[0])
+ {
+ update<boundary, exterior, '0'>(result);
+ }
+ }
+ else if (disjoint_found[0][0] == true)
+ {
+ update<interior, exterior, '0'>(result);
+ }
+
+ if (disjoint_found[1][2] == true)
+ {
+ update<exterior, interior, '2'>(result);
+ update<exterior, boundary, '1'>(result);
+ }
+ else if (disjoint_found[1][1] == true)
+ {
+ update<exterior, interior, '1'>(result);
+ if (disjoint_linear_boundary_found[1])
+ {
+ update<exterior, boundary, '0'>(result);
+ }
+ }
+ else if (disjoint_found[1][0] == true)
+ {
+ update<exterior, interior, '0'>(result);
+ }
+ }
+ }
+
+private:
+ template <typename Tuple, typename Geometry, typename Strategy>
+ static inline void merge_geometry(Tuple& tuple, Geometry const& geometry, Strategy const& strategy)
+ {
+ static const std::size_t index = kind_id<Geometry>::value;
+ typename boost::tuples::element<index, Tuple>::type temp_out;
+ geometry::union_(boost::get<index>(tuple), geometry, temp_out, strategy);
+ boost::get<index>(tuple) = std::move(temp_out);
+ }
+
+ template <typename Tuple, typename Strategy>
+ static inline void subtract_elements(Tuple& tuple, Strategy const& strategy)
+ {
+ if (! geometry::is_empty(boost::get<1>(tuple)))
+ {
+ if (! geometry::is_empty(boost::get<2>(tuple)))
+ {
+ typename boost::tuples::element<1, Tuple>::type mls;
+ geometry::difference(boost::get<1>(tuple), boost::get<2>(tuple), mls, strategy);
+ boost::get<1>(tuple) = std::move(mls);
+ }
+ }
+ if (! geometry::is_empty(boost::get<0>(tuple)))
+ {
+ if (! geometry::is_empty(boost::get<2>(tuple)))
+ {
+ typename boost::tuples::element<0, Tuple>::type mpt;
+ geometry::difference(boost::get<0>(tuple), boost::get<2>(tuple), mpt, strategy);
+ boost::get<0>(tuple) = std::move(mpt);
+ }
+ if (! geometry::is_empty(boost::get<1>(tuple)))
+ {
+ typename boost::tuples::element<0, Tuple>::type mpt;
+ geometry::difference(boost::get<0>(tuple), boost::get<1>(tuple), mpt, strategy);
+ boost::get<0>(tuple) = std::move(mpt);
+ }
+ }
+ }
+
+ template
+ <
+ typename Geometry, typename Strategy,
+ std::enable_if_t<util::is_linear<Geometry>::value, int> = 0
+ >
+ static inline bool has_linear_boundary(Geometry const& geometry, Strategy const& strategy)
+ {
+ topology_check<Geometry, Strategy> tc(geometry, strategy);
+ return tc.has_boundary();
+ }
+
+ template
+ <
+ typename Geometry, typename Strategy,
+ std::enable_if_t<! util::is_linear<Geometry>::value, int> = 0
+ >
+ static inline bool has_linear_boundary(Geometry const& , Strategy const& )
+ {
+ return false;
+ }
+
+
+ template <typename Multi1, typename Multi2, typename Result, typename Strategy>
+ static inline void call_relate(Multi1 const& multi1, Multi2 const& multi2,
+ Result& result, Strategy const& strategy)
+ {
+ dispatch::relate
+ <
+ Multi1, Multi2
+ >::apply(multi1, multi2, result, strategy);
+ }
+
+ template <typename MLs, typename MPo, typename MLsBoundary, typename Result, typename Strategy>
+ static inline void call_relate_la(MLs const& mls, MPo const& mpo,
+ MLsBoundary const& mls_boundary,
+ Result& result, Strategy const& strategy)
+ {
+ linear_areal<MLs, MPo>::apply(mls, mpo, mls_boundary, result, strategy);
+ }
+
+ template <typename MPo, typename MLs, typename MLsBoundary, typename Result, typename Strategy>
+ static inline void call_relate_al(MPo const& mls, MLs const& mpo,
+ MLsBoundary const& mls_boundary,
+ Result& result, Strategy const& strategy)
+ {
+ areal_linear<MPo, MLs>::apply(mls, mpo, mls_boundary, result, strategy);
+ }
+
+ template <typename MLs1, typename MLs2, typename MLs1Boundary, typename MLs2Boundary, typename Result, typename Strategy>
+ static inline void call_relate_ll(MLs1 const& mls1, MLs2 const& mls2,
+ MLs1Boundary const& mls1_boundary,
+ MLs2Boundary const& mls2_boundary,
+ Result& result, Strategy const& strategy)
+ {
+ linear_linear<MLs1, MLs2>::apply(mls1, mls2, mls1_boundary, mls2_boundary,
+ result, strategy);
+ }
+
+
+};
+
+
+}} // namespace detail::relate
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+template <typename Geometry1, typename Geometry2>
+struct relate<Geometry1, Geometry2, geometry_collection_tag, geometry_collection_tag, -1, -1, false>
+ : detail::relate::gc_gc<Geometry1, Geometry2>
+{};
+
+
+template <typename Geometry1, typename Geometry2, typename Tag1, int TopDim1>
+struct relate<Geometry1, Geometry2, Tag1, geometry_collection_tag, TopDim1, -1, false>
+{
+ static const bool interruption_enabled = true;
+
+ template <typename Result, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Result & result,
+ Strategy const& strategy)
+ {
+ using gc1_view_t = detail::geometry_collection_view<Geometry1>;
+ relate<gc1_view_t, Geometry2>::apply(gc1_view_t(geometry1), geometry2, result, strategy);
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Tag2, int TopDim2>
+struct relate<Geometry1, Geometry2, geometry_collection_tag, Tag2, -1, TopDim2, false>
+{
+ static const bool interruption_enabled = true;
+
+ template <typename Result, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Result & result,
+ Strategy const& strategy)
+ {
+ using gc2_view_t = detail::geometry_collection_view<Geometry2>;
+ relate<Geometry1, gc2_view_t>::apply(geometry1, gc2_view_t(geometry2), result, strategy);
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_IMPLEMENTATION_HPP
diff --git a/boost/geometry/algorithms/detail/relate/interface.hpp b/boost/geometry/algorithms/detail/relate/interface.hpp
index 801ad21db1..19568a870e 100644
--- a/boost/geometry/algorithms/detail/relate/interface.hpp
+++ b/boost/geometry/algorithms/detail/relate/interface.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -17,16 +17,13 @@
#include <tuple>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
#include <boost/geometry/algorithms/detail/relate/de9im.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/core/topological_dimension.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
@@ -160,8 +157,8 @@ struct result_handler_type<Geometry1, Geometry2, util::type_sequence<StaticMasks
}} // namespace detail::relate
#endif // DOXYGEN_NO_DETAIL
-namespace resolve_strategy {
-
+namespace resolve_strategy
+{
template
<
@@ -217,7 +214,7 @@ struct relate<default_strategy, false>
Geometry1,
Geometry2
>::type strategy_type;
-
+
dispatch::relate
<
Geometry1,
@@ -228,9 +225,15 @@ struct relate<default_strategy, false>
} // resolve_strategy
-namespace resolve_variant {
+namespace resolve_dynamic
+{
-template <typename Geometry1, typename Geometry2>
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct relate
{
template <typename Mask, typename Strategy>
@@ -256,109 +259,73 @@ struct relate
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct relate<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct relate<Geometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Mask, typename Strategy>
- struct visitor : boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Mask const& mask,
+ Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Mask const& m_mask;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Mask const& mask, Strategy const& strategy)
- : m_geometry2(geometry2), m_mask(mask), m_strategy(strategy) {}
-
- template <typename Geometry1>
- bool operator()(Geometry1 const& geometry1) const
+ bool result = false;
+ traits::visit<Geometry1>::apply([&](auto const& g1)
{
- return relate<Geometry1, Geometry2>
- ::apply(geometry1, m_geometry2, m_mask, m_strategy);
- }
- };
-
- template <typename Mask, typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Mask const& mask,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Mask, Strategy>(geometry2, mask, strategy), geometry1);
+ result = relate
+ <
+ util::remove_cref_t<decltype(g1)>,
+ Geometry2
+ >::apply(g1, geometry2, mask, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct relate<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct relate<Geometry1, Geometry2, Tag1, dynamic_geometry_tag>
{
template <typename Mask, typename Strategy>
- struct visitor : boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Mask const& mask,
+ Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Mask const& m_mask;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Mask const& mask, Strategy const& strategy)
- : m_geometry1(geometry1), m_mask(mask), m_strategy(strategy) {}
-
- template <typename Geometry2>
- bool operator()(Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry2>::apply([&](auto const& g2)
{
- return relate<Geometry1, Geometry2>
- ::apply(m_geometry1, geometry2, m_mask, m_strategy);
- }
- };
-
- template <typename Mask, typename Strategy>
- static inline bool
- apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Mask const& mask,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Mask, Strategy>(geometry1, mask, strategy), geometry2);
+ result = relate
+ <
+ Geometry1,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(geometry1, g2, mask, strategy);
+ }, geometry2);
+ return result;
}
};
-template <
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
-struct relate<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
->
+template <typename Geometry1, typename Geometry2>
+struct relate<Geometry1, Geometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Mask, typename Strategy>
- struct visitor : boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Mask const& mask,
+ Strategy const& strategy)
{
- Mask const& m_mask;
- Strategy const& m_strategy;
-
- visitor(Mask const& mask, Strategy const& strategy)
- : m_mask(mask), m_strategy(strategy) {}
-
- template <typename Geometry1, typename Geometry2>
- bool operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry1, Geometry2>::apply([&](auto const& g1, auto const& g2)
{
- return relate<Geometry1, Geometry2>
- ::apply(geometry1, geometry2, m_mask, m_strategy);
- }
- };
-
- template <typename Mask, typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Mask const& mask,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Mask, Strategy>(mask, strategy), geometry1, geometry2);
+ result = relate
+ <
+ util::remove_cref_t<decltype(g1)>,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(g1, g2, mask, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
\brief Checks relation between a pair of geometries defined by a mask.
@@ -382,7 +349,7 @@ inline bool relate(Geometry1 const& geometry1,
Mask const& mask,
Strategy const& strategy)
{
- return resolve_variant::relate
+ return resolve_dynamic::relate
<
Geometry1,
Geometry2
@@ -407,7 +374,7 @@ inline bool relate(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Mask const& mask)
{
- return resolve_variant::relate
+ return resolve_dynamic::relate
<
Geometry1,
Geometry2
diff --git a/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/boost/geometry/algorithms/detail/relate/linear_areal.hpp
index e32c4afcba..1e35e64fc5 100644
--- a/boost/geometry/algorithms/detail/relate/linear_areal.hpp
+++ b/boost/geometry/algorithms/detail/relate/linear_areal.hpp
@@ -1,10 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2021.
-// Modifications copyright (c) 2013-2021 Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -34,6 +34,8 @@
#include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp>
#include <boost/geometry/algorithms/detail/relate/follow_helpers.hpp>
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
#include <boost/geometry/views/detail/closed_clockwise_view.hpp>
namespace boost { namespace geometry
@@ -51,7 +53,7 @@ template
<
typename Geometry2,
typename Result,
- typename PointInArealStrategy,
+ typename Strategy,
typename BoundaryChecker,
bool TransposeResult
>
@@ -60,11 +62,11 @@ class no_turns_la_linestring_pred
public:
no_turns_la_linestring_pred(Geometry2 const& geometry2,
Result & res,
- PointInArealStrategy const& point_in_areal_strategy,
+ Strategy const& strategy,
BoundaryChecker const& boundary_checker)
: m_geometry2(geometry2)
, m_result(res)
- , m_point_in_areal_strategy(point_in_areal_strategy)
+ , m_strategy(strategy)
, m_boundary_checker(boundary_checker)
, m_interrupt_flags(0)
{
@@ -93,7 +95,7 @@ public:
bool operator()(Linestring const& linestring)
{
std::size_t const count = boost::size(linestring);
-
+
// invalid input
if ( count < 2 )
{
@@ -110,7 +112,7 @@ public:
int const pig = detail::within::point_in_geometry(range::front(linestring),
m_geometry2,
- m_point_in_areal_strategy);
+ m_strategy);
//BOOST_GEOMETRY_ASSERT_MSG(pig != 0, "There should be no IPs");
if ( pig > 0 )
@@ -125,11 +127,9 @@ public:
}
// check if there is a boundary
- if ( ( m_interrupt_flags & 0xC ) != 0xC // if wasn't already set
- && ( m_boundary_checker.template
- is_endpoint_boundary<boundary_front>(range::front(linestring))
- || m_boundary_checker.template
- is_endpoint_boundary<boundary_back>(range::back(linestring)) ) )
+ if ((m_interrupt_flags & 0xC) != 0xC // if wasn't already set
+ && (m_boundary_checker.is_endpoint_boundary(range::front(linestring))
+ || m_boundary_checker.is_endpoint_boundary(range::back(linestring))))
{
if ( pig > 0 )
{
@@ -150,7 +150,7 @@ public:
private:
Geometry2 const& m_geometry2;
Result & m_result;
- PointInArealStrategy const& m_point_in_areal_strategy;
+ Strategy const& m_strategy;
BoundaryChecker const& m_boundary_checker;
unsigned m_interrupt_flags;
};
@@ -177,9 +177,9 @@ public:
// TODO:
// handle empty/invalid geometries in a different way than below?
- typedef typename geometry::point_type<Areal>::type point_type;
- point_type dummy;
- bool const ok = boost::geometry::point_on_border(dummy, areal);
+ using point_type = typename geometry::point_type<Areal>::type;
+ typename helper_geometry<point_type>::type pt;
+ bool const ok = geometry::point_on_border(pt, areal);
// TODO: for now ignore, later throw an exception?
if ( !ok )
@@ -189,7 +189,7 @@ public:
update<interior, exterior, '2', TransposeResult>(m_result);
update<boundary, exterior, '1', TransposeResult>(m_result);
-
+
return false;
}
@@ -198,6 +198,129 @@ private:
bool const interrupt;
};
+
+template <typename It, typename Strategy>
+inline It find_next_non_duplicated(It first, It current, It last, Strategy const& strategy)
+{
+ BOOST_GEOMETRY_ASSERT(current != last);
+
+ It it = current;
+ for (++it ; it != last ; ++it)
+ {
+ if (! equals::equals_point_point(*current, *it, strategy))
+ {
+ return it;
+ }
+ }
+
+ // if not found start from the beginning
+ for (it = first ; it != current ; ++it)
+ {
+ if (! equals::equals_point_point(*current, *it, strategy))
+ {
+ return it;
+ }
+ }
+
+ return current;
+}
+
+// calculate inside or outside based on side_calc
+// this is simplified version of a check from equal<>
+template
+<
+ typename Pi, typename Pj, typename Pk,
+ typename Qi, typename Qj, typename Qk,
+ typename Strategy
+>
+inline bool calculate_from_inside_sides(Pi const& pi, Pj const& pj, Pk const& pk,
+ Qi const& , Qj const& qj, Qk const& qk,
+ Strategy const& strategy)
+{
+ auto const side_strategy = strategy.side();
+
+ int const side_pk_p = side_strategy.apply(pi, pj, pk);
+ int const side_qk_p = side_strategy.apply(pi, pj, qk);
+ // If they turn to same side (not opposite sides)
+ if (! overlay::base_turn_handler::opposite(side_pk_p, side_qk_p))
+ {
+ int const side_pk_q2 = side_strategy.apply(qj, qk, pk);
+ return side_pk_q2 == -1;
+ }
+ else
+ {
+ return side_pk_p == -1;
+ }
+}
+
+// check if the passed turn's segment of Linear geometry arrived
+// from the inside or the outside of the Areal geometry
+template
+<
+ std::size_t OpId,
+ typename Geometry1, typename Geometry2,
+ typename Turn, typename Strategy
+>
+inline bool calculate_from_inside(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Turn const& turn,
+ Strategy const& strategy)
+{
+ static const std::size_t op_id = OpId;
+ static const std::size_t other_op_id = (OpId + 1) % 2;
+
+ if (turn.operations[op_id].position == overlay::position_front)
+ {
+ return false;
+ }
+
+ auto const& range1 = sub_range(geometry1, turn.operations[op_id].seg_id);
+
+ using range2_view = detail::closed_clockwise_view<typename ring_type<Geometry2>::type const>;
+ range2_view const range2(sub_range(geometry2, turn.operations[other_op_id].seg_id));
+
+ BOOST_GEOMETRY_ASSERT(boost::size(range1));
+ std::size_t const s2 = boost::size(range2);
+ BOOST_GEOMETRY_ASSERT(s2 > 2);
+ std::size_t const seg_count2 = s2 - 1;
+
+ std::size_t const p_seg_ij = static_cast<std::size_t>(turn.operations[op_id].seg_id.segment_index);
+ std::size_t const q_seg_ij = static_cast<std::size_t>(turn.operations[other_op_id].seg_id.segment_index);
+
+ BOOST_GEOMETRY_ASSERT(p_seg_ij + 1 < boost::size(range1));
+ BOOST_GEOMETRY_ASSERT(q_seg_ij + 1 < s2);
+
+ auto const& pi = range::at(range1, p_seg_ij);
+ auto const& qi = range::at(range2, q_seg_ij);
+ auto const& qj = range::at(range2, q_seg_ij + 1);
+
+ bool const is_ip_qj = equals::equals_point_point(turn.point, qj, strategy);
+ // TODO: test this!
+ // BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, pi));
+ // BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, qi));
+
+ if (is_ip_qj)
+ {
+ std::size_t const q_seg_jk = (q_seg_ij + 1) % seg_count2;
+ // TODO: the following function should return immediately, however the worst case complexity is O(N)
+ // It would be good to replace it with some O(1) mechanism
+ auto qk_it = find_next_non_duplicated(boost::begin(range2),
+ range::pos(range2, q_seg_jk),
+ boost::end(range2),
+ strategy);
+
+ // Calculate sides in a different point order for P and Q
+ // Will this sequence of points be always correct?
+ return calculate_from_inside_sides(qi, turn.point, pi, qi, qj, *qk_it, strategy);
+ }
+ else
+ {
+ // Calculate sides with different points for P and Q
+ return calculate_from_inside_sides(qi, turn.point, pi, qi, turn.point, qj, strategy);
+ }
+}
+
+
// The implementation of an algorithm calculating relate() for L/A
template <typename Geometry1, typename Geometry2, bool TransposeResult = false>
struct linear_areal
@@ -208,9 +331,6 @@ struct linear_areal
static const bool interruption_enabled = true;
- typedef typename geometry::point_type<Geometry1>::type point1_type;
- typedef typename geometry::point_type<Geometry2>::type point2_type;
-
template <typename Geom1, typename Geom2, typename Strategy>
struct multi_turn_info
: turns::get_turns<Geom1, Geom2>::template turn_info_type<Strategy>::type
@@ -228,45 +348,49 @@ struct linear_areal
typename turns::get_turns<Geom1, Geom2>::template turn_info_type<Strategy>::type
>
{};
-
+
template <typename Result, typename Strategy>
static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
Result & result,
Strategy const& strategy)
{
-// TODO: If Areal geometry may have infinite size, change the following line:
+ boundary_checker<Geometry1, Strategy> boundary_checker1(geometry1, strategy);
+ apply(geometry1, geometry2, boundary_checker1, result, strategy);
+ }
+
+ template <typename BoundaryChecker1, typename Result, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ BoundaryChecker1 const& boundary_checker1,
+ Result & result,
+ Strategy const& strategy)
+ {
+ // TODO: If Areal geometry may have infinite size, change the following line:
- // The result should be FFFFFFFFF
- relate::set<exterior, exterior, result_dimension<Geometry2>::value, TransposeResult>(result);// FFFFFFFFd, d in [1,9] or T
+ update<exterior, exterior, result_dimension<Geometry2>::value, TransposeResult>(result);// FFFFFFFFd, d in [1,9] or T
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
+ {
return;
+ }
// get and analyse turns
- typedef typename turn_info_type<Geometry1, Geometry2, Strategy>::type turn_type;
+ using turn_type = typename turn_info_type<Geometry1, Geometry2, Strategy>::type;
std::vector<turn_type> turns;
interrupt_policy_linear_areal<Geometry2, Result> interrupt_policy(geometry2, result);
turns::get_turns<Geometry1, Geometry2>::apply(turns, geometry1, geometry2, interrupt_policy, strategy);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
+ {
return;
-
- typedef typename Strategy::cs_tag cs_tag;
-
- typedef boundary_checker
- <
- Geometry1,
- Strategy
- > boundary_checker1_type;
- boundary_checker1_type boundary_checker1(geometry1, strategy);
+ }
no_turns_la_linestring_pred
<
Geometry2,
Result,
Strategy,
- boundary_checker1_type,
+ BoundaryChecker1,
TransposeResult
> pred1(geometry2,
result,
@@ -274,24 +398,32 @@ struct linear_areal
boundary_checker1);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
+ {
return;
+ }
no_turns_la_areal_pred<Result, !TransposeResult> pred2(result);
for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
+ {
return;
-
+ }
+
if ( turns.empty() )
+ {
return;
+ }
// This is set here because in the case if empty Areal geometry were passed
// those shouldn't be set
- relate::set<exterior, interior, '2', TransposeResult>(result);// FFFFFF2Fd
+ update<exterior, interior, '2', TransposeResult>(result);// FFFFFF2Fd
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
+ {
return;
+ }
{
- sort_dispatch<cs_tag>(turns.begin(), turns.end(), util::is_multi<Geometry2>());
+ sort_dispatch(turns.begin(), turns.end(), strategy, util::is_multi<Geometry2>());
turns_analyser<turn_type> analyser;
analyse_each_turn(result, analyser,
@@ -301,13 +433,15 @@ struct linear_areal
strategy);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
+ {
return;
+ }
}
// If 'c' (insersection_boundary) was not found we know that any Ls isn't equal to one of the Rings
if ( !interrupt_policy.is_boundary_found )
{
- relate::set<exterior, boundary, '1', TransposeResult>(result);
+ update<exterior, boundary, '1', TransposeResult>(result);
}
// Don't calculate it if it's required
else if ( may_update<exterior, boundary, '1', TransposeResult>(result) )
@@ -323,12 +457,9 @@ struct linear_areal
// sort by multi_index and rind_index
std::sort(turns.begin(), turns.end(), less_ring());
- typedef typename std::vector<turn_type>::iterator turn_iterator;
-
- turn_iterator it = turns.begin();
segment_identifier * prev_seg_id_ptr = NULL;
// for each ring
- for ( ; it != turns.end() ; )
+ for (auto it = turns.begin() ; it != turns.end() ; )
{
// it's the next single geometry
if ( prev_seg_id_ptr == NULL
@@ -338,7 +469,7 @@ struct linear_areal
if ( it->operations[1].seg_id.ring_index > -1 )
{
// we can be sure that the exterior overlaps the boundary
- relate::set<exterior, boundary, '1', TransposeResult>(result);
+ update<exterior, boundary, '1', TransposeResult>(result);
break;
}
// if there was some previous ring
@@ -346,14 +477,14 @@ struct linear_areal
{
signed_size_type const next_ring_index = prev_seg_id_ptr->ring_index + 1;
BOOST_GEOMETRY_ASSERT(next_ring_index >= 0);
-
+
// if one of the last rings of previous single geometry was ommited
if ( static_cast<std::size_t>(next_ring_index)
< geometry::num_interior_rings(
single_geometry(geometry2, *prev_seg_id_ptr)) )
{
// we can be sure that the exterior overlaps the boundary
- relate::set<exterior, boundary, '1', TransposeResult>(result);
+ update<exterior, boundary, '1', TransposeResult>(result);
break;
}
}
@@ -366,7 +497,7 @@ struct linear_areal
&& prev_seg_id_ptr->ring_index + 1 < it->operations[1].seg_id.ring_index )
{
// we can be sure that the exterior overlaps the boundary
- relate::set<exterior, boundary, '1', TransposeResult>(result);
+ update<exterior, boundary, '1', TransposeResult>(result);
break;
}
}
@@ -375,25 +506,25 @@ struct linear_areal
// find the next ring first iterator and check if the analysis should be performed
has_boundary_intersection has_boundary_inters;
- turn_iterator next = find_next_ring(it, turns.end(), has_boundary_inters);
+ auto next = find_next_ring(it, turns.end(), has_boundary_inters);
// if there is no 1d overlap with the boundary
if ( !has_boundary_inters.result )
{
// we can be sure that the exterior overlaps the boundary
- relate::set<exterior, boundary, '1', TransposeResult>(result);
+ update<exterior, boundary, '1', TransposeResult>(result);
break;
}
// else there is 1d overlap with the boundary so we must analyse the boundary
else
{
// u, c
- typedef turns::less<1, turns::less_op_areal_linear<1>, cs_tag> less;
- std::sort(it, next, less());
+ using less_t = turns::less<1, turns::less_op_areal_linear<1>, Strategy>;
+ std::sort(it, next, less_t());
// analyse
areal_boundary_analyser<turn_type> analyser;
- for ( turn_iterator rit = it ; rit != next ; ++rit )
+ for (auto rit = it ; rit != next ; ++rit)
{
// if the analyser requests, break the search
if ( !analyser.apply(it, rit, next, strategy) )
@@ -404,7 +535,7 @@ struct linear_areal
if ( analyser.is_union_detected )
{
// we can be sure that the boundary of Areal overlaps the exterior of Linear
- relate::set<exterior, boundary, '1', TransposeResult>(result);
+ update<exterior, boundary, '1', TransposeResult>(result);
break;
}
}
@@ -424,7 +555,7 @@ struct linear_areal
single_geometry(geometry2, *prev_seg_id_ptr)) )
{
// we can be sure that the exterior overlaps the boundary
- relate::set<exterior, boundary, '1', TransposeResult>(result);
+ update<exterior, boundary, '1', TransposeResult>(result);
}
}
}
@@ -434,7 +565,9 @@ struct linear_areal
static void for_each_equal_range(It first, It last, Pred pred, Comp comp)
{
if ( first == last )
+ {
return;
+ }
It first_equal = first;
It prev = first;
@@ -445,9 +578,11 @@ struct linear_areal
pred(first_equal, first);
first_equal = first;
}
-
+
if ( first == last )
+ {
break;
+ }
}
}
@@ -516,12 +651,13 @@ struct linear_areal
}
};
- template <typename CSTag, typename TurnIt>
- static void sort_dispatch(TurnIt first, TurnIt last, std::true_type const& /*is_multi*/)
+ template <typename TurnIt, typename Strategy>
+ static void sort_dispatch(TurnIt first, TurnIt last, Strategy const& ,
+ std::true_type const& /*is_multi*/)
{
// sort turns by Linear seg_id, then by fraction, then by other multi_index
- typedef turns::less<0, turns::less_other_multi_index<0>, CSTag> less;
- std::sort(first, last, less());
+ using less_t = turns::less<0, turns::less_other_multi_index<0>, Strategy>;
+ std::sort(first, last, less_t());
// For the same IP and multi_index - the same other's single geometry
// set priorities as the least operation found for the whole single geometry
@@ -534,22 +670,23 @@ struct linear_areal
// When priorities for single geometries are set now sort turns for the same IP
// if multi_index is the same sort them according to the single-less
// else use priority of the whole single-geometry set earlier
- typedef turns::less<0, turns::less_op_linear_areal_single<0>, CSTag> single_less;
+ using single_less_t = turns::less<0, turns::less_op_linear_areal_single<0>, Strategy>;
for_each_equal_range(first, last,
- sort_turns_group<single_less>(),
+ sort_turns_group<single_less_t>(),
same_ip());
}
- template <typename CSTag, typename TurnIt>
- static void sort_dispatch(TurnIt first, TurnIt last, std::false_type const& /*is_multi*/)
+ template <typename TurnIt, typename Strategy>
+ static void sort_dispatch(TurnIt first, TurnIt last, Strategy const& ,
+ std::false_type const& /*is_multi*/)
{
// sort turns by Linear seg_id, then by fraction, then
// for same ring id: x, u, i, c
// for different ring id: c, i, u, x
- typedef turns::less<0, turns::less_op_linear_areal_single<0>, CSTag> less;
- std::sort(first, last, less());
+ using less_t = turns::less<0, turns::less_op_linear_areal_single<0>, Strategy>;
+ std::sort(first, last, less_t());
}
-
+
// interrupt policy which may be passed to get_turns to interrupt the analysis
// based on the info in the passed result/mask
@@ -569,9 +706,7 @@ struct linear_areal
template <typename Range>
inline bool apply(Range const& turns)
{
- typedef typename boost::range_iterator<Range const>::type iterator;
-
- for (iterator it = boost::begin(turns) ; it != boost::end(turns) ; ++it)
+ for (auto it = boost::begin(turns) ; it != boost::end(turns) ; ++it)
{
if ( it->operations[0].operation == overlay::operation_intersection )
{
@@ -619,39 +754,6 @@ struct linear_areal
static const std::size_t op_id = 0;
static const std::size_t other_op_id = 1;
- template <typename TurnPointCSTag, typename PointP, typename PointQ,
- typename Strategy,
- typename Pi = PointP, typename Pj = PointP, typename Pk = PointP,
- typename Qi = PointQ, typename Qj = PointQ, typename Qk = PointQ
- >
- struct la_side_calculator
- {
- typedef decltype(std::declval<Strategy>().side()) side_strategy_type;
-
- inline la_side_calculator(Pi const& pi, Pj const& pj, Pk const& pk,
- Qi const& qi, Qj const& qj, Qk const& qk,
- Strategy const& strategy)
- : m_pi(pi), m_pj(pj), m_pk(pk)
- , m_qi(qi), m_qj(qj), m_qk(qk)
- , m_side_strategy(strategy.side())
- {}
-
- inline int pk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_pk); }
- inline int qk_wrt_p1() const { return m_side_strategy.apply(m_pi, m_pj, m_qk); }
- inline int pk_wrt_q2() const { return m_side_strategy.apply(m_qj, m_qk, m_pk); }
-
- private :
- Pi const& m_pi;
- Pj const& m_pj;
- Pk const& m_pk;
- Qi const& m_qi;
- Qj const& m_qj;
- Qk const& m_qk;
-
- side_strategy_type m_side_strategy;
- };
-
-
public:
turns_analyser()
: m_previous_turn_ptr(NULL)
@@ -705,7 +807,7 @@ struct linear_areal
strategy) )
{
m_exit_watcher.reset_detected_exit();
-
+
update<interior, exterior, '1', TransposeResult>(res);
// next single geometry
@@ -714,9 +816,8 @@ struct linear_areal
// NOTE: similar code is in the post-last-ip-apply()
segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
- bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(
- range::back(sub_range(geometry, prev_seg_id)),
- boundary_checker);
+ bool const prev_back_b = boundary_checker.is_endpoint_boundary(
+ range::back(sub_range(geometry, prev_seg_id)));
// if there is a boundary on the last point
if ( prev_back_b )
@@ -790,7 +891,7 @@ struct linear_areal
// TODO: THIS IS POTENTIALLY ERROREOUS!
// THIS ALGORITHM DEPENDS ON SOME SPECIFIC SEQUENCE OF OPERATIONS
// IT WOULD GIVE WRONG RESULTS E.G.
-// IN THE CASE OF SELF-TOUCHING POINT WHEN 'i' WOULD BE BEFORE 'u'
+// IN THE CASE OF SELF-TOUCHING POINT WHEN 'i' WOULD BE BEFORE 'u'
// handle the interior overlap
if ( m_interior_detected )
@@ -809,9 +910,8 @@ struct linear_areal
{
segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
- bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(
- range::back(sub_range(geometry, prev_seg_id)),
- boundary_checker);
+ bool const prev_back_b = boundary_checker.is_endpoint_boundary(
+ range::back(sub_range(geometry, prev_seg_id)));
// if there is a boundary on the last point
if ( prev_back_b )
@@ -890,11 +990,8 @@ struct linear_areal
update<interior, boundary, '1', TransposeResult>(res);
}
- bool const this_b
- = is_ip_on_boundary<boundary_front>(it->point,
- it->operations[op_id],
- boundary_checker,
- seg_id);
+ bool const this_b = is_ip_on_boundary(it->point, it->operations[op_id],
+ boundary_checker);
// going inside on boundary point
if ( this_b )
{
@@ -911,11 +1008,11 @@ struct linear_areal
&& it->operations[op_id].position != overlay::position_front )
{
// TODO: calculate_from_inside() is only needed if the current Linestring is not closed
- bool const from_inside = first_point
- && calculate_from_inside(geometry,
- other_geometry,
- *it,
- strategy);
+ bool const from_inside =
+ first_point && calculate_from_inside<op_id>(geometry,
+ other_geometry,
+ *it,
+ strategy);
if ( from_inside )
update<interior, interior, '1', TransposeResult>(res);
@@ -925,9 +1022,8 @@ struct linear_areal
// if it's the first IP then the first point is outside
if ( first_point )
{
- bool const front_b = is_endpoint_on_boundary<boundary_front>(
- range::front(sub_range(geometry, seg_id)),
- boundary_checker);
+ bool const front_b = boundary_checker.is_endpoint_boundary(
+ range::front(sub_range(geometry, seg_id)));
// if there is a boundary on the first point
if ( front_b )
@@ -955,7 +1051,7 @@ struct linear_areal
// TODO: is this condition ok?
// TODO: move it into the exit_watcher?
&& m_exit_watcher.get_exit_operation() == overlay::operation_none;
-
+
if ( op == overlay::operation_union )
{
if ( m_boundary_counter > 0 && it->operations[op_id].is_collinear )
@@ -974,7 +1070,7 @@ struct linear_areal
{
// check if this is indeed the boundary point
// NOTE: is_ip_on_boundary<>() should be called here but the result will be the same
- if ( is_endpoint_on_boundary<boundary_back>(it->point, boundary_checker) )
+ if (boundary_checker.is_endpoint_boundary(it->point))
{
update<boundary, boundary, '0', TransposeResult>(res);
}
@@ -989,10 +1085,8 @@ struct linear_areal
// we're outside or inside and this is the first turn
else
{
- bool const this_b = is_ip_on_boundary<boundary_any>(it->point,
- it->operations[op_id],
- boundary_checker,
- seg_id);
+ bool const this_b = is_ip_on_boundary(it->point, it->operations[op_id],
+ boundary_checker);
// if current IP is on boundary of the geometry
if ( this_b )
{
@@ -1012,11 +1106,11 @@ struct linear_areal
// For LS/MultiPolygon multiple x/u turns may be generated
// the first checked Polygon may be the one which LS is outside for.
bool const first_point = first_in_range || m_first_from_unknown;
- bool const first_from_inside = first_point
- && calculate_from_inside(geometry,
- other_geometry,
- *it,
- strategy);
+ bool const first_from_inside =
+ first_point && calculate_from_inside<op_id>(geometry,
+ other_geometry,
+ *it,
+ strategy);
if ( first_from_inside )
{
update<interior, interior, '1', TransposeResult>(res);
@@ -1044,9 +1138,8 @@ struct linear_areal
// first IP on the last segment point - this means that the first point is outside or inside
if ( first_point && ( !this_b || op_blocked ) )
{
- bool const front_b = is_endpoint_on_boundary<boundary_front>(
- range::front(sub_range(geometry, seg_id)),
- boundary_checker);
+ bool const front_b = boundary_checker.is_endpoint_boundary(
+ range::front(sub_range(geometry, seg_id)));
// if there is a boundary on the first point
if ( front_b )
@@ -1135,9 +1228,8 @@ struct linear_areal
segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
- bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(
- range::back(sub_range(geometry, prev_seg_id)),
- boundary_checker);
+ bool const prev_back_b = boundary_checker.is_endpoint_boundary(
+ range::back(sub_range(geometry, prev_seg_id)));
// if there is a boundary on the last point
if ( prev_back_b )
@@ -1158,9 +1250,8 @@ struct linear_areal
segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
- bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(
- range::back(sub_range(geometry, prev_seg_id)),
- boundary_checker);
+ bool const prev_back_b = boundary_checker.is_endpoint_boundary(
+ range::back(sub_range(geometry, prev_seg_id)));
// if there is a boundary on the last point
if ( prev_back_b )
@@ -1184,9 +1275,8 @@ struct linear_areal
segment_identifier const& prev_seg_id = m_previous_turn_ptr->operations[op_id].seg_id;
- bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(
- range::back(sub_range(geometry, prev_seg_id)),
- boundary_checker);
+ bool const prev_back_b = boundary_checker.is_endpoint_boundary(
+ range::back(sub_range(geometry, prev_seg_id)));
// if there is a boundary on the last point
if ( prev_back_b )
@@ -1202,120 +1292,6 @@ struct linear_areal
m_first_from_unknown_boundary_detected = false;
}
- // check if the passed turn's segment of Linear geometry arrived
- // from the inside or the outside of the Areal geometry
- template <typename Turn, typename Strategy>
- static inline bool calculate_from_inside(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Turn const& turn,
- Strategy const& strategy)
- {
- typedef typename cs_tag<typename Turn::point_type>::type cs_tag;
-
- if ( turn.operations[op_id].position == overlay::position_front )
- return false;
-
- typename sub_range_return_type<Geometry1 const>::type
- range1 = sub_range(geometry1, turn.operations[op_id].seg_id);
-
- using range2_view = detail::closed_clockwise_view<typename ring_type<Geometry2>::type const>;
- using range2_iterator = typename boost::range_iterator<range2_view const>::type;
- range2_view const range2(sub_range(geometry2, turn.operations[other_op_id].seg_id));
-
- BOOST_GEOMETRY_ASSERT(boost::size(range1));
- std::size_t const s2 = boost::size(range2);
- BOOST_GEOMETRY_ASSERT(s2 > 2);
- std::size_t const seg_count2 = s2 - 1;
-
- std::size_t const p_seg_ij = static_cast<std::size_t>(turn.operations[op_id].seg_id.segment_index);
- std::size_t const q_seg_ij = static_cast<std::size_t>(turn.operations[other_op_id].seg_id.segment_index);
-
- BOOST_GEOMETRY_ASSERT(p_seg_ij + 1 < boost::size(range1));
- BOOST_GEOMETRY_ASSERT(q_seg_ij + 1 < s2);
-
- point1_type const& pi = range::at(range1, p_seg_ij);
- point2_type const& qi = range::at(range2, q_seg_ij);
- point2_type const& qj = range::at(range2, q_seg_ij + 1);
- point1_type qi_conv;
- geometry::convert(qi, qi_conv);
- bool const is_ip_qj = equals::equals_point_point(turn.point, qj, strategy);
-// TODO: test this!
-// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, pi));
-// BOOST_GEOMETRY_ASSERT(!equals::equals_point_point(turn.point, qi));
- point1_type new_pj;
- geometry::convert(turn.point, new_pj);
-
- if ( is_ip_qj )
- {
- std::size_t const q_seg_jk = (q_seg_ij + 1) % seg_count2;
-// TODO: the following function should return immediately, however the worst case complexity is O(N)
-// It would be good to replace it with some O(1) mechanism
- range2_iterator qk_it = find_next_non_duplicated(boost::begin(range2),
- range::pos(range2, q_seg_jk),
- boost::end(range2),
- strategy);
-
- // Will this sequence of points be always correct?
- la_side_calculator<cs_tag, point1_type, point2_type, Strategy>
- side_calc(qi_conv, new_pj, pi, qi, qj, *qk_it, strategy);
-
- return calculate_from_inside_sides(side_calc);
- }
- else
- {
- point2_type new_qj;
- geometry::convert(turn.point, new_qj);
-
- la_side_calculator<cs_tag, point1_type, point2_type, Strategy>
- side_calc(qi_conv, new_pj, pi, qi, new_qj, qj, strategy);
-
- return calculate_from_inside_sides(side_calc);
- }
- }
-
- template <typename It, typename Strategy>
- static inline It find_next_non_duplicated(It first, It current, It last,
- Strategy const& strategy)
- {
- BOOST_GEOMETRY_ASSERT( current != last );
-
- It it = current;
-
- for ( ++it ; it != last ; ++it )
- {
- if ( !equals::equals_point_point(*current, *it, strategy) )
- return it;
- }
-
- // if not found start from the beginning
- for ( it = first ; it != current ; ++it )
- {
- if ( !equals::equals_point_point(*current, *it, strategy) )
- return it;
- }
-
- return current;
- }
-
- // calculate inside or outside based on side_calc
- // this is simplified version of a check from equal<>
- template <typename SideCalc>
- static inline bool calculate_from_inside_sides(SideCalc const& side_calc)
- {
- int const side_pk_p = side_calc.pk_wrt_p1();
- int const side_qk_p = side_calc.qk_wrt_p1();
- // If they turn to same side (not opposite sides)
- if (! overlay::base_turn_handler::opposite(side_pk_p, side_qk_p))
- {
- int const side_pk_q2 = side_calc.pk_wrt_q2();
- return side_pk_q2 == -1;
- }
- else
- {
- return side_pk_p == -1;
- }
- }
-
private:
exit_watcher<TurnInfo, op_id> m_exit_watcher;
segment_watcher<same_single> m_seg_watcher;
@@ -1346,7 +1322,9 @@ struct linear_areal
Strategy const& strategy)
{
if ( first == last )
+ {
return;
+ }
for ( TurnIt it = first ; it != last ; ++it )
{
@@ -1356,7 +1334,9 @@ struct linear_areal
strategy);
if ( BOOST_GEOMETRY_CONDITION( res.interrupt ) )
+ {
return;
+ }
}
analyser.apply(res, first, last,
@@ -1472,7 +1452,7 @@ struct linear_areal
else
{
return false;
- }
+ }
}
bool is_union_detected;
@@ -1496,6 +1476,15 @@ struct areal_linear
{
linear_areal_type::apply(geometry2, geometry1, result, strategy);
}
+
+ template <typename BoundaryChecker2, typename Result, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ BoundaryChecker2 const& boundary_checker2,
+ Result & result,
+ Strategy const& strategy)
+ {
+ linear_areal_type::apply(geometry2, geometry1, boundary_checker2, result, strategy);
+ }
};
}} // namespace detail::relate
diff --git a/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/boost/geometry/algorithms/detail/relate/linear_linear.hpp
index fa46db2459..8a326265af 100644
--- a/boost/geometry/algorithms/detail/relate/linear_linear.hpp
+++ b/boost/geometry/algorithms/detail/relate/linear_linear.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2015, 2017, 2018, 2019.
-// Modifications copyright (c) 2013-2019 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -33,6 +33,8 @@
#include <boost/geometry/algorithms/detail/relate/boundary_checker.hpp>
#include <boost/geometry/algorithms/detail/relate/follow_helpers.hpp>
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
namespace boost { namespace geometry
{
@@ -68,7 +70,7 @@ public:
}
std::size_t const count = boost::size(linestring);
-
+
// invalid input
if ( count < 2 )
{
@@ -91,11 +93,9 @@ public:
m_flags |= 1;
// check if there is a boundary
- if ( m_flags < 2
- && ( m_boundary_checker.template
- is_endpoint_boundary<boundary_front>(range::front(linestring))
- || m_boundary_checker.template
- is_endpoint_boundary<boundary_back>(range::back(linestring)) ) )
+ if (m_flags < 2
+ && (m_boundary_checker.is_endpoint_boundary(range::front(linestring))
+ || m_boundary_checker.is_endpoint_boundary(range::back(linestring))))
{
update<boundary, exterior, '0', TransposeResult>(m_result);
m_flags |= 2;
@@ -117,26 +117,33 @@ struct linear_linear
{
static const bool interruption_enabled = true;
- typedef typename geometry::point_type<Geometry1>::type point1_type;
- typedef typename geometry::point_type<Geometry2>::type point2_type;
-
template <typename Result, typename Strategy>
static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
Result & result,
Strategy const& strategy)
{
- typedef typename Strategy::cs_tag cs_tag;
+ boundary_checker<Geometry1, Strategy> boundary_checker1(geometry1, strategy);
+ boundary_checker<Geometry2, Strategy> boundary_checker2(geometry2, strategy);
+ apply(geometry1, geometry2, boundary_checker1, boundary_checker2, result, strategy);
+ }
+ template <typename BoundaryChecker1, typename BoundaryChecker2, typename Result, typename Strategy>
+ static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ BoundaryChecker1 const& boundary_checker1,
+ BoundaryChecker2 const& boundary_checker2,
+ Result & result,
+ Strategy const& strategy)
+ {
// The result should be FFFFFFFFF
- relate::set<exterior, exterior, result_dimension<Geometry1>::value>(result);// FFFFFFFFd, d in [1,9] or T
+ update<exterior, exterior, result_dimension<Geometry1>::value>(result);// FFFFFFFFd, d in [1,9] or T
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
// get and analyse turns
- typedef typename turns::get_turns
+ using turn_type = typename turns::get_turns
<
Geometry1, Geometry2
- >::template turn_info_type<Strategy>::type turn_type;
+ >::template turn_info_type<Strategy>::type;
std::vector<turn_type> turns;
interrupt_policy_linear_linear<Result> interrupt_policy(result);
@@ -151,20 +158,16 @@ struct linear_linear
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
- typedef boundary_checker<Geometry1, Strategy> boundary_checker1_type;
- boundary_checker1_type boundary_checker1(geometry1, strategy);
- disjoint_linestring_pred<Result, boundary_checker1_type, false> pred1(result, boundary_checker1);
+ disjoint_linestring_pred<Result, BoundaryChecker1, false> pred1(result, boundary_checker1);
for_each_disjoint_geometry_if<0, Geometry1>::apply(turns.begin(), turns.end(), geometry1, pred1);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
- typedef boundary_checker<Geometry2, Strategy> boundary_checker2_type;
- boundary_checker2_type boundary_checker2(geometry2, strategy);
- disjoint_linestring_pred<Result, boundary_checker2_type, true> pred2(result, boundary_checker2);
+ disjoint_linestring_pred<Result, BoundaryChecker2, true> pred2(result, boundary_checker2);
for_each_disjoint_geometry_if<1, Geometry2>::apply(turns.begin(), turns.end(), geometry2, pred2);
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
-
+
if ( turns.empty() )
return;
@@ -178,8 +181,8 @@ struct linear_linear
|| may_update<boundary, boundary, '0'>(result)
|| may_update<boundary, exterior, '0'>(result) )
{
- typedef turns::less<0, turns::less_op_linear_linear<0>, cs_tag> less;
- std::sort(turns.begin(), turns.end(), less());
+ using less_t = turns::less<0, turns::less_op_linear_linear<0>, Strategy>;
+ std::sort(turns.begin(), turns.end(), less_t());
turns_analyser<turn_type, 0> analyser;
analyse_each_turn(result, analyser,
@@ -190,7 +193,7 @@ struct linear_linear
if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) )
return;
-
+
if ( may_update<interior, interior, '1', true>(result)
|| may_update<interior, boundary, '0', true>(result)
|| may_update<interior, exterior, '1', true>(result)
@@ -198,8 +201,8 @@ struct linear_linear
|| may_update<boundary, boundary, '0', true>(result)
|| may_update<boundary, exterior, '0', true>(result) )
{
- typedef turns::less<1, turns::less_op_linear_linear<1>, cs_tag> less;
- std::sort(turns.begin(), turns.end(), less());
+ using less_t = turns::less<1, turns::less_op_linear_linear<1>, Strategy>;
+ std::sort(turns.begin(), turns.end(), less_t());
turns_analyser<turn_type, 1> analyser;
analyse_each_turn(result, analyser,
@@ -224,9 +227,7 @@ struct linear_linear
template <typename Range>
inline bool apply(Range const& turns)
{
- typedef typename boost::range_iterator<Range const>::type iterator;
-
- for (iterator it = boost::begin(turns) ; it != boost::end(turns) ; ++it)
+ for (auto it = boost::begin(turns) ; it != boost::end(turns) ; ++it)
{
if ( it->operations[0].operation == overlay::operation_intersection
|| it->operations[1].operation == overlay::operation_intersection )
@@ -285,7 +286,6 @@ struct linear_linear
overlay::operation_type const op = it->operations[op_id].operation;
segment_identifier const& seg_id = it->operations[op_id].seg_id;
- segment_identifier const& other_id = it->operations[other_op_id].seg_id;
bool const first_in_range = m_seg_watcher.update(seg_id);
@@ -296,8 +296,8 @@ struct linear_linear
// degenerated turn
if ( op == overlay::operation_continue
&& it->method == overlay::method_none
- && m_exit_watcher.is_outside(*it)
- /*&& ( m_exit_watcher.get_exit_operation() == overlay::operation_none
+ && m_exit_watcher.is_outside(*it)
+ /*&& ( m_exit_watcher.get_exit_operation() == overlay::operation_none
|| ! turn_on_the_same_ip<op_id>(m_exit_watcher.get_exit_turn(), *it) )*/ )
{
// TODO: rewrite the above condition
@@ -336,7 +336,7 @@ struct linear_linear
boundary_checker.strategy()) )
{
m_exit_watcher.reset_detected_exit();
-
+
// not the last IP
update<interior, exterior, '1', transpose_result>(res);
}
@@ -374,20 +374,16 @@ struct linear_linear
update<interior, interior, '1', transpose_result>(res);
bool const this_b = it->operations[op_id].position == overlay::position_front // ignore spikes!
- && is_ip_on_boundary<boundary_front>(it->point,
- it->operations[op_id],
- boundary_checker,
- seg_id);
+ && is_ip_on_boundary(it->point, it->operations[op_id],
+ boundary_checker);
// going inside on boundary point
// may be front only
if ( this_b )
{
// may be front and back
- bool const other_b = is_ip_on_boundary<boundary_any>(it->point,
- it->operations[other_op_id],
- other_boundary_checker,
- other_id);
+ bool const other_b = is_ip_on_boundary(it->point, it->operations[other_op_id],
+ other_boundary_checker);
// it's also the boundary of the other geometry
if ( other_b )
@@ -413,9 +409,8 @@ struct linear_linear
// if it's the first IP then the first point is outside
if ( first_in_range )
{
- bool const front_b = is_endpoint_on_boundary<boundary_front>(
- range::front(sub_range(geometry, seg_id)),
- boundary_checker);
+ bool const front_b = boundary_checker.is_endpoint_boundary(
+ range::front(sub_range(geometry, seg_id)));
// if there is a boundary on the first point
if ( front_b )
@@ -461,13 +456,12 @@ struct linear_linear
{
// check if this is indeed the boundary point
// NOTE: is_ip_on_boundary<>() should be called here but the result will be the same
- if ( is_endpoint_on_boundary<boundary_back>(it->point, boundary_checker) )
+ if (boundary_checker.is_endpoint_boundary(it->point))
{
// may be front and back
- bool const other_b = is_ip_on_boundary<boundary_any>(it->point,
- it->operations[other_op_id],
- other_boundary_checker,
- other_id);
+ bool const other_b = is_ip_on_boundary(it->point,
+ it->operations[other_op_id],
+ other_boundary_checker);
// it's also the boundary of the other geometry
if ( other_b )
{
@@ -501,9 +495,8 @@ struct linear_linear
// it's the first point in range
if ( first_in_range )
{
- bool const front_b = is_endpoint_on_boundary<boundary_front>(
- range::front(sub_range(geometry, seg_id)),
- boundary_checker);
+ bool const front_b = boundary_checker.is_endpoint_boundary(
+ range::front(sub_range(geometry, seg_id)));
// if there is a boundary on the first point
if ( front_b )
@@ -515,16 +508,14 @@ struct linear_linear
// method other than crosses, check more conditions
else
{
- bool const this_b = is_ip_on_boundary<boundary_any>(it->point,
- it->operations[op_id],
- boundary_checker,
- seg_id);
-
- bool const other_b = is_ip_on_boundary<boundary_any>(it->point,
- it->operations[other_op_id],
- other_boundary_checker,
- other_id);
-
+ bool const this_b = is_ip_on_boundary(it->point,
+ it->operations[op_id],
+ boundary_checker);
+
+ bool const other_b = is_ip_on_boundary(it->point,
+ it->operations[other_op_id],
+ other_boundary_checker);
+
// if current IP is on boundary of the geometry
if ( this_b )
{
@@ -560,9 +551,8 @@ struct linear_linear
&& ! m_collinear_spike_exit
/*&& !is_collinear*/ )
{
- bool const front_b = is_endpoint_on_boundary<boundary_front>(
- range::front(sub_range(geometry, seg_id)),
- boundary_checker);
+ bool const front_b = boundary_checker.is_endpoint_boundary(
+ range::front(sub_range(geometry, seg_id)));
// if there is a boundary on the first point
if ( front_b )
@@ -570,7 +560,7 @@ struct linear_linear
update<boundary, exterior, '0', transpose_result>(res);
}
}
-
+
}
}
}
@@ -613,15 +603,14 @@ struct linear_linear
turn_ptr = m_degenerated_turn_ptr;
else if ( m_previous_turn_ptr )
turn_ptr = m_previous_turn_ptr;
-
+
if ( turn_ptr )
{
segment_identifier const& prev_seg_id = turn_ptr->operations[op_id].seg_id;
//BOOST_GEOMETRY_ASSERT(!boost::empty(sub_range(geometry, prev_seg_id)));
- bool const prev_back_b = is_endpoint_on_boundary<boundary_back>(
- range::back(sub_range(geometry, prev_seg_id)),
- boundary_checker);
+ bool const prev_back_b = boundary_checker.is_endpoint_boundary(
+ range::back(sub_range(geometry, prev_seg_id)));
// if there is a boundary on the last point
if ( prev_back_b )
@@ -659,19 +648,17 @@ struct linear_linear
OtherBoundaryChecker const& other_boundary_checker,
bool first_in_range)
{
- typename detail::single_geometry_return_type<Geometry const>::type
- ls1_ref = detail::single_geometry(geometry, turn.operations[op_id].seg_id);
- typename detail::single_geometry_return_type<OtherGeometry const>::type
- ls2_ref = detail::single_geometry(other_geometry, turn.operations[other_op_id].seg_id);
+ auto const& ls1 = detail::single_geometry(geometry, turn.operations[op_id].seg_id);
+ auto const& ls2 = detail::single_geometry(other_geometry, turn.operations[other_op_id].seg_id);
// only one of those should be true:
if ( turn.operations[op_id].position == overlay::position_front )
{
// valid, point-sized
- if ( boost::size(ls2_ref) == 2 )
+ if ( boost::size(ls2) == 2 )
{
- bool const front_b = is_endpoint_on_boundary<boundary_front>(turn.point, boundary_checker);
+ bool const front_b = boundary_checker.is_endpoint_boundary(turn.point);
if ( front_b )
{
@@ -691,11 +678,11 @@ struct linear_linear
else if ( turn.operations[op_id].position == overlay::position_back )
{
// valid, point-sized
- if ( boost::size(ls2_ref) == 2 )
+ if ( boost::size(ls2) == 2 )
{
update<interior, exterior, '1', transpose_result>(res);
- bool const back_b = is_endpoint_on_boundary<boundary_back>(turn.point, boundary_checker);
+ bool const back_b = boundary_checker.is_endpoint_boundary(turn.point);
if ( back_b )
{
@@ -708,9 +695,9 @@ struct linear_linear
if ( first_in_range )
{
- //BOOST_GEOMETRY_ASSERT(!boost::empty(ls1_ref));
- bool const front_b = is_endpoint_on_boundary<boundary_front>(
- range::front(ls1_ref), boundary_checker);
+ //BOOST_GEOMETRY_ASSERT(!boost::empty(ls1));
+ bool const front_b = boundary_checker.is_endpoint_boundary(
+ range::front(ls1));
if ( front_b )
{
update<boundary, exterior, '0', transpose_result>(res);
@@ -725,13 +712,13 @@ struct linear_linear
// here we don't know which one is degenerated
- bool const is_point1 = boost::size(ls1_ref) == 2
- && equals::equals_point_point(range::front(ls1_ref),
- range::back(ls1_ref),
+ bool const is_point1 = boost::size(ls1) == 2
+ && equals::equals_point_point(range::front(ls1),
+ range::back(ls1),
boundary_checker.strategy());
- bool const is_point2 = boost::size(ls2_ref) == 2
- && equals::equals_point_point(range::front(ls2_ref),
- range::back(ls2_ref),
+ bool const is_point2 = boost::size(ls2) == 2
+ && equals::equals_point_point(range::front(ls2),
+ range::back(ls2),
other_boundary_checker.strategy());
// if the second one is degenerated
@@ -741,9 +728,9 @@ struct linear_linear
if ( first_in_range )
{
- //BOOST_GEOMETRY_ASSERT(!boost::empty(ls1_ref));
- bool const front_b = is_endpoint_on_boundary<boundary_front>(
- range::front(ls1_ref), boundary_checker);
+ //BOOST_GEOMETRY_ASSERT(!boost::empty(ls1));
+ bool const front_b = boundary_checker.is_endpoint_boundary(
+ range::front(ls1));
if ( front_b )
{
update<boundary, exterior, '0', transpose_result>(res);
diff --git a/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp b/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp
index 7da7f2be5e..204a4fe22d 100644
--- a/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp
+++ b/boost/geometry/algorithms/detail/relate/multi_point_geometry.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry
-// Copyright (c) 2017-2020 Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -94,9 +95,8 @@ struct multi_point_geometry_eb<Geometry, linestring_tag>
template <typename Point, typename Strategy>
bool apply(Point const& boundary_point, Strategy const& strategy)
{
- if ( std::find_if(m_points.begin(), m_points.end(),
- find_pred<Point, Strategy>(boundary_point, strategy))
- == m_points.end() )
+ if ( std::none_of(m_points.begin(), m_points.end(),
+ find_pred<Point, Strategy>(boundary_point, strategy)))
{
m_boundary_found = true;
return false;
@@ -135,7 +135,7 @@ struct multi_point_geometry_eb<Geometry, multi_linestring_tag>
template <typename Point, typename Strategy>
bool apply(Point const& boundary_point, Strategy const&)
{
- typedef geometry::less<void, -1, typename Strategy::cs_tag> less_type;
+ typedef geometry::less<void, -1, Strategy> less_type;
if (! std::binary_search(m_points.begin(), m_points.end(),
boundary_point, less_type()) )
@@ -159,9 +159,9 @@ struct multi_point_geometry_eb<Geometry, multi_linestring_tag>
{
typedef typename boost::range_value<MultiPoint>::type point_type;
typedef std::vector<point_type> points_type;
- typedef geometry::less<void, -1, typename Strategy::cs_tag> less_type;
+ typedef geometry::less<void, -1, Strategy> less_type;
- points_type points(boost::begin(multi_point), boost::end(multi_point));
+ points_type points(boost::begin(multi_point), boost::end(multi_point));
std::sort(points.begin(), points.end(), less_type());
boundary_visitor<points_type> visitor(points);
@@ -184,13 +184,12 @@ struct multi_point_single_geometry
{
typedef typename point_type<SingleGeometry>::type point2_type;
typedef model::box<point2_type> box2_type;
-
+
box2_type box2;
geometry::envelope(single_geometry, box2, strategy);
geometry::detail::expand_by_epsilon(box2);
- typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
- for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ for (auto it = boost::begin(multi_point); it != boost::end(multi_point); ++it)
{
if (! (relate::may_update<interior, interior, '0', Transpose>(result)
|| relate::may_update<interior, boundary, '0', Transpose>(result)
@@ -202,7 +201,7 @@ struct multi_point_single_geometry
// The default strategy is enough for Point/Box
if (detail::disjoint::disjoint_point_box(*it, box2, strategy))
{
- relate::set<interior, exterior, '0', Transpose>(result);
+ update<interior, exterior, '0', Transpose>(result);
}
else
{
@@ -210,15 +209,15 @@ struct multi_point_single_geometry
if (in_val > 0) // within
{
- relate::set<interior, interior, '0', Transpose>(result);
+ update<interior, interior, '0', Transpose>(result);
}
else if (in_val == 0)
{
- relate::set<interior, boundary, '0', Transpose>(result);
+ update<interior, boundary, '0', Transpose>(result);
}
else // in_val < 0 - not within
{
- relate::set<interior, exterior, '0', Transpose>(result);
+ update<interior, exterior, '0', Transpose>(result);
}
}
@@ -240,7 +239,7 @@ struct multi_point_single_geometry
{
// TODO: this is not true if a linestring is degenerated to a point
// then the interior has topological dimension = 0, not 1
- relate::set<exterior, interior, tc_t::interior, Transpose>(result);
+ update<exterior, interior, tc_t::interior, Transpose>(result);
}
if ( relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result)
@@ -248,12 +247,12 @@ struct multi_point_single_geometry
{
if (multi_point_geometry_eb<SingleGeometry>::apply(multi_point, tc))
{
- relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
+ update<exterior, boundary, tc_t::boundary, Transpose>(result);
}
}
}
- relate::set<exterior, exterior, result_dimension<MultiPoint>::value, Transpose>(result);
+ update<exterior, exterior, result_dimension<MultiPoint>::value, Transpose>(result);
}
};
@@ -365,14 +364,18 @@ class multi_point_multi_geometry_ii_ib
if (in_val > 0) // within
{
- relate::set<interior, interior, '0', Transpose>(m_result);
+ update<interior, interior, '0', Transpose>(m_result);
}
else if (in_val == 0)
{
if (m_tc.check_boundary_point(point))
- relate::set<interior, boundary, '0', Transpose>(m_result);
+ {
+ update<interior, boundary, '0', Transpose>(m_result);
+ }
else
- relate::set<interior, interior, '0', Transpose>(m_result);
+ {
+ update<interior, interior, '0', Transpose>(m_result);
+ }
}
}
@@ -442,7 +445,6 @@ struct multi_point_multi_geometry_ii_ib_ie
typedef model::box<point2_type> box2_type;
typedef std::pair<box2_type, std::size_t> box_pair_type;
typedef std::vector<box_pair_type> boxes_type;
- typedef typename boxes_type::const_iterator boxes_iterator;
template <typename Result, typename Strategy>
static inline void apply(MultiPoint const& multi_point,
@@ -463,8 +465,7 @@ struct multi_point_multi_geometry_ii_ib_ie
rtree(boxes.begin(), boxes.end(),
index_parameters_type(index::rstar<4>(), strategy));
- typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
- for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ for (auto it = boost::begin(multi_point); it != boost::end(multi_point); ++it)
{
if (! (relate::may_update<interior, interior, '0', Transpose>(result)
|| relate::may_update<interior, boundary, '0', Transpose>(result)
@@ -479,24 +480,28 @@ struct multi_point_multi_geometry_ii_ib_ie
rtree.query(index::intersects(point), std::back_inserter(boxes_found));
bool found_ii_or_ib = false;
- for (boxes_iterator bi = boxes_found.begin() ; bi != boxes_found.end() ; ++bi)
+ for (auto const& box_found : boxes_found)
{
typename boost::range_value<MultiGeometry>::type const&
- single = range::at(multi_geometry, bi->second);
+ single = range::at(multi_geometry, box_found.second);
int in_val = detail::within::point_in_geometry(point, single, strategy);
if (in_val > 0) // within
{
- relate::set<interior, interior, '0', Transpose>(result);
+ update<interior, interior, '0', Transpose>(result);
found_ii_or_ib = true;
}
else if (in_val == 0) // on boundary of single
{
if (tc.check_boundary_point(point))
- relate::set<interior, boundary, '0', Transpose>(result);
+ {
+ update<interior, boundary, '0', Transpose>(result);
+ }
else
- relate::set<interior, interior, '0', Transpose>(result);
+ {
+ update<interior, interior, '0', Transpose>(result);
+ }
found_ii_or_ib = true;
}
}
@@ -504,7 +509,7 @@ struct multi_point_multi_geometry_ii_ib_ie
// neither interior nor boundary found -> exterior
if (found_ii_or_ib == false)
{
- relate::set<interior, exterior, '0', Transpose>(result);
+ update<interior, exterior, '0', Transpose>(result);
}
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
@@ -573,7 +578,7 @@ struct multi_point_multi_geometry
{
// TODO: this is not true if a linestring is degenerated to a point
// then the interior has topological dimension = 0, not 1
- relate::set<exterior, interior, tc_t::interior, Transpose>(result);
+ update<exterior, interior, tc_t::interior, Transpose>(result);
}
if ( relate::may_update<exterior, boundary, tc_t::boundary, Transpose>(result)
@@ -581,12 +586,12 @@ struct multi_point_multi_geometry
{
if (multi_point_geometry_eb<MultiGeometry>::apply(multi_point, tc))
{
- relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
+ update<exterior, boundary, tc_t::boundary, Transpose>(result);
}
}
}
- relate::set<exterior, exterior, result_dimension<MultiPoint>::value, Transpose>(result);
+ update<exterior, exterior, result_dimension<MultiPoint>::value, Transpose>(result);
}
};
diff --git a/boost/geometry/algorithms/detail/relate/point_geometry.hpp b/boost/geometry/algorithms/detail/relate/point_geometry.hpp
index 501c5f3dd6..e570a7209b 100644
--- a/boost/geometry/algorithms/detail/relate/point_geometry.hpp
+++ b/boost/geometry/algorithms/detail/relate/point_geometry.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -14,12 +14,9 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_GEOMETRY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_RELATE_POINT_GEOMETRY_HPP
-#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
-//#include <boost/geometry/algorithms/within.hpp>
-//#include <boost/geometry/algorithms/covered_by.hpp>
-
#include <boost/geometry/algorithms/detail/relate/result.hpp>
#include <boost/geometry/algorithms/detail/relate/topology_check.hpp>
+#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
#include <boost/geometry/util/condition.hpp>
@@ -44,18 +41,18 @@ struct point_geometry
if ( pig > 0 ) // within
{
- relate::set<interior, interior, '0', Transpose>(result);
+ update<interior, interior, '0', Transpose>(result);
}
else if ( pig == 0 )
{
- relate::set<interior, boundary, '0', Transpose>(result);
+ update<interior, boundary, '0', Transpose>(result);
}
else // pig < 0 - not within
{
- relate::set<interior, exterior, '0', Transpose>(result);
+ update<interior, exterior, '0', Transpose>(result);
}
- relate::set<exterior, exterior, result_dimension<Point>::value, Transpose>(result);
+ update<exterior, exterior, result_dimension<Point>::value, Transpose>(result);
if ( BOOST_GEOMETRY_CONDITION(result.interrupt) )
return;
@@ -70,17 +67,21 @@ struct point_geometry
{
// NOTE: even for MLs, if there is at least one boundary point,
// somewhere there must be another one
- relate::set<exterior, interior, tc_t::interior, Transpose>(result);
- relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
+ update<exterior, interior, tc_t::interior, Transpose>(result);
+ update<exterior, boundary, tc_t::boundary, Transpose>(result);
}
else
{
// check if there is a boundary in Geometry
tc_t tc(geometry, strategy);
if ( tc.has_interior() )
- relate::set<exterior, interior, tc_t::interior, Transpose>(result);
+ {
+ update<exterior, interior, tc_t::interior, Transpose>(result);
+ }
if ( tc.has_boundary() )
- relate::set<exterior, boundary, tc_t::boundary, Transpose>(result);
+ {
+ update<exterior, boundary, tc_t::boundary, Transpose>(result);
+ }
}
}
}
@@ -168,7 +169,7 @@ struct geometry_point
// //}
// return result("F0FFFF**T");
// }
-// else
+// else
// {
// /*if ( box_has_interior<Box>::apply(box) )
// {
@@ -194,7 +195,7 @@ struct geometry_point
// return result("0FTFFTFFT");
// else if ( geometry::covered_by(point, box) )
// return result("FF*0F*FFT");
-// else
+// else
// return result("FF*FFT0FT");
// }
//};
diff --git a/boost/geometry/algorithms/detail/relate/point_point.hpp b/boost/geometry/algorithms/detail/relate/point_point.hpp
index 7103e2dc92..c987bb44cb 100644
--- a/boost/geometry/algorithms/detail/relate/point_point.hpp
+++ b/boost/geometry/algorithms/detail/relate/point_point.hpp
@@ -2,9 +2,10 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013, 2014, 2017, 2018.
-// Modifications copyright (c) 2013-2018, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -44,15 +45,15 @@ struct point_point
bool equal = detail::equals::equals_point_point(point1, point2, strategy);
if ( equal )
{
- relate::set<interior, interior, '0'>(result);
+ update<interior, interior, '0'>(result);
}
else
{
- relate::set<interior, exterior, '0'>(result);
- relate::set<exterior, interior, '0'>(result);
+ update<interior, exterior, '0'>(result);
+ update<exterior, interior, '0'>(result);
}
- relate::set<exterior, exterior, result_dimension<Point1>::value>(result);
+ update<exterior, exterior, result_dimension<Point1>::value>(result);
}
};
@@ -67,20 +68,25 @@ std::pair<bool, bool> point_multipoint_check(Point const& point,
// point_in_geometry could be used here but why iterate over MultiPoint twice?
// we must search for a point in the exterior because all points in MultiPoint can be equal
- typedef typename boost::range_iterator<MultiPoint const>::type iterator;
- iterator it = boost::begin(multi_point);
- iterator last = boost::end(multi_point);
- for ( ; it != last ; ++it )
+
+ auto const end = boost::end(multi_point);
+ for (auto it = boost::begin(multi_point); it != end; ++it)
{
bool ii = detail::equals::equals_point_point(point, *it, strategy);
- if ( ii )
+ if (ii)
+ {
found_inside = true;
+ }
else
+ {
found_outside = true;
+ }
- if ( found_inside && found_outside )
+ if (found_inside && found_outside)
+ {
break;
+ }
}
return std::make_pair(found_inside, found_outside);
@@ -99,7 +105,7 @@ struct point_multipoint
if ( boost::empty(multi_point) )
{
// TODO: throw on empty input?
- relate::set<interior, exterior, '0', Transpose>(result);
+ update<interior, exterior, '0', Transpose>(result);
return;
}
@@ -107,20 +113,20 @@ struct point_multipoint
if ( rel.first ) // some point of MP is equal to P
{
- relate::set<interior, interior, '0', Transpose>(result);
+ update<interior, interior, '0', Transpose>(result);
if ( rel.second ) // a point of MP was found outside P
{
- relate::set<exterior, interior, '0', Transpose>(result);
+ update<exterior, interior, '0', Transpose>(result);
}
}
else
{
- relate::set<interior, exterior, '0', Transpose>(result);
- relate::set<exterior, interior, '0', Transpose>(result);
+ update<interior, exterior, '0', Transpose>(result);
+ update<exterior, interior, '0', Transpose>(result);
}
- relate::set<exterior, exterior, result_dimension<Point>::value, Transpose>(result);
+ update<exterior, exterior, result_dimension<Point>::value, Transpose>(result);
}
};
@@ -148,8 +154,6 @@ struct multipoint_multipoint
Result & result,
Strategy const& /*strategy*/)
{
- typedef typename Strategy::cs_tag cs_tag;
-
{
// TODO: throw on empty input?
bool empty1 = boost::empty(multi_point1);
@@ -160,12 +164,12 @@ struct multipoint_multipoint
}
else if ( empty1 )
{
- relate::set<exterior, interior, '0'>(result);
+ update<exterior, interior, '0'>(result);
return;
}
else if ( empty2 )
{
- relate::set<interior, exterior, '0'>(result);
+ update<interior, exterior, '0'>(result);
return;
}
}
@@ -173,17 +177,17 @@ struct multipoint_multipoint
// The geometry containing smaller number of points will be analysed first
if ( boost::size(multi_point1) < boost::size(multi_point2) )
{
- search_both<false, cs_tag>(multi_point1, multi_point2, result);
+ search_both<false, Strategy>(multi_point1, multi_point2, result);
}
else
{
- search_both<true, cs_tag>(multi_point2, multi_point1, result);
+ search_both<true, Strategy>(multi_point2, multi_point1, result);
}
- relate::set<exterior, exterior, result_dimension<MultiPoint1>::value>(result);
+ update<exterior, exterior, result_dimension<MultiPoint1>::value>(result);
}
- template <bool Transpose, typename CSTag, typename MPt1, typename MPt2, typename Result>
+ template <bool Transpose, typename Strategy, typename MPt1, typename MPt2, typename Result>
static inline void search_both(MPt1 const& first_sorted_mpt, MPt2 const& first_iterated_mpt,
Result & result)
{
@@ -192,7 +196,7 @@ struct multipoint_multipoint
|| relate::may_update<exterior, interior, '0'>(result) )
{
// NlogN + MlogN
- bool is_disjoint = search<Transpose, CSTag>(first_sorted_mpt, first_iterated_mpt, result);
+ bool is_disjoint = search<Transpose, Strategy>(first_sorted_mpt, first_iterated_mpt, result);
if ( BOOST_GEOMETRY_CONDITION(is_disjoint || result.interrupt) )
return;
@@ -203,12 +207,12 @@ struct multipoint_multipoint
|| relate::may_update<exterior, interior, '0'>(result) )
{
// MlogM + NlogM
- search<! Transpose, CSTag>(first_iterated_mpt, first_sorted_mpt, result);
+ search<! Transpose, Strategy>(first_iterated_mpt, first_sorted_mpt, result);
}
}
template <bool Transpose,
- typename CSTag,
+ typename Strategy,
typename SortedMultiPoint,
typename IteratedMultiPoint,
typename Result>
@@ -218,7 +222,7 @@ struct multipoint_multipoint
{
// sort points from the 1 MPt
typedef typename geometry::point_type<SortedMultiPoint>::type point_type;
- typedef geometry::less<void, -1, CSTag> less_type;
+ typedef geometry::less<void, -1, Strategy> less_type;
std::vector<point_type> points(boost::begin(sorted_mpt), boost::end(sorted_mpt));
@@ -229,19 +233,22 @@ struct multipoint_multipoint
bool found_outside = false;
// for each point in the second MPt
- typedef typename boost::range_iterator<IteratedMultiPoint const>::type iterator;
- for ( iterator it = boost::begin(iterated_mpt) ;
- it != boost::end(iterated_mpt) ; ++it )
+ for (auto it = boost::begin(iterated_mpt); it != boost::end(iterated_mpt); ++it)
{
- bool ii =
- std::binary_search(points.begin(), points.end(), *it, less);
- if ( ii )
+ bool ii = std::binary_search(points.begin(), points.end(), *it, less);
+ if (ii)
+ {
found_inside = true;
+ }
else
+ {
found_outside = true;
+ }
- if ( found_inside && found_outside )
+ if (found_inside && found_outside)
+ {
break;
+ }
}
if ( found_inside ) // some point of MP2 is equal to some of MP1
@@ -249,17 +256,17 @@ struct multipoint_multipoint
// TODO: if I/I is set for one MPt, this won't be changed when the other one in analysed
// so if e.g. only I/I must be analysed we musn't check the other MPt
- relate::set<interior, interior, '0', Transpose>(result);
+ update<interior, interior, '0', Transpose>(result);
if ( found_outside ) // some point of MP2 was found outside of MP1
{
- relate::set<exterior, interior, '0', Transpose>(result);
+ update<exterior, interior, '0', Transpose>(result);
}
}
else
{
- relate::set<interior, exterior, '0', Transpose>(result);
- relate::set<exterior, interior, '0', Transpose>(result);
+ update<interior, exterior, '0', Transpose>(result);
+ update<exterior, interior, '0', Transpose>(result);
}
// if no point is intersecting the other MPt then we musn't analyse the reversed case
diff --git a/boost/geometry/algorithms/detail/relate/result.hpp b/boost/geometry/algorithms/detail/relate/result.hpp
index c7a83665bd..84c342e636 100644
--- a/boost/geometry/algorithms/detail/relate/result.hpp
+++ b/boost/geometry/algorithms/detail/relate/result.hpp
@@ -1,11 +1,10 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates.
+// Copyright (c) 2017-2023 Adam Wulkiewicz, Lodz, Poland.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -19,10 +18,10 @@
#include <cstddef>
#include <cstring>
#include <string>
+#include <tuple>
#include <type_traits>
#include <boost/throw_exception.hpp>
-#include <boost/tuple/tuple.hpp>
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
@@ -44,6 +43,13 @@ enum field { interior = 0, boundary = 1, exterior = 2 };
// but for safety reasons (STATIC_ASSERT) we should check if parameter D is valid and set() doesn't do that
// so some additional function could be added, e.g. set_dim()
+
+template <typename MatrixOrMask, field F1, field F2>
+using fields_in_bounds = util::bool_constant
+ <
+ (F1 < MatrixOrMask::static_height && F2 < MatrixOrMask::static_width)
+ >;
+
// --------------- MATRIX ----------------
// matrix
@@ -60,25 +66,31 @@ public:
static const std::size_t static_width = Width;
static const std::size_t static_height = Height;
static const std::size_t static_size = Width * Height;
-
+
inline matrix()
{
- ::memset(m_array, 'F', static_size);
+ std::fill_n(m_array, static_size, 'F');
}
- template <field F1, field F2>
+ template
+ <
+ field F1, field F2,
+ std::enable_if_t<fields_in_bounds<matrix, F1, F2>::value, int> = 0
+ >
inline char get() const
{
- BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);
static const std::size_t index = F1 * Width + F2;
BOOST_STATIC_ASSERT(index < static_size);
return m_array[index];
}
- template <field F1, field F2, char V>
+ template
+ <
+ field F1, field F2, char V,
+ std::enable_if_t<fields_in_bounds<matrix, F1, F2>::value, int> = 0
+ >
inline void set()
{
- BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);
static const std::size_t index = F1 * Width + F2;
BOOST_STATIC_ASSERT(index < static_size);
m_array[index] = V;
@@ -104,7 +116,7 @@ public:
{
return static_size;
}
-
+
inline const char * data() const
{
return m_array;
@@ -151,56 +163,36 @@ public:
inline bool may_update() const
{
BOOST_STATIC_ASSERT('0' <= D && D <= '9');
-
char const c = m_matrix.template get<F1, F2>();
return D > c || c > '9';
}
template <field F1, field F2, char V>
- inline void set()
- {
- static const bool in_bounds = F1 < Matrix::static_height
- && F2 < Matrix::static_width;
- typedef std::integral_constant<bool, in_bounds> in_bounds_t;
- set_dispatch<F1, F2, V>(in_bounds_t());
- }
-
- template <field F1, field F2, char D>
inline void update()
{
- static const bool in_bounds = F1 < Matrix::static_height
- && F2 < Matrix::static_width;
- typedef std::integral_constant<bool, in_bounds> in_bounds_t;
- update_dispatch<F1, F2, D>(in_bounds_t());
+ BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T');
+ char const c = m_matrix.template get<F1, F2>();
+ // If c == T and V == T it will be set anyway but that's fine
+ if (V > c || c > '9')
+ {
+ m_matrix.template set<F1, F2, V>();
+ }
}
-private:
template <field F1, field F2, char V>
- inline void set_dispatch(std::true_type)
+ inline void set()
{
- static const std::size_t index = F1 * Matrix::static_width + F2;
- BOOST_STATIC_ASSERT(index < Matrix::static_size);
- BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T' || V == 'F');
+ BOOST_STATIC_ASSERT(('0' <= V && V <= '9') || V == 'T');
m_matrix.template set<F1, F2, V>();
}
- template <field F1, field F2, char V>
- inline void set_dispatch(std::false_type)
- {}
- template <field F1, field F2, char D>
- inline void update_dispatch(std::true_type)
+ template <field F1, field F2>
+ inline char get() const
{
- static const std::size_t index = F1 * Matrix::static_width + F2;
- BOOST_STATIC_ASSERT(index < Matrix::static_size);
- BOOST_STATIC_ASSERT('0' <= D && D <= '9');
- char const c = m_matrix.template get<F1, F2>();
- if ( D > c || c > '9')
- m_matrix.template set<F1, F2, D>();
+ return m_matrix.template get<F1, F2>();
}
- template <field F1, field F2, char D>
- inline void update_dispatch(std::false_type)
- {}
+private:
Matrix m_matrix;
};
@@ -228,7 +220,7 @@ public:
}
if ( it != last )
{
- ::memset(it, '*', last - it);
+ std::fill(it, last, '*');
}
}
@@ -241,18 +233,21 @@ public:
if ( count > 0 )
{
std::for_each(s, s + count, check_char);
- ::memcpy(m_array, s, count);
+ std::copy_n(s, count, m_array);
}
if ( count < static_size )
{
- ::memset(m_array + count, '*', static_size - count);
+ std::fill_n(m_array + count, static_size - count, '*');
}
}
- template <field F1, field F2>
+ template
+ <
+ field F1, field F2,
+ std::enable_if_t<fields_in_bounds<mask, F1, F2>::value, int> = 0
+ >
inline char get() const
{
- BOOST_STATIC_ASSERT(F1 < Height && F2 < Width);
static const std::size_t index = F1 * Width + F2;
BOOST_STATIC_ASSERT(index < static_size);
return m_array[index];
@@ -362,7 +357,7 @@ struct may_update_dispatch
BOOST_STATIC_ASSERT('0' <= D && D <= '9');
char const m = mask.template get<F1, F2>();
-
+
if ( m == 'F' )
{
return true;
@@ -575,37 +570,41 @@ public:
template <field F1, field F2, char D>
inline bool may_update() const
{
- return detail::relate::may_update<F1, F2, D>(
- m_mask, base_t::matrix()
- );
+ return detail::relate::may_update<F1, F2, D>(m_mask, base_t::matrix());
}
template <field F1, field F2, char V>
- inline void set()
+ inline void update()
{
- if ( relate::interrupt<F1, F2, V, Interrupt>(m_mask) )
+ if (relate::interrupt<F1, F2, V, Interrupt>(m_mask))
{
interrupt = true;
}
else
{
- base_t::template set<F1, F2, V>();
+ base_t::template update<F1, F2, V>();
}
}
template <field F1, field F2, char V>
- inline void update()
+ inline void set()
{
- if ( relate::interrupt<F1, F2, V, Interrupt>(m_mask) )
+ if (relate::interrupt<F1, F2, V, Interrupt>(m_mask))
{
interrupt = true;
}
else
{
- base_t::template update<F1, F2, V>();
+ base_t::template set<F1, F2, V>();
}
}
+ template <field F1, field F2>
+ inline char get() const
+ {
+ return base_t::template get<F1, F2>();
+ }
+
private:
Mask const& m_mask;
};
@@ -647,7 +646,7 @@ struct static_mask
BOOST_STATIC_ASSERT(
std::size_t(util::sequence_size<Seq>::value) == static_size);
-
+
template <detail::relate::field F1, detail::relate::field F2>
struct static_get
{
@@ -744,7 +743,7 @@ struct static_interrupt_dispatch<StaticMask, V, F1, F2, true, IsSequence>
static const char mask_el = StaticMask::template static_get<F1, F2>::value;
static const bool value
- = ( V >= '0' && V <= '9' ) ?
+ = ( V >= '0' && V <= '9' ) ?
( mask_el == 'F' || ( mask_el < V && mask_el >= '0' && mask_el <= '9' ) ) :
( ( V == 'T' ) ? mask_el == 'F' : false );
};
@@ -930,7 +929,7 @@ struct static_check_dispatch
&& per_one<exterior, boundary>::apply(matrix)
&& per_one<exterior, exterior>::apply(matrix);
}
-
+
template <field F1, field F2>
struct per_one
{
@@ -1067,24 +1066,6 @@ public:
apply(base_type::matrix());
}
- template <field F1, field F2>
- static inline bool expects()
- {
- return static_should_handle_element<StaticMask, F1, F2>::value;
- }
-
- template <field F1, field F2, char V>
- inline void set()
- {
- static const bool interrupt_c = static_interrupt<StaticMask, V, F1, F2, Interrupt>::value;
- static const bool should_handle = static_should_handle_element<StaticMask, F1, F2>::value;
- static const int version = interrupt_c ? 0
- : should_handle ? 1
- : 2;
-
- set_dispatch<F1, F2, V>(integral_constant<int, version>());
- }
-
template <field F1, field F2, char V>
inline void update()
{
@@ -1097,24 +1078,33 @@ public:
update_dispatch<F1, F2, V>(integral_constant<int, version>());
}
-private:
- // Interrupt && interrupt
- template <field F1, field F2, char V>
- inline void set_dispatch(integral_constant<int, 0>)
+ template
+ <
+ field F1, field F2, char V,
+ std::enable_if_t<static_interrupt<StaticMask, V, F1, F2, Interrupt>::value, int> = 0
+ >
+ inline void set()
{
interrupt = true;
}
- // else should_handle
- template <field F1, field F2, char V>
- inline void set_dispatch(integral_constant<int, 1>)
+
+ template
+ <
+ field F1, field F2, char V,
+ std::enable_if_t<! static_interrupt<StaticMask, V, F1, F2, Interrupt>::value, int> = 0
+ >
+ inline void set()
{
base_type::template set<F1, F2, V>();
}
- // else
- template <field F1, field F2, char V>
- inline void set_dispatch(integral_constant<int, 2>)
- {}
+ template <field F1, field F2>
+ inline char get() const
+ {
+ return base_type::template get<F1, F2>();
+ }
+
+private:
// Interrupt && interrupt
template <field F1, field F2, char V>
inline void update_dispatch(integral_constant<int, 0>)
@@ -1135,40 +1125,6 @@ private:
// --------------- UTIL FUNCTIONS ----------------
-// set
-
-template <field F1, field F2, char V, typename Result>
-inline void set(Result & res)
-{
- res.template set<F1, F2, V>();
-}
-
-template <field F1, field F2, char V, bool Transpose>
-struct set_dispatch
-{
- template <typename Result>
- static inline void apply(Result & res)
- {
- res.template set<F1, F2, V>();
- }
-};
-
-template <field F1, field F2, char V>
-struct set_dispatch<F1, F2, V, true>
-{
- template <typename Result>
- static inline void apply(Result & res)
- {
- res.template set<F2, F1, V>();
- }
-};
-
-template <field F1, field F2, char V, bool Transpose, typename Result>
-inline void set(Result & res)
-{
- set_dispatch<F1, F2, V, Transpose>::apply(res);
-}
-
// update
template <field F1, field F2, char D, typename Result>
@@ -1177,30 +1133,24 @@ inline void update(Result & res)
res.template update<F1, F2, D>();
}
-template <field F1, field F2, char D, bool Transpose>
-struct update_result_dispatch
-{
- template <typename Result>
- static inline void apply(Result & res)
- {
- update<F1, F2, D>(res);
- }
-};
-
-template <field F1, field F2, char D>
-struct update_result_dispatch<F1, F2, D, true>
+template
+<
+ field F1, field F2, char D, bool Transpose, typename Result,
+ std::enable_if_t<! Transpose, int> = 0
+>
+inline void update(Result & res)
{
- template <typename Result>
- static inline void apply(Result & res)
- {
- update<F2, F1, D>(res);
- }
-};
+ res.template update<F1, F2, D>();
+}
-template <field F1, field F2, char D, bool Transpose, typename Result>
+template
+<
+ field F1, field F2, char D, bool Transpose, typename Result,
+ std::enable_if_t<Transpose, int> = 0
+>
inline void update(Result & res)
{
- update_result_dispatch<F1, F2, D, Transpose>::apply(res);
+ res.template update<F2, F1, D>();
}
// may_update
@@ -1211,30 +1161,24 @@ inline bool may_update(Result const& res)
return res.template may_update<F1, F2, D>();
}
-template <field F1, field F2, char D, bool Transpose>
-struct may_update_result_dispatch
-{
- template <typename Result>
- static inline bool apply(Result const& res)
- {
- return may_update<F1, F2, D>(res);
- }
-};
-
-template <field F1, field F2, char D>
-struct may_update_result_dispatch<F1, F2, D, true>
+template
+<
+ field F1, field F2, char D, bool Transpose, typename Result,
+ std::enable_if_t<! Transpose, int> = 0
+>
+inline bool may_update(Result const& res)
{
- template <typename Result>
- static inline bool apply(Result const& res)
- {
- return may_update<F2, F1, D>(res);
- }
-};
+ return res.template may_update<F1, F2, D>();
+}
-template <field F1, field F2, char D, bool Transpose, typename Result>
+template
+<
+ field F1, field F2, char D, bool Transpose, typename Result,
+ std::enable_if_t<Transpose, int> = 0
+>
inline bool may_update(Result const& res)
{
- return may_update_result_dispatch<F1, F2, D, Transpose>::apply(res);
+ return res.template may_update<F2, F1, D>();
}
// result_dimension
@@ -1242,11 +1186,9 @@ inline bool may_update(Result const& res)
template <typename Geometry>
struct result_dimension
{
- BOOST_STATIC_ASSERT(geometry::dimension<Geometry>::value >= 0);
- static const char value
- = ( geometry::dimension<Geometry>::value <= 9 ) ?
- ( '0' + geometry::dimension<Geometry>::value ) :
- 'T';
+ static const std::size_t dim = geometry::dimension<Geometry>::value;
+ BOOST_STATIC_ASSERT(dim >= 0);
+ static const char value = (dim <= 9) ? ('0' + dim) : 'T';
};
}} // namespace detail::relate
diff --git a/boost/geometry/algorithms/detail/relate/topology_check.hpp b/boost/geometry/algorithms/detail/relate/topology_check.hpp
index 459c816143..2fc31ab51b 100644
--- a/boost/geometry/algorithms/detail/relate/topology_check.hpp
+++ b/boost/geometry/algorithms/detail/relate/topology_check.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -170,22 +171,22 @@ struct topology_check<MultiLinestring, Strategy, multi_linestring_tag>
}
private:
- typedef geometry::less<void, -1, typename Strategy::cs_tag> less_type;
+ typedef geometry::less<void, -1, Strategy> less_type;
void init() const
{
if (m_is_initialized)
+ {
return;
+ }
m_endpoints.reserve(boost::size(m_mls) * 2);
m_has_interior = false;
- typedef typename boost::range_iterator<MultiLinestring const>::type ls_iterator;
- for ( ls_iterator it = boost::begin(m_mls) ; it != boost::end(m_mls) ; ++it )
+ for (auto it = boost::begin(m_mls); it != boost::end(m_mls); ++it)
{
- typename boost::range_reference<MultiLinestring const>::type
- ls = *it;
+ auto const& ls = *it;
std::size_t count = boost::size(ls);
@@ -196,13 +197,8 @@ private:
if (count > 1)
{
- typedef typename boost::range_reference
- <
- typename boost::range_value<MultiLinestring const>::type const
- >::type point_reference;
-
- point_reference front_pt = range::front(ls);
- point_reference back_pt = range::back(ls);
+ auto const& front_pt = range::front(ls);
+ auto const& back_pt = range::back(ls);
// don't store boundaries of linear rings, this doesn't change anything
if (! equals::equals_point_point(front_pt, back_pt, m_strategy))
@@ -226,7 +222,7 @@ private:
m_has_boundary = false;
- if (! m_endpoints.empty() )
+ if (! m_endpoints.empty())
{
std::sort(m_endpoints.begin(), m_endpoints.end(), less_type());
m_has_boundary = find_odd_count(m_endpoints.begin(), m_endpoints.end());
@@ -341,7 +337,7 @@ struct topology_check<MultiPolygon, Strategy, multi_polygon_tag>
: topology_check_areal
{
topology_check(MultiPolygon const&, Strategy const&) {}
-
+
template <typename Point>
static bool check_boundary_point(Point const& ) { return true; }
};
diff --git a/boost/geometry/algorithms/detail/relate/turns.hpp b/boost/geometry/algorithms/detail/relate/turns.hpp
index 7d82887300..d98794e78a 100644
--- a/boost/geometry/algorithms/detail/relate/turns.hpp
+++ b/boost/geometry/algorithms/detail/relate/turns.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -20,6 +20,8 @@
#include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
#include <boost/geometry/algorithms/detail/overlay/get_turn_info.hpp>
+#include <boost/geometry/geometries/helper_geometry.hpp>
+
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/policies/robustness/segment_ratio_type.hpp>
@@ -40,7 +42,7 @@ struct assign_policy
static bool const include_degenerate = IncludeDegenerate;
};
-// GET_TURNS
+// turn retriever, calling get_turns
template
<
@@ -53,7 +55,10 @@ template
>
struct get_turns
{
- typedef typename geometry::point_type<Geometry1>::type point1_type;
+ using turn_point_type = typename helper_geometry
+ <
+ typename geometry::point_type<Geometry1>::type
+ >::type;
template <typename Strategy>
struct robust_policy_type
@@ -72,16 +77,16 @@ struct get_turns
>
struct turn_info_type
{
- typedef typename segment_ratio_type<point1_type, RobustPolicy>::type ratio_type;
- typedef overlay::turn_info
+ using ratio_type = typename segment_ratio_type<turn_point_type, RobustPolicy>::type;
+ using type = overlay::turn_info
<
- point1_type,
+ turn_point_type,
ratio_type,
typename detail::get_turns::turn_operation_type
<
- Geometry1, Geometry2, ratio_type
+ Geometry1, Geometry2, turn_point_type, ratio_type
>::type
- > type;
+ >;
};
template <typename Turns, typename InterruptPolicy, typename Strategy>
@@ -167,7 +172,7 @@ struct less_op_xxx_linear
template <std::size_t OpId>
struct less_op_linear_linear
- : less_op_xxx_linear< OpId, op_to_int<0,2,3,1,4,0> >
+ : less_op_xxx_linear< OpId, op_to_int<0,2,3,1,4,0> > // xuic
{};
template <std::size_t OpId>
@@ -244,7 +249,7 @@ struct less_op_areal_areal
else if ( right_operation.operation == overlay::operation_intersection )
return false;
}
-
+
return op_to_int_iuxc(left_operation) < op_to_int_iuxc(right_operation);
}
}
@@ -270,7 +275,7 @@ struct less_other_multi_index
// sort turns by G1 - source_index == 0 by:
// seg_id -> distance and coordinates -> operation
-template <std::size_t OpId, typename LessOp, typename CSTag>
+template <std::size_t OpId, typename LessOp, typename Strategy>
struct less
{
BOOST_STATIC_ASSERT(OpId < 2);
@@ -278,14 +283,8 @@ struct less
template <typename Turn>
static inline bool use_fraction(Turn const& left, Turn const& right)
{
- typedef typename geometry::strategy::within::services::default_strategy
- <
- typename Turn::point_type, typename Turn::point_type,
- point_tag, point_tag,
- pointlike_tag, pointlike_tag,
- typename tag_cast<CSTag, spherical_tag>::type,
- typename tag_cast<CSTag, spherical_tag>::type
- >::type eq_pp_strategy_type;
+ using eq_pp_strategy_type = decltype(std::declval<Strategy>().relate(
+ detail::dummy_point(), detail::dummy_point()));
static LessOp less_op;
diff --git a/boost/geometry/algorithms/detail/relation/interface.hpp b/boost/geometry/algorithms/detail/relation/interface.hpp
index e9d940c3e9..4c3616ab42 100644
--- a/boost/geometry/algorithms/detail/relation/interface.hpp
+++ b/boost/geometry/algorithms/detail/relation/interface.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -35,10 +35,15 @@ struct result_handler_type<Geometry1, Geometry2, geometry::de9im::matrix>
}} // namespace detail::relate
#endif // DOXYGEN_NO_DETAIL
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry1, typename Geometry2>
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct relation
{
template <typename Matrix, typename Strategy>
@@ -66,105 +71,70 @@ struct relation
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct relation<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct relation<Geometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Matrix, typename Strategy>
- struct visitor : boost::static_visitor<Matrix>
+ static inline Matrix apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Strategy const& strategy)
- : m_geometry2(geometry2), m_strategy(strategy) {}
-
- template <typename Geometry1>
- Matrix operator()(Geometry1 const& geometry1) const
+ Matrix result;
+ traits::visit<Geometry1>::apply([&](auto const& g1)
{
- return relation<Geometry1, Geometry2>
- ::template apply<Matrix>(geometry1, m_geometry2, m_strategy);
- }
- };
-
- template <typename Matrix, typename Strategy>
- static inline Matrix
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Matrix, Strategy>(geometry2, strategy), geometry1);
+ result = relation
+ <
+ util::remove_cref_t<decltype(g1)>,
+ Geometry2
+ >::template apply<Matrix>(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct relation<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct relation<Geometry1, Geometry2, Tag1, dynamic_geometry_tag>
{
template <typename Matrix, typename Strategy>
- struct visitor : boost::static_visitor<Matrix>
+ static inline Matrix apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Strategy const& strategy)
- : m_geometry1(geometry1), m_strategy(strategy) {}
-
- template <typename Geometry2>
- Matrix operator()(Geometry2 const& geometry2) const
+ Matrix result;
+ traits::visit<Geometry2>::apply([&](auto const& g2)
{
- return relation<Geometry1, Geometry2>
- ::template apply<Matrix>(m_geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Matrix, typename Strategy>
- static inline Matrix
- apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Matrix, Strategy>(geometry1, strategy), geometry2);
+ result = relation
+ <
+ Geometry1,
+ util::remove_cref_t<decltype(g2)>
+ >::template apply<Matrix>(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
}
};
-template
-<
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
-struct relation
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
- >
+template <typename Geometry1, typename Geometry2>
+struct relation<Geometry1, Geometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Matrix, typename Strategy>
- struct visitor : boost::static_visitor<Matrix>
+ static inline Matrix apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy)
- : m_strategy(strategy) {}
-
- template <typename Geometry1, typename Geometry2>
- Matrix operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ Matrix result;
+ traits::visit<Geometry1, Geometry2>::apply([&](auto const& g1, auto const& g2)
{
- return relation<Geometry1, Geometry2>
- ::template apply<Matrix>(geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Matrix, typename Strategy>
- static inline Matrix
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Matrix, Strategy>(strategy), geometry1, geometry2);
+ result = relation
+ <
+ util::remove_cref_t<decltype(g1)>,
+ util::remove_cref_t<decltype(g2)>
+ >::template apply<Matrix>(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -186,7 +156,7 @@ inline de9im::matrix relation(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
- return resolve_variant::relation
+ return resolve_dynamic::relation
<
Geometry1,
Geometry2
@@ -209,7 +179,7 @@ template <typename Geometry1, typename Geometry2>
inline de9im::matrix relation(Geometry1 const& geometry1,
Geometry2 const& geometry2)
{
- return resolve_variant::relation
+ return resolve_dynamic::relation
<
Geometry1,
Geometry2
diff --git a/boost/geometry/algorithms/detail/sections/section_functions.hpp b/boost/geometry/algorithms/detail/sections/section_functions.hpp
index abc6de409c..df4f31025a 100644
--- a/boost/geometry/algorithms/detail/sections/section_functions.hpp
+++ b/boost/geometry/algorithms/detail/sections/section_functions.hpp
@@ -70,7 +70,7 @@ struct preceding_check<0, Geometry, spherical_tag>
calc_t const value = get<0>(point);
calc_t const other_min = get<min_corner, 0>(other_box);
calc_t const other_max = get<max_corner, 0>(other_box);
-
+
bool const pt_covered = strategy::within::detail::covered_by_range
<
Point, 0, spherical_tag
@@ -124,13 +124,14 @@ template
typename Box,
typename RobustPolicy
>
-static inline bool preceding(int dir,
- Point const& point,
- Box const& point_box,
- Box const& other_box,
- RobustPolicy const& robust_policy)
+inline bool preceding(int dir,
+ Point const& point,
+ Box const& point_box,
+ Box const& other_box,
+ RobustPolicy const& robust_policy)
{
- typename geometry::robust_point_type<Point, RobustPolicy>::type robust_point;
+ using box_point_type = typename geometry::point_type<Box>::type;
+ typename geometry::robust_point_type<box_point_type, RobustPolicy>::type robust_point;
geometry::recalculate(robust_point, point, robust_policy);
// After recalculate() to prevent warning: 'robust_point' may be used uninitialized
@@ -148,11 +149,11 @@ template
typename Box,
typename RobustPolicy
>
-static inline bool exceeding(int dir,
- Point const& point,
- Box const& point_box,
- Box const& other_box,
- RobustPolicy const& robust_policy)
+inline bool exceeding(int dir,
+ Point const& point,
+ Box const& point_box,
+ Box const& other_box,
+ RobustPolicy const& robust_policy)
{
return preceding<Dimension>(-dir, point, point_box, other_box, robust_policy);
}
diff --git a/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/boost/geometry/algorithms/detail/sections/sectionalize.hpp
index e98536e3fd..3317ff70a9 100644
--- a/boost/geometry/algorithms/detail/sections/sectionalize.hpp
+++ b/boost/geometry/algorithms/detail/sections/sectionalize.hpp
@@ -38,11 +38,9 @@
#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/algorithms/expand.hpp>
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/recalculate.hpp>
#include <boost/geometry/algorithms/detail/ring_identifier.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
-#include <boost/geometry/algorithms/detail/buffer/buffer_box.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/closure.hpp>
@@ -87,7 +85,7 @@ template
>
struct section
{
- typedef Box box_type;
+ using box_type = Box;
static std::size_t const dimension_count = DimensionCount;
int directions[DimensionCount];
@@ -134,7 +132,7 @@ struct section
template <typename Box, std::size_t DimensionCount>
struct sections : std::vector<section<Box, DimensionCount> >
{
- typedef Box box_type;
+ using box_type = Box;
static std::size_t const value = DimensionCount;
};
@@ -161,16 +159,14 @@ template
>
struct get_direction_loop
{
- typedef typename util::sequence_element<Index, DimensionVector>::type dimension;
+ using dimension = typename util::sequence_element<Index, DimensionVector>::type;
template <typename Segment>
static inline void apply(Segment const& seg,
int directions[Count])
{
- typedef typename coordinate_type<Segment>::type coordinate_type;
-
- coordinate_type const c0 = geometry::get<0, dimension::value>(seg);
- coordinate_type const c1 = geometry::get<1, dimension::value>(seg);
+ auto const& c0 = geometry::get<0, dimension::value>(seg);
+ auto const& c1 = geometry::get<1, dimension::value>(seg);
directions[Index] = c1 > c0 ? 1 : c1 < c0 ? -1 : 0;
@@ -193,14 +189,14 @@ template
>
struct get_direction_loop<Point, DimensionVector, 0, Count, spherical_tag>
{
- typedef typename util::sequence_element<0, DimensionVector>::type dimension;
+ using dimension = typename util::sequence_element<0, DimensionVector>::type;
template <typename Segment>
static inline void apply(Segment const& seg,
int directions[Count])
{
- typedef typename coordinate_type<Segment>::type coordinate_type;
- typedef typename coordinate_system<Point>::type::units units_t;
+ using coordinate_type = typename coordinate_type<Segment>::type;
+ using units_t = typename coordinate_system<Point>::type::units;
coordinate_type const diff = math::longitude_distance_signed
<
@@ -381,11 +377,7 @@ struct box_next_in_section<cartesian_tag>
};
/// @brief Helper class to create sections of a part of a range, on the fly
-template
-<
- typename Point,
- typename DimensionVector
->
+template<typename DimensionVector>
struct sectionalize_part
{
static const std::size_t dimension_count
@@ -407,18 +399,21 @@ struct sectionalize_part
{
boost::ignore_unused(robust_policy);
- typedef typename boost::range_value<Sections>::type section_type;
+ using section_type = typename boost::range_value<Sections>::type;
+ using box_type = typename section_type::box_type;
+ using point_type = typename geometry::point_type<box_type>::type;
+
BOOST_STATIC_ASSERT
(
section_type::dimension_count
== util::sequence_size<DimensionVector>::value
);
- typedef typename geometry::robust_point_type
+ using robust_point_type = typename geometry::robust_point_type
<
- Point,
+ point_type,
RobustPolicy
- >::type robust_point_type;
+ >::type;
std::size_t const count = std::distance(begin, end);
if (count == 0)
@@ -436,7 +431,7 @@ struct sectionalize_part
Iterator it = begin;
robust_point_type previous_robust_point;
geometry::recalculate(previous_robust_point, *it, robust_policy);
-
+
for(Iterator previous = it++;
it != end;
++previous, ++it, index++)
@@ -449,7 +444,7 @@ struct sectionalize_part
int direction_classes[dimension_count] = {0};
get_direction_loop
<
- Point, DimensionVector, 0, dimension_count
+ point_type, DimensionVector, 0, dimension_count
>::apply(robust_segment, direction_classes);
// if "dir" == 0 for all point-dimensions, it is duplicate.
@@ -463,7 +458,7 @@ struct sectionalize_part
// (dimension_count might be < dimension<P>::value)
if (check_duplicate_loop
<
- 0, geometry::dimension<Point>::type::value
+ 0, geometry::dimension<point_type>::type::value
>::apply(robust_segment)
)
{
@@ -562,7 +557,6 @@ template
<
closure_selector Closure,
bool Reverse,
- typename Point,
typename DimensionVector
>
struct sectionalize_range
@@ -601,7 +595,7 @@ struct sectionalize_range
return;
}
- sectionalize_part<Point, DimensionVector>::apply(sections,
+ sectionalize_part<DimensionVector>::apply(sections,
boost::begin(view), boost::end(view),
robust_policy, strategy,
ring_id, max_count);
@@ -629,23 +623,21 @@ struct sectionalize_polygon
ring_identifier ring_id,
std::size_t max_count)
{
- typedef typename point_type<Polygon>::type point_type;
- typedef sectionalize_range
+ using sectionalizer = sectionalize_range
<
- closure<Polygon>::value, Reverse, point_type, DimensionVector
- > per_range;
+ closure<Polygon>::value, Reverse, DimensionVector
+ >;
ring_id.ring_index = -1;
- per_range::apply(exterior_ring(poly), robust_policy, sections,
+ sectionalizer::apply(exterior_ring(poly), robust_policy, sections,
strategy, ring_id, max_count);
ring_id.ring_index++;
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(poly);
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it, ++ring_id.ring_index)
+ auto const& rings = interior_rings(poly);
+ for (auto it = boost::begin(rings); it != boost::end(rings);
+ ++it, ++ring_id.ring_index)
{
- per_range::apply(*it, robust_policy, sections,
+ sectionalizer::apply(*it, robust_policy, sections,
strategy, ring_id, max_count);
}
}
@@ -667,7 +659,7 @@ struct sectionalize_box
Strategy const& strategy,
ring_identifier const& ring_id, std::size_t max_count)
{
- typedef typename point_type<Box>::type point_type;
+ using point_type = typename point_type<Box>::type;
assert_dimension<Box, 2>();
@@ -693,7 +685,7 @@ struct sectionalize_box
// because edges of a box are not geodesic segments
sectionalize_range
<
- closed, false, point_type, DimensionVector
+ closed, false, DimensionVector
>::apply(points, robust_policy, sections,
strategy, ring_id, max_count);
}
@@ -717,10 +709,7 @@ struct sectionalize_multi
std::size_t max_count)
{
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)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it, ++ring_id.multi_index)
{
Policy::apply(*it, robust_policy, sections,
strategy,
@@ -729,77 +718,28 @@ struct sectionalize_multi
}
};
-// TODO: If it depends on CS it should probably be made into strategy.
-// For now implemented here because of ongoing work on robustness
-// the fact that it interferes with detail::buffer::buffer_box
-// and that we probably need a general strategy for defining epsilon in
-// various coordinate systems, e.g. for point comparison, enlargement of
-// bounding boxes, etc.
-template <typename CSTag>
-struct expand_by_epsilon
- : not_implemented<CSTag>
-{};
-
-template <>
-struct expand_by_epsilon<cartesian_tag>
-{
- template <typename Box>
- static inline void apply(Box & box)
- {
- detail::expand_by_epsilon(box);
- }
-};
-
-template <>
-struct expand_by_epsilon<spherical_tag>
-{
- template <typename Box>
- static inline void apply(Box & box)
- {
- typedef typename coordinate_type<Box>::type coord_t;
- static const coord_t eps = std::is_same<coord_t, float>::value
- ? coord_t(1e-6)
- : coord_t(1e-12);
- detail::expand_by_epsilon(box, eps);
- }
-};
-
-// TODO: In geographic CS it should probably also depend on FormulaPolicy.
-template <>
-struct expand_by_epsilon<geographic_tag>
- : expand_by_epsilon<spherical_tag>
-{};
-
template <typename Sections, typename Strategy>
inline void enlarge_sections(Sections& sections, Strategy const&)
{
- // Enlarge sections slightly, this should be consistent with math::equals()
- // and with the tolerances used in general_form intersections.
- // This avoids missing turns.
-
- // Points and Segments are equal-compared WRT machine epsilon, but Boxes aren't
- // Enlarging Boxes ensures that they correspond to the bound objects,
- // Segments in this case, since Sections are collections of Segments.
-
- // It makes section a tiny bit too large, which might cause (a small number)
- // of more comparisons
- for (typename boost::range_iterator<Sections>::type it = boost::begin(sections);
- it != boost::end(sections);
- ++it)
+ // Expand the box to avoid missing any intersection. The amount is
+ // should be larger than epsilon. About the value itself: the smaller
+ // it is, the higher the risk to miss intersections. The larger it is,
+ // the more comparisons are made, which is not harmful for the result
+ // (but it might be for the performance).
+ // So it should be on the high side.
+
+ // Use a compilable and workable epsilon for all types, for example:
+ // - for double :~ 2.22e-13
+ // - for float :~ 1e-4
+ // - for Boost.Multiprecision (50) :~ 5.35e-48
+ // - for Boost.Rational : 0/1
+
+ for (auto& section : sections)
{
-#if defined(BOOST_GEOMETRY_USE_RESCALING)
- detail::sectionalize::expand_by_epsilon
- <
- typename Strategy::cs_tag
- >::apply(it->bounding_box);
-
-#else
- // Expand the box to avoid missing any intersection. The amount is
- // should be larger than epsilon. About the value itself: the smaller
- // it is, the higher the risk to miss intersections. The larger it is,
- // the more comparisons are made. So it should be on the high side.
- detail::buffer::buffer_box(it->bounding_box, 0.001, it->bounding_box);
-#endif
+ using gt = decltype(section.bounding_box);
+ using ct = typename geometry::coordinate_type<gt>::type;
+ static ct const eps = math::scaled_epsilon<ct>(1000);
+ expand_by_epsilon(section.bounding_box, eps);
}
}
@@ -848,12 +788,7 @@ struct sectionalize
false,
DimensionVector
>
- : detail::sectionalize::sectionalize_range
- <
- closed, false,
- typename point_type<LineString>::type,
- DimensionVector
- >
+ : detail::sectionalize::sectionalize_range<closed, false, DimensionVector>
{};
template
@@ -866,7 +801,6 @@ struct sectionalize<ring_tag, Ring, Reverse, DimensionVector>
: detail::sectionalize::sectionalize_range
<
geometry::closure<Ring>::value, Reverse,
- typename point_type<Ring>::type,
DimensionVector
>
{};
@@ -913,12 +847,7 @@ struct sectionalize<multi_linestring_tag, MultiLinestring, Reverse, DimensionVec
: detail::sectionalize::sectionalize_multi
<
DimensionVector,
- detail::sectionalize::sectionalize_range
- <
- closed, false,
- typename point_type<MultiLinestring>::type,
- DimensionVector
- >
+ detail::sectionalize::sectionalize_range<closed, false, DimensionVector>
>
{};
@@ -960,26 +889,6 @@ inline void sectionalize(Geometry const& geometry,
{
concepts::check<Geometry const>();
- typedef typename boost::range_value<Sections>::type section_type;
-
- // Compiletime check for point type of section boxes
- // and point type related to robust policy
- typedef typename geometry::coordinate_type
- <
- typename section_type::box_type
- >::type ctype1;
- typedef typename geometry::coordinate_type
- <
- typename geometry::robust_point_type
- <
- typename geometry::point_type<Geometry>::type,
- RobustPolicy
- >::type
- >::type ctype2;
-
- BOOST_STATIC_ASSERT((std::is_same<ctype1, ctype2>::value));
-
-
sections.clear();
ring_identifier ring_id;
@@ -1013,11 +922,12 @@ inline void sectionalize(Geometry const& geometry,
int source_index = 0,
std::size_t max_count = 10)
{
- typedef typename strategies::envelope::services::default_strategy
+ using box_type = typename Sections::box_type;
+ using strategy_type = typename strategies::envelope::services::default_strategy
<
Geometry,
- model::box<typename point_type<Geometry>::type>
- >::type strategy_type;
+ box_type
+ >::type;
boost::geometry::sectionalize
<
diff --git a/boost/geometry/algorithms/detail/select_geometry_type.hpp b/boost/geometry/algorithms/detail/select_geometry_type.hpp
index 2e94ae73e6..5592fa5c4b 100644
--- a/boost/geometry/algorithms/detail/select_geometry_type.hpp
+++ b/boost/geometry/algorithms/detail/select_geometry_type.hpp
@@ -11,6 +11,9 @@
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SELECT_GEOMETRY_TYPE_HPP
#include <boost/geometry/core/geometry_types.hpp>
+#include <boost/geometry/core/static_assert.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/util/sequence.hpp>
#include <boost/geometry/util/type_traits.hpp>
@@ -21,29 +24,33 @@ namespace boost { namespace geometry
namespace detail
{
-template
-<
- typename Geometry,
- template <typename, typename> class LessPred,
- bool IsDynamicOrCollection = util::is_dynamic_geometry<Geometry>::value
- || util::is_geometry_collection<Geometry>::value
->
-struct select_geometry_type
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct first_geometry_type
{
using type = Geometry;
};
-template
-<
- typename Geometry,
- template <typename, typename> class LessPred
->
-struct select_geometry_type<Geometry, LessPred, true>
- : util::select_element
+template <typename Geometry>
+struct first_geometry_type<Geometry, geometry_collection_tag>
+{
+ template <typename T>
+ using pred = util::bool_constant
<
- typename traits::geometry_types<std::remove_const_t<Geometry>>::type,
- LessPred
- >
+ ! util::is_dynamic_geometry<T>::value
+ && ! util::is_geometry_collection<T>::value
+ >;
+
+ using type = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Geometry>::type,
+ pred
+ >::type;
+};
+
+template <typename Geometry>
+struct first_geometry_type<Geometry, dynamic_geometry_tag>
+ : first_geometry_type<Geometry, geometry_collection_tag>
{};
@@ -67,6 +74,32 @@ struct geometry_types<Geometry, true>
template
<
+ typename Geometry,
+ template <typename, typename> class LessPred,
+ bool IsDynamicOrCollection = util::is_dynamic_geometry<Geometry>::value
+ || util::is_geometry_collection<Geometry>::value
+>
+struct select_geometry_type
+{
+ using type = Geometry;
+};
+
+template
+<
+ typename Geometry,
+ template <typename, typename> class LessPred
+>
+struct select_geometry_type<Geometry, LessPred, true>
+ : util::sequence_min_element
+ <
+ typename traits::geometry_types<std::remove_const_t<Geometry>>::type,
+ LessPred
+ >
+{};
+
+
+template
+<
typename Geometry1, typename Geometry2,
template <typename, typename> class LessPred,
bool IsDynamicOrCollection = util::is_dynamic_geometry<Geometry1>::value
@@ -89,10 +122,13 @@ template
template <typename, typename> class LessPred
>
struct select_geometry_types<Geometry1, Geometry2, LessPred, true>
- : util::select_combination_element
+ : util::sequence_min_element
<
- typename geometry_types<Geometry1>::type,
- typename geometry_types<Geometry2>::type,
+ typename util::sequence_combine
+ <
+ typename geometry_types<Geometry1>::type,
+ typename geometry_types<Geometry2>::type
+ >::type,
LessPred
>
{};
diff --git a/boost/geometry/algorithms/detail/sweep.hpp b/boost/geometry/algorithms/detail/sweep.hpp
index 3dc78261f2..a8c7f9a91a 100644
--- a/boost/geometry/algorithms/detail/sweep.hpp
+++ b/boost/geometry/algorithms/detail/sweep.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2015, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2015, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
@@ -10,6 +11,8 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SWEEP_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SWEEP_HPP
+#include <boost/geometry/util/condition.hpp>
+
#include <boost/core/ignore_unused.hpp>
@@ -56,7 +59,7 @@ inline void sweep(Range const& range, PriorityQueue& queue,
event_type event = queue.top();
queue.pop();
event_visitor.apply(event, queue);
- if (interrupt_policy.enabled && interrupt_policy.apply(event))
+ if (BOOST_GEOMETRY_CONDITION(interrupt_policy.enabled) && interrupt_policy.apply(event))
{
break;
}
diff --git a/boost/geometry/algorithms/detail/touches/implementation.hpp b/boost/geometry/algorithms/detail/touches/implementation.hpp
index b37e7bc7ea..15a899e701 100644
--- a/boost/geometry/algorithms/detail/touches/implementation.hpp
+++ b/boost/geometry/algorithms/detail/touches/implementation.hpp
@@ -3,10 +3,10 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2013-2022 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2020.
-// Modifications copyright (c) 2013-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -24,15 +24,20 @@
#include <type_traits>
#include <boost/geometry/algorithms/detail/for_each_range.hpp>
+#include <boost/geometry/algorithms/detail/gc_topological_dimension.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
#include <boost/geometry/algorithms/detail/overlay/self_turn_points.hpp>
#include <boost/geometry/algorithms/detail/sub_range.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation_gc.hpp>
#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
#include <boost/geometry/algorithms/detail/touches/interface.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/algorithms/disjoint.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
#include <boost/geometry/algorithms/num_geometries.hpp>
-#include <boost/geometry/algorithms/relate.hpp>
+
+#include <boost/geometry/geometries/helper_geometry.hpp>
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
@@ -40,6 +45,8 @@
#include <boost/geometry/strategies/relate/geographic.hpp>
#include <boost/geometry/strategies/relate/spherical.hpp>
+#include <boost/geometry/views/detail/geometry_collection_view.hpp>
+
namespace boost { namespace geometry
{
@@ -80,7 +87,7 @@ struct box_box_loop
{
touch = true;
}
-
+
return box_box_loop
<
Dimension + 1,
@@ -150,19 +157,20 @@ struct areal_interrupt_policy
inline bool apply(Range const& range)
{
// if already rejected (temp workaround?)
- if ( found_not_touch )
+ if (found_not_touch)
+ {
return true;
+ }
- typedef typename boost::range_iterator<Range const>::type iterator;
- for ( iterator it = boost::begin(range) ; it != boost::end(range) ; ++it )
+ for (auto it = boost::begin(range); it != boost::end(range); ++it)
{
- if ( it->has(overlay::operation_intersection) )
+ if (it->has(overlay::operation_intersection))
{
found_not_touch = true;
return true;
}
- switch(it->method)
+ switch (it->method)
{
case overlay::method_crosses:
found_not_touch = true;
@@ -211,7 +219,8 @@ inline bool point_on_border_within(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
- typename geometry::point_type<Geometry1>::type pt;
+ using point_type = typename geometry::point_type<Geometry1>::type;
+ typename helper_geometry<point_type>::type pt;
return geometry::point_on_border(pt, geometry1)
&& geometry::within(pt, geometry2, strategy);
}
@@ -235,17 +244,18 @@ struct areal_areal
Geometry2 const& geometry2,
Strategy const& strategy)
{
- typedef typename geometry::point_type<Geometry1>::type point_type;
- typedef detail::overlay::turn_info<point_type> turn_info;
+ using point_type = typename geometry::point_type<Geometry1>::type;
+ using mutable_point_type = typename helper_geometry<point_type>::type;
+ using turn_info = detail::overlay::turn_info<mutable_point_type>;
std::deque<turn_info> turns;
detail::touches::areal_interrupt_policy policy;
- boost::geometry::get_turns
- <
- detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
- detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
- detail::overlay::assign_null_policy
- >(geometry1, geometry2, strategy, detail::no_rescale_policy(), turns, policy);
+ geometry::get_turns
+ <
+ detail::overlay::do_reverse<geometry::point_order<Geometry1>::value>::value,
+ detail::overlay::do_reverse<geometry::point_order<Geometry2>::value>::value,
+ detail::overlay::assign_null_policy
+ >(geometry1, geometry2, strategy, detail::no_rescale_policy(), turns, policy);
return policy.result()
&& ! geometry::detail::touches::rings_containing(geometry1, geometry2, strategy)
@@ -264,6 +274,55 @@ struct use_point_in_geometry
}
};
+// GC
+
+struct gc_gc
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ int const dimension1 = detail::gc_topological_dimension(geometry1);
+ int const dimension2 = detail::gc_topological_dimension(geometry2);
+
+ if (dimension1 == 0 && dimension2 == 0)
+ {
+ return false;
+ }
+ else
+ {
+ return detail::relate::relate_impl
+ <
+ detail::de9im::static_mask_touches_not_pp_type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
+ }
+ }
+};
+
+struct notgc_gc
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ using gc1_view_t = detail::geometry_collection_view<Geometry1>;
+ return gc_gc::apply(gc1_view_t(geometry1), geometry2, strategy);
+ }
+};
+
+struct gc_notgc
+{
+ template <typename Geometry1, typename Geometry2, typename Strategy>
+ static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
+ {
+ using gc2_view_t = detail::geometry_collection_view<Geometry2>;
+ return gc_gc::apply(geometry1, gc2_view_t(geometry2), strategy);
+ }
+};
+
}}
#endif // DOXYGEN_NO_DETAIL
@@ -396,14 +455,52 @@ struct touches<Areal1, Areal2, ring_tag, ring_tag, areal_tag, areal_tag, false>
: detail::touches::areal_areal<Areal1, Areal2>
{};
+// GC
+
+template <typename Geometry1, typename Geometry2>
+struct touches
+ <
+ Geometry1, Geometry2,
+ geometry_collection_tag, geometry_collection_tag,
+ geometry_collection_tag, geometry_collection_tag,
+ false
+ >
+ : detail::touches::gc_gc
+{};
+
+
+template <typename Geometry1, typename Geometry2, typename Tag1, typename CastedTag1>
+struct touches
+ <
+ Geometry1, Geometry2,
+ Tag1, geometry_collection_tag,
+ CastedTag1, geometry_collection_tag,
+ false
+ >
+ : detail::touches::notgc_gc
+{};
+
+
+template <typename Geometry1, typename Geometry2, typename Tag2, typename CastedTag2>
+struct touches
+ <
+ Geometry1, Geometry2,
+ geometry_collection_tag, Tag2,
+ geometry_collection_tag, CastedTag2,
+ false
+ >
+ : detail::touches::gc_notgc
+{};
+
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry>
+template <typename Geometry, typename Tag>
struct self_touches
{
static bool apply(Geometry const& geometry)
@@ -436,7 +533,7 @@ struct self_touches
}
};
-}
+} // namespace resolve_dynamic
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/detail/touches/interface.hpp b/boost/geometry/algorithms/detail/touches/interface.hpp
index 39d997463e..271697c5d9 100644
--- a/boost/geometry/algorithms/detail/touches/interface.hpp
+++ b/boost/geometry/algorithms/detail/touches/interface.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2021.
-// Modifications copyright (c) 2013-2021, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -23,15 +23,13 @@
#include <deque>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
#include <boost/geometry/core/reverse_dispatch.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
@@ -146,13 +144,19 @@ struct touches<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant {
+namespace resolve_dynamic {
-template <typename Geometry1, typename Geometry2>
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct touches
{
template <typename Strategy>
- static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
+ static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
concepts::check<Geometry1 const>();
concepts::check<Geometry2 const>();
@@ -164,120 +168,87 @@ struct touches
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct touches<Geometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Strategy const& strategy)
- : m_geometry2(geometry2)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- bool operator()(Geometry1 const& geometry1) const
+ bool result = false;
+ traits::visit<Geometry1>::apply([&](auto const& g1)
{
- return touches<Geometry1, Geometry2>::apply(geometry1, m_geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
+ result = touches
+ <
+ util::remove_cref_t<decltype(g1)>,
+ Geometry2
+ >::apply(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct touches<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct touches<Geometry1, Geometry2, Tag1, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Strategy const& strategy)
- : m_geometry1(geometry1)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- bool operator()(Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry2>::apply([&](auto const& g2)
{
- return touches<Geometry1, Geometry2>::apply(m_geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy), geometry2);
+ result = touches
+ <
+ Geometry1,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)>
-struct touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
+template <typename Geometry1, typename Geometry2>
+struct touches<Geometry1, Geometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy)
- : m_strategy(strategy)
- {}
-
- template <typename Geometry1, typename Geometry2>
- bool operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry1, Geometry2>::apply([&](auto const& g1, auto const& g2)
{
- return touches<Geometry1, Geometry2>::apply(geometry1, geometry2, m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(strategy), geometry1, geometry2);
+ result = touches
+ <
+ util::remove_cref_t<decltype(g1)>,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
-template <typename Geometry>
+template <typename Geometry, typename Tag = typename geometry::tag<Geometry>::type>
struct self_touches;
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct self_touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct self_touches<Geometry, dynamic_geometry_tag>
{
- struct visitor: boost::static_visitor<bool>
+ static bool apply(Geometry const& geometry)
{
- template <typename Geometry>
- bool operator()(Geometry const& geometry) const
+ bool result = false;
+ traits::visit<Geometry>::apply([&](auto const& g)
{
- return self_touches<Geometry>::apply(geometry);
- }
- };
-
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
- {
- return boost::apply_visitor(visitor(), geometry);
+ result = self_touches
+ <
+ util::remove_cref_t<decltype(g)>
+ >::apply(g);
+ }, geometry);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -301,7 +272,7 @@ struct self_touches<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline bool touches(Geometry const& geometry)
{
- return resolve_variant::self_touches<Geometry>::apply(geometry);
+ return resolve_dynamic::self_touches<Geometry>::apply(geometry);
}
@@ -325,7 +296,7 @@ inline bool touches(Geometry const& geometry)
template <typename Geometry1, typename Geometry2>
inline bool touches(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- return resolve_variant::touches
+ return resolve_dynamic::touches
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, default_strategy());
@@ -350,7 +321,7 @@ inline bool touches(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
- return resolve_variant::touches
+ return resolve_dynamic::touches
<
Geometry1, Geometry2
>::apply(geometry1, geometry2, strategy);
diff --git a/boost/geometry/algorithms/detail/tupled_output.hpp b/boost/geometry/algorithms/detail/tupled_output.hpp
index e0f889745b..8d9652683a 100644
--- a/boost/geometry/algorithms/detail/tupled_output.hpp
+++ b/boost/geometry/algorithms/detail/tupled_output.hpp
@@ -389,7 +389,7 @@ struct output_geometry_access<TupledOut, Tag, DefaultTag, void>
>::value;
typedef typename geometry::tuples::element<index, TupledOut>::type type;
-
+
template <typename Tuple>
static typename geometry::tuples::element<index, Tuple>::type&
get(Tuple & tup)
@@ -593,8 +593,7 @@ struct convert_to_output<Geometry, SingleOut, true>
static OutputIterator apply(Geometry const& geometry,
OutputIterator oit)
{
- typedef typename boost::range_iterator<Geometry const>::type iterator;
- for (iterator it = boost::begin(geometry); it != boost::end(geometry); ++it)
+ for (auto it = boost::begin(geometry); it != boost::end(geometry); ++it)
{
SingleOut single_out;
geometry::convert(*it, single_out);
diff --git a/boost/geometry/algorithms/detail/turns/remove_duplicate_turns.hpp b/boost/geometry/algorithms/detail/turns/remove_duplicate_turns.hpp
index ccb19efb73..7819b5e2e1 100644
--- a/boost/geometry/algorithms/detail/turns/remove_duplicate_turns.hpp
+++ b/boost/geometry/algorithms/detail/turns/remove_duplicate_turns.hpp
@@ -1,18 +1,19 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014, Oracle and/or its affiliates.
+// Copyright (c) 2014-2022, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
-// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
-
#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_REMOVE_DUPLICATE_TURNS_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_TURNS_REMOVE_DUPLICATE_TURNS_HPP
#include <algorithm>
-#include <boost/geometry/algorithms/equals.hpp>
+#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
namespace boost { namespace geometry
{
@@ -23,33 +24,27 @@ namespace detail { namespace turns
template <typename Turns, bool Enable>
struct remove_duplicate_turns
{
- static inline void apply(Turns&) {}
+ template <typename Strategy>
+ static inline void apply(Turns const&, Strategy const&) {}
};
template <typename Turns>
-class remove_duplicate_turns<Turns, true>
+struct remove_duplicate_turns<Turns, true>
{
-private:
- struct TurnEqualsTo
- {
- template <typename Turn>
- bool operator()(Turn const& t1, Turn const& t2) const
- {
- return geometry::equals(t1.point, t2.point)
- && t1.operations[0].seg_id == t2.operations[0].seg_id
- && t1.operations[1].seg_id == t2.operations[1].seg_id;
- }
- };
-
-public:
- static inline void apply(Turns& turns)
+ template <typename Strategy>
+ static inline void apply(Turns& turns, Strategy const& strategy)
{
- turns.erase( std::unique(turns.begin(), turns.end(),
- TurnEqualsTo()),
- turns.end()
- );
+ turns.erase(
+ std::unique(turns.begin(), turns.end(),
+ [&](auto const& t1, auto const& t2)
+ {
+ return detail::equals::equals_point_point(t1.point, t2.point, strategy)
+ && t1.operations[0].seg_id == t2.operations[0].seg_id
+ && t1.operations[1].seg_id == t2.operations[1].seg_id;
+ }),
+ turns.end());
}
};
diff --git a/boost/geometry/algorithms/detail/visit.hpp b/boost/geometry/algorithms/detail/visit.hpp
index 60958f4b40..7cbf9e2318 100644
--- a/boost/geometry/algorithms/detail/visit.hpp
+++ b/boost/geometry/algorithms/detail/visit.hpp
@@ -181,20 +181,16 @@ struct visit_breadth_first<Geometry, dynamic_geometry_tag>
}
};
-// NOTE: This specialization works partially like std::visit and partially like
-// std::ranges::for_each. If the argument is rvalue reference then the elements
-// are passed into the function as rvalue references as well. This is consistent
-// with std::visit but different than std::ranges::for_each. It's done this way
-// because visit_breadth_first is also specialized for static and dynamic geometries
-// which and references for them has to be propagated like that. If this is not
-// desireable then the support for other kinds of geometries should be dropped and
-// this algorithm should work only for geometry collection.
-// This is not a problem right now because only non-rvalue references are passed
-// but in the future there might be some issues. Consider e.g. passing a temporary
-// mutable proxy range as geometry collection. In such case the elements would be
-// passed as rvalue references which would be incorrect.
-template <typename Geometry>
-struct visit_breadth_first<Geometry, geometry_collection_tag>
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <bool PassIterator = false>
+struct visit_breadth_first_impl
{
template <typename F, typename Geom>
static bool apply(F function, Geom && geom)
@@ -217,7 +213,8 @@ struct visit_breadth_first<Geometry, geometry_collection_tag>
bool result = true;
traits::iter_visit<util::remove_cref_t<Geom>>::apply([&](auto && g)
{
- result = visit_or_enqueue(function, std::forward<decltype(g)>(g), queue, it);
+ result = visit_breadth_first_impl::visit_or_enqueue<PassIterator>(
+ function, std::forward<decltype(g)>(g), queue, it);
}, it);
if (! result)
@@ -235,7 +232,7 @@ struct visit_breadth_first<Geometry, geometry_collection_tag>
// so this call can be avoided.
traits::iter_visit<util::remove_cref_t<Geom>>::apply([&](auto && g)
{
- set_iterators(std::forward<decltype(g)>(g), it, end);
+ visit_breadth_first_impl::set_iterators(std::forward<decltype(g)>(g), it, end);
}, queue.front());
queue.pop_front();
}
@@ -246,7 +243,7 @@ struct visit_breadth_first<Geometry, geometry_collection_tag>
private:
template
<
- typename F, typename Geom, typename Iterator,
+ bool PassIter, typename F, typename Geom, typename Iterator,
std::enable_if_t<util::is_geometry_collection<Geom>::value, int> = 0
>
static bool visit_or_enqueue(F &, Geom &&, std::deque<Iterator> & queue, Iterator iter)
@@ -256,13 +253,22 @@ private:
}
template
<
- typename F, typename Geom, typename Iterator,
- std::enable_if_t<! util::is_geometry_collection<Geom>::value, int> = 0
+ bool PassIter, typename F, typename Geom, typename Iterator,
+ std::enable_if_t<! util::is_geometry_collection<Geom>::value && ! PassIter, int> = 0
>
static bool visit_or_enqueue(F & f, Geom && g, std::deque<Iterator> & , Iterator)
{
return f(std::forward<Geom>(g));
}
+ template
+ <
+ bool PassIter, typename F, typename Geom, typename Iterator,
+ std::enable_if_t<! util::is_geometry_collection<Geom>::value && PassIter, int> = 0
+ >
+ static bool visit_or_enqueue(F & f, Geom && g, std::deque<Iterator> & , Iterator iter)
+ {
+ return f(std::forward<Geom>(g), iter);
+ }
template
<
@@ -283,6 +289,32 @@ private:
{}
};
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+// NOTE: This specialization works partially like std::visit and partially like
+// std::ranges::for_each. If the argument is rvalue reference then the elements
+// are passed into the function as rvalue references as well. This is consistent
+// with std::visit but different than std::ranges::for_each. It's done this way
+// because visit_breadth_first is also specialized for static and dynamic geometries
+// and references for them has to be propagated like that. If this is not
+// desireable then the support for other kinds of geometries should be dropped and
+// this algorithm should work only for geometry collection. Or forwarding of rvalue
+// references should simply be dropped entirely.
+// This is not a problem right now because only non-rvalue references are passed
+// but in the future there might be some issues. Consider e.g. passing a temporary
+// mutable proxy range as geometry collection. In such case the elements would be
+// passed as rvalue references which would be incorrect.
+template <typename Geometry>
+struct visit_breadth_first<Geometry, geometry_collection_tag>
+ : detail::visit_breadth_first_impl<>
+{};
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/algorithms/detail/within/implementation.hpp b/boost/geometry/algorithms/detail/within/implementation.hpp
index 72561cd890..b5300a9934 100644
--- a/boost/geometry/algorithms/detail/within/implementation.hpp
+++ b/boost/geometry/algorithms/detail/within/implementation.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2013-2021.
-// Modifications copyright (c) 2013-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -29,7 +29,8 @@
#include <boost/geometry/algorithms/detail/within/interface.hpp>
#include <boost/geometry/algorithms/detail/within/multi_point.hpp>
#include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
-#include <boost/geometry/algorithms/relate.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation.hpp>
+#include <boost/geometry/algorithms/detail/relate/relate_impl.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/closure.hpp>
@@ -68,11 +69,12 @@ struct use_relate
template <typename Geometry1, typename Geometry2, typename Strategy>
static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy)
{
- typedef typename detail::de9im::static_mask_within_type
+ return detail::relate::relate_impl
<
- Geometry1, Geometry2
- >::type within_mask;
- return geometry::relate(geometry1, geometry2, within_mask(), strategy);
+ detail::de9im::static_mask_within_type,
+ Geometry1,
+ Geometry2
+ >::apply(geometry1, geometry2, strategy);
}
};
diff --git a/boost/geometry/algorithms/detail/within/implementation_gc.hpp b/boost/geometry/algorithms/detail/within/implementation_gc.hpp
new file mode 100644
index 0000000000..6f40f318d8
--- /dev/null
+++ b/boost/geometry/algorithms/detail/within/implementation_gc.hpp
@@ -0,0 +1,46 @@
+// Boost.Geometry
+
+// Copyright (c) 2022 Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// 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_WITHIN_IMPLEMENTATION_GC_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_IMPLEMENTATION_GC_HPP
+
+
+#include <boost/geometry/algorithms/detail/relate/implementation_gc.hpp>
+#include <boost/geometry/algorithms/detail/within/implementation.hpp>
+
+
+namespace boost { namespace geometry {
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch {
+
+template <typename Geometry1, typename Geometry2>
+struct within<Geometry1, Geometry2, geometry_collection_tag, geometry_collection_tag>
+ : detail::within::use_relate
+{};
+
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct within<Geometry1, Geometry2, Tag1, geometry_collection_tag>
+ : detail::within::use_relate
+{};
+
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct within<Geometry1, Geometry2, geometry_collection_tag, Tag2>
+ : detail::within::use_relate
+{};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_WITHIN_IMPLEMENTATION_GC_HPP
diff --git a/boost/geometry/algorithms/detail/within/interface.hpp b/boost/geometry/algorithms/detail/within/interface.hpp
index 1a10ca84d8..572e0e5c94 100644
--- a/boost/geometry/algorithms/detail/within/interface.hpp
+++ b/boost/geometry/algorithms/detail/within/interface.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2013-2021.
-// Modifications copyright (c) 2013-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -21,16 +21,14 @@
#include <boost/concept_check.hpp>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tag_cast.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
+
#include <boost/geometry/strategies/concepts/within_concept.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
@@ -126,10 +124,15 @@ struct within<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry1, typename Geometry2>
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct within
{
template <typename Strategy>
@@ -148,110 +151,66 @@ struct within
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct within<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename Geometry1, typename Geometry2, typename Tag2>
+struct within<Geometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2, Strategy const& strategy)
- : m_geometry2(geometry2)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- bool operator()(Geometry1 const& geometry1) const
+ bool result = false;
+ traits::visit<Geometry1>::apply([&](auto const& g1)
{
- return within<Geometry1, Geometry2>::apply(geometry1,
- m_geometry2,
- m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry2, strategy),
- geometry1);
+ result = within
+ <
+ util::remove_cref_t<decltype(g1)>,
+ Geometry2
+ >::apply(g1, geometry2, strategy);
+ }, geometry1);
+ return result;
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct within<Geometry1, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename Geometry2, typename Tag1>
+struct within<Geometry1, Geometry2, Tag1, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1, Strategy const& strategy)
- : m_geometry1(geometry1)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- bool operator()(Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry2>::apply([&](auto const& g2)
{
- return within<Geometry1, Geometry2>::apply(m_geometry1,
- geometry2,
- m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(Geometry1 const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(geometry1, strategy),
- geometry2
- );
+ result = within
+ <
+ Geometry1,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(geometry1, g2, strategy);
+ }, geometry2);
+ return result;
}
};
-template <
- BOOST_VARIANT_ENUM_PARAMS(typename T1),
- BOOST_VARIANT_ENUM_PARAMS(typename T2)
->
-struct within<
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)>,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)>
->
+template <typename Geometry1, typename Geometry2>
+struct within<Geometry1, Geometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static inline bool apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Strategy const& strategy)
{
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy): m_strategy(strategy) {}
-
- template <typename Geometry1, typename Geometry2>
- bool operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ bool result = false;
+ traits::visit<Geometry1, Geometry2>::apply([&](auto const& g1, auto const& g2)
{
- return within<Geometry1, Geometry2>::apply(geometry1,
- geometry2,
- m_strategy);
- }
- };
-
- template <typename Strategy>
- static inline bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Strategy const& strategy)
- {
- return boost::apply_visitor(visitor<Strategy>(strategy),
- geometry1,
- geometry2);
+ result = within
+ <
+ util::remove_cref_t<decltype(g1)>,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(g1, g2, strategy);
+ }, geometry1, geometry2);
+ return result;
}
};
@@ -282,7 +241,7 @@ struct within<
template<typename Geometry1, typename Geometry2>
inline bool within(Geometry1 const& geometry1, Geometry2 const& geometry2)
{
- return resolve_variant::within
+ return resolve_dynamic::within
<
Geometry1,
Geometry2
@@ -320,7 +279,7 @@ inline bool within(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Strategy const& strategy)
{
- return resolve_variant::within
+ return resolve_dynamic::within
<
Geometry1,
Geometry2
diff --git a/boost/geometry/algorithms/detail/within/multi_point.hpp b/boost/geometry/algorithms/detail/within/multi_point.hpp
index 349ef03026..be984e9364 100644
--- a/boost/geometry/algorithms/detail/within/multi_point.hpp
+++ b/boost/geometry/algorithms/detail/within/multi_point.hpp
@@ -1,6 +1,10 @@
// Boost.Geometry
-// Copyright (c) 2017-2020, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+
+// Copyright (c) 2017-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -38,6 +42,7 @@
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/disjoint.hpp>
+#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/type_traits.hpp>
@@ -55,8 +60,7 @@ struct multi_point_point
{
auto const s = strategy.relate(multi_point, point);
- typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
- for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ for (auto it = boost::begin(multi_point); it != boost::end(multi_point); ++it)
{
if (! s.apply(*it, point))
{
@@ -78,8 +82,7 @@ struct multi_point_multi_point
Strategy const& /*strategy*/)
{
typedef typename boost::range_value<MultiPoint2>::type point2_type;
- typedef typename Strategy::cs_tag cs_tag;
- typedef geometry::less<void, -1, cs_tag> less_type;
+ typedef geometry::less<void, -1, Strategy> less_type;
less_type const less = less_type();
@@ -88,8 +91,7 @@ struct multi_point_multi_point
bool result = false;
- typedef typename boost::range_const_iterator<MultiPoint1>::type iterator;
- for ( iterator it = boost::begin(multi_point1) ; it != boost::end(multi_point1) ; ++it )
+ for (auto it = boost::begin(multi_point1); it != boost::end(multi_point1); ++it)
{
if (! std::binary_search(points2.begin(), points2.end(), *it, less))
{
@@ -134,13 +136,12 @@ struct multi_point_single_geometry
// If in the exterior, break
bool result = false;
- typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
- for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ for (auto it = boost::begin(multi_point); it != boost::end(multi_point); ++it )
{
typedef decltype(strategy.covered_by(*it, box)) point_in_box_type;
int in_val = 0;
-
+
// exterior of box and of geometry
if (! point_in_box_type::apply(*it, box)
|| (in_val = point_in_geometry(*it, linear_or_areal, strategy)) < 0)
@@ -198,8 +199,7 @@ struct multi_point_multi_geometry
// If a point is in the exterior break
bool result = false;
- typedef typename boost::range_const_iterator<MultiPoint>::type iterator;
- for ( iterator it = boost::begin(multi_point) ; it != boost::end(multi_point) ; ++it )
+ for (auto it = boost::begin(multi_point); it != boost::end(multi_point); ++it)
{
// TODO: investigate the possibility of using satisfies
// TODO: investigate the possibility of using iterative queries (optimization below)
@@ -238,7 +238,7 @@ struct multi_point_multi_geometry
if (boundaries > 0)
{
- if (is_linear && boundaries % 2 == 0)
+ if (BOOST_GEOMETRY_CONDITION(is_linear) && boundaries % 2 == 0)
{
found_interior = true;
}
diff --git a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
index c9b9cbfd81..459e54ec85 100644
--- a/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
+++ b/boost/geometry/algorithms/detail/within/point_in_geometry.hpp
@@ -30,7 +30,6 @@
#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/concepts/within_concept.hpp>
@@ -49,13 +48,12 @@ int point_in_range(Point const& point, Range const& range, Strategy const& strat
{
typename Strategy::state_type state;
- typedef typename boost::range_iterator<Range const>::type iterator_type;
- iterator_type it = boost::begin(range);
- iterator_type end = boost::end(range);
+ auto it = boost::begin(range);
+ auto const end = boost::end(range);
- for ( iterator_type previous = it++ ; it != end ; ++previous, ++it )
+ for (auto previous = it++; it != end; ++previous, ++it)
{
- if ( ! strategy.apply(point, *previous, *it, state) )
+ if (! strategy.apply(point, *previous, *it, state))
{
break;
}
@@ -202,13 +200,8 @@ struct point_in_geometry<Polygon, polygon_tag>
if (code == 1)
{
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(polygon);
-
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings);
- it != boost::end(rings);
- ++it)
+ auto const& rings = interior_rings(polygon);
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
int const interior_code = point_in_geometry
<
@@ -235,14 +228,16 @@ struct point_in_geometry<Geometry, multi_point_tag>
int apply(Point const& point, Geometry const& geometry, Strategy const& strategy)
{
typedef typename boost::range_value<Geometry>::type point_type;
- typedef typename boost::range_const_iterator<Geometry>::type iterator;
- for ( iterator it = boost::begin(geometry) ; it != boost::end(geometry) ; ++it )
+ for (auto it = boost::begin(geometry); it != boost::end(geometry); ++it)
{
int pip = point_in_geometry<point_type>::apply(point, *it, strategy);
//BOOST_GEOMETRY_ASSERT(pip != 0);
- if ( pip > 0 ) // inside
+ if (pip > 0)
+ {
+ // inside
return 1;
+ }
}
return -1; // outside
@@ -259,14 +254,13 @@ struct point_in_geometry<Geometry, multi_linestring_tag>
typedef typename boost::range_value<Geometry>::type linestring_type;
typedef typename boost::range_value<linestring_type>::type point_type;
- typedef typename boost::range_iterator<Geometry const>::type iterator;
- iterator it = boost::begin(geometry);
- for ( ; it != boost::end(geometry) ; ++it )
+ auto it = boost::begin(geometry);
+ for ( ; it != boost::end(geometry); ++it)
{
pip = point_in_geometry<linestring_type>::apply(point, *it, strategy);
// inside or on the boundary
- if ( pip >= 0 )
+ if (pip >= 0)
{
++it;
break;
@@ -274,24 +268,30 @@ struct point_in_geometry<Geometry, multi_linestring_tag>
}
// outside
- if ( pip < 0 )
+ if (pip < 0)
+ {
return -1;
+ }
// TODO: the following isn't needed for covered_by()
unsigned boundaries = pip == 0 ? 1 : 0;
- for ( ; it != boost::end(geometry) ; ++it )
+ for (; it != boost::end(geometry); ++it)
{
- if ( boost::size(*it) < 2 )
+ if (boost::size(*it) < 2)
+ {
continue;
+ }
point_type const& front = range::front(*it);
point_type const& back = range::back(*it);
// is closed_ring - no boundary
- if ( detail::equals::equals_point_point(front, back, strategy) )
+ if (detail::equals::equals_point_point(front, back, strategy))
+ {
continue;
+ }
// is point on boundary
if ( detail::equals::equals_point_point(point, front, strategy)
@@ -316,14 +316,15 @@ struct point_in_geometry<Geometry, multi_polygon_tag>
//int res = -1; // outside
typedef typename boost::range_value<Geometry>::type polygon_type;
- typedef typename boost::range_const_iterator<Geometry>::type iterator;
- for ( iterator it = boost::begin(geometry) ; it != boost::end(geometry) ; ++it )
+ for (auto it = boost::begin(geometry); it != boost::end(geometry); ++it)
{
int pip = point_in_geometry<polygon_type>::apply(point, *it, strategy);
// inside or on the boundary
- if ( pip >= 0 )
+ if (pip >= 0)
+ {
return pip;
+ }
// For invalid multi-polygons
//if ( 1 == pip ) // inside polygon
diff --git a/boost/geometry/algorithms/detail/within/within_no_turns.hpp b/boost/geometry/algorithms/detail/within/within_no_turns.hpp
index 8da05e58fd..d6d0417c3b 100644
--- a/boost/geometry/algorithms/detail/within/within_no_turns.hpp
+++ b/boost/geometry/algorithms/detail/within/within_no_turns.hpp
@@ -4,8 +4,9 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2013.
-// Modifications copyright (c) 2013, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2023.
+// Modifications copyright (c) 2013-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
@@ -41,8 +42,10 @@ struct within_no_turns
{
typedef typename geometry::point_type<Geometry1>::type point1_type;
point1_type p;
- if ( !geometry::point_on_border(p, geometry1) )
+ if (! geometry::point_on_border(p, geometry1))
+ {
return false;
+ }
return detail::within::point_in_geometry(p, geometry2, strategy) >= 0;
}
@@ -57,25 +60,28 @@ struct within_no_turns<Geometry1, Geometry2, ring_tag, polygon_tag>
typedef typename geometry::point_type<Geometry1>::type point1_type;
typedef typename geometry::point_type<Geometry2>::type point2_type;
point1_type p;
- if ( !geometry::point_on_border(p, geometry1) )
+ if (! geometry::point_on_border(p, geometry1))
+ {
return false;
+ }
// check if one of ring points is outside the polygon
- if ( detail::within::point_in_geometry(p, geometry2, strategy) < 0 )
+ if (detail::within::point_in_geometry(p, geometry2, strategy) < 0)
+ {
return false;
+ }
// Now check if holes of G2 aren't inside G1
- typedef typename boost::range_const_iterator
- <
- typename geometry::interior_type<Geometry2>::type
- >::type iterator;
- for ( iterator it = boost::begin(geometry::interior_rings(geometry2)) ;
- it != boost::end(geometry::interior_rings(geometry2)) ;
- ++it )
+ auto const& rings2 = geometry::interior_rings(geometry2);
+ for (auto it = boost::begin(rings2); it != boost::end(rings2); ++it)
{
point2_type p;
- if ( !geometry::point_on_border(p, *it) )
+ if (! geometry::point_on_border(p, *it))
+ {
return false;
- if ( detail::within::point_in_geometry(p, geometry1, strategy) > 0 )
+ }
+ if (detail::within::point_in_geometry(p, geometry1, strategy) > 0)
+ {
return false;
+ }
}
return true;
}
@@ -90,44 +96,42 @@ struct within_no_turns<Geometry1, Geometry2, polygon_tag, polygon_tag>
typedef typename geometry::point_type<Geometry1>::type point1_type;
typedef typename geometry::point_type<Geometry2>::type point2_type;
point1_type p;
- if ( !geometry::point_on_border(p, geometry1) )
+ if (! geometry::point_on_border(p, geometry1))
+ {
return false;
+ }
// check if one of ring points is outside the polygon
- if ( detail::within::point_in_geometry(p, geometry2, strategy) < 0 )
+ if (detail::within::point_in_geometry(p, geometry2, strategy) < 0)
+ {
return false;
+ }
// Now check if holes of G2 aren't inside G1
- typedef typename boost::range_const_iterator
- <
- typename geometry::interior_type<Geometry2>::type
- >::type iterator2;
- for ( iterator2 it = boost::begin(geometry::interior_rings(geometry2)) ;
- it != boost::end(geometry::interior_rings(geometry2)) ;
- ++it )
+ auto const& rings2 = geometry::interior_rings(geometry2);
+ for (auto it2 = boost::begin(rings2); it2 != boost::end(rings2); ++it2)
{
point2_type p2;
- if ( !geometry::point_on_border(p2, *it) )
+ if (! geometry::point_on_border(p2, *it2))
+ {
return false;
+ }
// if the hole of G2 is inside G1
- if ( detail::within::point_in_geometry(p2, geometry1, strategy) > 0 )
+ if (detail::within::point_in_geometry(p2, geometry1, strategy) > 0)
{
// if it's also inside one of the G1 holes, it's ok
bool ok = false;
- typedef typename boost::range_const_iterator
- <
- typename geometry::interior_type<Geometry1>::type
- >::type iterator1;
- for ( iterator1 it1 = boost::begin(geometry::interior_rings(geometry1)) ;
- it1 != boost::end(geometry::interior_rings(geometry1)) ;
- ++it1 )
+ auto const& rings1 = geometry::interior_rings(geometry1);
+ for (auto it1 = boost::begin(rings1); it1 != boost::end(rings1); ++it1)
{
- if ( detail::within::point_in_geometry(p2, *it1, strategy) < 0 )
+ if (detail::within::point_in_geometry(p2, *it1, strategy) < 0)
{
ok = true;
break;
}
}
- if ( !ok )
+ if (! ok)
+ {
return false;
+ }
}
}
return true;
@@ -157,11 +161,12 @@ struct within_no_turns_multi<Geometry1, Geometry2, Tag1, Tag2, true, false>
{
// All values of G1 must be inside G2
typedef typename boost::range_value<Geometry1>::type subgeometry1;
- typedef typename boost::range_const_iterator<Geometry1>::type iterator;
- for ( iterator it = boost::begin(geometry1) ; it != boost::end(geometry1) ; ++it )
+ for (auto it = boost::begin(geometry1) ; it != boost::end(geometry1) ; ++it )
{
- if ( !within_no_turns<subgeometry1, Geometry2>::apply(*it, geometry2, strategy) )
+ if (! within_no_turns<subgeometry1, Geometry2>::apply(*it, geometry2, strategy))
+ {
return false;
+ }
}
return true;
}
@@ -175,11 +180,12 @@ struct within_no_turns_multi<Geometry1, Geometry2, Tag1, Tag2, false, true>
{
// G1 must be within at least one value of G2
typedef typename boost::range_value<Geometry2>::type subgeometry2;
- typedef typename boost::range_const_iterator<Geometry2>::type iterator;
- for ( iterator it = boost::begin(geometry2) ; it != boost::end(geometry2) ; ++it )
+ for (auto it = boost::begin(geometry2); it != boost::end(geometry2); ++it)
{
- if ( within_no_turns<Geometry1, subgeometry2>::apply(geometry1, *it, strategy) )
+ if (within_no_turns<Geometry1, subgeometry2>::apply(geometry1, *it, strategy))
+ {
return true;
+ }
}
return false;
}
@@ -193,11 +199,12 @@ struct within_no_turns_multi<Geometry1, Geometry2, Tag1, Tag2, true, true>
{
// each value of G1 must be inside at least one value of G2
typedef typename boost::range_value<Geometry1>::type subgeometry1;
- typedef typename boost::range_const_iterator<Geometry1>::type iterator;
- for ( iterator it = boost::begin(geometry1) ; it != boost::end(geometry1) ; ++it )
+ for (auto it = boost::begin(geometry1) ; it != boost::end(geometry1) ; ++it)
{
- if ( !within_no_turns_multi<subgeometry1, Geometry2>::apply(*it, geometry2, strategy) )
+ if (! within_no_turns_multi<subgeometry1, Geometry2>::apply(*it, geometry2, strategy))
+ {
return false;
+ }
}
return true;
}
diff --git a/boost/geometry/algorithms/difference.hpp b/boost/geometry/algorithms/difference.hpp
index 2155b9e546..ec6e4ea734 100644
--- a/boost/geometry/algorithms/difference.hpp
+++ b/boost/geometry/algorithms/difference.hpp
@@ -2,9 +2,9 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2017-2021.
-// Modifications copyright (c) 2017-2021, Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2017-2023.
+// Modifications copyright (c) 2017-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,19 +15,21 @@
#define BOOST_GEOMETRY_ALGORITHMS_DIFFERENCE_HPP
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
+#include <boost/geometry/algorithms/detail/gc_make_rtree.hpp>
+#include <boost/geometry/algorithms/detail/intersection/gc.hpp>
#include <boost/geometry/algorithms/detail/intersection/multi.hpp>
#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
+#include <boost/geometry/core/geometry_types.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/relate/cartesian.hpp>
#include <boost/geometry/strategies/relate/geographic.hpp>
#include <boost/geometry/strategies/relate/spherical.hpp>
-#include <boost/geometry/util/range.hpp>
+#include <boost/geometry/util/sequence.hpp>
+#include <boost/geometry/views/detail/geometry_collection_view.hpp>
namespace boost { namespace geometry
@@ -37,14 +39,23 @@ namespace boost { namespace geometry
namespace detail { namespace difference
{
+
+// True if the result of difference can be different than Geometry1
+template <typename Geometry1, typename Geometry2>
+using is_subtractable_t = util::bool_constant
+ <
+ (geometry::topological_dimension<Geometry1>::value
+ <= geometry::topological_dimension<Geometry2>::value)
+ >;
+
+
template
<
typename Geometry1,
typename Geometry2,
typename SingleOut,
typename OutTag = typename detail::setop_insert_output_tag<SingleOut>::type,
- bool ReturnGeometry1 = (topological_dimension<Geometry1>::value
- > topological_dimension<Geometry2>::value)
+ bool ReturnGeometry1 = (! is_subtractable_t<Geometry1, Geometry2>::value)
>
struct call_intersection_insert
{
@@ -71,6 +82,26 @@ struct call_intersection_insert
}
};
+
+template <typename Geometry1, typename Geometry2, typename SingleOut, typename OutTag>
+struct call_intersection_insert<Geometry1, Geometry2, SingleOut, OutTag, true>
+{
+ template <typename OutputIterator, typename RobustPolicy, typename Strategy>
+ static inline OutputIterator apply(Geometry1 const& geometry1,
+ Geometry2 const& ,
+ RobustPolicy const& ,
+ OutputIterator out,
+ Strategy const& )
+ {
+ return geometry::detail::convert_to_output
+ <
+ Geometry1,
+ SingleOut
+ >::apply(geometry1, out);
+ }
+};
+
+
template
<
typename Geometry1,
@@ -268,10 +299,237 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1,
}
+template
+<
+ typename Geometry, typename Collection,
+ typename CastedTag = typename geometry::tag_cast
+ <
+ typename geometry::tag<Geometry>::type,
+ pointlike_tag, linear_tag, areal_tag
+ >::type
+>
+struct multi_output_type
+{
+ BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
+ "Not implemented this Geometry type.",
+ Geometry, CastedTag);
+};
+
+template <typename Geometry, typename Collection>
+struct multi_output_type<Geometry, Collection, pointlike_tag>
+{
+ using type = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Collection>::type,
+ util::is_multi_point
+ >::type;
+};
+
+template <typename Geometry, typename Collection>
+struct multi_output_type<Geometry, Collection, linear_tag>
+{
+ using type = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Collection>::type,
+ util::is_multi_linestring
+ >::type;
+};
+
+template <typename Geometry, typename Collection>
+struct multi_output_type<Geometry, Collection, areal_tag>
+{
+ using type = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<Collection>::type,
+ util::is_multi_polygon
+ >::type;
+};
+
+
}} // namespace detail::difference
#endif // DOXYGEN_NO_DETAIL
+namespace resolve_collection
+{
+
+
+template
+<
+ typename Geometry1, typename Geometry2, typename Collection,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type,
+ typename CollectionTag = typename geometry::tag<Collection>::type
+>
+struct difference
+{
+ template <typename Strategy>
+ static void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection & output_collection,
+ Strategy const& strategy)
+ {
+ using single_out = typename geometry::detail::output_geometry_value
+ <
+ Collection
+ >::type;
+
+ detail::difference::difference_insert<single_out>(
+ geometry1, geometry2,
+ geometry::detail::output_geometry_back_inserter(output_collection),
+ strategy);
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Collection>
+struct difference
+ <
+ Geometry1, Geometry2, Collection,
+ geometry_collection_tag, geometry_collection_tag, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ auto const rtree2 = detail::gc_make_rtree_iterators(geometry2, strategy);
+ detail::visit_breadth_first([&](auto const& g1)
+ {
+ // multi-point, multi-linestring or multi_polygon
+ typename detail::difference::multi_output_type
+ <
+ util::remove_cref_t<decltype(g1)>, Collection
+ >::type out;
+
+ g1_minus_gc2(g1, rtree2, out, strategy);
+
+ detail::intersection::gc_move_multi_back(output_collection, out);
+
+ return true;
+ }, geometry1);
+ }
+
+private:
+ // Implemented as separate function because msvc is unable to do nested lambda capture
+ template <typename G1, typename Rtree2, typename MultiOut, typename Strategy>
+ static void g1_minus_gc2(G1 const& g1, Rtree2 const& rtree2, MultiOut& out, Strategy const& strategy)
+ {
+ {
+ using single_out_t = typename geometry::detail::output_geometry_value<MultiOut>::type;
+ auto out_it = geometry::detail::output_geometry_back_inserter(out);
+ geometry::detail::convert_to_output<G1, single_out_t>::apply(g1, out_it);
+ }
+
+ using box1_t = detail::gc_make_rtree_box_t<G1>;
+ box1_t b1 = geometry::return_envelope<box1_t>(g1, strategy);
+ detail::expand_by_epsilon(b1);
+
+ for (auto qit = rtree2.qbegin(index::intersects(b1)); qit != rtree2.qend(); ++qit)
+ {
+ traits::iter_visit<Geometry2>::apply([&](auto const& g2)
+ {
+ multi_out_minus_g2(out, g2, strategy);
+ }, qit->second);
+
+ if (boost::empty(out))
+ {
+ return;
+ }
+ }
+ }
+
+ template
+ <
+ typename MultiOut, typename G2, typename Strategy,
+ std::enable_if_t<detail::difference::is_subtractable_t<MultiOut, G2>::value, int> = 0
+ >
+ static void multi_out_minus_g2(MultiOut& out, G2 const& g2, Strategy const& strategy)
+ {
+ MultiOut result;
+ difference<MultiOut, G2, MultiOut>::apply(out, g2, result, strategy);
+ out = std::move(result);
+ }
+
+ template
+ <
+ typename MultiOut, typename G2, typename Strategy,
+ std::enable_if_t<(! detail::difference::is_subtractable_t<MultiOut, G2>::value), int> = 0
+ >
+ static void multi_out_minus_g2(MultiOut& , G2 const& , Strategy const& )
+ {}
+};
+
+
+template <typename Geometry1, typename Geometry2, typename Collection, typename Tag1>
+struct difference
+ <
+ Geometry1, Geometry2, Collection,
+ Tag1, geometry_collection_tag, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection & output_collection,
+ Strategy const& strategy)
+ {
+ using gc_view_t = geometry::detail::geometry_collection_view<Geometry1>;
+ difference
+ <
+ gc_view_t, Geometry2, Collection
+ >::apply(gc_view_t(geometry1), geometry2, output_collection, strategy);
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Collection, typename Tag2>
+struct difference
+ <
+ Geometry1, Geometry2, Collection,
+ geometry_collection_tag, Tag2, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection & output_collection,
+ Strategy const& strategy)
+ {
+ using gc_view_t = geometry::detail::geometry_collection_view<Geometry2>;
+ difference
+ <
+ Geometry1, gc_view_t, Collection
+ >::apply(geometry1, gc_view_t(geometry2), output_collection, strategy);
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Collection, typename Tag1, typename Tag2>
+struct difference
+ <
+ Geometry1, Geometry2, Collection,
+ Tag1, Tag2, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection & output_collection,
+ Strategy const& strategy)
+ {
+ using gc1_view_t = geometry::detail::geometry_collection_view<Geometry1>;
+ using gc2_view_t = geometry::detail::geometry_collection_view<Geometry2>;
+ difference
+ <
+ gc1_view_t, gc2_view_t, Collection
+ >::apply(gc1_view_t(geometry1), gc2_view_t(geometry2), output_collection, strategy);
+ }
+};
+
+
+} // namespace resolve_collection
+
+
namespace resolve_strategy {
template
@@ -287,15 +545,10 @@ struct difference
Collection & output_collection,
Strategy const& strategy)
{
- typedef typename geometry::detail::output_geometry_value
+ resolve_collection::difference
<
- Collection
- >::type single_out;
-
- detail::difference::difference_insert<single_out>(
- geometry1, geometry2,
- geometry::detail::output_geometry_back_inserter(output_collection),
- strategy);
+ Geometry1, Geometry2, Collection
+ >::apply(geometry1, geometry2, output_collection, strategy);
}
};
@@ -309,7 +562,7 @@ struct difference<Strategy, false>
Strategy const& strategy)
{
using strategies::relate::services::strategy_converter;
-
+
difference
<
decltype(strategy_converter<Strategy>::get(strategy))
@@ -332,7 +585,7 @@ struct difference<default_strategy, false>
Geometry1,
Geometry2
>::type strategy_type;
-
+
difference
<
strategy_type
@@ -343,17 +596,20 @@ struct difference<default_strategy, false>
} // resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-
-template <typename Geometry1, typename Geometry2>
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct difference
{
template <typename Collection, typename Strategy>
- static inline void apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Collection& output_collection,
- Strategy const& strategy)
+ static void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ Collection& output_collection, Strategy const& strategy)
{
resolve_strategy::difference
<
@@ -362,135 +618,58 @@ struct difference
}
};
-
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct difference<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
+struct difference<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Collection, typename Strategy>
- struct visitor: static_visitor<>
+ static void apply(DynamicGeometry1 const& geometry1, Geometry2 const& geometry2,
+ Collection& output_collection, Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Collection& m_output_collection;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2,
- Collection& output_collection,
- Strategy const& strategy)
- : m_geometry2(geometry2)
- , m_output_collection(output_collection)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- void operator()(Geometry1 const& geometry1) const
+ traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
{
- difference
+ resolve_strategy::difference
<
- Geometry1,
- Geometry2
- >::apply(geometry1, m_geometry2, m_output_collection, m_strategy);
- }
- };
-
- template <typename Collection, typename Strategy>
- static inline void
- apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Collection& output_collection,
- Strategy const& strategy)
- {
- boost::apply_visitor(visitor<Collection, Strategy>(geometry2,
- output_collection,
- strategy),
- geometry1);
+ Strategy
+ >::apply(g1, geometry2, output_collection, strategy);
+ }, geometry1);
}
};
-
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct difference<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
+struct difference<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
{
template <typename Collection, typename Strategy>
- struct visitor: static_visitor<>
+ static void apply(Geometry1 const& geometry1, DynamicGeometry2 const& geometry2,
+ Collection& output_collection, Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Collection& m_output_collection;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1,
- Collection& output_collection,
- Strategy const& strategy)
- : m_geometry1(geometry1)
- , m_output_collection(output_collection)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- void operator()(Geometry2 const& geometry2) const
+ traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
{
- difference
+ resolve_strategy::difference
<
- Geometry1,
- Geometry2
- >::apply(m_geometry1, geometry2, m_output_collection, m_strategy);
- }
- };
-
- template <typename Collection, typename Strategy>
- static inline void
- apply(Geometry1 const& geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Collection& output_collection,
- Strategy const& strategy)
- {
- boost::apply_visitor(visitor<Collection, Strategy>(geometry1,
- output_collection,
- strategy),
- geometry2);
+ Strategy
+ >::apply(geometry1, g2, output_collection, strategy);
+ }, geometry2);
}
};
-
-template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
-struct difference<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
+template <typename DynamicGeometry1, typename DynamicGeometry2>
+struct difference<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Collection, typename Strategy>
- struct visitor: static_visitor<>
+ static void apply(DynamicGeometry1 const& geometry1, DynamicGeometry2 const& geometry2,
+ Collection& output_collection, Strategy const& strategy)
{
- Collection& m_output_collection;
- Strategy const& m_strategy;
-
- visitor(Collection& output_collection, Strategy const& strategy)
- : m_output_collection(output_collection)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1, typename Geometry2>
- void operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
{
- difference
+ resolve_strategy::difference
<
- Geometry1,
- Geometry2
- >::apply(geometry1, geometry2, m_output_collection, m_strategy);
- }
- };
-
- template <typename Collection, typename Strategy>
- static inline void
- apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Collection& output_collection,
- Strategy const& strategy)
- {
- boost::apply_visitor(visitor<Collection, Strategy>(output_collection,
- strategy),
- geometry1, geometry2);
+ Strategy
+ >::apply(g1, g2, output_collection, strategy);
+ }, geometry1, geometry2);
}
};
-
-} // namespace resolve_variant
+
+} // namespace resolve_dynamic
/*!
@@ -521,7 +700,7 @@ inline void difference(Geometry1 const& geometry1,
Collection& output_collection,
Strategy const& strategy)
{
- resolve_variant::difference
+ resolve_dynamic::difference
<
Geometry1,
Geometry2
@@ -552,7 +731,7 @@ inline void difference(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Collection& output_collection)
{
- resolve_variant::difference
+ resolve_dynamic::difference
<
Geometry1,
Geometry2
diff --git a/boost/geometry/algorithms/discrete_frechet_distance.hpp b/boost/geometry/algorithms/discrete_frechet_distance.hpp
index fb264d5b7a..094ae14a3b 100644
--- a/boost/geometry/algorithms/discrete_frechet_distance.hpp
+++ b/boost/geometry/algorithms/discrete_frechet_distance.hpp
@@ -4,8 +4,9 @@
// Contributed and/or modified by Yaghyavardhan Singh Khangarot,
// as part of Google Summer of Code 2018 program.
-// This file was modified by Oracle on 2018-2021.
-// Modifications copyright (c) 2018-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2018-2023.
+// Modifications copyright (c) 2018-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,16 +16,11 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_DISCRETE_FRECHET_DISTANCE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_DISCRETE_FRECHET_DISTANCE_HPP
-#include <algorithm>
-
#ifdef BOOST_GEOMETRY_DEBUG_FRECHET_DISTANCE
#include <iostream>
#endif
-#include <iterator>
-#include <utility>
#include <vector>
-#include <limits>
#include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
#include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
diff --git a/boost/geometry/algorithms/discrete_hausdorff_distance.hpp b/boost/geometry/algorithms/discrete_hausdorff_distance.hpp
index 9cc2ef0d57..115909c06a 100644
--- a/boost/geometry/algorithms/discrete_hausdorff_distance.hpp
+++ b/boost/geometry/algorithms/discrete_hausdorff_distance.hpp
@@ -187,7 +187,7 @@ struct multi_range_multi_range
boost::geometry::detail::throw_on_empty_input(mrng1);
boost::geometry::detail::throw_on_empty_input(mrng2);
-
+
size_type n = boost::size(mrng1);
result_type haus_dis = 0;
diff --git a/boost/geometry/algorithms/dispatch/closest_points.hpp b/boost/geometry/algorithms/dispatch/closest_points.hpp
new file mode 100644
index 0000000000..e4f72de66a
--- /dev/null
+++ b/boost/geometry/algorithms/dispatch/closest_points.hpp
@@ -0,0 +1,67 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_DISPATCH_CLOSEST_POINTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_DISPATCH_CLOSEST_POINTS_HPP
+
+
+#include <boost/geometry/algorithms/not_implemented.hpp>
+
+#include <boost/geometry/core/reverse_dispatch.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tag_cast.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/strategies/detail.hpp>
+#include <boost/geometry/strategies/closest_points/services.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename tag_cast
+ <
+ typename tag<Geometry1>::type,
+ segment_tag,
+ box_tag,
+ linear_tag,
+ areal_tag
+ >::type,
+ typename Tag2 = typename tag_cast
+ <
+ typename tag<Geometry2>::type,
+ segment_tag,
+ box_tag,
+ linear_tag,
+ areal_tag
+ >::type,
+ bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
+>
+struct closest_points : not_implemented<Tag1, Tag2>
+{};
+
+
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_DISPATCH_CLOSEST_POINTS_HPP
diff --git a/boost/geometry/algorithms/dispatch/distance.hpp b/boost/geometry/algorithms/dispatch/distance.hpp
index 4d56a3aa0d..eb9cd92f66 100644
--- a/boost/geometry/algorithms/dispatch/distance.hpp
+++ b/boost/geometry/algorithms/dispatch/distance.hpp
@@ -70,6 +70,29 @@ struct distance_strategy_type<Geometry1, Geometry2, Strategies, true, true>
template
<
+ typename Geometry1, typename Geometry2, typename Strategies,
+ bool IsDynamicOrGC = util::is_dynamic_geometry<Geometry1>::value
+ || util::is_dynamic_geometry<Geometry2>::value
+ || util::is_geometry_collection<Geometry1>::value
+ || util::is_geometry_collection<Geometry2>::value
+>
+struct distance_strategy_tag
+{
+ using type = void;
+};
+
+template <typename Geometry1, typename Geometry2, typename Strategies>
+struct distance_strategy_tag<Geometry1, Geometry2, Strategies, false>
+{
+ using type = typename strategy::distance::services::tag
+ <
+ typename distance_strategy_type<Geometry1, Geometry2, Strategies>::type
+ >::type;
+};
+
+
+template
+<
typename Geometry1, typename Geometry2,
typename Strategy = typename strategies::distance::services::default_strategy
<
@@ -91,11 +114,11 @@ template
linear_tag,
areal_tag
>::type,
- typename StrategyTag = typename strategy::distance::services::tag
+ typename StrategyTag = typename distance_strategy_tag
<
- typename distance_strategy_type<Geometry1, Geometry2, Strategy>::type
+ Geometry1, Geometry2, Strategy
>::type,
- bool Reverse = reverse_dispatch<Geometry1, Geometry2>::type::value
+ bool Reverse = reverse_dispatch<Geometry1, Geometry2>::value
>
struct distance : not_implemented<Tag1, Tag2>
{};
diff --git a/boost/geometry/algorithms/equals.hpp b/boost/geometry/algorithms/equals.hpp
index 77b8977d22..38950df356 100644
--- a/boost/geometry/algorithms/equals.hpp
+++ b/boost/geometry/algorithms/equals.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2014-2015 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014, 2015, 2016, 2017.
-// Modifications copyright (c) 2014-2017 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -24,6 +24,7 @@
#include <boost/geometry/algorithms/detail/equals/interface.hpp>
#include <boost/geometry/algorithms/detail/equals/implementation.hpp>
+#include <boost/geometry/algorithms/detail/equals/implementation_gc.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_EQUALS_HPP
diff --git a/boost/geometry/algorithms/for_each.hpp b/boost/geometry/algorithms/for_each.hpp
index d1aa1b10fd..d03643ab1b 100644
--- a/boost/geometry/algorithms/for_each.hpp
+++ b/boost/geometry/algorithms/for_each.hpp
@@ -5,9 +5,9 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014-2020.
-// Modifications copyright (c) 2014-2020, Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2014-2023.
+// Modifications copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -22,14 +22,11 @@
#define BOOST_GEOMETRY_ALGORITHMS_FOR_EACH_HPP
-#include <algorithm>
-
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/reference.hpp>
#include <boost/range/value_type.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
@@ -42,9 +39,6 @@
#include <boost/geometry/geometries/segment.hpp>
-#include <boost/geometry/util/range.hpp>
-#include <boost/geometry/util/type_traits.hpp>
-
#include <boost/geometry/views/detail/indexed_point_view.hpp>
@@ -277,7 +271,10 @@ struct fe_segment_range_with_closure<open>
template <typename Range, typename Functor>
static inline bool apply(Range& range, Functor&& f)
{
- fe_segment_range_with_closure<closed>::apply(range, f);
+ if (! fe_segment_range_with_closure<closed>::apply(range, f))
+ {
+ return false;
+ }
auto const begin = boost::begin(range);
auto end = boost::end(range);
@@ -285,9 +282,9 @@ struct fe_segment_range_with_closure<open>
{
return true;
}
-
+
--end;
-
+
if (begin == end)
{
// single point ranges already handled in closed case above
@@ -323,9 +320,7 @@ struct for_each_polygon
return false;
}
- typename interior_return_type<Polygon>::type
- rings = interior_rings(poly);
-
+ auto&& rings = interior_rings(poly);
auto const end = boost::end(rings);
for (auto it = boost::begin(rings); it != end; ++it)
{
diff --git a/boost/geometry/algorithms/is_convex.hpp b/boost/geometry/algorithms/is_convex.hpp
index 036b0d6b80..afde6453f5 100644
--- a/boost/geometry/algorithms/is_convex.hpp
+++ b/boost/geometry/algorithms/is_convex.hpp
@@ -2,9 +2,9 @@
// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2017-2021.
-// Modifications copyright (c) 2017-2021 Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2017-2023.
+// Modifications copyright (c) 2017-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -17,19 +17,14 @@
#include <boost/range/empty.hpp>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
#include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
-#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/core/closure.hpp>
-#include <boost/geometry/core/cs.hpp>
-#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
-#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/interior_rings.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/iterators/ever_circling_iterator.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
@@ -53,10 +48,7 @@ struct ring_is_convex
static inline bool apply(Ring const& ring, Strategies const& strategies)
{
std::size_t n = boost::size(ring);
- if (boost::size(ring) < core_detail::closure::minimum_ring_size
- <
- geometry::closure<Ring>::value
- >::value)
+ if (n < detail::minimum_ring_size<Ring>::value)
{
// (Too) small rings are considered as non-concave, is convex
return true;
@@ -137,6 +129,18 @@ struct polygon_is_convex
}
};
+struct multi_polygon_is_convex
+{
+ template <typename MultiPolygon, typename Strategies>
+ static inline bool apply(MultiPolygon const& multi_polygon, Strategies const& strategies)
+ {
+ auto const size = boost::size(multi_polygon);
+ // TODO: this looks wrong, it should only return convex if all its rings are convex
+ return size == 0 // For consistency with ring_is_convex
+ || (size == 1 && polygon_is_convex::apply(range::front(multi_polygon), strategies));
+ }
+};
+
}} // namespace detail::is_convex
#endif // DOXYGEN_NO_DETAIL
@@ -151,14 +155,29 @@ template
typename Geometry,
typename Tag = typename tag<Geometry>::type
>
-struct is_convex : not_implemented<Tag>
-{};
+struct is_convex
+{
+ template <typename Strategies>
+ static inline bool apply(Geometry const&, Strategies const&)
+ {
+ // Convexity is not defined for PointLike and Linear geometries.
+ // We could implement this because the following definitions would work:
+ // - no line segment between two points on the interior or boundary ever goes outside.
+ // - convex_hull of geometry is equal to the original geometry, this implies equal
+ // topological dimension.
+ // For MultiPoint we'd have to check whether or not an arbitrary number of equal points
+ // is stored.
+ // MultiPolygon we'd have to check for continuous chain of Linestrings which would require
+ // the use of relate(pt, seg) or distance(pt, pt) strategy.
+ return false;
+ }
+};
template <typename Box>
struct is_convex<Box, box_tag>
{
- template <typename Strategy>
- static inline bool apply(Box const& , Strategy const& )
+ template <typename Strategies>
+ static inline bool apply(Box const& , Strategies const& )
{
// Any box is convex (TODO: consider spherical boxes)
// TODO: in spherical and geographic the answer would be "false" most of the time.
@@ -187,6 +206,10 @@ template <typename Polygon>
struct is_convex<Polygon, polygon_tag> : detail::is_convex::polygon_is_convex
{};
+template <typename MultiPolygon>
+struct is_convex<MultiPolygon, multi_polygon_tag> : detail::is_convex::multi_polygon_is_convex
+{};
+
} // namespace dispatch
#endif // DOXYGEN_NO_DISPATCH
@@ -238,51 +261,63 @@ struct is_convex<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant {
+namespace resolve_dynamic {
-template <typename Geometry>
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct is_convex
{
template <typename Strategy>
static bool apply(Geometry const& geometry, Strategy const& strategy)
{
- concepts::check<Geometry>();
+ concepts::check<Geometry const>();
return resolve_strategy::is_convex<Strategy>::apply(geometry, strategy);
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct is_convex<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct is_convex<Geometry, dynamic_geometry_tag>
{
template <typename Strategy>
- struct visitor: boost::static_visitor<bool>
+ static inline bool apply(Geometry const& geometry, Strategy const& strategy)
{
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy) : m_strategy(strategy) {}
-
- template <typename Geometry>
- bool operator()(Geometry const& geometry) const
+ bool result = false;
+ traits::visit<Geometry>::apply([&](auto const& g)
{
- return is_convex<Geometry>::apply(geometry, m_strategy);
- }
- };
+ result = is_convex<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
+ }, geometry);
+ return result;
+ }
+};
+// NOTE: This is a simple implementation checking if a GC contains single convex geometry.
+// Technically a GC could store e.g. polygons touching with edges and together creating a convex
+// region. To check this we'd require relate() strategy and the algorithm would be quite complex.
+template <typename Geometry>
+struct is_convex<Geometry, geometry_collection_tag>
+{
template <typename Strategy>
- static inline bool apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- Strategy const& strategy)
+ static inline bool apply(Geometry const& geometry, Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
+ bool result = false;
+ bool is_first = true;
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ result = is_first
+ && is_convex<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
+ is_first = false;
+ return result;
+ }, geometry);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
// TODO: documentation / qbk
template<typename Geometry>
inline bool is_convex(Geometry const& geometry)
{
- return resolve_variant::is_convex
+ return resolve_dynamic::is_convex
<
Geometry
>::apply(geometry, geometry::default_strategy());
@@ -292,7 +327,7 @@ inline bool is_convex(Geometry const& geometry)
template<typename Geometry, typename Strategy>
inline bool is_convex(Geometry const& geometry, Strategy const& strategy)
{
- return resolve_variant::is_convex<Geometry>::apply(geometry, strategy);
+ return resolve_dynamic::is_convex<Geometry>::apply(geometry, strategy);
}
diff --git a/boost/geometry/algorithms/is_empty.hpp b/boost/geometry/algorithms/is_empty.hpp
index 3fe5359fa3..ddb7faaf8b 100644
--- a/boost/geometry/algorithms/is_empty.hpp
+++ b/boost/geometry/algorithms/is_empty.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2015-2020, Oracle and/or its affiliates.
+// Copyright (c) 2015-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -15,21 +16,19 @@
#include <boost/range/empty.hpp>
#include <boost/range/end.hpp>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/visit.hpp>
-#include <boost/geometry/algorithms/not_implemented.hpp>
-
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
-
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/util/type_traits_std.hpp>
namespace boost { namespace geometry
{
@@ -62,10 +61,8 @@ class polygon_is_empty
template <typename InteriorRings>
static inline bool check_interior_rings(InteriorRings const& interior_rings)
{
- return check_iterator_range
- <
- range_is_empty, true // allow empty range
- >::apply(boost::begin(interior_rings), boost::end(interior_rings));
+ return std::all_of(boost::begin(interior_rings), boost::end(interior_rings),
+ []( auto const& range ){ return boost::empty(range); });
}
public:
@@ -83,12 +80,10 @@ struct multi_is_empty
template <typename MultiGeometry>
static inline bool apply(MultiGeometry const& multigeometry)
{
- return check_iterator_range
- <
- Policy, true // allow empty range
- >::apply(boost::begin(multigeometry), boost::end(multigeometry));
+ return std::all_of(boost::begin(multigeometry),
+ boost::end(multigeometry),
+ []( auto const& range ){ return Policy::apply(range); });
}
-
};
}} // namespace detail::is_empty
@@ -152,10 +147,10 @@ struct is_empty<Geometry, multi_polygon_tag>
#endif // DOXYGEN_NO_DISPATCH
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry>
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct is_empty
{
static inline bool apply(Geometry const& geometry)
@@ -166,26 +161,36 @@ struct is_empty
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct is_empty<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct is_empty<Geometry, dynamic_geometry_tag>
{
- struct visitor : boost::static_visitor<bool>
+ static inline bool apply(Geometry const& geometry)
{
- template <typename Geometry>
- inline bool operator()(Geometry const& geometry) const
+ bool result = true;
+ traits::visit<Geometry>::apply([&](auto const& g)
{
- return is_empty<Geometry>::apply(geometry);
- }
- };
+ result = is_empty<util::remove_cref_t<decltype(g)>>::apply(g);
+ }, geometry);
+ return result;
+ }
+};
- static bool
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
+template <typename Geometry>
+struct is_empty<Geometry, geometry_collection_tag>
+{
+ static inline bool apply(Geometry const& geometry)
{
- return boost::apply_visitor(visitor(), geometry);
+ bool result = true;
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ result = is_empty<util::remove_cref_t<decltype(g)>>::apply(g);
+ return result;
+ }, geometry);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -200,7 +205,7 @@ struct is_empty<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline bool is_empty(Geometry const& geometry)
{
- return resolve_variant::is_empty<Geometry>::apply(geometry);
+ return resolve_dynamic::is_empty<Geometry>::apply(geometry);
}
diff --git a/boost/geometry/algorithms/length.hpp b/boost/geometry/algorithms/length.hpp
index cc3219f585..6e4533896a 100644
--- a/boost/geometry/algorithms/length.hpp
+++ b/boost/geometry/algorithms/length.hpp
@@ -4,9 +4,9 @@
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2014-2023.
+// Modifications copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -20,22 +20,17 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_LENGTH_HPP
#define BOOST_GEOMETRY_ALGORITHMS_LENGTH_HPP
-#include <iterator>
-
-#include <boost/core/ignore_unused.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
-#include <boost/range/iterator.hpp>
#include <boost/range/value_type.hpp>
-#include <boost/geometry/algorithms/assign.hpp>
+#include "boost/geometry/algorithms/detail/assign_indexed_point.hpp"
#include <boost/geometry/algorithms/detail/calculate_null.hpp>
#include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
#include <boost/geometry/algorithms/detail/multi_sum.hpp>
// #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
#include <boost/geometry/algorithms/detail/visit.hpp>
-#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
diff --git a/boost/geometry/algorithms/line_interpolate.hpp b/boost/geometry/algorithms/line_interpolate.hpp
index a3b4b2ba83..5739c444ee 100644
--- a/boost/geometry/algorithms/line_interpolate.hpp
+++ b/boost/geometry/algorithms/line_interpolate.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2018-2021 Oracle and/or its affiliates.
+// Copyright (c) 2018-2023 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -11,21 +11,19 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_LINE_INTERPOLATE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_LINE_INTERPOLATE_HPP
-#include <iterator>
#include <type_traits>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
-#include <boost/range/iterator.hpp>
#include <boost/range/value_type.hpp>
+#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
#include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
-#include <boost/geometry/core/cs.hpp>
-#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/exception.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -37,6 +35,12 @@
#include <boost/geometry/strategies/line_interpolate/geographic.hpp>
#include <boost/geometry/strategies/line_interpolate/spherical.hpp>
+#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/range.hpp>
+#include <boost/geometry/util/type_traits.hpp>
+
+#include <boost/geometry/views/segment_view.hpp>
+
namespace boost { namespace geometry
{
@@ -86,11 +90,10 @@ struct interpolate_range
PointLike & pointlike,
Strategies const& strategies)
{
- typedef typename boost::range_iterator<Range const>::type iterator_t;
typedef typename boost::range_value<Range const>::type point_t;
- iterator_t it = boost::begin(range);
- iterator_t end = boost::end(range);
+ auto it = boost::begin(range);
+ auto const end = boost::end(range);
if (it == end) // empty(range)
{
@@ -109,7 +112,7 @@ struct interpolate_range
typedef decltype(pp_strategy.apply(
std::declval<point_t>(), std::declval<point_t>())) distance_type;
- iterator_t prev = it++;
+ auto prev = it++;
distance_type repeated_distance = max_distance;
distance_type prev_distance = 0;
distance_type current_distance = 0;
@@ -130,7 +133,7 @@ struct interpolate_range
p,
diff_distance);
Policy::apply(p, pointlike);
- if (std::is_same<PointLike, point_t>::value)
+ if ( BOOST_GEOMETRY_CONDITION(util::is_point<PointLike>::value) )
{
return;
}
@@ -256,7 +259,7 @@ struct line_interpolate<Strategy, false>
Distance const& max_distance,
Pointlike & pointlike,
Strategy const& strategy)
- {
+ {
using strategies::line_interpolate::services::strategy_converter;
dispatch::line_interpolate
@@ -275,7 +278,7 @@ struct line_interpolate<default_strategy, false>
Distance const& max_distance,
Pointlike & pointlike,
default_strategy)
- {
+ {
typedef typename strategies::line_interpolate::services::default_strategy
<
Geometry
diff --git a/boost/geometry/algorithms/make.hpp b/boost/geometry/algorithms/make.hpp
index b3a3034bf2..40cc5c0e4a 100644
--- a/boost/geometry/algorithms/make.hpp
+++ b/boost/geometry/algorithms/make.hpp
@@ -4,7 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// Copyright (c) 2020, Oracle and/or its affiliates.
+// Copyright (c) 2020-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -19,7 +20,7 @@
#include <type_traits>
-#include <boost/geometry/algorithms/assign.hpp>
+#include "boost/geometry/algorithms/detail/assign_values.hpp"
#include <boost/geometry/core/make.hpp>
diff --git a/boost/geometry/algorithms/merge_elements.hpp b/boost/geometry/algorithms/merge_elements.hpp
new file mode 100644
index 0000000000..76c1cf63ba
--- /dev/null
+++ b/boost/geometry/algorithms/merge_elements.hpp
@@ -0,0 +1,424 @@
+// Boost.Geometry
+
+// Copyright (c) 2022-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_ALGORITHMS_MERGE_ELEMENTS_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_MERGE_ELEMENTS_HPP
+
+
+#include <vector>
+
+#include <boost/geometry/algorithms/detail/point_on_border.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
+#include <boost/geometry/algorithms/difference.hpp>
+#include <boost/geometry/algorithms/union.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/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/geometries/point.hpp>
+#include <boost/geometry/policies/compare.hpp>
+#include <boost/geometry/util/range.hpp>
+#include <boost/geometry/strategies/relate/cartesian.hpp>
+#include <boost/geometry/strategies/relate/geographic.hpp>
+#include <boost/geometry/strategies/relate/spherical.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail { namespace merge_elements
+{
+
+
+template <typename T>
+using is_pla = util::bool_constant<util::is_pointlike<T>::value || util::is_linear<T>::value || util::is_areal<T>::value>;
+template <typename T, typename ...Ts>
+struct are_areal : util::bool_constant<util::is_areal<T>::value && are_areal<Ts...>::value> {};
+template <typename T>
+struct are_areal<T> : util::is_areal<T> {};
+template <typename T, typename ...Ts>
+struct are_linear : util::bool_constant<util::is_linear<T>::value && are_linear<Ts...>::value> {};
+template <typename T>
+struct are_linear<T> : util::is_linear<T> {};
+template <typename T, typename ...Ts>
+struct are_pointlike : util::bool_constant<util::is_pointlike<T>::value && are_pointlike<Ts...>::value> {};
+template <typename T>
+struct are_pointlike<T> : util::is_pointlike<T> {};
+template <typename ...Ts>
+using are_same_kind = util::bool_constant<are_areal<Ts...>::value || are_linear<Ts...>::value || are_pointlike<Ts...>::value>;
+
+
+template
+<
+ typename Geometry, typename It, typename PointLike, typename Linear, typename Areal,
+ std::enable_if_t<util::is_areal<Geometry>::value, int> = 0
+>
+inline void distribute_element(Geometry const& geometry, It it, PointLike& , Linear&, Areal& areal)
+{
+ typename geometry::point_type<Geometry>::type point;
+ if (geometry::point_on_border(point, geometry))
+ {
+ using point_t = typename Areal::value_type::first_type;
+ areal.emplace_back(point_t(geometry::get<0>(point), geometry::get<1>(point)), it);
+ }
+}
+
+template
+<
+ typename Geometry, typename It, typename PointLike, typename Linear, typename Areal,
+ std::enable_if_t<util::is_linear<Geometry>::value, int> = 0
+>
+inline void distribute_element(Geometry const& geometry, It it, PointLike& , Linear& linear, Areal& )
+{
+ typename geometry::point_type<Geometry>::type point;
+ if (geometry::point_on_border(point, geometry))
+ {
+ using point_t = typename Linear::value_type::first_type;
+ linear.emplace_back(point_t(geometry::get<0>(point), geometry::get<1>(point)), it);
+ }
+}
+
+template
+<
+ typename Geometry, typename It, typename PointLike, typename Linear, typename Areal,
+ std::enable_if_t<util::is_pointlike<Geometry>::value, int> = 0
+>
+inline void distribute_element(Geometry const& geometry, It it, PointLike& pointlike, Linear& , Areal& )
+{
+ typename geometry::point_type<Geometry>::type point;
+ if (geometry::point_on_border(point, geometry))
+ {
+ using point_t = typename Linear::value_type::first_type;
+ pointlike.emplace_back(point_t(geometry::get<0>(point), geometry::get<1>(point)), it);
+ }
+}
+
+template
+<
+ typename Geometry, typename It, typename PointLike, typename Linear, typename Areal,
+ std::enable_if_t<! is_pla<Geometry>::value, int> = 0
+>
+inline void distribute_element(Geometry const& , It const&, PointLike const& , Linear const&, Areal const&)
+{}
+
+
+template
+<
+ typename Geometry, typename MultiGeometry,
+ std::enable_if_t<are_same_kind<Geometry, MultiGeometry>::value, int> = 0
+>
+inline void convert(Geometry const& geometry, MultiGeometry& result)
+{
+ geometry::convert(geometry, result);
+}
+
+template
+<
+ typename Geometry, typename MultiGeometry,
+ std::enable_if_t<! are_same_kind<Geometry, MultiGeometry>::value, int> = 0
+>
+inline void convert(Geometry const& , MultiGeometry const& )
+{}
+
+
+template
+<
+ typename Geometry1, typename Geometry2, typename MultiGeometry, typename Strategy,
+ std::enable_if_t<are_same_kind<Geometry1, Geometry2, MultiGeometry>::value, int> = 0
+>
+inline void union_(Geometry1 const& geometry1, Geometry2 const& geometry2, MultiGeometry& result, Strategy const& strategy)
+{
+ geometry::union_(geometry1, geometry2, result, strategy);
+}
+
+template
+<
+ typename Geometry1, typename Geometry2, typename MultiGeometry, typename Strategy,
+ std::enable_if_t<! are_same_kind<Geometry1, Geometry2, MultiGeometry>::value, int> = 0
+>
+inline void union_(Geometry1 const& , Geometry2 const& , MultiGeometry const& , Strategy const&)
+{}
+
+
+template <typename It>
+struct merge_data
+{
+ merge_data(It first_, It last_)
+ : first(first_), last(last_)
+ {}
+ It first, last;
+ bool merge_results = false;
+};
+
+template <typename GeometryCollection, typename RandomIt, typename MultiGeometry, typename Strategy>
+inline void merge(RandomIt const first, RandomIt const last, MultiGeometry& out, Strategy const& strategy)
+{
+ auto const size = last - first;
+ if (size <= 0)
+ {
+ return;
+ }
+
+ auto const less = [](auto const& l, auto const& r)
+ {
+ return geometry::less<void, -1, Strategy>()(l.first, r.first);
+ };
+
+ std::vector<merge_data<RandomIt>> stack_in;
+ std::vector<MultiGeometry> stack_out;
+ stack_in.reserve(size / 2 + 1);
+ stack_out.reserve(size / 2 + 1);
+
+ stack_in.emplace_back(first, last);
+
+ while (! stack_in.empty())
+ {
+ auto & b = stack_in.back();
+ if (! b.merge_results)
+ {
+ auto const s = b.last - b.first;
+ if (s > 2)
+ {
+ RandomIt const mid = b.first + s / 2;
+ std::nth_element(b.first, mid, b.last, less);
+ RandomIt const fir = b.first;
+ RandomIt const las = b.last;
+ b.merge_results = true;
+ stack_in.emplace_back(fir, mid);
+ stack_in.emplace_back(mid, las);
+ }
+ else if (s == 2)
+ {
+ MultiGeometry result;
+ // VERSION 1
+// traits::iter_visit<GeometryCollection>::apply([&](auto const& g1)
+// {
+// traits::iter_visit<GeometryCollection>::apply([&](auto const& g2)
+// {
+// merge_elements::union_(g1, g2, result, strategy);
+// }, (b.first + 1)->second);
+// }, b.first->second);
+ // VERSION 2
+ // calling iter_visit non-recursively seems to decrease compilation time
+ // greately with GCC
+ MultiGeometry temp1, temp2;
+ traits::iter_visit<GeometryCollection>::apply([&](auto const& g1)
+ {
+ merge_elements::convert(g1, temp1);
+ }, b.first->second);
+ traits::iter_visit<GeometryCollection>::apply([&](auto const& g2)
+ {
+ merge_elements::convert(g2, temp2);
+ }, (b.first + 1)->second);
+ geometry::union_(temp1, temp2, result, strategy);
+
+ stack_out.push_back(std::move(result));
+ stack_in.pop_back();
+ }
+ else if (s == 1)
+ {
+ MultiGeometry result;
+ traits::iter_visit<GeometryCollection>::apply([&](auto const& g)
+ {
+ merge_elements::convert(g, result);
+ }, b.first->second);
+ stack_out.push_back(std::move(result));
+ stack_in.pop_back();
+ }
+ }
+ else if (b.merge_results)
+ {
+ MultiGeometry m2 = std::move(stack_out.back());
+ stack_out.pop_back();
+ MultiGeometry m1 = std::move(stack_out.back());
+ stack_out.pop_back();
+ MultiGeometry result;
+ geometry::union_(m1, m2, result, strategy);
+ stack_out.push_back(std::move(result));
+ stack_in.pop_back();
+ }
+ }
+
+ out = std::move(stack_out.back());
+}
+
+template <typename MultiGeometry, typename Geometry, typename Strategy>
+inline void subtract(MultiGeometry & multi, Geometry const& geometry, Strategy const& strategy)
+{
+ MultiGeometry temp;
+ geometry::difference(multi, geometry, temp, strategy);
+ multi = std::move(temp);
+}
+
+struct merge_gc
+{
+ template <typename GeometryCollection, typename Strategy>
+ static void apply(GeometryCollection const& geometry_collection,
+ GeometryCollection & out,
+ Strategy const& strategy)
+ {
+ using original_point_t = typename geometry::point_type<GeometryCollection>::type;
+ using iterator_t = typename boost::range_iterator<GeometryCollection const>::type;
+ using coordinate_t = typename geometry::coordinate_type<original_point_t>::type;
+ using cs_t = typename geometry::coordinate_system<original_point_t>::type;
+ using point_t = model::point<coordinate_t, 2, cs_t>;
+
+ using multi_point_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<std::remove_const_t<GeometryCollection>>::type,
+ util::is_multi_point
+ >::type;
+ using multi_linestring_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<std::remove_const_t<GeometryCollection>>::type,
+ util::is_multi_linestring
+ >::type;
+ using multi_polygon_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<std::remove_const_t<GeometryCollection>>::type,
+ util::is_multi_polygon
+ >::type;
+
+ // NOTE: Right now GC containing all of the above is required but technically
+ // we could allow only some combinations and the algorithm below could
+ // normalize GC accordingly.
+
+ multi_point_t multi_point;
+ multi_linestring_t multi_linestring;
+ multi_polygon_t multi_polygon;
+
+ std::vector<std::pair<point_t, iterator_t>> pointlike;
+ std::vector<std::pair<point_t, iterator_t>> linear;
+ std::vector<std::pair<point_t, iterator_t>> areal;
+
+ detail::visit_breadth_first_impl<true>::apply([&](auto const& g, auto it)
+ {
+ merge_elements::distribute_element(g, it, pointlike, linear, areal);
+ return true;
+ }, geometry_collection);
+
+ // TODO: make this optional?
+ // TODO: merge linear at the end? (difference can break linear rings, their parts would be joined)
+ merge<GeometryCollection>(pointlike.begin(), pointlike.end(), multi_point, strategy);
+ merge<GeometryCollection>(linear.begin(), linear.end(), multi_linestring, strategy);
+ merge<GeometryCollection>(areal.begin(), areal.end(), multi_polygon, strategy);
+
+ // L \ A
+ subtract(multi_linestring, multi_polygon, strategy);
+ // P \ A
+ subtract(multi_point, multi_polygon, strategy);
+ // P \ L
+ subtract(multi_point, multi_linestring, strategy);
+
+ if (! geometry::is_empty(multi_point))
+ {
+ range::emplace_back(out, std::move(multi_point));
+ }
+ if (! geometry::is_empty(multi_linestring))
+ {
+ range::emplace_back(out, std::move(multi_linestring));
+ }
+ if (! geometry::is_empty(multi_polygon))
+ {
+ range::emplace_back(out, std::move(multi_polygon));
+ }
+ }
+};
+
+
+}} // namespace detail::merge_elements
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
+struct merge_elements
+ : not_implemented<Geometry, Tag>
+{};
+
+template <typename GeometryCollection>
+struct merge_elements<GeometryCollection, geometry_collection_tag>
+ : geometry::detail::merge_elements::merge_gc
+{};
+
+
+} // namespace dispatch
+#endif
+
+
+namespace resolve_strategy
+{
+
+template <typename Strategy>
+struct merge_elements
+{
+ template <typename Geometry>
+ static void apply(Geometry const& geometry, Geometry & out, Strategy const& strategy)
+ {
+ dispatch::merge_elements
+ <
+ Geometry
+ >::apply(geometry, out, strategy);
+ }
+};
+
+template <>
+struct merge_elements<default_strategy>
+{
+ template <typename Geometry>
+ static void apply(Geometry const& geometry, Geometry & out, default_strategy)
+ {
+ using strategy_type = typename strategies::relate::services::default_strategy
+ <
+ Geometry, Geometry
+ >::type;
+
+ dispatch::merge_elements
+ <
+ Geometry
+ >::apply(geometry, out, strategy_type());
+ }
+};
+
+} // namespace resolve_strategy
+
+
+template <typename Geometry, typename Strategy>
+inline void merge_elements(Geometry const& geometry, Geometry & out, Strategy const& strategy)
+{
+ resolve_strategy::merge_elements
+ <
+ Strategy
+ >::apply(geometry, out, strategy);
+}
+
+
+template <typename Geometry>
+inline void merge_elements(Geometry const& geometry, Geometry & out)
+{
+ resolve_strategy::merge_elements
+ <
+ default_strategy
+ >::apply(geometry, out, default_strategy());
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_MERGE_ELEMENTS_HPP
diff --git a/boost/geometry/algorithms/num_points.hpp b/boost/geometry/algorithms/num_points.hpp
index a5d46833f7..ee1609dc71 100644
--- a/boost/geometry/algorithms/num_points.hpp
+++ b/boost/geometry/algorithms/num_points.hpp
@@ -5,8 +5,8 @@
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014-2020.
-// Modifications copyright (c) 2014-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2021.
+// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -26,21 +26,20 @@
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
+#include <boost/geometry/algorithms/detail/counting.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/visit.hpp>
-#include <boost/geometry/algorithms/not_implemented.hpp>
-
-#include <boost/geometry/algorithms/detail/counting.hpp>
-
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
+#include <boost/geometry/util/type_traits_std.hpp>
namespace boost { namespace geometry
{
@@ -140,48 +139,54 @@ struct num_points<Geometry, AddForOpen, multi_tag>
#endif
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry>
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct num_points
{
- static inline std::size_t apply(Geometry const& geometry,
- bool add_for_open)
+ static inline std::size_t apply(Geometry const& geometry, bool add_for_open)
{
concepts::check<Geometry const>();
return add_for_open
- ? dispatch::num_points<Geometry, true>::apply(geometry)
- : dispatch::num_points<Geometry, false>::apply(geometry);
+ ? dispatch::num_points<Geometry, true>::apply(geometry)
+ : dispatch::num_points<Geometry, false>::apply(geometry);
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct num_points<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct num_points<Geometry, dynamic_geometry_tag>
{
- struct visitor: boost::static_visitor<std::size_t>
+ static inline std::size_t apply(Geometry const& geometry, bool add_for_open)
{
- bool m_add_for_open;
-
- visitor(bool add_for_open): m_add_for_open(add_for_open) {}
-
- template <typename Geometry>
- inline std::size_t operator()(Geometry const& geometry) const
+ std::size_t result = 0;
+ traits::visit<Geometry>::apply([&](auto const& g)
{
- return num_points<Geometry>::apply(geometry, m_add_for_open);
- }
- };
+ result = num_points<util::remove_cref_t<decltype(g)>>::apply(g, add_for_open);
+ }, geometry);
+ return result;
+ }
+};
+
- static inline std::size_t
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- bool add_for_open)
+template <typename Geometry>
+struct num_points<Geometry, geometry_collection_tag>
+{
+ static inline std::size_t apply(Geometry const& geometry, bool add_for_open)
{
- return boost::apply_visitor(visitor(add_for_open), geometry);
+ std::size_t result = 0;
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ result += num_points<util::remove_cref_t<decltype(g)>>::apply(g, add_for_open);
+ return true;
+ }, geometry);
+ return result;
}
};
-} // namespace resolve_variant
+
+} // namespace resolve_dynamic
/*!
@@ -198,7 +203,7 @@ struct num_points<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline std::size_t num_points(Geometry const& geometry, bool add_for_open = false)
{
- return resolve_variant::num_points<Geometry>::apply(geometry, add_for_open);
+ return resolve_dynamic::num_points<Geometry>::apply(geometry, add_for_open);
}
#if defined(_MSC_VER)
diff --git a/boost/geometry/algorithms/num_segments.hpp b/boost/geometry/algorithms/num_segments.hpp
index 4868c09dc3..d73a8b4fc4 100644
--- a/boost/geometry/algorithms/num_segments.hpp
+++ b/boost/geometry/algorithms/num_segments.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -16,23 +17,18 @@
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
+#include <boost/geometry/algorithms/detail/counting.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
+#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/visit.hpp>
-#include <boost/geometry/util/range.hpp>
-
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
-#include <boost/geometry/algorithms/not_implemented.hpp>
-
-#include <boost/geometry/algorithms/detail/counting.hpp>
-
-
namespace boost { namespace geometry
{
@@ -140,11 +136,11 @@ struct num_segments<Geometry, multi_polygon_tag>
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry>
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct num_segments
{
static inline std::size_t apply(Geometry const& geometry)
@@ -156,27 +152,38 @@ struct num_segments
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct num_segments<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct num_segments<Geometry, dynamic_geometry_tag>
{
- struct visitor: boost::static_visitor<std::size_t>
+ static inline std::size_t apply(Geometry const& geometry)
{
- template <typename Geometry>
- inline std::size_t operator()(Geometry const& geometry) const
+ std::size_t result = 0;
+ traits::visit<Geometry>::apply([&](auto const& g)
{
- return num_segments<Geometry>::apply(geometry);
- }
- };
+ result = num_segments<util::remove_cref_t<decltype(g)>>::apply(g);
+ }, geometry);
+ return result;
+ }
+};
- static inline std::size_t
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry)
+
+template <typename Geometry>
+struct num_segments<Geometry, geometry_collection_tag>
+{
+ static inline std::size_t apply(Geometry const& geometry)
{
- return boost::apply_visitor(visitor(), geometry);
+ std::size_t result = 0;
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ result += num_segments<util::remove_cref_t<decltype(g)>>::apply(g);
+ return true;
+ }, geometry);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
@@ -193,7 +200,7 @@ struct num_segments<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline std::size_t num_segments(Geometry const& geometry)
{
- return resolve_variant::num_segments<Geometry>::apply(geometry);
+ return resolve_dynamic::num_segments<Geometry>::apply(geometry);
}
diff --git a/boost/geometry/algorithms/perimeter.hpp b/boost/geometry/algorithms/perimeter.hpp
index ff88857ed2..3b7f7e693c 100644
--- a/boost/geometry/algorithms/perimeter.hpp
+++ b/boost/geometry/algorithms/perimeter.hpp
@@ -4,8 +4,9 @@
// Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2023.
+// Modifications copyright (c) 2014-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -21,20 +22,18 @@
#include <boost/range/value_type.hpp>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.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/multi_sum.hpp>
// #include <boost/geometry/algorithms/detail/throw_on_empty_input.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
-#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/strategies/default_length_result.hpp>
@@ -162,9 +161,9 @@ struct perimeter<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant {
+namespace resolve_dynamic {
-template <typename Geometry>
+template <typename Geometry, typename Tag = typename geometry::tag<Geometry>::type>
struct perimeter
{
template <typename Strategy>
@@ -176,39 +175,40 @@ struct perimeter
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct perimeter<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct perimeter<Geometry, dynamic_geometry_tag>
{
- typedef typename default_length_result
- <
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>
- >::type result_type;
-
template <typename Strategy>
- struct visitor: boost::static_visitor<result_type>
+ static inline typename default_length_result<Geometry>::type
+ apply(Geometry const& geometry, Strategy const& strategy)
{
- Strategy const& m_strategy;
-
- visitor(Strategy const& strategy): m_strategy(strategy) {}
-
- template <typename Geometry>
- typename default_length_result<Geometry>::type
- operator()(Geometry const& geometry) const
+ typename default_length_result<Geometry>::type result = 0;
+ traits::visit<Geometry>::apply([&](auto const& g)
{
- return perimeter<Geometry>::apply(geometry, m_strategy);
- }
- };
+ result = perimeter<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
+ }, geometry);
+ return result;
+ }
+};
+template <typename Geometry>
+struct perimeter<Geometry, geometry_collection_tag>
+{
template <typename Strategy>
- static inline result_type
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- Strategy const& strategy)
+ static inline typename default_length_result<Geometry>::type
+ apply(Geometry const& geometry, Strategy const& strategy)
{
- return boost::apply_visitor(visitor<Strategy>(strategy), geometry);
+ typename default_length_result<Geometry>::type result = 0;
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ result += perimeter<util::remove_cref_t<decltype(g)>>::apply(g, strategy);
+ return true;
+ }, geometry);
+ return result;
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -232,7 +232,7 @@ inline typename default_length_result<Geometry>::type perimeter(
Geometry const& geometry)
{
// detail::throw_on_empty_input(geometry);
- return resolve_variant::perimeter<Geometry>::apply(geometry, default_strategy());
+ return resolve_dynamic::perimeter<Geometry>::apply(geometry, default_strategy());
}
/*!
@@ -254,7 +254,7 @@ inline typename default_length_result<Geometry>::type perimeter(
Geometry const& geometry, Strategy const& strategy)
{
// detail::throw_on_empty_input(geometry);
- return resolve_variant::perimeter<Geometry>::apply(geometry, strategy);
+ return resolve_dynamic::perimeter<Geometry>::apply(geometry, strategy);
}
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/point_on_surface.hpp b/boost/geometry/algorithms/point_on_surface.hpp
index 803f71a91d..5b90db472a 100644
--- a/boost/geometry/algorithms/point_on_surface.hpp
+++ b/boost/geometry/algorithms/point_on_surface.hpp
@@ -5,8 +5,9 @@
// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2014-2020.
-// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2023.
+// Modifications copyright (c) 2014-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -16,23 +17,16 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_POINT_ON_SURFACE_HPP
#define BOOST_GEOMETRY_ALGORITHMS_POINT_ON_SURFACE_HPP
-
-#include <cstddef>
-#include <numeric>
-
-#include <boost/concept_check.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.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/detail/extreme_points.hpp>
#include <boost/geometry/algorithms/detail/signed_size_type.hpp>
-#include <boost/geometry/strategies/cartesian/centroid_bashein_detmer.hpp>
#include <boost/geometry/strategies/side.hpp>
@@ -82,11 +76,11 @@ template <int Dimension, typename Collection, typename Value, typename Predicate
inline bool max_value(Collection const& collection, Value& the_max, Predicate const& predicate)
{
bool first = true;
- for (typename Collection::const_iterator it = collection.begin(); it != collection.end(); ++it)
+ for (auto const& item : collection)
{
- if (! it->empty())
+ if (! item.empty())
{
- Value the_value = geometry::get<Dimension>(*std::max_element(it->begin(), it->end(), predicate));
+ Value the_value = geometry::get<Dimension>(*std::max_element(item.begin(), item.end(), predicate));
if (first || the_value > the_max)
{
the_max = the_value;
@@ -153,16 +147,14 @@ template <typename Point, typename P>
inline void calculate_average(Point& point, std::vector<P> const& points)
{
typedef typename geometry::coordinate_type<Point>::type coordinate_type;
- typedef typename std::vector<P>::const_iterator iterator_type;
coordinate_type x = 0;
coordinate_type y = 0;
- iterator_type end = points.end();
- for ( iterator_type it = points.begin() ; it != end ; ++it)
+ for (auto const& p : points)
{
- x += geometry::get<0>(*it);
- y += geometry::get<1>(*it);
+ x += geometry::get<0>(p);
+ y += geometry::get<1>(p);
}
signed_size_type const count = points.size();
diff --git a/boost/geometry/algorithms/relate.hpp b/boost/geometry/algorithms/relate.hpp
index 34733ec596..e560d2df1a 100644
--- a/boost/geometry/algorithms/relate.hpp
+++ b/boost/geometry/algorithms/relate.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2015 Oracle and/or its affiliates.
+// Copyright (c) 2015-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -13,5 +13,7 @@
#include <boost/geometry/algorithms/detail/relate/interface.hpp>
#include <boost/geometry/algorithms/detail/relate/implementation.hpp>
+// Implementation is divided into two files to avoid cyclic dependency with set operations
+#include <boost/geometry/algorithms/detail/relate/implementation_gc.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_RELATE_HPP
diff --git a/boost/geometry/algorithms/relation.hpp b/boost/geometry/algorithms/relation.hpp
index c3cf2f99f8..f727815307 100644
--- a/boost/geometry/algorithms/relation.hpp
+++ b/boost/geometry/algorithms/relation.hpp
@@ -13,5 +13,6 @@
#include <boost/geometry/algorithms/detail/relation/interface.hpp>
#include <boost/geometry/algorithms/detail/relation/implementation.hpp>
+#include <boost/geometry/algorithms/detail/relate/implementation_gc.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_RELATION_HPP
diff --git a/boost/geometry/algorithms/remove_spikes.hpp b/boost/geometry/algorithms/remove_spikes.hpp
index ad631183d5..7a144db154 100644
--- a/boost/geometry/algorithms/remove_spikes.hpp
+++ b/boost/geometry/algorithms/remove_spikes.hpp
@@ -5,9 +5,9 @@
// Copyright (c) 2009-2013 Mateusz Loskot, London, UK.
// Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017-2020.
-// Modifications copyright (c) 2017-2020 Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2017-2023.
+// Modifications copyright (c) 2017-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -17,8 +17,6 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_REMOVE_SPIKES_HPP
#define BOOST_GEOMETRY_ALGORITHMS_REMOVE_SPIKES_HPP
-#include <deque>
-
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
@@ -28,16 +26,13 @@
#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/core/closure.hpp>
-#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/interior_rings.hpp>
-#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/algorithms/detail/point_is_spike_or_equal.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
@@ -88,11 +83,10 @@ struct range_remove_spikes
std::vector<point_type> cleaned;
cleaned.reserve(n);
- for (typename boost::range_iterator<Range const>::type it = boost::begin(range);
- it != boost::end(range); ++it)
+ for (auto const& p : range)
{
// Add point
- cleaned.push_back(*it);
+ cleaned.push_back(p);
while(cleaned.size() >= 3
&& detail::is_spike_or_equal(range::at(cleaned, cleaned.size() - 3),
@@ -105,9 +99,8 @@ struct range_remove_spikes
}
}
- typedef typename std::vector<point_type>::iterator cleaned_iterator;
- cleaned_iterator cleaned_b = cleaned.begin();
- cleaned_iterator cleaned_e = cleaned.end();
+ auto cleaned_b = cleaned.begin();
+ auto cleaned_e = cleaned.end();
std::size_t cleaned_count = cleaned.size();
// For a closed-polygon, remove closing point, this makes checking first point(s) easier and consistent
@@ -178,11 +171,9 @@ struct polygon_remove_spikes
typedef range_remove_spikes per_range;
per_range::apply(exterior_ring(polygon), strategy);
- typename interior_return_type<Polygon>::type
- rings = interior_rings(polygon);
+ auto&& rings = interior_rings(polygon);
- for (typename detail::interior_iterator<Polygon>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
per_range::apply(*it, strategy);
}
@@ -196,10 +187,7 @@ struct multi_remove_spikes
template <typename MultiGeometry, typename SideStrategy>
static inline void apply(MultiGeometry& multi, SideStrategy const& strategy)
{
- for (typename boost::range_iterator<MultiGeometry>::type
- it = boost::begin(multi);
- it != boost::end(multi);
- ++it)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
SingleVersion::apply(*it, strategy);
}
diff --git a/boost/geometry/algorithms/reverse.hpp b/boost/geometry/algorithms/reverse.hpp
index f124ee615c..307f8294fa 100644
--- a/boost/geometry/algorithms/reverse.hpp
+++ b/boost/geometry/algorithms/reverse.hpp
@@ -5,8 +5,9 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2023.
+// Modifications copyright (c) 2020-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -24,14 +25,12 @@
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/detail/multi_modify.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -61,11 +60,9 @@ struct polygon_reverse: private range_reverse
{
range_reverse::apply(exterior_ring(polygon));
- typename interior_return_type<Polygon>::type
- rings = interior_rings(polygon);
-
- for (typename detail::interior_iterator<Polygon>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ auto&& rings = interior_rings(polygon);
+ auto const end = boost::end(rings);
+ for (auto it = boost::begin(rings); it != end; ++it)
{
range_reverse::apply(*it);
}
@@ -110,21 +107,13 @@ struct reverse<Polygon, polygon_tag>
template <typename Geometry>
struct reverse<Geometry, multi_linestring_tag>
- : detail::multi_modify
- <
- Geometry,
- detail::reverse::range_reverse
- >
+ : detail::multi_modify<detail::reverse::range_reverse>
{};
template <typename Geometry>
struct reverse<Geometry, multi_polygon_tag>
- : detail::multi_modify
- <
- Geometry,
- detail::reverse::polygon_reverse
- >
+ : detail::multi_modify<detail::reverse::polygon_reverse>
{};
@@ -133,10 +122,10 @@ struct reverse<Geometry, multi_polygon_tag>
#endif
-namespace resolve_variant
+namespace resolve_dynamic
{
-template <typename Geometry>
+template <typename Geometry, typename Tag = typename tag<Geometry>::type>
struct reverse
{
static void apply(Geometry& geometry)
@@ -146,25 +135,32 @@ struct reverse
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct reverse<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry>
+struct reverse<Geometry, dynamic_geometry_tag>
{
- struct visitor: boost::static_visitor<void>
+ static void apply(Geometry& geometry)
{
- template <typename Geometry>
- void operator()(Geometry& geometry) const
+ traits::visit<Geometry>::apply([](auto & g)
{
- reverse<Geometry>::apply(geometry);
- }
- };
+ reverse<util::remove_cref_t<decltype(g)>>::apply(g);
+ }, geometry);
+ }
+};
- static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry)
+template <typename Geometry>
+struct reverse<Geometry, geometry_collection_tag>
+{
+ static void apply(Geometry& geometry)
{
- boost::apply_visitor(visitor(), geometry);
+ detail::visit_breadth_first([](auto & g)
+ {
+ reverse<util::remove_cref_t<decltype(g)>>::apply(g);
+ return true;
+ }, geometry);
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
@@ -181,7 +177,7 @@ struct reverse<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
template <typename Geometry>
inline void reverse(Geometry& geometry)
{
- resolve_variant::reverse<Geometry>::apply(geometry);
+ resolve_dynamic::reverse<Geometry>::apply(geometry);
}
}} // namespace boost::geometry
diff --git a/boost/geometry/algorithms/simplify.hpp b/boost/geometry/algorithms/simplify.hpp
index bea8f6cbaa..40c66e91a8 100644
--- a/boost/geometry/algorithms/simplify.hpp
+++ b/boost/geometry/algorithms/simplify.hpp
@@ -3,9 +3,11 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2018-2021.
-// Modifications copyright (c) 2018-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2018-2023.
+// Modifications copyright (c) 2018-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -26,20 +28,17 @@
#include <vector>
#include <boost/core/addressof.hpp>
-#include <boost/core/ignore_unused.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
#include <boost/geometry/algorithms/area.hpp>
#include <boost/geometry/algorithms/clear.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/dummy_geometries.hpp>
#include <boost/geometry/algorithms/detail/equals/point_point.hpp>
+#include <boost/geometry/algorithms/detail/visit.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/perimeter.hpp>
@@ -50,16 +49,20 @@
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/mutable_range.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp> // For backward compatibility
#include <boost/geometry/geometries/concepts/check.hpp>
-#include <boost/geometry/strategies/concepts/simplify_concept.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
#include <boost/geometry/strategies/detail.hpp>
+#include <boost/geometry/strategies/distance/comparable.hpp>
#include <boost/geometry/strategies/simplify/cartesian.hpp>
#include <boost/geometry/strategies/simplify/geographic.hpp>
#include <boost/geometry/strategies/simplify/spherical.hpp>
+#include <boost/geometry/util/type_traits_std.hpp>
+
#ifdef BOOST_GEOMETRY_DEBUG_DOUGLAS_PEUCKER
#include <boost/geometry/io/dsv/write.hpp>
#endif
@@ -95,10 +98,8 @@ struct douglas_peucker_point
\brief Implements the simplify algorithm.
\details The douglas_peucker policy simplifies a linestring, ring or
vector of points using the well-known Douglas-Peucker algorithm.
-\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
+\note This strategy uses itself a point-segment potentially comparable
+ distance strategy
\author Barend and Maarten, 1995/1996
\author Barend, revised for Generic Geometry Library, 2008
*/
@@ -301,6 +302,23 @@ struct simplify_range_insert
};
+struct simplify_copy_assign
+{
+ template
+ <
+ typename In, typename Out, typename Distance,
+ typename Impl, typename Strategies
+ >
+ static inline void apply(In const& in, Out& out,
+ Distance const& ,
+ Impl const& ,
+ Strategies const& )
+ {
+ out = in;
+ }
+};
+
+
struct simplify_copy
{
template
@@ -369,29 +387,27 @@ private :
static std::size_t get_opposite(std::size_t index, Ring const& ring,
Strategies const& strategies)
{
- // TODO: Use Pt-Pt distance strategy instead?
- // TODO: Use comparable distance strategy
+ // TODO: Instead of calling the strategy call geometry::comparable_distance() ?
- auto distance_strategy = strategies.distance(detail::dummy_point(), detail::dummy_segment());
+ auto const cdistance_strategy = strategies::distance::detail::make_comparable(strategies)
+ .distance(detail::dummy_point(), detail::dummy_point());
- typedef typename geometry::point_type<Ring>::type point_type;
- typedef decltype(distance_strategy.apply(std::declval<point_type>(),
- std::declval<point_type>(), std::declval<point_type>())) distance_type;
+ using point_type = typename geometry::point_type<Ring>::type;
+ using cdistance_type = decltype(cdistance_strategy.apply(
+ std::declval<point_type>(), std::declval<point_type>()));
// Verify if it is NOT the case that all points are less than the
// simplifying distance. If so, output is empty.
- distance_type max_distance(-1);
+ cdistance_type max_cdistance(-1);
point_type const& point = range::at(ring, index);
std::size_t i = 0;
for (auto it = boost::begin(ring); it != boost::end(ring); ++it, ++i)
{
- // This actually is point-segment distance but will result
- // in point-point distance
- distance_type dist = distance_strategy.apply(*it, point, point);
- if (dist > max_distance)
+ cdistance_type const cdistance = cdistance_strategy.apply(*it, point);
+ if (cdistance > max_cdistance)
{
- max_distance = dist;
+ max_cdistance = cdistance;
index = i;
}
}
@@ -399,8 +415,12 @@ private :
}
public :
- template <typename Ring, typename Distance, typename Impl, typename Strategies>
- static inline void apply(Ring const& ring, Ring& out, Distance const& max_distance,
+ template
+ <
+ typename RingIn, typename RingOut,
+ typename Distance, typename Impl, typename Strategies
+ >
+ static inline void apply(RingIn const& ring, RingOut& out, Distance const& max_distance,
Impl const& impl, Strategies const& strategies)
{
std::size_t const size = boost::size(ring);
@@ -409,6 +429,11 @@ public :
return;
}
+ bool const is_closed_in = geometry::closure<RingIn>::value == closed;
+ bool const is_closed_out = geometry::closure<RingOut>::value == closed;
+ bool const is_clockwise_in = geometry::point_order<RingIn>::value == clockwise;
+ bool const is_clockwise_out = geometry::point_order<RingOut>::value == clockwise;
+
// TODO: instead of area() use calculate_point_order() ?
int const input_sign = area_sign(geometry::area(ring, strategies));
@@ -418,9 +443,10 @@ public :
// Rotate it into a copied vector
// (vector, because source type might not support rotation)
// (duplicate end point will be simplified away)
- typedef typename geometry::point_type<Ring>::type point_type;
+ typedef typename geometry::point_type<RingIn>::type point_type;
- std::vector<point_type> rotated(size);
+ std::vector<point_type> rotated;
+ rotated.reserve(size + 1); // 1 because open rings are closed
// Closing point (but it will not start here)
std::size_t index = 0;
@@ -453,14 +479,29 @@ public :
continue;
}
- std::rotate_copy(boost::begin(ring), range::pos(ring, index),
- boost::end(ring), rotated.begin());
+ // Do not duplicate the closing point
+ auto rot_end = boost::end(ring);
+ std::size_t rot_index = index;
+ if (BOOST_GEOMETRY_CONDITION(is_closed_in) && size > 1)
+ {
+ --rot_end;
+ if (rot_index == size - 1) { rot_index = 0; }
+ }
+
+ std::rotate_copy(boost::begin(ring), range::pos(ring, rot_index),
+ rot_end, std::back_inserter(rotated));
// Close the rotated copy
- rotated.push_back(range::at(ring, index));
+ rotated.push_back(range::at(ring, rot_index));
simplify_range<0>::apply(rotated, out, max_distance, impl, strategies);
+ // Open output if needed
+ if (BOOST_GEOMETRY_CONDITION(! is_closed_out) && boost::size(out) > 1)
+ {
+ range::pop_back(out);
+ }
+
// TODO: instead of area() use calculate_point_order() ?
// Verify that what was positive, stays positive (or goes to 0)
@@ -488,7 +529,12 @@ public :
// Prepare next try
visited_indexes.insert(index);
- rotated.resize(size);
+ rotated.clear();
+ }
+
+ if (BOOST_GEOMETRY_CONDITION(is_clockwise_in != is_clockwise_out))
+ {
+ std::reverse(boost::begin(out), boost::end(out));
}
}
};
@@ -545,8 +591,12 @@ private:
}
public:
- template <typename Polygon, typename Distance, typename Impl, typename Strategies>
- static inline void apply(Polygon const& poly_in, Polygon& poly_out,
+ template
+ <
+ typename PolygonIn, typename PolygonOut,
+ typename Distance, typename Impl, typename Strategies
+ >
+ static inline void apply(PolygonIn const& poly_in, PolygonOut& poly_out,
Distance const& max_distance,
Impl const& impl, Strategies const& strategies)
{
@@ -565,17 +615,20 @@ public:
template<typename Policy>
struct simplify_multi
{
- template <typename MultiGeometry, typename Distance, typename Impl, typename Strategies>
- static inline void apply(MultiGeometry const& multi, MultiGeometry& out,
+ template
+ <
+ typename MultiGeometryIn, typename MultiGeometryOut,
+ typename Distance, typename Impl, typename Strategies
+ >
+ static inline void apply(MultiGeometryIn const& multi, MultiGeometryOut& out,
Distance const& max_distance,
Impl const& impl, Strategies const& strategies)
{
range::clear(out);
- typedef typename boost::range_value<MultiGeometry>::type single_type;
+ using single_type = typename boost::range_value<MultiGeometryOut>::type;
- for (typename boost::range_iterator<MultiGeometry const>::type
- it = boost::begin(multi); it != boost::end(multi); ++it)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
single_type single_out;
Policy::apply(*it, single_out, max_distance, impl, strategies);
@@ -588,6 +641,35 @@ struct simplify_multi
};
+template <typename Geometry>
+struct has_same_tag_as
+{
+ template <typename OtherGeometry>
+ struct pred
+ : std::is_same
+ <
+ typename geometry::tag<Geometry>::type,
+ typename geometry::tag<OtherGeometry>::type
+ >
+ {};
+};
+
+template <typename StaticGeometryIn, typename DynamicGeometryOut>
+struct static_geometry_type
+{
+ using type = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<DynamicGeometryOut>::type,
+ detail::simplify::has_same_tag_as<StaticGeometryIn>::template pred
+ >::type;
+
+ BOOST_GEOMETRY_STATIC_ASSERT(
+ (! std::is_void<type>::value),
+ "Unable to find corresponding geometry in GeometryOut",
+ StaticGeometryIn, DynamicGeometryOut);
+};
+
+
}} // namespace detail::simplify
#endif // DOXYGEN_NO_DETAIL
@@ -598,39 +680,66 @@ namespace dispatch
template
<
- typename Geometry,
- typename Tag = typename tag<Geometry>::type
+ typename GeometryIn,
+ typename GeometryOut,
+ typename TagIn = typename tag<GeometryIn>::type,
+ typename TagOut = typename tag<GeometryOut>::type
>
-struct simplify: not_implemented<Tag>
+struct simplify: not_implemented<TagIn, TagOut>
{};
-template <typename Point>
-struct simplify<Point, point_tag>
+template <typename PointIn, typename PointOut>
+struct simplify<PointIn, PointOut, point_tag, point_tag>
{
template <typename Distance, typename Impl, typename Strategy>
- static inline void apply(Point const& point, Point& out, Distance const& ,
+ static inline void apply(PointIn const& point, PointOut& out, Distance const& ,
Impl const& , Strategy const& )
{
geometry::convert(point, out);
}
};
+template <typename SegmentIn, typename SegmentOut>
+struct simplify<SegmentIn, SegmentOut, segment_tag, segment_tag>
+ : detail::simplify::simplify_copy_assign
+{};
+
+template <typename BoxIn, typename BoxOut>
+struct simplify<BoxIn, BoxOut, box_tag, box_tag>
+ : detail::simplify::simplify_copy_assign
+{};
+
// Linestring, keep 2 points (unless those points are the same)
-template <typename Linestring>
-struct simplify<Linestring, linestring_tag>
+template <typename LinestringIn, typename LinestringOut>
+struct simplify<LinestringIn, LinestringOut, linestring_tag, linestring_tag>
: detail::simplify::simplify_range<2>
{};
-template <typename Ring>
-struct simplify<Ring, ring_tag>
+template <typename RingIn, typename RingOut>
+struct simplify<RingIn, RingOut, ring_tag, ring_tag>
: detail::simplify::simplify_ring
{};
-template <typename Polygon>
-struct simplify<Polygon, polygon_tag>
+template <typename PolygonIn, typename PolygonOut>
+struct simplify<PolygonIn, PolygonOut, polygon_tag, polygon_tag>
: detail::simplify::simplify_polygon
{};
+template <typename MultiPointIn, typename MultiPointOut>
+struct simplify<MultiPointIn, MultiPointOut, multi_point_tag, multi_point_tag>
+ : detail::simplify::simplify_copy
+{};
+
+template <typename MultiLinestringIn, typename MultiLinestringOut>
+struct simplify<MultiLinestringIn, MultiLinestringOut, multi_linestring_tag, multi_linestring_tag>
+ : detail::simplify::simplify_multi<detail::simplify::simplify_range<2> >
+{};
+
+template <typename MultiPolygonIn, typename MultiPolygonOut>
+struct simplify<MultiPolygonIn, MultiPolygonOut, multi_polygon_tag, multi_polygon_tag>
+ : detail::simplify::simplify_multi<detail::simplify::simplify_polygon>
+{};
+
template
<
@@ -651,23 +760,6 @@ struct simplify_insert<Ring, ring_tag>
: detail::simplify::simplify_range_insert
{};
-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
@@ -683,15 +775,15 @@ template
>
struct simplify
{
- template <typename Geometry, typename Distance>
- static inline void apply(Geometry const& geometry,
- Geometry& out,
+ template <typename GeometryIn, typename GeometryOut, typename Distance>
+ static inline void apply(GeometryIn const& geometry,
+ GeometryOut& out,
Distance const& max_distance,
Strategies const& strategies)
{
dispatch::simplify
<
- Geometry
+ GeometryIn, GeometryOut
>::apply(geometry, out, max_distance,
detail::simplify::douglas_peucker(),
strategies);
@@ -701,9 +793,9 @@ struct simplify
template <typename Strategy>
struct simplify<Strategy, false>
{
- template <typename Geometry, typename Distance>
- static inline void apply(Geometry const& geometry,
- Geometry& out,
+ template <typename GeometryIn, typename GeometryOut, typename Distance>
+ static inline void apply(GeometryIn const& geometry,
+ GeometryOut& out,
Distance const& max_distance,
Strategy const& strategy)
{
@@ -720,15 +812,23 @@ struct simplify<Strategy, false>
template <>
struct simplify<default_strategy, false>
{
- template <typename Geometry, typename Distance>
- static inline void apply(Geometry const& geometry,
- Geometry& out,
+ template <typename GeometryIn, typename GeometryOut, typename Distance>
+ static inline void apply(GeometryIn const& geometry,
+ GeometryOut& out,
Distance const& max_distance,
default_strategy)
{
+ // NOTE: Alternatively take two geometry types in default_strategy
+ using cs_tag1_t = typename geometry::cs_tag<GeometryIn>::type;
+ using cs_tag2_t = typename geometry::cs_tag<GeometryOut>::type;
+ BOOST_GEOMETRY_STATIC_ASSERT(
+ (std::is_same<cs_tag1_t, cs_tag2_t>::value),
+ "Incompatible coordinate systems",
+ cs_tag1_t, cs_tag2_t);
+
typedef typename strategies::simplify::services::default_strategy
<
- Geometry
+ GeometryIn
>::type strategy_type;
simplify
@@ -792,7 +892,7 @@ struct simplify_insert<default_strategy, false>
<
Geometry
>::type strategy_type;
-
+
simplify_insert
<
strategy_type
@@ -803,14 +903,19 @@ struct simplify_insert<default_strategy, false>
} // namespace resolve_strategy
-namespace resolve_variant {
+namespace resolve_dynamic {
-template <typename Geometry>
+template
+<
+ typename GeometryIn, typename GeometryOut,
+ typename TagIn = typename tag<GeometryIn>::type,
+ typename TagOut = typename tag<GeometryOut>::type
+>
struct simplify
{
template <typename Distance, typename Strategy>
- static inline void apply(Geometry const& geometry,
- Geometry& out,
+ static inline void apply(GeometryIn const& geometry,
+ GeometryOut& out,
Distance const& max_distance,
Strategy const& strategy)
{
@@ -818,49 +923,57 @@ struct simplify
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct simplify<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename GeometryIn, typename GeometryOut>
+struct simplify<GeometryIn, GeometryOut, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Distance, typename Strategy>
- struct visitor: boost::static_visitor<void>
+ static inline void apply(GeometryIn const& geometry,
+ GeometryOut& out,
+ Distance const& max_distance,
+ Strategy const& strategy)
{
- Distance const& m_max_distance;
- Strategy const& m_strategy;
-
- visitor(Distance const& max_distance, Strategy const& strategy)
- : m_max_distance(max_distance)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry>
- void operator()(Geometry const& geometry, Geometry& out) const
+ traits::visit<GeometryIn>::apply([&](auto const& g)
{
- simplify<Geometry>::apply(geometry, out, m_max_distance, m_strategy);
- }
- };
+ using geom_t = util::remove_cref_t<decltype(g)>;
+ using detail::simplify::static_geometry_type;
+ using geom_out_t = typename static_geometry_type<geom_t, GeometryOut>::type;
+ geom_out_t o;
+ simplify<geom_t, geom_out_t>::apply(g, o, max_distance, strategy);
+ out = std::move(o);
+ }, geometry);
+ }
+};
+template <typename GeometryIn, typename GeometryOut>
+struct simplify<GeometryIn, GeometryOut, geometry_collection_tag, geometry_collection_tag>
+{
template <typename Distance, typename Strategy>
- static inline void
- apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
- boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& out,
- Distance const& max_distance,
- Strategy const& strategy)
+ static inline void apply(GeometryIn const& geometry,
+ GeometryOut& out,
+ Distance const& max_distance,
+ Strategy const& strategy)
{
- boost::apply_visitor(
- visitor<Distance, Strategy>(max_distance, strategy),
- geometry,
- out
- );
+ detail::visit_breadth_first([&](auto const& g)
+ {
+ using geom_t = util::remove_cref_t<decltype(g)>;
+ using detail::simplify::static_geometry_type;
+ using geom_out_t = typename static_geometry_type<geom_t, GeometryOut>::type;
+ geom_out_t o;
+ simplify<geom_t, geom_out_t>::apply(g, o, max_distance, strategy);
+ traits::emplace_back<GeometryOut>::apply(out, std::move(o));
+ return true;
+ }, geometry);
}
};
-} // namespace resolve_variant
+} // namespace resolve_dynamic
/*!
\brief Simplify a geometry using a specified strategy
\ingroup simplify
\tparam Geometry \tparam_geometry
+\tparam GeometryOut The output geometry
\tparam Distance A numerical distance measure
\tparam Strategy A type fulfilling a SimplifyStrategy concept
\param strategy A strategy to calculate simplification
@@ -868,21 +981,22 @@ struct simplify<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
\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
+\param strategy simplify strategy to be used for simplification
+\note The simplification is done with Douglas-Peucker algorithm
\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,
+template<typename Geometry, typename GeometryOut, typename Distance, typename Strategy>
+inline void simplify(Geometry const& geometry, GeometryOut& out,
Distance const& max_distance, Strategy const& strategy)
{
- concepts::check<Geometry>();
+ concepts::check<Geometry const>();
+ concepts::check<GeometryOut>();
geometry::clear(out);
- resolve_variant::simplify<Geometry>::apply(geometry, out, max_distance, strategy);
+ resolve_dynamic::simplify<Geometry, GeometryOut>::apply(geometry, out, max_distance, strategy);
}
@@ -892,21 +1006,22 @@ inline void simplify(Geometry const& geometry, Geometry& out,
\brief Simplify a geometry
\ingroup simplify
\tparam Geometry \tparam_geometry
+\tparam GeometryOut The output 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
+\note The simplification is done with Douglas-Peucker algorithm
\qbk{[include reference/algorithms/simplify.qbk]}
*/
-template<typename Geometry, typename Distance>
-inline void simplify(Geometry const& geometry, Geometry& out,
+template<typename Geometry, typename GeometryOut, typename Distance>
+inline void simplify(Geometry const& geometry, GeometryOut& out,
Distance const& max_distance)
{
- concepts::check<Geometry>();
+ concepts::check<Geometry const>();
+ concepts::check<GeometryOut>();
geometry::simplify(geometry, out, max_distance, default_strategy());
}
@@ -926,8 +1041,7 @@ namespace detail { namespace simplify
\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
+\param strategy simplify strategy to be used for simplification
\qbk{distinguish,with strategy}
\qbk{[include reference/algorithms/simplify.qbk]}
diff --git a/boost/geometry/algorithms/sym_difference.hpp b/boost/geometry/algorithms/sym_difference.hpp
index 854364ea33..894e88c7cc 100644
--- a/boost/geometry/algorithms/sym_difference.hpp
+++ b/boost/geometry/algorithms/sym_difference.hpp
@@ -2,9 +2,9 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2015-2021.
-// Modifications copyright (c) 2015-2021 Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2015-2023.
+// Modifications copyright (c) 2015-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -16,16 +16,11 @@
#define BOOST_GEOMETRY_ALGORITHMS_SYM_DIFFERENCE_HPP
-#include <algorithm>
#include <iterator>
-#include <vector>
-
-#include <boost/variant/apply_visitor.hpp>
-#include <boost/variant/static_visitor.hpp>
-#include <boost/variant/variant_fwd.hpp>
-#include <boost/geometry/algorithms/intersection.hpp>
+#include <boost/geometry/algorithms/difference.hpp>
#include <boost/geometry/algorithms/union.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
@@ -33,7 +28,6 @@
#include <boost/geometry/strategies/relate/cartesian.hpp>
#include <boost/geometry/strategies/relate/geographic.hpp>
#include <boost/geometry/strategies/relate/spherical.hpp>
-#include <boost/geometry/util/range.hpp>
namespace boost { namespace geometry
@@ -512,20 +506,23 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1,
#endif // DOXYGEN_NO_DETAIL
-namespace resolve_strategy {
+namespace resolve_collection
+{
template
<
- typename Strategy,
- bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
+ typename Geometry1, typename Geometry2, typename Collection,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type,
+ typename CollectionTag = typename geometry::tag<Collection>::type
>
struct sym_difference
{
- template <typename Geometry1, typename Geometry2, typename Collection>
- static inline void apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Collection & output_collection,
- Strategy const& strategy)
+ template <typename Strategy>
+ static void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection & output_collection,
+ Strategy const& strategy)
{
typedef typename geometry::detail::output_geometry_value
<
@@ -539,6 +536,127 @@ struct sym_difference
}
};
+
+template <typename Geometry1, typename Geometry2, typename Collection>
+struct sym_difference
+ <
+ Geometry1, Geometry2, Collection,
+ geometry_collection_tag, geometry_collection_tag, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection& output_collection,
+ Strategy const& strategy)
+ {
+ Collection temp1, temp2;
+ resolve_collection::difference
+ <
+ Geometry1, Geometry2, Collection
+ >::apply(geometry1, geometry2, temp1, strategy);
+ resolve_collection::difference
+ <
+ Geometry2, Geometry1, Collection
+ >::apply(geometry2, geometry1, temp2, strategy);
+ resolve_collection::union_
+ <
+ Collection, Collection, Collection
+ >::apply(temp1, temp2, output_collection, strategy);
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Collection, typename Tag1>
+struct sym_difference
+ <
+ Geometry1, Geometry2, Collection,
+ Tag1, geometry_collection_tag, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection & output_collection,
+ Strategy const& strategy)
+ {
+ using gc_view_t = geometry::detail::geometry_collection_view<Geometry1>;
+ sym_difference
+ <
+ gc_view_t, Geometry2, Collection
+ >::apply(gc_view_t(geometry1), geometry2, output_collection, strategy);
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Collection, typename Tag2>
+struct sym_difference
+ <
+ Geometry1, Geometry2, Collection,
+ geometry_collection_tag, Tag2, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection & output_collection,
+ Strategy const& strategy)
+ {
+ using gc_view_t = geometry::detail::geometry_collection_view<Geometry2>;
+ sym_difference
+ <
+ Geometry1, gc_view_t, Collection
+ >::apply(geometry1, gc_view_t(geometry2), output_collection, strategy);
+ }
+};
+
+template <typename Geometry1, typename Geometry2, typename Collection, typename Tag1, typename Tag2>
+struct sym_difference
+ <
+ Geometry1, Geometry2, Collection,
+ Tag1, Tag2, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection & output_collection,
+ Strategy const& strategy)
+ {
+ using gc1_view_t = geometry::detail::geometry_collection_view<Geometry1>;
+ using gc2_view_t = geometry::detail::geometry_collection_view<Geometry2>;
+ sym_difference
+ <
+ gc1_view_t, gc2_view_t, Collection
+ >::apply(gc1_view_t(geometry1), gc2_view_t(geometry2), output_collection, strategy);
+ }
+};
+
+
+} // namespace resolve_collection
+
+
+namespace resolve_strategy
+{
+
+template
+<
+ typename Strategy,
+ bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
+>
+struct sym_difference
+{
+ template <typename Geometry1, typename Geometry2, typename Collection>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection & output_collection,
+ Strategy const& strategy)
+ {
+ resolve_collection::sym_difference
+ <
+ Geometry1, Geometry2, Collection
+ >::apply(geometry1, geometry2, output_collection, strategy);
+ }
+};
+
template <typename Strategy>
struct sym_difference<Strategy, false>
{
@@ -567,7 +685,7 @@ struct sym_difference<default_strategy, false>
Collection & output_collection,
default_strategy)
{
- typedef typename strategy::relate::services::default_strategy
+ typedef typename strategies::relate::services::default_strategy
<
Geometry1, Geometry2
>::type strategy_type;
@@ -582,10 +700,15 @@ struct sym_difference<default_strategy, false>
} // resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-
-template <typename Geometry1, typename Geometry2>
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct sym_difference
{
template <typename Collection, typename Strategy>
@@ -602,134 +725,60 @@ struct sym_difference
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct sym_difference<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
+struct sym_difference<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Collection, typename Strategy>
- struct visitor: static_visitor<>
+ static void apply(DynamicGeometry1 const& geometry1, Geometry2 const& geometry2,
+ Collection& output_collection, Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Collection& m_output_collection;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2,
- Collection& output_collection,
- Strategy const& strategy)
- : m_geometry2(geometry2)
- , m_output_collection(output_collection)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- void operator()(Geometry1 const& geometry1) const
+ traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
{
- sym_difference
+ resolve_strategy::sym_difference
<
- Geometry1,
- Geometry2
- >::apply(geometry1, m_geometry2, m_output_collection, m_strategy);
- }
- };
-
- template <typename Collection, typename Strategy>
- static inline void
- apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Collection& output_collection,
- Strategy const& strategy)
- {
- boost::apply_visitor(visitor<Collection, Strategy>(geometry2,
- output_collection,
- strategy),
- geometry1);
+ Strategy
+ >::apply(g1, geometry2, output_collection, strategy);
+ }, geometry1);
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct sym_difference<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
+struct sym_difference<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
{
template <typename Collection, typename Strategy>
- struct visitor: static_visitor<>
+ static void apply(Geometry1 const& geometry1, DynamicGeometry2 const& geometry2,
+ Collection& output_collection, Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Collection& m_output_collection;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1,
- Collection& output_collection,
- Strategy const& strategy)
- : m_geometry1(geometry1)
- , m_output_collection(output_collection)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- void operator()(Geometry2 const& geometry2) const
+ traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
{
- sym_difference
+ resolve_strategy::sym_difference
<
- Geometry1,
- Geometry2
- >::apply(m_geometry1, geometry2, m_output_collection, m_strategy);
- }
- };
-
- template <typename Collection, typename Strategy>
- static inline void
- apply(Geometry1 const& geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Collection& output_collection,
- Strategy const& strategy)
- {
- boost::apply_visitor(visitor<Collection, Strategy>(geometry1,
- output_collection,
- strategy),
- geometry2);
+ Strategy
+ >::apply(geometry1, g2, output_collection, strategy);
+ }, geometry2);
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
-struct sym_difference<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
+template <typename DynamicGeometry1, typename DynamicGeometry2>
+struct sym_difference<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Collection, typename Strategy>
- struct visitor: static_visitor<>
+ static void apply(DynamicGeometry1 const& geometry1, DynamicGeometry2 const& geometry2,
+ Collection& output_collection, Strategy const& strategy)
{
- Collection& m_output_collection;
- Strategy const& m_strategy;
-
- visitor(Collection& output_collection, Strategy const& strategy)
- : m_output_collection(output_collection)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1, typename Geometry2>
- void operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
{
- sym_difference
+ resolve_strategy::sym_difference
<
- Geometry1,
- Geometry2
- >::apply(geometry1, geometry2, m_output_collection, m_strategy);
- }
- };
-
- template <typename Collection, typename Strategy>
- static inline void
- apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Collection& output_collection,
- Strategy const& strategy)
- {
- boost::apply_visitor(visitor<Collection, Strategy>(output_collection,
- strategy),
- geometry1, geometry2);
+ Strategy
+ >::apply(g1, g2, output_collection, strategy);
+ }, geometry1, geometry2);
}
};
-
-} // namespace resolve_variant
+
+} // namespace resolve_dynamic
/*!
@@ -761,7 +810,7 @@ inline void sym_difference(Geometry1 const& geometry1,
Collection& output_collection,
Strategy const& strategy)
{
- resolve_variant::sym_difference
+ resolve_dynamic::sym_difference
<
Geometry1,
Geometry2
@@ -793,11 +842,11 @@ inline void sym_difference(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Collection& output_collection)
{
- resolve_variant::sym_difference
+ resolve_dynamic::sym_difference
<
Geometry1,
Geometry2
- >::apply(geometry1, geometry2, output_collection, default_strategy());
+ >::apply(geometry1, geometry2, output_collection, default_strategy());
}
diff --git a/boost/geometry/algorithms/transform.hpp b/boost/geometry/algorithms/transform.hpp
index 9b63a85073..66d56d7143 100644
--- a/boost/geometry/algorithms/transform.hpp
+++ b/boost/geometry/algorithms/transform.hpp
@@ -5,8 +5,9 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2023.
+// Modifications copyright (c) 2020-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -19,8 +20,6 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP
#define BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP
-#include <cmath>
-#include <iterator>
#include <type_traits>
#include <boost/range/begin.hpp>
@@ -28,20 +27,18 @@
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
-#include <boost/variant/apply_visitor.hpp>
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
-#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/clear.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
+#include "boost/geometry/algorithms/detail/assign_indexed_point.hpp"
+#include "boost/geometry/algorithms/detail/assign_values.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/core/tags.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
@@ -143,10 +140,7 @@ 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)
+ for (auto it = boost::begin(range); it != boost::end(range); ++it)
{
if (! transform_point::apply(*it, point_out, strategy))
{
@@ -184,15 +178,11 @@ struct transform_polygon
>::apply(geometry::interior_rings(poly2),
geometry::num_interior_rings(poly1));
- typename geometry::interior_return_type<Polygon1 const>::type
- rings1 = geometry::interior_rings(poly1);
- typename geometry::interior_return_type<Polygon2>::type
- rings2 = geometry::interior_rings(poly2);
+ auto const& rings1 = geometry::interior_rings(poly1);
+ auto&& rings2 = geometry::interior_rings(poly2);
- typename detail::interior_iterator<Polygon1 const>::type
- it1 = boost::begin(rings1);
- typename detail::interior_iterator<Polygon2>::type
- it2 = boost::begin(rings2);
+ auto it1 = boost::begin(rings1);
+ auto it2 = boost::begin(rings2);
for ( ; it1 != boost::end(rings1); ++it1, ++it2)
{
if ( ! transform_range_out<point2_type>(*it1,
@@ -251,10 +241,8 @@ struct transform_multi
{
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);
+ auto it1 = boost::begin(multi1);
+ auto it2 = boost::begin(multi2);
for (; it1 != boost::end(multi1); ++it1, ++it2)
{
diff --git a/boost/geometry/algorithms/union.hpp b/boost/geometry/algorithms/union.hpp
index 1a9bcd64dc..3d88cc1414 100644
--- a/boost/geometry/algorithms/union.hpp
+++ b/boost/geometry/algorithms/union.hpp
@@ -2,9 +2,9 @@
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2014-2023.
+// Modifications copyright (c) 2014-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -16,9 +16,8 @@
#define BOOST_GEOMETRY_ALGORITHMS_UNION_HPP
-#include <boost/range/value_type.hpp>
-
-#include <boost/geometry/algorithms/detail/intersection/multi.hpp>
+#include <boost/geometry/algorithms/detail/gc_group_elements.hpp>
+#include <boost/geometry/algorithms/detail/intersection/gc.hpp>
#include <boost/geometry/algorithms/detail/overlay/intersection_insert.hpp>
#include <boost/geometry/algorithms/detail/overlay/linear_linear.hpp>
#include <boost/geometry/algorithms/detail/overlay/overlay.hpp>
@@ -26,6 +25,7 @@
#include <boost/geometry/algorithms/not_implemented.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/reverse_dispatch.hpp>
+#include <boost/geometry/geometries/adapted/boost_variant.hpp>
#include <boost/geometry/geometries/concepts/check.hpp>
#include <boost/geometry/policies/robustness/get_rescale_policy.hpp>
#include <boost/geometry/strategies/default_strategy.hpp>
@@ -33,8 +33,9 @@
#include <boost/geometry/strategies/relate/cartesian.hpp>
#include <boost/geometry/strategies/relate/geographic.hpp>
#include <boost/geometry/strategies/relate/spherical.hpp>
-#include <boost/geometry/util/range.hpp>
-
+#include <boost/geometry/util/type_traits_std.hpp>
+#include <boost/geometry/views/detail/geometry_collection_view.hpp>
+#include <boost/geometry/views/detail/random_access_view.hpp>
namespace boost { namespace geometry
@@ -165,20 +166,20 @@ struct union_insert
false
>
{
- typedef typename geometry::detail::single_tag_from_base_tag
+ using single_tag = typename geometry::detail::single_tag_from_base_tag
<
CastedTagIn
- >::type single_tag;
+ >::type;
- typedef detail::expect_output
+ using expect_check = detail::expect_output
<
Geometry1, Geometry2, SingleTupledOut, single_tag
- > expect_check;
+ >;
- typedef typename geometry::detail::output_geometry_access
+ using access = typename geometry::detail::output_geometry_access
<
SingleTupledOut, single_tag, single_tag
- > access;
+ >;
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Geometry1 const& g1,
@@ -206,15 +207,15 @@ template
>
struct union_insert_tupled_different
{
- typedef typename geometry::detail::output_geometry_access
+ using access1 = typename geometry::detail::output_geometry_access
<
SingleTupledOut, SingleTag1, SingleTag1
- > access1;
+ >;
- typedef typename geometry::detail::output_geometry_access
+ using access2 = typename geometry::detail::output_geometry_access
<
SingleTupledOut, SingleTag2, SingleTag2
- > access2;
+ >;
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Geometry1 const& g1,
@@ -282,25 +283,25 @@ struct union_insert
false
>
{
- typedef typename geometry::detail::single_tag_from_base_tag
+ using single_tag1 = typename geometry::detail::single_tag_from_base_tag
<
CastedTagIn1
- >::type single_tag1;
+ >::type;
- typedef detail::expect_output
+ using expect_check1 = detail::expect_output
<
Geometry1, Geometry2, SingleTupledOut, single_tag1
- > expect_check1;
+ >;
- typedef typename geometry::detail::single_tag_from_base_tag
+ using single_tag2 = typename geometry::detail::single_tag_from_base_tag
<
CastedTagIn2
- >::type single_tag2;
+ >::type;
- typedef detail::expect_output
+ using expect_check2 = detail::expect_output
<
Geometry1, Geometry2, SingleTupledOut, single_tag2
- > expect_check2;
+ >;
template <typename RobustPolicy, typename OutputIterator, typename Strategy>
static inline OutputIterator apply(Geometry1 const& g1,
@@ -358,11 +359,11 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
Geometry1, Geometry2
>::type strategy;
- typedef typename geometry::rescale_overlay_policy_type
+ using rescale_policy_type = typename geometry::rescale_overlay_policy_type
<
Geometry1,
Geometry2
- >::type rescale_policy_type;
+ >::type;
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(
@@ -379,32 +380,33 @@ inline OutputIterator union_insert(Geometry1 const& geometry1,
#endif // DOXYGEN_NO_DETAIL
-namespace resolve_strategy {
+namespace resolve_collection
+{
template
<
- typename Strategy,
- bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
+ typename Geometry1, typename Geometry2, typename GeometryOut,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type,
+ typename TagOut = typename geometry::tag<GeometryOut>::type
>
struct union_
{
- template <typename Geometry1, typename Geometry2, typename Collection>
- static inline void apply(Geometry1 const& geometry1,
- Geometry2 const& geometry2,
- Collection & output_collection,
- Strategy const& strategy)
+ template <typename Strategy>
+ static void apply(Geometry1 const& geometry1, Geometry2 const& geometry2,
+ GeometryOut & geometry_out, Strategy const& strategy)
{
- typedef typename geometry::detail::output_geometry_value
+ using single_out = typename geometry::detail::output_geometry_value
<
- Collection
- >::type single_out;
+ GeometryOut
+ >::type;
- typedef typename geometry::rescale_overlay_policy_type
+ using rescale_policy_type = typename geometry::rescale_overlay_policy_type
<
Geometry1,
Geometry2,
typename Strategy::cs_tag
- >::type rescale_policy_type;
+ >::type;
rescale_policy_type robust_policy
= geometry::get_rescale_policy<rescale_policy_type>(
@@ -414,11 +416,303 @@ struct union_
<
Geometry1, Geometry2, single_out
>::apply(geometry1, geometry2, robust_policy,
- geometry::detail::output_geometry_back_inserter(output_collection),
+ geometry::detail::output_geometry_back_inserter(geometry_out),
strategy);
}
};
+template
+<
+ typename Geometry1, typename Geometry2, typename GeometryOut
+>
+struct union_
+ <
+ Geometry1, Geometry2, GeometryOut,
+ geometry_collection_tag, geometry_collection_tag, geometry_collection_tag
+ >
+{
+ // NOTE: for now require all of the possible output types
+ // technically only a subset could be needed.
+ using multi_point_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<GeometryOut>::type,
+ util::is_multi_point
+ >::type;
+ using multi_linestring_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<GeometryOut>::type,
+ util::is_multi_linestring
+ >::type;
+ using multi_polygon_t = typename util::sequence_find_if
+ <
+ typename traits::geometry_types<GeometryOut>::type,
+ util::is_multi_polygon
+ >::type;
+ using tuple_out_t = boost::tuple<multi_point_t, multi_linestring_t, multi_polygon_t>;
+
+ template <typename Strategy>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
+ {
+ detail::random_access_view<Geometry1 const> gc1_view(geometry1);
+ detail::random_access_view<Geometry2 const> gc2_view(geometry2);
+
+ detail::gc_group_elements(gc1_view, gc2_view, strategy,
+ [&](auto const& inters_group)
+ {
+ tuple_out_t out;
+ merge_group(gc1_view, gc2_view, strategy, inters_group, out);
+ detail::intersection::gc_move_multi_back(geometry_out, boost::get<0>(out));
+ detail::intersection::gc_move_multi_back(geometry_out, boost::get<1>(out));
+ detail::intersection::gc_move_multi_back(geometry_out, boost::get<2>(out));
+ return true;
+ },
+ [&](auto const& disjoint_group)
+ {
+ copy_disjoint(gc1_view, gc2_view, disjoint_group, geometry_out);
+ });
+ }
+
+private:
+ template <typename GC1View, typename GC2View, typename Strategy, typename Group>
+ static inline void merge_group(GC1View const& gc1_view, GC2View const& gc2_view,
+ Strategy const& strategy, Group const& inters_group,
+ tuple_out_t& out)
+ {
+ for (auto const& id : inters_group)
+ {
+ if (id.source_id == 0)
+ {
+ traits::iter_visit<GC1View>::apply([&](auto const& g1)
+ {
+ merge_one(out, g1, strategy);
+ }, boost::begin(gc1_view) + id.gc_id);
+ }
+ else
+ {
+ traits::iter_visit<GC2View>::apply([&](auto const& g2)
+ {
+ merge_one(out, g2, strategy);
+ }, boost::begin(gc2_view) + id.gc_id);
+ }
+ }
+ /*
+ // L = L \ A
+ {
+ multi_linestring_t l;
+ subtract_greater_topodim(boost::get<1>(out), boost::get<2>(out), l, strategy);
+ boost::get<1>(out) = std::move(l);
+ }
+ // P = P \ A
+ {
+ multi_point_t p;
+ subtract_greater_topodim(boost::get<0>(out), boost::get<2>(out), p, strategy);
+ boost::get<0>(out) = std::move(p);
+ }
+ // P = P \ L
+ {
+ multi_point_t p;
+ subtract_greater_topodim(boost::get<0>(out), boost::get<1>(out), p, strategy);
+ boost::get<0>(out) = std::move(p);
+ }
+ */
+ }
+
+ template <typename G, typename Strategy, std::enable_if_t<util::is_pointlike<G>::value, int> = 0>
+ static inline void merge_one(tuple_out_t& out, G const& g, Strategy const& strategy)
+ {
+ multi_point_t p;
+ union_<multi_point_t, G, multi_point_t>::apply(boost::get<0>(out), g, p, strategy);
+ boost::get<0>(out) = std::move(p);
+ }
+
+ template <typename G, typename Strategy, std::enable_if_t<util::is_linear<G>::value, int> = 0>
+ static inline void merge_one(tuple_out_t& out, G const& g, Strategy const& strategy)
+ {
+ multi_linestring_t l;
+ union_<multi_linestring_t, G, multi_linestring_t>::apply(boost::get<1>(out), g, l, strategy);
+ boost::get<1>(out) = std::move(l);
+ }
+
+ template <typename G, typename Strategy, std::enable_if_t<util::is_areal<G>::value, int> = 0>
+ static inline void merge_one(tuple_out_t& out, G const& g, Strategy const& strategy)
+ {
+ multi_polygon_t a;
+ union_<multi_polygon_t, G, multi_polygon_t>::apply(boost::get<2>(out), g, a, strategy);
+ boost::get<2>(out) = std::move(a);
+ }
+
+ template <typename GC1View, typename GC2View, typename Group>
+ static inline void copy_disjoint(GC1View const& gc1_view, GC2View const& gc2_view,
+ Group const& disjoint_group, GeometryOut& geometry_out)
+ {
+ for (auto const& id : disjoint_group)
+ {
+ if (id.source_id == 0)
+ {
+ traits::iter_visit<GC1View>::apply([&](auto const& g1)
+ {
+ copy_one(g1, geometry_out);
+ }, boost::begin(gc1_view) + id.gc_id);
+ }
+ else
+ {
+ traits::iter_visit<GC2View>::apply([&](auto const& g2)
+ {
+ copy_one(g2, geometry_out);
+ }, boost::begin(gc2_view) + id.gc_id);
+ }
+ }
+ }
+
+ template <typename G, std::enable_if_t<util::is_pointlike<G>::value, int> = 0>
+ static inline void copy_one(G const& g, GeometryOut& geometry_out)
+ {
+ multi_point_t p;
+ geometry::convert(g, p);
+ detail::intersection::gc_move_multi_back(geometry_out, p);
+ }
+
+ template <typename G, std::enable_if_t<util::is_linear<G>::value, int> = 0>
+ static inline void copy_one(G const& g, GeometryOut& geometry_out)
+ {
+ multi_linestring_t l;
+ geometry::convert(g, l);
+ detail::intersection::gc_move_multi_back(geometry_out, l);
+ }
+
+ template <typename G, std::enable_if_t<util::is_areal<G>::value, int> = 0>
+ static inline void copy_one(G const& g, GeometryOut& geometry_out)
+ {
+ multi_polygon_t a;
+ geometry::convert(g, a);
+ detail::intersection::gc_move_multi_back(geometry_out, a);
+ }
+ /*
+ template <typename Multi1, typename Multi2, typename Strategy>
+ static inline void subtract_greater_topodim(Multi1 const& multi1, Multi2 const& multi2, Multi1& multi_out, Strategy const& strategy)
+ {
+ using rescale_policy_type = typename geometry::rescale_overlay_policy_type
+ <
+ Multi1, Multi2
+ >::type;
+
+ rescale_policy_type robust_policy
+ = geometry::get_rescale_policy<rescale_policy_type>(
+ multi1, multi2, strategy);
+
+ geometry::dispatch::intersection_insert
+ <
+ Multi1, Multi2,
+ typename boost::range_value<Multi1>::type,
+ overlay_difference,
+ geometry::detail::overlay::do_reverse<geometry::point_order<Multi1>::value>::value,
+ geometry::detail::overlay::do_reverse<geometry::point_order<Multi2>::value, true>::value
+ >::apply(multi1, multi2, robust_policy, range::back_inserter(multi_out), strategy);
+ }
+ */
+};
+
+template
+<
+ typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag1
+>
+struct union_
+ <
+ Geometry1, Geometry2, GeometryOut,
+ Tag1, geometry_collection_tag, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
+ {
+ using gc_view_t = geometry::detail::geometry_collection_view<Geometry1>;
+ union_
+ <
+ gc_view_t, Geometry2, GeometryOut
+ >::apply(gc_view_t(geometry1), geometry2, geometry_out, strategy);
+ }
+};
+
+template
+<
+ typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag2
+>
+struct union_
+ <
+ Geometry1, Geometry2, GeometryOut,
+ geometry_collection_tag, Tag2, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
+ {
+ using gc_view_t = geometry::detail::geometry_collection_view<Geometry2>;
+ union_
+ <
+ Geometry1, gc_view_t, GeometryOut
+ >::apply(geometry1, gc_view_t(geometry2), geometry_out, strategy);
+ }
+};
+
+template
+<
+ typename Geometry1, typename Geometry2, typename GeometryOut, typename Tag1, typename Tag2
+>
+struct union_
+ <
+ Geometry1, Geometry2, GeometryOut,
+ Tag1, Tag2, geometry_collection_tag
+ >
+{
+ template <typename Strategy>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ GeometryOut& geometry_out,
+ Strategy const& strategy)
+ {
+ using gc1_view_t = geometry::detail::geometry_collection_view<Geometry1>;
+ using gc2_view_t = geometry::detail::geometry_collection_view<Geometry2>;
+ union_
+ <
+ gc1_view_t, gc2_view_t, GeometryOut
+ >::apply(gc1_view_t(geometry1), gc2_view_t(geometry2), geometry_out, strategy);
+ }
+};
+
+} // namespace resolve_collection
+
+
+namespace resolve_strategy {
+
+template
+<
+ typename Strategy,
+ bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategy>::value
+>
+struct union_
+{
+ template <typename Geometry1, typename Geometry2, typename Collection>
+ static inline void apply(Geometry1 const& geometry1,
+ Geometry2 const& geometry2,
+ Collection & output_collection,
+ Strategy const& strategy)
+ {
+ resolve_collection::union_
+ <
+ Geometry1, Geometry2, Collection
+ >::apply(geometry1, geometry2, output_collection, strategy);
+ }
+};
+
template <typename Strategy>
struct union_<Strategy, false>
{
@@ -447,11 +741,11 @@ struct union_<default_strategy, false>
Collection & output_collection,
default_strategy)
{
- typedef typename strategies::relate::services::default_strategy
+ using strategy_type = typename strategies::relate::services::default_strategy
<
Geometry1,
Geometry2
- >::type strategy_type;
+ >::type;
union_
<
@@ -463,10 +757,15 @@ struct union_<default_strategy, false>
} // resolve_strategy
-namespace resolve_variant
+namespace resolve_dynamic
{
-
-template <typename Geometry1, typename Geometry2>
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename geometry::tag<Geometry1>::type,
+ typename Tag2 = typename geometry::tag<Geometry2>::type
+>
struct union_
{
template <typename Collection, typename Strategy>
@@ -494,134 +793,64 @@ struct union_
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
-struct union_<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
+template <typename DynamicGeometry1, typename Geometry2, typename Tag2>
+struct union_<DynamicGeometry1, Geometry2, dynamic_geometry_tag, Tag2>
{
template <typename Collection, typename Strategy>
- struct visitor: static_visitor<>
+ static inline void apply(DynamicGeometry1 const& geometry1, Geometry2 const& geometry2,
+ Collection& output_collection, Strategy const& strategy)
{
- Geometry2 const& m_geometry2;
- Collection& m_output_collection;
- Strategy const& m_strategy;
-
- visitor(Geometry2 const& geometry2,
- Collection& output_collection,
- Strategy const& strategy)
- : m_geometry2(geometry2)
- , m_output_collection(output_collection)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1>
- void operator()(Geometry1 const& geometry1) const
+ traits::visit<DynamicGeometry1>::apply([&](auto const& g1)
{
union_
<
- Geometry1,
+ util::remove_cref_t<decltype(g1)>,
Geometry2
- >::apply(geometry1, m_geometry2, m_output_collection, m_strategy);
- }
- };
-
- template <typename Collection, typename Strategy>
- static inline void
- apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
- Geometry2 const& geometry2,
- Collection& output_collection,
- Strategy const& strategy)
- {
- boost::apply_visitor(visitor<Collection, Strategy>(geometry2,
- output_collection,
- strategy),
- geometry1);
+ >::apply(g1, geometry2, output_collection, strategy);
+ }, geometry1);
}
};
-template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-struct union_<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+template <typename Geometry1, typename DynamicGeometry2, typename Tag1>
+struct union_<Geometry1, DynamicGeometry2, Tag1, dynamic_geometry_tag>
{
template <typename Collection, typename Strategy>
- struct visitor: static_visitor<>
+ static inline void apply(Geometry1 const& geometry1, DynamicGeometry2 const& geometry2,
+ Collection& output_collection, Strategy const& strategy)
{
- Geometry1 const& m_geometry1;
- Collection& m_output_collection;
- Strategy const& m_strategy;
-
- visitor(Geometry1 const& geometry1,
- Collection& output_collection,
- Strategy const& strategy)
- : m_geometry1(geometry1)
- , m_output_collection(output_collection)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry2>
- void operator()(Geometry2 const& geometry2) const
+ traits::visit<DynamicGeometry2>::apply([&](auto const& g2)
{
union_
<
Geometry1,
- Geometry2
- >::apply(m_geometry1, geometry2, m_output_collection, m_strategy);
- }
- };
-
- template <typename Collection, typename Strategy>
- static inline void
- apply(Geometry1 const& geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2,
- Collection& output_collection,
- Strategy const& strategy)
- {
- boost::apply_visitor(visitor<Collection, Strategy>(geometry1,
- output_collection,
- strategy),
- geometry2);
+ util::remove_cref_t<decltype(g2)>
+ >::apply(geometry1, g2, output_collection, strategy);
+ }, geometry2);
}
};
-template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
-struct union_<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
+template <typename DynamicGeometry1, typename DynamicGeometry2>
+struct union_<DynamicGeometry1, DynamicGeometry2, dynamic_geometry_tag, dynamic_geometry_tag>
{
template <typename Collection, typename Strategy>
- struct visitor: static_visitor<>
+ static inline void apply(DynamicGeometry1 const& geometry1, DynamicGeometry2 const& geometry2,
+ Collection& output_collection, Strategy const& strategy)
{
- Collection& m_output_collection;
- Strategy const& m_strategy;
-
- visitor(Collection& output_collection, Strategy const& strategy)
- : m_output_collection(output_collection)
- , m_strategy(strategy)
- {}
-
- template <typename Geometry1, typename Geometry2>
- void operator()(Geometry1 const& geometry1,
- Geometry2 const& geometry2) const
+ traits::visit<DynamicGeometry1, DynamicGeometry2>::apply([&](auto const& g1, auto const& g2)
{
union_
<
- Geometry1,
- Geometry2
- >::apply(geometry1, geometry2, m_output_collection, m_strategy);
- }
- };
-
- template <typename Collection, typename Strategy>
- static inline void
- apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)> const& geometry1,
- variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2,
- Collection& output_collection,
- Strategy const& strategy)
- {
- boost::apply_visitor(visitor<Collection, Strategy>(output_collection,
- strategy),
- geometry1, geometry2);
+ util::remove_cref_t<decltype(g1)>,
+ util::remove_cref_t<decltype(g2)>
+ >::apply(g1, g2, output_collection, strategy);
+ }, geometry1, geometry2);
}
};
-
-} // namespace resolve_variant
+
+
+} // namespace resolve_dynamic
/*!
@@ -654,7 +883,7 @@ inline void union_(Geometry1 const& geometry1,
Collection& output_collection,
Strategy const& strategy)
{
- resolve_variant::union_
+ resolve_dynamic::union_
<
Geometry1,
Geometry2
@@ -687,7 +916,7 @@ inline void union_(Geometry1 const& geometry1,
Geometry2 const& geometry2,
Collection& output_collection)
{
- resolve_variant::union_
+ resolve_dynamic::union_
<
Geometry1,
Geometry2
diff --git a/boost/geometry/algorithms/unique.hpp b/boost/geometry/algorithms/unique.hpp
index c953311bbd..618087e14e 100644
--- a/boost/geometry/algorithms/unique.hpp
+++ b/boost/geometry/algorithms/unique.hpp
@@ -24,7 +24,6 @@
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/mutable_range.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -46,7 +45,7 @@ struct range_unique
template <typename Range, typename ComparePolicy>
static inline void apply(Range& range, ComparePolicy const& policy)
{
- typename boost::range_iterator<Range>::type it
+ auto it
= std::unique
(
boost::begin(range),
@@ -66,11 +65,9 @@ struct polygon_unique
{
range_unique::apply(exterior_ring(polygon), policy);
- typename interior_return_type<Polygon>::type
- rings = interior_rings(polygon);
+ auto&& rings = interior_rings(polygon);
- for (typename detail::interior_iterator<Polygon>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
range_unique::apply(*it, policy);
}
@@ -84,10 +81,7 @@ 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)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
Policy::apply(*it, compare);
}
diff --git a/boost/geometry/algorithms/within.hpp b/boost/geometry/algorithms/within.hpp
index e657bbda24..9a914821ac 100644
--- a/boost/geometry/algorithms/within.hpp
+++ b/boost/geometry/algorithms/within.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2013, 2014, 2017.
-// Modifications copyright (c) 2013-2017 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2022.
+// Modifications copyright (c) 2013-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -22,6 +22,7 @@
#include <boost/geometry/algorithms/detail/within/interface.hpp>
#include <boost/geometry/algorithms/detail/within/implementation.hpp>
+#include <boost/geometry/algorithms/detail/within/implementation_gc.hpp>
#endif // BOOST_GEOMETRY_ALGORITHMS_WITHIN_HPP
diff --git a/boost/geometry/arithmetic/arithmetic.hpp b/boost/geometry/arithmetic/arithmetic.hpp
index bf09e7a1cb..b88bd5cceb 100644
--- a/boost/geometry/arithmetic/arithmetic.hpp
+++ b/boost/geometry/arithmetic/arithmetic.hpp
@@ -3,6 +3,7 @@
// 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.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2021.
// Modifications copyright (c) 2021 Oracle and/or its affiliates.
@@ -20,7 +21,6 @@
#include <functional>
-#include <boost/call_traits.hpp>
#include <boost/concept/requires.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
@@ -32,24 +32,6 @@
namespace boost { namespace geometry
{
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail
-{
-
-
-template <typename Point>
-struct param
-{
- typedef typename boost::call_traits
- <
- typename coordinate_type<Point>::type
- >::param_type type;
-};
-
-
-} // namespace detail
-#endif // DOXYGEN_NO_DETAIL
-
/*!
\brief Adds the same value to each coordinate of a point
\ingroup arithmetic
@@ -59,7 +41,7 @@ struct param
\param value value to add
*/
template <typename Point>
-inline void add_value(Point& p, typename detail::param<Point>::type value)
+inline void add_value(Point& p, typename coordinate_type<Point>::type const& value)
{
BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
@@ -101,7 +83,7 @@ inline void add_point(Point1& p1, Point2 const& p2)
\param value value to subtract
*/
template <typename Point>
-inline void subtract_value(Point& p, typename detail::param<Point>::type value)
+inline void subtract_value(Point& p, typename coordinate_type<Point>::type const& value)
{
BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
@@ -143,7 +125,7 @@ inline void subtract_point(Point1& p1, Point2 const& p2)
\param value value to multiply by
*/
template <typename Point>
-inline void multiply_value(Point& p, typename detail::param<Point>::type value)
+inline void multiply_value(Point& p, typename coordinate_type<Point>::type const& value)
{
BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
@@ -186,7 +168,7 @@ inline void multiply_point(Point1& p1, Point2 const& p2)
\param value value to divide by
*/
template <typename Point>
-inline void divide_value(Point& p, typename detail::param<Point>::type value)
+inline void divide_value(Point& p, typename coordinate_type<Point>::type const& value)
{
BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
@@ -228,7 +210,7 @@ inline void divide_point(Point1& p1, Point2 const& p2)
\param value value to assign
*/
template <typename Point>
-inline void assign_value(Point& p, typename detail::param<Point>::type value)
+inline void assign_value(Point& p, typename coordinate_type<Point>::type const& value)
{
BOOST_CONCEPT_ASSERT( (concepts::Point<Point>) );
diff --git a/boost/geometry/arithmetic/dot_product.hpp b/boost/geometry/arithmetic/dot_product.hpp
index 00a168fe1d..2d7643666b 100644
--- a/boost/geometry/arithmetic/dot_product.hpp
+++ b/boost/geometry/arithmetic/dot_product.hpp
@@ -68,7 +68,7 @@ struct dot_product_maker<P1, P2, DimensionCount, DimensionCount>
\param p1 first point
\param p2 second point
\return the dot product
-
+
\qbk{[heading Examples]}
\qbk{[dot_product] [dot_product_output]}
diff --git a/boost/geometry/arithmetic/normalize.hpp b/boost/geometry/arithmetic/normalize.hpp
index 7dfdbd2b03..64e08c2dce 100644
--- a/boost/geometry/arithmetic/normalize.hpp
+++ b/boost/geometry/arithmetic/normalize.hpp
@@ -45,7 +45,7 @@ inline bool vec_normalize(Point & pt, typename coordinate_type<Point>::type & le
coord_t const c0 = 0;
len = vec_length(pt);
-
+
if (math::equals(len, c0))
{
return false;
diff --git a/boost/geometry/core/config.hpp b/boost/geometry/core/config.hpp
index 1c6fab8e03..f5ab449fbb 100644
--- a/boost/geometry/core/config.hpp
+++ b/boost/geometry/core/config.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry
-// Copyright (c) 2019 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2019-2021 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2018-2020 Oracle and/or its affiliates.
+// Copyright (c) 2018-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -13,24 +14,25 @@
#define BOOST_GEOMETRY_CORE_CONFIG_HPP
#include <boost/config.hpp>
-
-// NOTE: workaround for VC++ 12 (aka 2013): cannot specify explicit initializer for arrays
-#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && (!defined(_MSC_VER) || (_MSC_VER >= 1900))
-#define BOOST_GEOMETRY_CXX11_ARRAY_UNIFIED_INITIALIZATION
+#include <boost/config/pragma_message.hpp>
+
+// If no define is specified, it uses BOOST_GEOMETRY_NO_ROBUSTNESS, which means: no rescaling.
+// (Rescaling was an earlier approach to fix robustness issues.)
+// However, if BOOST_GEOMETRY_ROBUSTNESS_ALTERNATIVE is specified, it flips the default.
+#if !defined(BOOST_GEOMETRY_NO_ROBUSTNESS) && !defined(BOOST_GEOMETRY_USE_RESCALING)
+ #if defined(BOOST_GEOMETRY_ROBUSTNESS_ALTERNATIVE)
+ #define BOOST_GEOMETRY_USE_RESCALING
+ #else
+ #define BOOST_GEOMETRY_NO_ROBUSTNESS
+ #endif
#endif
-#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_VARIADIC_TEMPLATES)
-#define BOOST_GEOMETRY_CXX11_TUPLE
+#if defined(BOOST_GEOMETRY_USE_RESCALING) && ! defined(BOOST_GEOMETRY_ROBUSTNESS_ALTERNATIVE)
+ BOOST_PRAGMA_MESSAGE("Rescaling is deprecated and its functionality will be removed in Boost 1.84")
#endif
-// Defining this selects Kramer rule for segment-intersection
-// That is default behaviour.
-#define BOOST_GEOMETRY_USE_KRAMER_RULE
-
-// Rescaling is turned on, unless NO_ROBUSTNESS is defined
-// In future versions of Boost.Geometry, it will be turned off by default
-#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
-#define BOOST_GEOMETRY_USE_RESCALING
+#if defined(BOOST_GEOMETRY_USE_RESCALING) && defined(BOOST_GEOMETRY_NO_ROBUSTNESS)
+ #error "Define either BOOST_GEOMETRY_NO_ROBUSTNESS (default) or BOOST_GEOMETRY_USE_RESCALING"
#endif
#endif // BOOST_GEOMETRY_CORE_CONFIG_HPP
diff --git a/boost/geometry/core/coordinate_promotion.hpp b/boost/geometry/core/coordinate_promotion.hpp
new file mode 100644
index 0000000000..efbcdff7d2
--- /dev/null
+++ b/boost/geometry/core/coordinate_promotion.hpp
@@ -0,0 +1,111 @@
+// Boost.Geometry
+
+// Copyright (c) 2021 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_CORE_COORDINATE_PROMOTION_HPP
+#define BOOST_GEOMETRY_CORE_COORDINATE_PROMOTION_HPP
+
+#include <boost/geometry/core/coordinate_type.hpp>
+
+// TODO: move this to a future headerfile implementing traits for these types
+#include <boost/rational.hpp>
+#include <boost/multiprecision/cpp_bin_float.hpp>
+#include <boost/multiprecision/cpp_int.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace traits
+{
+
+// todo
+
+} // namespace traits
+
+/*!
+ \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
+ */
+// TODO: replace with, or call, promoted_to_floating_point
+template <typename T, typename PromoteIntegerTo = double>
+struct promote_floating_point
+{
+ typedef std::conditional_t
+ <
+ std::is_integral<T>::value,
+ PromoteIntegerTo,
+ T
+ > type;
+};
+
+// TODO: replace with promoted_to_floating_point
+template <typename Geometry>
+struct fp_coordinate_type
+{
+ typedef typename promote_floating_point
+ <
+ typename coordinate_type<Geometry>::type
+ >::type type;
+};
+
+namespace detail
+{
+
+// Promote any integral type to double. Floating point
+// and other user defined types stay as they are, unless specialized.
+// TODO: we shold add a coordinate_promotion traits for promotion to
+// floating point or (larger) integer types.
+template <typename Type>
+struct promoted_to_floating_point
+{
+ using type = std::conditional_t
+ <
+ std::is_integral<Type>::value, double, Type
+ >;
+};
+
+// Boost.Rational goes to double
+template <typename T>
+struct promoted_to_floating_point<boost::rational<T>>
+{
+ using type = double;
+};
+
+// Any Boost.Multiprecision goes to double (for example int128_t),
+// unless specialized
+template <typename Backend>
+struct promoted_to_floating_point<boost::multiprecision::number<Backend>>
+{
+ using type = double;
+};
+
+// Boost.Multiprecision binary floating point numbers are used as FP.
+template <unsigned Digits>
+struct promoted_to_floating_point
+ <
+ boost::multiprecision::number
+ <
+ boost::multiprecision::cpp_bin_float<Digits>
+ >
+ >
+{
+ using type = boost::multiprecision::number
+ <
+ boost::multiprecision::cpp_bin_float<Digits>
+ >;
+};
+
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_CORE_COORDINATE_PROMOTION_HPP
diff --git a/boost/geometry/core/coordinate_type.hpp b/boost/geometry/core/coordinate_type.hpp
index e4c391ec45..760b122ad3 100644
--- a/boost/geometry/core/coordinate_type.hpp
+++ b/boost/geometry/core/coordinate_type.hpp
@@ -22,7 +22,6 @@
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tag.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/type_traits_std.hpp>
@@ -94,15 +93,6 @@ struct coordinate_type
>::type type;
};
-template <typename Geometry>
-struct fp_coordinate_type
-{
- typedef typename promote_floating_point
- <
- typename coordinate_type<Geometry>::type
- >::type type;
-};
-
/*!
\brief assert_coordinate_type_equal, a compile-time check for equality of two coordinate types
\ingroup utility
diff --git a/boost/geometry/core/geometry_id.hpp b/boost/geometry/core/geometry_id.hpp
index 27901eca4f..2c68cedcd9 100644
--- a/boost/geometry/core/geometry_id.hpp
+++ b/boost/geometry/core/geometry_id.hpp
@@ -45,39 +45,43 @@ struct geometry_id
template <>
-struct geometry_id<point_tag> : std::integral_constant<int, 1> {};
+struct geometry_id<point_tag> : std::integral_constant<int, 1> {};
template <>
-struct geometry_id<linestring_tag> : std::integral_constant<int, 2> {};
+struct geometry_id<linestring_tag> : std::integral_constant<int, 2> {};
template <>
-struct geometry_id<polygon_tag> : std::integral_constant<int, 3> {};
+struct geometry_id<polygon_tag> : std::integral_constant<int, 3> {};
template <>
-struct geometry_id<multi_point_tag> : std::integral_constant<int, 4> {};
+struct geometry_id<multi_point_tag> : std::integral_constant<int, 4> {};
template <>
-struct geometry_id<multi_linestring_tag> : std::integral_constant<int, 5> {};
+struct geometry_id<multi_linestring_tag> : std::integral_constant<int, 5> {};
template <>
-struct geometry_id<multi_polygon_tag> : std::integral_constant<int, 6> {};
+struct geometry_id<multi_polygon_tag> : std::integral_constant<int, 6> {};
template <>
-struct geometry_id<segment_tag> : std::integral_constant<int, 92> {};
+struct geometry_id<geometry_collection_tag> : std::integral_constant<int, 7> {};
template <>
-struct geometry_id<ring_tag> : std::integral_constant<int, 93> {};
+struct geometry_id<segment_tag> : std::integral_constant<int, 92> {};
template <>
-struct geometry_id<box_tag> : std::integral_constant<int, 94> {};
+struct geometry_id<ring_tag> : std::integral_constant<int, 93> {};
+
+
+template <>
+struct geometry_id<box_tag> : std::integral_constant<int, 94> {};
} // namespace core_dispatch
diff --git a/boost/geometry/core/interior_rings.hpp b/boost/geometry/core/interior_rings.hpp
index 52e6b756af..b8b5c6280d 100644
--- a/boost/geometry/core/interior_rings.hpp
+++ b/boost/geometry/core/interior_rings.hpp
@@ -4,8 +4,9 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2023.
+// Modifications copyright (c) 2020-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -18,7 +19,6 @@
#ifndef BOOST_GEOMETRY_CORE_INTERIOR_RINGS_HPP
#define BOOST_GEOMETRY_CORE_INTERIOR_RINGS_HPP
-#include <cstddef>
#include <type_traits>
#include <boost/range/value_type.hpp>
diff --git a/boost/geometry/core/mutable_range.hpp b/boost/geometry/core/mutable_range.hpp
index d6a4a44fbf..365beb7ae9 100644
--- a/boost/geometry/core/mutable_range.hpp
+++ b/boost/geometry/core/mutable_range.hpp
@@ -4,8 +4,9 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2020-2021.
-// Modifications copyright (c) 2020-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2023.
+// Modifications copyright (c) 2020-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -19,7 +20,6 @@
#define BOOST_GEOMETRY_CORE_MUTABLE_RANGE_HPP
-#include <cstddef>
#include <type_traits>
#include <boost/range/size_type.hpp>
diff --git a/boost/geometry/core/point_type.hpp b/boost/geometry/core/point_type.hpp
index 696e1e56ad..f5d2823726 100644
--- a/boost/geometry/core/point_type.hpp
+++ b/boost/geometry/core/point_type.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2021.
+// Modifications copyright (c) 2020-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -21,10 +21,12 @@
#include <boost/range/value_type.hpp>
+#include <boost/geometry/core/geometry_types.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/sequence.hpp>
#include <boost/geometry/util/type_traits_std.hpp>
@@ -137,6 +139,36 @@ struct point_type<multi_polygon_tag, MultiPolygon>
};
+template <typename DynamicGeometry>
+struct point_type<dynamic_geometry_tag, DynamicGeometry>
+{
+ using geometry_t = typename util::sequence_front
+ <
+ typename traits::geometry_types<DynamicGeometry>::type
+ >::type;
+ using type = typename point_type
+ <
+ typename tag<geometry_t>::type,
+ typename util::remove_cptrref<geometry_t>::type
+ >::type;
+};
+
+
+template <typename GeometryCollection>
+struct point_type<geometry_collection_tag, GeometryCollection>
+{
+ using geometry_t = typename util::sequence_front
+ <
+ typename traits::geometry_types<GeometryCollection>::type
+ >::type;
+ using type = typename point_type
+ <
+ typename tag<geometry_t>::type,
+ typename util::remove_cptrref<geometry_t>::type
+ >::type;
+};
+
+
} // namespace core_dispatch
#endif // DOXYGEN_NO_DISPATCH
diff --git a/boost/geometry/core/radian_access.hpp b/boost/geometry/core/radian_access.hpp
index 993a6cc4c4..c2f00552dd 100644
--- a/boost/geometry/core/radian_access.hpp
+++ b/boost/geometry/core/radian_access.hpp
@@ -27,8 +27,7 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/cs.hpp>
-#include <boost/geometry/core/coordinate_type.hpp>
-
+#include <boost/geometry/core/coordinate_promotion.hpp>
#include <boost/geometry/util/math.hpp>
diff --git a/boost/geometry/core/topological_dimension.hpp b/boost/geometry/core/topological_dimension.hpp
index b0c36b4ac0..a4bc16eb4d 100644
--- a/boost/geometry/core/topological_dimension.hpp
+++ b/boost/geometry/core/topological_dimension.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2022.
+// Modifications copyright (c) 2020-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -78,6 +78,10 @@ template <>
struct top_dim<multi_polygon_tag> : std::integral_constant<int, 2> {};
+template <>
+struct top_dim<geometry_collection_tag> : std::integral_constant<int, -1> {};
+
+
} // namespace core_dispatch
#endif
diff --git a/boost/geometry/formulas/area_formulas.hpp b/boost/geometry/formulas/area_formulas.hpp
index d459528c27..b8da8a6727 100644
--- a/boost/geometry/formulas/area_formulas.hpp
+++ b/boost/geometry/formulas/area_formulas.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry
-// Copyright (c) 2015-2021 Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2015-2022 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -342,6 +343,15 @@ public:
}
}
+ static inline CT trapezoidal_formula(CT lat1r, CT lat2r, CT lon21r)
+ {
+ CT const c1 = CT(1);
+ CT const c2 = CT(2);
+ CT const tan_lat1 = tan(lat1r / c2);
+ CT const tan_lat2 = tan(lat2r / c2);
+
+ return c2 * atan(((tan_lat1 + tan_lat2) / (c1 + tan_lat1 * tan_lat2))* tan(lon21r / c2));
+ }
/*
Compute the spherical excess of a geodesic (or shperical) segment
@@ -354,43 +364,44 @@ public:
static inline CT spherical(PointOfSegment const& p1,
PointOfSegment const& p2)
{
+ CT const pi = math::pi<CT>();
+
CT excess;
- if (LongSegment) // not for segments parallel to equator
+ CT const lon1r = get_as_radian<0>(p1);
+ CT const lat1r = get_as_radian<1>(p1);
+ CT const lon2r = get_as_radian<0>(p2);
+ CT const lat2r = get_as_radian<1>(p2);
+
+ CT lon12r = lon2r - lon1r;
+ math::normalize_longitude<radian, CT>(lon12r);
+
+ if (lon12r == pi || lon12r == -pi)
{
- CT cbet1 = cos(geometry::get_as_radian<1>(p1));
- CT sbet1 = sin(geometry::get_as_radian<1>(p1));
- CT cbet2 = cos(geometry::get_as_radian<1>(p2));
- CT sbet2 = sin(geometry::get_as_radian<1>(p2));
+ return pi;
+ }
- CT omg12 = geometry::get_as_radian<0>(p1)
- - geometry::get_as_radian<0>(p2);
- CT comg12 = cos(omg12);
- CT somg12 = sin(omg12);
+ if (BOOST_GEOMETRY_CONDITION(LongSegment) && lat1r != lat2r) // not for segments parallel to equator
+ {
+ CT const cbet1 = cos(lat1r);
+ CT const sbet1 = sin(lat1r);
+ CT const cbet2 = cos(lat2r);
+ CT const sbet2 = sin(lat2r);
- CT alp1 = atan2(cbet1 * sbet2
- - sbet1 * cbet2 * comg12,
- cbet2 * somg12);
+ CT const omg12 = lon2r - lon1r;
+ CT const comg12 = cos(omg12);
+ CT const somg12 = sin(omg12);
- CT alp2 = atan2(cbet1 * sbet2 * comg12
- - sbet1 * cbet2,
- cbet1 * somg12);
+ CT const cbet1_sbet2 = cbet1 * sbet2;
+ CT const sbet1_cbet2 = sbet1 * cbet2;
+ CT const alp1 = atan2(cbet1_sbet2 - sbet1_cbet2 * comg12, cbet2 * somg12);
+ CT const alp2 = atan2(cbet1_sbet2 * comg12 - sbet1_cbet2, cbet1 * somg12);
excess = alp2 - alp1;
} else {
- // Trapezoidal formula
-
- CT tan_lat1 =
- tan(geometry::get_as_radian<1>(p1) / 2.0);
- CT tan_lat2 =
- tan(geometry::get_as_radian<1>(p2) / 2.0);
-
- excess = CT(2.0)
- * atan(((tan_lat1 + tan_lat2) / (CT(1) + tan_lat1 * tan_lat2))
- * tan((geometry::get_as_radian<0>(p2)
- - geometry::get_as_radian<0>(p1)) / 2));
+ excess = trapezoidal_formula(lat1r, lat2r, lon12r);
}
return excess;
@@ -437,8 +448,13 @@ public:
// Constants
+ CT const c0 = CT(0);
+ CT const c1 = CT(1);
+ CT const c2 = CT(2);
+ CT const pi = math::pi<CT>();
+ CT const half_pi = pi / c2;
CT const ep = spheroid_const.m_ep;
- CT const one_minus_f = CT(1) - spheroid_const.m_f;
+ CT const one_minus_f = c1 - spheroid_const.m_f;
// Basic trigonometric computations
// the compiler could optimize here using sincos function
@@ -472,43 +488,47 @@ public:
CT excess;
- auto const half_pi = math::pi<CT>() / 2;
- bool meridian = lon2r - lon1r == CT(0)
- || lat1r == half_pi || lat1r == -half_pi
- || lat2r == half_pi || lat2r == -half_pi;
+ CT lon12r = lon2r - lon1r;
+ math::normalize_longitude<radian, CT>(lon12r);
- if (!meridian && (i_res.distance)
- < mean_radius<CT>(spheroid_const.m_spheroid) / CT(638)) // short segment
+ // Comparing with "==" works with all test cases here, but could potential create numerical issues
+ if (lon12r == pi || lon12r == -pi)
{
- CT tan_lat1 = tan(lat1r / 2.0);
- CT tan_lat2 = tan(lat2r / 2.0);
-
- excess = CT(2.0)
- * atan(((tan_lat1 + tan_lat2) / (CT(1) + tan_lat1 * tan_lat2))
- * tan((lon2r - lon1r) / 2));
+ result.spherical_term = pi;
}
else
{
- /* in some cases this formula gives more accurate results
- *
- * CT sin_omg12 = cos_omg1 * sin_omg2 - sin_omg1 * cos_omg2;
- normalize(sin_omg12, cos_omg12);
-
- CT cos_omg12p1 = CT(1) + cos_omg12;
- CT cos_bet1p1 = CT(1) + cos_bet1;
- CT cos_bet2p1 = CT(1) + cos_bet2;
- excess = CT(2) * atan2(sin_omg12 * (sin_bet1 * cos_bet2p1 + sin_bet2 * cos_bet1p1),
- cos_omg12p1 * (sin_bet1 * sin_bet2 + cos_bet1p1 * cos_bet2p1));
- */
-
- excess = alp2 - alp1;
+ bool const meridian = lon12r == c0
+ || lat1r == half_pi || lat1r == -half_pi
+ || lat2r == half_pi || lat2r == -half_pi;
+
+ if (!meridian && (i_res.distance)
+ < mean_radius<CT>(spheroid_const.m_spheroid) / CT(638)) // short segment
+ {
+ excess = trapezoidal_formula(lat1r, lat2r, lon12r);
+ }
+ else
+ {
+ /* in some cases this formula gives more accurate results
+ CT sin_omg12 = cos_omg1 * sin_omg2 - sin_omg1 * cos_omg2;
+ normalize(sin_omg12, cos_omg12);
+
+ CT cos_omg12p1 = CT(1) + cos_omg12;
+ CT cos_bet1p1 = CT(1) + cos_bet1;
+ CT cos_bet2p1 = CT(1) + cos_bet2;
+ excess = CT(2) * atan2(sin_omg12 * (sin_bet1 * cos_bet2p1 + sin_bet2 * cos_bet1p1),
+ cos_omg12p1 * (sin_bet1 * sin_bet2 + cos_bet1p1 * cos_bet2p1));
+ */
+
+ excess = alp2 - alp1;
+ }
+
+ result.spherical_term = excess;
}
- result.spherical_term = excess;
-
// Ellipsoidal term computation (uses integral approximation)
- CT const cos_alp0 = math::sqrt(CT(1) - math::sqr(sin_alp0));
+ CT const cos_alp0 = math::sqrt(c1 - math::sqr(sin_alp0));
//CT const cos_alp0 = hypot(cos_alp1, sin_alp1 * sin_bet1);
CT cos_sig1 = cos_alp1 * cos_bet1;
CT cos_sig2 = cos_alp2 * cos_bet2;
@@ -523,8 +543,8 @@ public:
if (ExpandEpsN) // expand by eps and n
{
CT const k2 = math::sqr(ep * cos_alp0);
- CT const sqrt_k2_plus_one = math::sqrt(CT(1) + k2);
- CT const eps = (sqrt_k2_plus_one - CT(1)) / (sqrt_k2_plus_one + CT(1));
+ CT const sqrt_k2_plus_one = math::sqrt(c1 + k2);
+ CT const eps = (sqrt_k2_plus_one - c1) / (sqrt_k2_plus_one + c1);
// Generate and evaluate the polynomials on eps (i.e. var2 = eps)
// to get the final series coefficients
@@ -563,20 +583,26 @@ public:
static inline bool crosses_prime_meridian(PointOfSegment const& p1,
PointOfSegment const& p2)
{
- CT const pi
- = geometry::math::pi<CT>();
- CT const two_pi
- = geometry::math::two_pi<CT>();
-
- CT p1_lon = get_as_radian<0>(p1)
- - ( floor( get_as_radian<0>(p1) / two_pi )
- * two_pi );
- CT p2_lon = get_as_radian<0>(p2)
- - ( floor( get_as_radian<0>(p2) / two_pi )
- * two_pi );
-
- CT max_lon = (std::max)(p1_lon, p2_lon);
- CT min_lon = (std::min)(p1_lon, p2_lon);
+ CT const pi = geometry::math::pi<CT>();
+ CT const two_pi = geometry::math::two_pi<CT>();
+
+ CT const lon1r = get_as_radian<0>(p1);
+ CT const lon2r = get_as_radian<0>(p2);
+
+ CT lon12 = lon2r - lon1r;
+ math::normalize_longitude<radian, CT>(lon12);
+
+ // Comparing with "==" works with all test cases here, but could potential create numerical issues
+ if (lon12 == pi || lon12 == -pi)
+ {
+ return true;
+ }
+
+ CT const p1_lon = lon1r - ( std::floor( lon1r / two_pi ) * two_pi );
+ CT const p2_lon = lon2r - ( std::floor( lon2r / two_pi ) * two_pi );
+
+ CT const max_lon = (std::max)(p1_lon, p2_lon);
+ CT const min_lon = (std::min)(p1_lon, p2_lon);
return max_lon > pi && min_lon < pi && max_lon - min_lon > pi;
}
diff --git a/boost/geometry/formulas/differential_quantities.hpp b/boost/geometry/formulas/differential_quantities.hpp
index 789275f145..1df9adb8e6 100644
--- a/boost/geometry/formulas/differential_quantities.hpp
+++ b/boost/geometry/formulas/differential_quantities.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry
-// Copyright (c) 2016-2019 Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2016-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -67,7 +68,7 @@ public:
CT sin_bet1 = one_minus_f * sin_lat1;
CT sin_bet2 = one_minus_f * sin_lat2;
-
+
// equator
if (math::equals(sin_bet1, c0) && math::equals(sin_bet2, c0))
{
@@ -80,7 +81,7 @@ public:
CT m12 = azi_sign * sin(sig_12) * b;
reduced_length = m12;
}
-
+
if (BOOST_GEOMETRY_CONDITION(EnableGeodesicScale))
{
CT M12 = cos(sig_12);
@@ -162,7 +163,7 @@ private:
CT const& sin_sig2, CT const& cos_sig2,
CT const& cos_alp0_sqr, CT const& f)
{
- if (Order == 0)
+ if (BOOST_GEOMETRY_CONDITION(Order == 0))
{
return 0;
}
@@ -176,15 +177,15 @@ private:
CT const sin_2sig_12 = sin_2sig2 - sin_2sig1;
CT const L1 = sig_12 - sin_2sig_12 / c2;
- if (Order == 1)
+ if (BOOST_GEOMETRY_CONDITION(Order == 1))
{
return cos_alp0_sqr * f * L1;
}
-
+
CT const sin_4sig1 = c2 * sin_2sig1 * (math::sqr(cos_sig1) - math::sqr(sin_sig1)); // sin(4sig1)
CT const sin_4sig2 = c2 * sin_2sig2 * (math::sqr(cos_sig2) - math::sqr(sin_sig2)); // sin(4sig2)
CT const sin_4sig_12 = sin_4sig2 - sin_4sig1;
-
+
CT const c8 = 8;
CT const c12 = 12;
CT const c16 = 16;
@@ -195,7 +196,7 @@ private:
+ (c12 * cos_alp0_sqr - c24) * sig_12)
/ c16;
- if (Order == 2)
+ if (BOOST_GEOMETRY_CONDITION(Order == 2))
{
return cos_alp0_sqr * f * (L1 + f * L2);
}
@@ -241,7 +242,7 @@ private:
CT const& sin_sig2, CT const& cos_sig2,
CT const& cos_alp0_sqr, CT const& ep_sqr)
{
- if (Order == 0)
+ if (BOOST_GEOMETRY_CONDITION(Order == 0))
{
return 0;
}
@@ -259,21 +260,21 @@ private:
CT const L1 = (c2 * sig_12 - sin_2sig_12) / c4;
- if (Order == 1)
+ if (BOOST_GEOMETRY_CONDITION(Order == 1))
{
return c2a0ep2 * L1;
}
CT const c8 = 8;
CT const c64 = 64;
-
+
CT const sin_4sig1 = c2 * sin_2sig1 * (math::sqr(cos_sig1) - math::sqr(sin_sig1)); // sin(4sig1)
CT const sin_4sig2 = c2 * sin_2sig2 * (math::sqr(cos_sig2) - math::sqr(sin_sig2)); // sin(4sig2)
CT const sin_4sig_12 = sin_4sig2 - sin_4sig1;
-
+
CT const L2 = (sin_4sig_12 - c8 * sin_2sig_12 + 12 * sig_12) / c64;
- if (Order == 2)
+ if (BOOST_GEOMETRY_CONDITION(Order == 2))
{
return c2a0ep2 * (L1 + c2a0ep2 * L2);
}
diff --git a/boost/geometry/formulas/geographic.hpp b/boost/geometry/formulas/geographic.hpp
index 9501526ba8..cc726876aa 100644
--- a/boost/geometry/formulas/geographic.hpp
+++ b/boost/geometry/formulas/geographic.hpp
@@ -29,7 +29,7 @@
#include <boost/geometry/util/select_coordinate_type.hpp>
namespace boost { namespace geometry {
-
+
namespace formula {
template <typename Point3d, typename PointGeo, typename Spheroid>
@@ -107,11 +107,11 @@ inline PointGeo cart3d_to_geo(Point3d const& point_3d, Spheroid const& spheroid)
calc_t const xy_l = math::sqrt(math::sqr(x) + math::sqr(y));
calc_t const lonr = atan2(y, x);
-
+
// NOTE: Alternative version
// http://www.iag-aig.org/attach/989c8e501d9c5b5e2736955baf2632f5/V60N2_5FT.pdf
// calc_t const lonr = c2 * atan2(y, x + xy_l);
-
+
calc_t const latr = atan2(z, (c1 - e_sqr) * xy_l);
// NOTE: If h is equal to 0 then there is no need to improve value of latitude
@@ -141,8 +141,8 @@ inline PointGeo cart3d_to_geo(Point3d const& point_3d, Spheroid const& spheroid)
template <typename Point3d, typename Spheroid>
inline Point3d projected_to_xy(Point3d const& point_3d, Spheroid const& spheroid)
{
- typedef typename coordinate_type<Point3d>::type coord_t;
-
+ typedef typename coordinate_type<Point3d>::type coord_t;
+
// len_xy = sqrt(x^2 + y^2)
// r = len_xy - |z / tan(lat)|
// assuming h = 0
@@ -151,7 +151,7 @@ inline Point3d projected_to_xy(Point3d const& point_3d, Spheroid const& spheroid
// r = e^2 * len_xy
// x_res = r * cos(lon) = e^2 * len_xy * x / len_xy = e^2 * x
// y_res = r * sin(lon) = e^2 * len_xy * y / len_xy = e^2 * y
-
+
coord_t const c0 = 0;
coord_t const e_sqr = formula::eccentricity_sqr<coord_t>(spheroid);
@@ -178,7 +178,7 @@ inline Point3d projected_to_surface(Point3d const& direction, Spheroid const& sp
//(x*x+y*y)/(a*a) + z*z/(b*b) = 1
// x = d.x * t
// y = d.y * t
- // z = d.z * t
+ // z = d.z * t
coord_t const dx = get<0>(direction);
coord_t const dy = get<1>(direction);
coord_t const dz = get<2>(direction);
@@ -217,7 +217,7 @@ inline bool projected_to_surface(Point3d const& origin, Point3d const& direction
//(x*x+y*y)/(a*a) + z*z/(b*b) = 1
// x = o.x + d.x * t
// y = o.y + d.y * t
- // z = o.z + d.z * t
+ // z = o.z + d.z * t
coord_t const ox = get<0>(origin);
coord_t const oy = get<1>(origin);
coord_t const oz = get<2>(origin);
diff --git a/boost/geometry/formulas/gnomonic_intersection.hpp b/boost/geometry/formulas/gnomonic_intersection.hpp
index 7e1b7bcdab..64795f7625 100644
--- a/boost/geometry/formulas/gnomonic_intersection.hpp
+++ b/boost/geometry/formulas/gnomonic_intersection.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry
-// Copyright (c) 2016 Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2016 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -60,7 +61,7 @@ public:
return apply(lon_a1, lat_a1, lon_a2, lat_a2, lon_b1, lat_b1, lon_b2, lat_b2, lon, lat, spheroid);
}
-
+
template <typename Spheroid>
static inline bool apply(CT const& lona1, CT const& lata1,
CT const& lona2, CT const& lata2,
@@ -80,7 +81,7 @@ public:
CT xa1, ya1, xa2, ya2;
CT xb1, yb1, xb2, yb2;
CT x, y;
- double lat1, lon1;
+ CT lon1, lat1;
bool ok = gnom_t::forward(lon, lat, lona1, lata1, xa1, ya1, spheroid)
&& gnom_t::forward(lon, lat, lona2, lata2, xa2, ya2, spheroid)
@@ -93,7 +94,7 @@ public:
{
return false;
}
-
+
if (math::equals(lat1, lat) && math::equals(lon1, lon))
{
break;
@@ -137,7 +138,7 @@ private:
x = get<0>(p) / z;
y = get<1>(p) / z;
-
+
return true;
}
};
diff --git a/boost/geometry/formulas/gnomonic_spheroid.hpp b/boost/geometry/formulas/gnomonic_spheroid.hpp
index 4710c6c063..75544fc7db 100644
--- a/boost/geometry/formulas/gnomonic_spheroid.hpp
+++ b/boost/geometry/formulas/gnomonic_spheroid.hpp
@@ -66,7 +66,7 @@ public:
CT rho = m / M;
x = sin(i_res.azimuth) * rho;
y = cos(i_res.azimuth) * rho;
-
+
return true;
}
@@ -78,7 +78,7 @@ public:
{
CT const a = get_radius<0>(spheroid);
CT const ds_threshold = a * std::numeric_limits<CT>::epsilon(); // TODO: 0 for non-fundamental type
-
+
CT const azimuth = atan2(x, y);
CT const rho = math::sqrt(math::sqr(x) + math::sqr(y)); // use hypot?
CT distance = a * atan(rho / a);
@@ -95,7 +95,7 @@ public:
// found = false;
return found;
}
-
+
CT const drho = m / M - rho; // rho = m / M
CT const ds = drho * math::sqr(M); // drho/ds = 1/M^2
distance -= ds;
diff --git a/boost/geometry/formulas/interpolate_point_spherical.hpp b/boost/geometry/formulas/interpolate_point_spherical.hpp
index 2e712d44ce..ad0b746997 100644
--- a/boost/geometry/formulas/interpolate_point_spherical.hpp
+++ b/boost/geometry/formulas/interpolate_point_spherical.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2019-2021 Oracle and/or its affiliates.
+// Copyright (c) 2019-2023 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -12,6 +12,7 @@
#ifndef BOOST_GEOMETRY_FORMULAS_INTERPOLATE_POINT_SPHERICAL_HPP
#define BOOST_GEOMETRY_FORMULAS_INTERPOLATE_POINT_SPHERICAL_HPP
+#include <boost/geometry/arithmetic/normalize.hpp>
#include <boost/geometry/formulas/spherical.hpp>
#include <boost/geometry/geometries/point.hpp>
@@ -29,7 +30,7 @@ public :
void compute_angle(Point const& p0,
Point const& p1,
CalculationType& angle01)
- {
+ {
m_xyz0 = formula::sph_to_cart3d<point3d_t>(p0);
m_xyz1 = formula::sph_to_cart3d<point3d_t>(p1);
CalculationType const dot01 = geometry::dot_product(m_xyz0, m_xyz1);
diff --git a/boost/geometry/formulas/karney_direct.hpp b/boost/geometry/formulas/karney_direct.hpp
index 463697e4bc..bfe35ddc49 100644
--- a/boost/geometry/formulas/karney_direct.hpp
+++ b/boost/geometry/formulas/karney_direct.hpp
@@ -1,12 +1,14 @@
// Boost.Geometry
// Copyright (c) 2018 Adeel Ahmad, Islamabad, Pakistan.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// Contributed and/or modified by Adeel Ahmad,
// as part of Google Summer of Code 2018 program.
-// This file was modified by Oracle on 2018-2020.
-// Modifications copyright (c) 2018-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2018-2022.
+// Modifications copyright (c) 2018-2022 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -30,8 +32,6 @@
#define BOOST_GEOMETRY_FORMULAS_KARNEY_DIRECT_HPP
-#include <boost/array.hpp>
-
#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/hypot.hpp>
@@ -82,10 +82,10 @@ public:
{
result_type result;
- CT lon1 = lo1;
- CT const lat1 = la1;
+ CT lon1 = lo1 * math::r2d<CT>();
+ CT const lat1 = la1 * math::r2d<CT>();
- Azi azi12 = azimuth12;
+ Azi azi12 = azimuth12 * math::r2d<CT>();
math::normalize_azimuth<degree, Azi>(azi12);
CT const c0 = 0;
@@ -151,10 +151,9 @@ public:
// Index zero element of coeffs_C1p is unused.
se::coeffs_C1p<SeriesOrder, CT> const coeffs_C1p(epsilon);
- CT const B12 = - se::sin_cos_series
- (sin_tau1 * cos_tau12 + cos_tau1 * sin_tau12,
- cos_tau1 * cos_tau12 - sin_tau1 * sin_tau12,
- coeffs_C1p);
+ CT const B12 = - se::sin_cos_series(sin_tau1 * cos_tau12 + cos_tau1 * sin_tau12,
+ cos_tau1 * cos_tau12 - sin_tau1 * sin_tau12,
+ coeffs_C1p);
CT const sigma12 = tau12 - (B12 - B11);
CT const sin_sigma12 = sin(sigma12);
@@ -169,9 +168,6 @@ public:
CT const cos_alpha2 = cos_alpha0 * cos_sigma2;
result.reverse_azimuth = atan2(sin_alpha2, cos_alpha2);
-
- // Convert the angle to radians.
- result.reverse_azimuth /= math::d2r<CT>();
}
if (BOOST_GEOMETRY_CONDITION(CalcCoordinates))
@@ -182,9 +178,6 @@ public:
result.lat2 = atan2(sin_beta2, one_minus_f * cos_beta2);
- // Convert the coordinate to radians.
- result.lat2 /= math::d2r<CT>();
-
// Find the longitude at the second point.
CT const sin_omega2 = sin_alpha0 * sin_sigma2;
CT const cos_omega2 = cos_sigma2;
@@ -201,15 +194,11 @@ public:
CT const B31 = se::sin_cos_series(sin_sigma1, cos_sigma1, coeffs_C3);
- CT const lam12 = omega12 + A3c *
- (sigma12 + (se::sin_cos_series
- (sin_sigma2,
- cos_sigma2,
- coeffs_C3) - B31));
+ CT const sin_cos_res = se::sin_cos_series(sin_sigma2, cos_sigma2, coeffs_C3);
+ CT const lam12 = omega12 + A3c * (sigma12 + (sin_cos_res - B31));
- // Convert to radians to get the
- // longitudinal difference.
- CT lon12 = lam12 / math::d2r<CT>();
+ // Convert to degrees to get the longitudinal difference.
+ CT lon12 = lam12 * math::r2d<CT>();
// Add the longitude at first point to the longitudinal
// difference and normalize the result.
@@ -224,6 +213,8 @@ public:
// otherwise differential quantities are calculated incorrectly.
// But here it's ok since result.lon2 is not used after this point.
math::normalize_longitude<degree, CT>(result.lon2);
+
+ result.lon2 *= math::d2r<CT>();
}
if (BOOST_GEOMETRY_CONDITION(CalcQuantities))
@@ -252,12 +243,10 @@ public:
cos_sigma1 * cos_sigma2 * J12);
// Find the geodesic scale.
- CT const t = k2 * (sin_sigma2 - sin_sigma1) *
- (sin_sigma2 + sin_sigma1) / (dn1 + dn2);
+ CT const t = k2 * (sin_sigma2 - sin_sigma1) * (sin_sigma2 + sin_sigma1) / (dn1 + dn2);
- result.geodesic_scale = cos_sigma12 +
- (t * sin_sigma2 - cos_sigma2 * J12) *
- sin_sigma1 / dn1;
+ result.geodesic_scale = cos_sigma12 + (t * sin_sigma2 - cos_sigma2 * J12) *
+ sin_sigma1 / dn1;
}
return result;
diff --git a/boost/geometry/formulas/karney_inverse.hpp b/boost/geometry/formulas/karney_inverse.hpp
index 936fbe22c4..47efc9ff5e 100644
--- a/boost/geometry/formulas/karney_inverse.hpp
+++ b/boost/geometry/formulas/karney_inverse.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry
// Copyright (c) 2018 Adeel Ahmad, Islamabad, Pakistan.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// Contributed and/or modified by Adeel Ahmad, as part of Google Summer of Code 2018 program.
@@ -267,8 +268,8 @@ public:
CT sin_sigma2 = sin_beta2;
CT cos_sigma2 = cos_alpha2 * cos_beta2;
- CT sigma12 = std::atan2((std::max)(c0, cos_sigma1 * sin_sigma2 - sin_sigma1 * cos_sigma2),
- cos_sigma1 * cos_sigma2 + sin_sigma1 * sin_sigma2);
+ sigma12 = std::atan2((std::max)(c0, cos_sigma1 * sin_sigma2 - sin_sigma1 * cos_sigma2),
+ cos_sigma1 * cos_sigma2 + sin_sigma1 * sin_sigma2);
CT dummy;
meridian_length(n, ep2, sigma12, sin_sigma1, cos_sigma1, dn1,
@@ -281,7 +282,7 @@ public:
{
if (sigma12 < c3 * tiny)
{
- sigma12 = m12x = s12x = c0;
+ sigma12 = m12x = s12x = c0;
}
m12x *= b;
@@ -381,7 +382,7 @@ public:
cos_alpha1 / sin_alpha1 > cos_alpha1b / sin_alpha1b))
{
sin_alpha1b = sin_alpha1;
- cos_alpha1b = cos_alpha1;
+ cos_alpha1b = cos_alpha1;
}
else if (v < c0 && (iteration > max_iterations ||
cos_alpha1 / sin_alpha1 < cos_alpha1a / sin_alpha1a))
diff --git a/boost/geometry/formulas/meridian_direct.hpp b/boost/geometry/formulas/meridian_direct.hpp
index f8e73f57c6..330af6703f 100644
--- a/boost/geometry/formulas/meridian_direct.hpp
+++ b/boost/geometry/formulas/meridian_direct.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry
-// Copyright (c) 2018 Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2018 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -127,14 +128,14 @@ public:
CT mp = formula::quarter_meridian<CT>(spheroid);
CT mu = geometry::math::pi<CT>()/CT(2) * m / mp;
- if (Order == 0)
+ if (BOOST_GEOMETRY_CONDITION(Order == 0))
{
return mu;
}
CT H2 = 1.5 * n;
- if (Order == 1)
+ if (BOOST_GEOMETRY_CONDITION(Order == 1))
{
return mu + H2 * sin(2*mu);
}
@@ -142,7 +143,7 @@ public:
CT n2 = n * n;
CT H4 = 1.3125 * n2;
- if (Order == 2)
+ if (BOOST_GEOMETRY_CONDITION(Order == 2))
{
return mu + H2 * sin(2*mu) + H4 * sin(4*mu);
}
@@ -151,7 +152,7 @@ public:
H2 -= 0.84375 * n3;
CT H6 = 1.572916667 * n3;
- if (Order == 3)
+ if (BOOST_GEOMETRY_CONDITION(Order == 3))
{
return mu + H2 * sin(2*mu) + H4 * sin(4*mu) + H6 * sin(6*mu);
}
diff --git a/boost/geometry/formulas/meridian_inverse.hpp b/boost/geometry/formulas/meridian_inverse.hpp
index 43bec19970..c21196f5c9 100644
--- a/boost/geometry/formulas/meridian_inverse.hpp
+++ b/boost/geometry/formulas/meridian_inverse.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry
-// Copyright (c) 2017-2018 Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2017-2018 Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -118,14 +119,14 @@ public :
CT M = a/(1+n);
CT C0 = 1;
- if (Order == 0)
+ if (BOOST_GEOMETRY_CONDITION(Order == 0))
{
return M * C0 * lat;
}
CT C2 = -1.5 * n;
- if (Order == 1)
+ if (BOOST_GEOMETRY_CONDITION(Order == 1))
{
return M * (C0 * lat + C2 * sin(2*lat));
}
@@ -134,7 +135,7 @@ public :
C0 += .25 * n2;
CT C4 = 0.9375 * n2;
- if (Order == 2)
+ if (BOOST_GEOMETRY_CONDITION(Order == 2))
{
return M * (C0 * lat + C2 * sin(2*lat) + C4 * sin(4*lat));
}
@@ -143,7 +144,7 @@ public :
C2 += 0.1875 * n3;
CT C6 = -0.729166667 * n3;
- if (Order == 3)
+ if (BOOST_GEOMETRY_CONDITION(Order == 3))
{
return M * (C0 * lat + C2 * sin(2*lat) + C4 * sin(4*lat)
+ C6 * sin(6*lat));
@@ -153,7 +154,7 @@ public :
C4 -= 0.234375 * n4;
CT C8 = 0.615234375 * n4;
- if (Order == 4)
+ if (BOOST_GEOMETRY_CONDITION(Order == 4))
{
return M * (C0 * lat + C2 * sin(2*lat) + C4 * sin(4*lat)
+ C6 * sin(6*lat) + C8 * sin(8*lat));
diff --git a/boost/geometry/formulas/sjoberg_intersection.hpp b/boost/geometry/formulas/sjoberg_intersection.hpp
index 12abb76757..af56f285f4 100644
--- a/boost/geometry/formulas/sjoberg_intersection.hpp
+++ b/boost/geometry/formulas/sjoberg_intersection.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry
-// Copyright (c) 2016-2019 Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2016-2019 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -71,7 +72,7 @@ struct sjoberg_intersection_spherical_02
CT const tan_lat_a2 = tan(lat_a2);
CT const tan_lat_b2 = tan(lat_b2);
-
+
return apply(lon1, lon_a2, lon2, lon_b2,
sin_lon1, cos_lon1, sin_lat1, cos_lat1,
sin_lon2, cos_lon2, sin_lat2, cos_lat2,
@@ -103,7 +104,7 @@ private:
CT const tan_alpha1_x = cos_lat1 * tan_lat_a2 - sin_lat1 * cos_dlon1;
CT const tan_alpha2_x = cos_lat2 * tan_lat_b2 - sin_lat2 * cos_dlon2;
-
+
CT const c0 = 0;
bool const is_vertical1 = math::equals(sin_dlon1, c0) || math::equals(tan_alpha1_x, c0);
bool const is_vertical2 = math::equals(sin_dlon2, c0) || math::equals(tan_alpha2_x, c0);
@@ -132,7 +133,7 @@ private:
{
tan_alpha1 = sin_dlon1 / tan_alpha1_x;
tan_alpha2 = sin_dlon2 / tan_alpha2_x;
-
+
CT const T1 = tan_alpha1 * cos_lat1;
CT const T2 = tan_alpha2 * cos_lat2;
CT const T1T2 = T1*T2;
@@ -152,12 +153,12 @@ private:
CT const lon_dist2 = (std::max)((std::min)(math::longitude_difference<radian>(lon1, lon_2),
math::longitude_difference<radian>(lon_a2, lon_2)),
(std::min)(math::longitude_difference<radian>(lon2, lon_2),
- math::longitude_difference<radian>(lon_b2, lon_2)));
+ math::longitude_difference<radian>(lon_b2, lon_2)));
if (lon_dist2 < lon_dist1)
{
lon = lon_2;
}
-
+
CT const sin_lon = sin(lon);
CT const cos_lon = cos(lon);
@@ -177,7 +178,7 @@ private:
CT const lat_x_2 = tan_alpha2 * cos_lat2;
tan_lat = lat_y_2 / lat_x_2;
}
-
+
return true;
}
};
@@ -206,19 +207,19 @@ inline CT sjoberg_d_lambda_e_sqr(CT const& sin_betaj, CT const& sin_beta,
{
using math::detail::bounded;
- if (Order == 0)
+ if (BOOST_GEOMETRY_CONDITION(Order == 0))
{
return 0;
}
CT const c1 = 1;
CT const c2 = 2;
-
+
CT const asin_B = asin(bounded(sin_beta / sqrt_1_Cj_sqr, -c1, c1));
CT const asin_Bj = asin(sin_betaj / sqrt_1_Cj_sqr);
CT const L0 = (asin_B - asin_Bj) / c2;
- if (Order == 1)
+ if (BOOST_GEOMETRY_CONDITION(Order == 1))
{
return -Cj * e_sqr * L0;
}
@@ -237,7 +238,7 @@ inline CT sjoberg_d_lambda_e_sqr(CT const& sin_betaj, CT const& sin_beta,
CT const sqrt_Yj = math::sqrt(-Xj_sqr + one_minus_Cj_sqr);
CT const L1 = (Cj_sqr_plus_one * (asin_B - asin_Bj) + X * sqrt_Y - Xj * sqrt_Yj) / c16;
- if (Order == 2)
+ if (BOOST_GEOMETRY_CONDITION(Order == 2))
{
return -Cj * e_sqr * (L0 + e_sqr * L1);
}
@@ -251,7 +252,7 @@ inline CT sjoberg_d_lambda_e_sqr(CT const& sin_betaj, CT const& sin_beta,
CT const Fj = Xj * (-c2 * Xj_sqr + c3 * Cj_sqr + c5);
CT const L2 = (E * (asin_B - asin_Bj) + F * sqrt_Y - Fj * sqrt_Yj) / c128;
- if (Order == 3)
+ if (BOOST_GEOMETRY_CONDITION(Order == 3))
{
return -Cj * e_sqr * (L0 + e_sqr * (L1 + e_sqr * L2));
}
@@ -405,7 +406,7 @@ public:
{
return false;
}
-
+
// NOTE: beta may be slightly out of bounds here but d_lambda handles that
CT const dLj = d_lambda(sin_beta);
delta_k = sign_lon_diff * (/*asin_t_t0j*/ - asin_tj_t0j + dLj);
@@ -451,7 +452,7 @@ public:
delta_k_behind = sign_lon_diff * pi;
return true;
}
-
+
// beta out of bounds and not close
if (check_sin_beta
&& ! (is_sin_beta_ok(sin_beta)
@@ -459,7 +460,7 @@ public:
{
return false;
}
-
+
// NOTE: beta may be slightly out of bounds here but d_lambda handles that
CT const dLj = d_lambda(sin_beta);
delta_k_before = sign_lon_diff * (/*asin_t_t0j*/ - asin_tj_t0j + dLj);
@@ -768,7 +769,7 @@ public:
}
t = one_minus_f * tan_lat_sph; // tan(beta)
- }
+ }
// TODO: no need to calculate atan here if reduced latitudes were used
// instead of latitudes above, in sjoberg_intersection_spherical_02
@@ -802,7 +803,7 @@ private:
CT const c1 = 1;
CT const e_sqr = geod1.e_sqr;
-
+
CT lon1_diff = 0;
CT lon2_diff = 0;
@@ -892,7 +893,7 @@ private:
if (math::equals(dbeta_denom, c0))
{
return false;
- }
+ }
// The sign of dbeta is changed WRT [Sjoberg02]
CT const dbeta = (lon1_minus_lon2 + lon1_diff - lon2_diff) / dbeta_denom;
@@ -1027,7 +1028,7 @@ private:
{
break;
}
-
+
bool try_t2 = false;
converge_07_result result_curr;
if (converge_07_step_one(CT(sin(beta1)), t1, lon1_minus_lon2, geodesics, lon_sph, result_curr))
@@ -1063,7 +1064,7 @@ private:
}
}
-
+
if (try_t2)
{
CT t2 = t;
@@ -1156,7 +1157,7 @@ private:
{
using math::detail::bounded;
CT const c1 = 1;
-
+
CT k_diff_before = 0;
CT k_diff_behind = 0;
diff --git a/boost/geometry/formulas/spherical.hpp b/boost/geometry/formulas/spherical.hpp
index c73b8b1555..3a388bfbce 100644
--- a/boost/geometry/formulas/spherical.hpp
+++ b/boost/geometry/formulas/spherical.hpp
@@ -29,7 +29,7 @@
#include <boost/geometry/formulas/result_direct.hpp>
namespace boost { namespace geometry {
-
+
namespace formula {
template <typename T>
diff --git a/boost/geometry/formulas/thomas_inverse.hpp b/boost/geometry/formulas/thomas_inverse.hpp
index cf69c9df1d..c93aaf838c 100644
--- a/boost/geometry/formulas/thomas_inverse.hpp
+++ b/boost/geometry/formulas/thomas_inverse.hpp
@@ -136,7 +136,7 @@ public:
CT const f_sqr = math::sqr(f);
CT const f_sqr_per_64 = f_sqr / CT(64);
-
+
if ( BOOST_GEOMETRY_CONDITION(EnableDistance) )
{
CT const n1 = X * (A + C*X);
@@ -151,7 +151,7 @@ public:
//result.distance = a * sin_d * (T - delta1d);
result.distance = a * sin_d * (T - delta1d + delta2d);
}
-
+
if ( BOOST_GEOMETRY_CONDITION(CalcAzimuths) )
{
// NOTE: if both cos_latX == 0 then below we'd have 0 * INF
@@ -162,7 +162,7 @@ public:
CT const F = c2*Y-E*(c4-X);
CT const M = CT(32)*T-(CT(20)*T-A)*X-(B+c4)*Y;
CT const G = f*T/c2 + f_sqr_per_64 * M;
-
+
// TODO:
// If d_lambda is close to 90 or -90 deg then tan(d_lambda) is big
// and F is small. The result is not accurate.
diff --git a/boost/geometry/formulas/vertex_longitude.hpp b/boost/geometry/formulas/vertex_longitude.hpp
index e8c5e8775b..bef8f5a3f6 100644
--- a/boost/geometry/formulas/vertex_longitude.hpp
+++ b/boost/geometry/formulas/vertex_longitude.hpp
@@ -212,7 +212,7 @@ public:
CT const sign = bet3 >= c0
? c1
: cminus1;
-
+
CT const dlon_max = omg13 - sign * f * sin_alp0 * I3;
return dlon_max;
diff --git a/boost/geometry/formulas/vincenty_direct.hpp b/boost/geometry/formulas/vincenty_direct.hpp
index bc150e6d43..274af3f2f2 100644
--- a/boost/geometry/formulas/vincenty_direct.hpp
+++ b/boost/geometry/formulas/vincenty_direct.hpp
@@ -141,7 +141,7 @@ public:
result.lat2
= atan2( sin_U1 * cos_sigma + cos_U1 * sin_sigma * cos_azimuth12,
one_min_f * math::sqrt(sin_alpha_sqr + math::sqr(sin_U1 * sin_sigma - cos_U1 * cos_sigma * cos_azimuth12))); // (8)
-
+
CT const lambda = atan2( sin_sigma * sin_azimuth12,
cos_U1 * cos_sigma - sin_U1 * sin_sigma * cos_azimuth12); // (9)
CT const C = (flattening/CT(16)) * cos_alpha_sqr * ( CT(4) + flattening * ( CT(4) - CT(3) * cos_alpha_sqr ) ); // (10)
diff --git a/boost/geometry/formulas/vincenty_inverse.hpp b/boost/geometry/formulas/vincenty_inverse.hpp
index a25e5a0843..24f285d9bc 100644
--- a/boost/geometry/formulas/vincenty_inverse.hpp
+++ b/boost/geometry/formulas/vincenty_inverse.hpp
@@ -159,7 +159,7 @@ public:
} while ( geometry::math::abs(previous_lambda - lambda) > c_e_12
&& geometry::math::abs(lambda) < pi
&& counter < BOOST_GEOMETRY_DETAIL_VINCENTY_MAX_STEPS ); // robustness
-
+
if ( BOOST_GEOMETRY_CONDITION(EnableDistance) )
{
// Some types cannot divide by doubles
@@ -187,7 +187,7 @@ public:
result.distance = radius_b * A * (sigma - delta_sigma); // (19)
}
-
+
if ( BOOST_GEOMETRY_CONDITION(CalcAzimuths) )
{
if (BOOST_GEOMETRY_CONDITION(CalcFwdAzimuth))
diff --git a/boost/geometry/geometries/adapted/boost_variant.hpp b/boost/geometry/geometries/adapted/boost_variant.hpp
index cc21da59ce..35660c6fc9 100644
--- a/boost/geometry/geometries/adapted/boost_variant.hpp
+++ b/boost/geometry/geometries/adapted/boost_variant.hpp
@@ -38,16 +38,6 @@ namespace boost { namespace geometry
namespace detail
{
-template <typename ...>
-struct parameter_pack_first_type {};
-
-template <typename T, typename ... Ts>
-struct parameter_pack_first_type<T, Ts...>
-{
- typedef T type;
-};
-
-
template <typename Seq, typename ResultSeq = util::type_sequence<>>
struct boost_variant_types;
@@ -78,7 +68,7 @@ template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
struct point_type<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
: point_type
<
- typename detail::parameter_pack_first_type
+ typename util::pack_front
<
BOOST_VARIANT_ENUM_PARAMS(T)
>::type
diff --git a/boost/geometry/geometries/adapted/std_array.hpp b/boost/geometry/geometries/adapted/std_array.hpp
index 5d2c81dee3..dfbd179d61 100644
--- a/boost/geometry/geometries/adapted/std_array.hpp
+++ b/boost/geometry/geometries/adapted/std_array.hpp
@@ -18,10 +18,6 @@
#include <boost/config.hpp>
-
-#ifndef BOOST_NO_CXX11_HDR_ARRAY
-
-
#define BOOST_GEOMETRY_ADAPTED_STD_ARRAY_TAG_DEFINED
@@ -121,15 +117,5 @@ struct access<std::array<CoordinateType, DimensionCount>, Dimension>
}; \
}}}
-
-#else
-
-
-#warning "This file requires compiler and library support for the ISO C++ 2011 standard."
-
-
-#endif // BOOST_NO_CXX11_HDR_ARRAY
-
-
#endif // BOOST_GEOMETRY_GEOMETRIES_ADAPTED_STD_ARRAY_HPP
diff --git a/boost/geometry/geometries/concepts/box_concept.hpp b/boost/geometry/geometries/concepts/box_concept.hpp
index de7572a936..c96d39f6a4 100644
--- a/boost/geometry/geometries/concepts/box_concept.hpp
+++ b/boost/geometry/geometries/concepts/box_concept.hpp
@@ -30,21 +30,6 @@
namespace boost { namespace geometry { namespace concepts
{
-
-/*!
-\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
{
diff --git a/boost/geometry/geometries/concepts/check.hpp b/boost/geometry/geometries/concepts/check.hpp
index 5f59238649..34eb740329 100644
--- a/boost/geometry/geometries/concepts/check.hpp
+++ b/boost/geometry/geometries/concepts/check.hpp
@@ -22,6 +22,8 @@
#include <boost/concept_check.hpp>
#include <boost/concept/requires.hpp>
+#include <boost/geometry/algorithms/detail/select_geometry_type.hpp>
+
#include <boost/geometry/geometries/concepts/concept_type.hpp>
#include <boost/geometry/geometries/concepts/box_concept.hpp>
#include <boost/geometry/geometries/concepts/dynamic_geometry_concept.hpp>
@@ -39,7 +41,6 @@
namespace boost { namespace geometry { namespace concepts
{
-
/*!
\brief Checks, in compile-time, the concept of any geometry
\ingroup concepts
@@ -69,7 +70,11 @@ inline void check_concepts_and_equal_dimensions()
{
check<Geometry1>();
check<Geometry2>();
- assert_dimension_equal<Geometry1, Geometry2>();
+ assert_dimension_equal
+ <
+ typename geometry::detail::first_geometry_type<Geometry1>::type,
+ typename geometry::detail::first_geometry_type<Geometry2>::type
+ >();
}
diff --git a/boost/geometry/geometries/concepts/geometry_collection_concept.hpp b/boost/geometry/geometries/concepts/geometry_collection_concept.hpp
index 0c40ab3209..7d232c145f 100644
--- a/boost/geometry/geometries/concepts/geometry_collection_concept.hpp
+++ b/boost/geometry/geometries/concepts/geometry_collection_concept.hpp
@@ -113,8 +113,8 @@ struct GeometryCollection
BOOST_CONCEPT_USAGE(GeometryCollection)
{
- Geometry* gc = nullptr;
- traits::clear<Geometry>::apply(*gc);
+ Geometry* gc = nullptr;
+ traits::clear<Geometry>::apply(*gc);
traits::iter_visit<Geometry>::apply([](auto &&) {}, boost::begin(*gc));
}
#endif // DOXYGEN_NO_CONCEPT_MEMBERS
diff --git a/boost/geometry/geometries/concepts/linestring_concept.hpp b/boost/geometry/geometries/concepts/linestring_concept.hpp
index c9adf1d447..49dc8b221b 100644
--- a/boost/geometry/geometries/concepts/linestring_concept.hpp
+++ b/boost/geometry/geometries/concepts/linestring_concept.hpp
@@ -35,45 +35,6 @@
namespace boost { namespace geometry { namespace concepts
{
-
-/*!
-\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
{
diff --git a/boost/geometry/geometries/concepts/multi_linestring_concept.hpp b/boost/geometry/geometries/concepts/multi_linestring_concept.hpp
index 26b86eca76..837b905fd6 100644
--- a/boost/geometry/geometries/concepts/multi_linestring_concept.hpp
+++ b/boost/geometry/geometries/concepts/multi_linestring_concept.hpp
@@ -31,18 +31,6 @@
namespace boost { namespace geometry { namespace concepts
{
-
-/*!
-\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
{
@@ -61,7 +49,7 @@ public :
traits::clear<Geometry>::apply(*mls);
traits::resize<Geometry>::apply(*mls, 0);
linestring_type* ls = 0;
- traits::push_back<Geometry>::apply(*mls, *ls);
+ traits::push_back<Geometry>::apply(*mls, std::move(*ls));
}
#endif
};
diff --git a/boost/geometry/geometries/concepts/multi_point_concept.hpp b/boost/geometry/geometries/concepts/multi_point_concept.hpp
index da1991d657..23534deee8 100644
--- a/boost/geometry/geometries/concepts/multi_point_concept.hpp
+++ b/boost/geometry/geometries/concepts/multi_point_concept.hpp
@@ -33,17 +33,6 @@
namespace boost { namespace geometry { namespace concepts
{
-
-/*!
-\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
{
diff --git a/boost/geometry/geometries/concepts/multi_polygon_concept.hpp b/boost/geometry/geometries/concepts/multi_polygon_concept.hpp
index 5118502c13..aa907f8daa 100644
--- a/boost/geometry/geometries/concepts/multi_polygon_concept.hpp
+++ b/boost/geometry/geometries/concepts/multi_polygon_concept.hpp
@@ -31,18 +31,6 @@
namespace boost { namespace geometry { namespace concepts
{
-
-/*!
-\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
{
@@ -60,8 +48,9 @@ public :
Geometry* mp = 0;
traits::clear<Geometry>::apply(*mp);
traits::resize<Geometry>::apply(*mp, 0);
+ // The concept should support the second version of push_back, using &&
polygon_type* poly = 0;
- traits::push_back<Geometry>::apply(*mp, *poly);
+ traits::push_back<Geometry>::apply(*mp, std::move(*poly));
}
#endif
};
diff --git a/boost/geometry/geometries/concepts/point_concept.hpp b/boost/geometry/geometries/concepts/point_concept.hpp
index 5657f9f710..dbe004a582 100644
--- a/boost/geometry/geometries/concepts/point_concept.hpp
+++ b/boost/geometry/geometries/concepts/point_concept.hpp
@@ -35,63 +35,6 @@
namespace boost { namespace geometry { namespace concepts
{
-/*!
-\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 std::integral_constant&lt;std::size_t, 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)
-- for non-Cartesian coordinate systems, the coordinate system's units
- must either be boost::geometry::degree or boost::geometry::radian
-
-
-\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
{
diff --git a/boost/geometry/geometries/concepts/ring_concept.hpp b/boost/geometry/geometries/concepts/ring_concept.hpp
index 7afbc4e18c..b4cf961adb 100644
--- a/boost/geometry/geometries/concepts/ring_concept.hpp
+++ b/boost/geometry/geometries/concepts/ring_concept.hpp
@@ -34,22 +34,6 @@
namespace boost { namespace geometry { namespace concepts
{
-
-/*!
-\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
{
diff --git a/boost/geometry/geometries/concepts/segment_concept.hpp b/boost/geometry/geometries/concepts/segment_concept.hpp
index 0240764212..7dac9e3ed7 100644
--- a/boost/geometry/geometries/concepts/segment_concept.hpp
+++ b/boost/geometry/geometries/concepts/segment_concept.hpp
@@ -32,25 +32,6 @@
namespace boost { namespace geometry { namespace concepts
{
-
-/*!
-\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
{
diff --git a/boost/geometry/geometries/helper_geometry.hpp b/boost/geometry/geometries/helper_geometry.hpp
index 699af88e54..881f143dd4 100644
--- a/boost/geometry/geometries/helper_geometry.hpp
+++ b/boost/geometry/geometries/helper_geometry.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2015-2020, Oracle and/or its affiliates.
+// Copyright (c) 2015-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -12,15 +12,19 @@
#define BOOST_GEOMETRY_GEOMETRIES_HELPER_GEOMETRY_HPP
-#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/geometries/box.hpp>
+#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/point.hpp>
+#include <boost/geometry/geometries/ring.hpp>
#include <boost/geometry/algorithms/not_implemented.hpp>
@@ -69,23 +73,50 @@ struct helper_geometry : not_implemented<Geometry>
template <typename Point, typename NewCoordinateType, typename NewUnits>
struct helper_geometry<Point, NewCoordinateType, NewUnits, point_tag>
{
- typedef typename detail::helper_geometries::helper_point
+ using type = typename detail::helper_geometries::helper_point
<
Point, NewCoordinateType, NewUnits
- >::type type;
+ >::type;
};
template <typename Box, typename NewCoordinateType, typename NewUnits>
struct helper_geometry<Box, NewCoordinateType, NewUnits, box_tag>
{
- typedef model::box
+ using type = model::box
<
typename helper_geometry
<
typename point_type<Box>::type, NewCoordinateType, NewUnits
>::type
- > type;
+ >;
+};
+
+
+template <typename Linestring, typename NewCoordinateType, typename NewUnits>
+struct helper_geometry<Linestring, NewCoordinateType, NewUnits, linestring_tag>
+{
+ using type = model::linestring
+ <
+ typename helper_geometry
+ <
+ typename point_type<Linestring>::type, NewCoordinateType, NewUnits
+ >::type
+ >;
+};
+
+template <typename Ring, typename NewCoordinateType, typename NewUnits>
+struct helper_geometry<Ring, NewCoordinateType, NewUnits, ring_tag>
+{
+ using type = model::ring
+ <
+ typename helper_geometry
+ <
+ typename point_type<Ring>::type, NewCoordinateType, NewUnits
+ >::type,
+ point_order<Ring>::value != counterclockwise,
+ closure<Ring>::value != open
+ >;
};
@@ -103,10 +134,10 @@ template
>
struct helper_geometry
{
- typedef typename detail_dispatch::helper_geometry
+ using type = typename detail_dispatch::helper_geometry
<
Geometry, NewCoordinateType, NewUnits
- >::type type;
+ >::type;
};
diff --git a/boost/geometry/geometries/linestring.hpp b/boost/geometry/geometries/linestring.hpp
index a826167abf..37d3edd165 100644
--- a/boost/geometry/geometries/linestring.hpp
+++ b/boost/geometry/geometries/linestring.hpp
@@ -29,9 +29,7 @@
#include <boost/geometry/geometries/concepts/point_concept.hpp>
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
#include <initializer_list>
-#endif
namespace boost { namespace geometry
{
@@ -77,8 +75,6 @@ public :
: base_type(begin, end)
{}
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
-
/// \constructor_initializer_list{linestring}
inline linestring(std::initializer_list<Point> l)
: base_type(l.begin(), l.end())
@@ -96,8 +92,6 @@ public :
// return *this;
// }
//#endif
-
-#endif
};
} // namespace model
diff --git a/boost/geometry/geometries/multi_linestring.hpp b/boost/geometry/geometries/multi_linestring.hpp
index 67003522b0..79b59efeb8 100644
--- a/boost/geometry/geometries/multi_linestring.hpp
+++ b/boost/geometry/geometries/multi_linestring.hpp
@@ -24,9 +24,8 @@
#include <boost/geometry/geometries/concepts/linestring_concept.hpp>
#include <boost/config.hpp>
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+
#include <initializer_list>
-#endif
namespace boost { namespace geometry
{
@@ -57,8 +56,6 @@ class multi_linestring : public Container<LineString, Allocator<LineString> >
{
BOOST_CONCEPT_ASSERT( (concepts::Linestring<LineString>) );
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
-
// default constructor and base_type definitions are required only
// if the constructor taking std::initializer_list is defined
@@ -87,8 +84,6 @@ public:
// return *this;
// }
//#endif
-
-#endif
};
diff --git a/boost/geometry/geometries/multi_point.hpp b/boost/geometry/geometries/multi_point.hpp
index 9579f4f602..1458d57a40 100644
--- a/boost/geometry/geometries/multi_point.hpp
+++ b/boost/geometry/geometries/multi_point.hpp
@@ -24,9 +24,8 @@
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/config.hpp>
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+
#include <initializer_list>
-#endif
namespace boost { namespace geometry
{
@@ -74,8 +73,6 @@ public :
: base_type(begin, end)
{}
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
-
/// \constructor_initializer_list{multi_point}
inline multi_point(std::initializer_list<Point> l)
: base_type(l.begin(), l.end())
@@ -94,7 +91,6 @@ public :
// }
//#endif
-#endif
};
} // namespace model
diff --git a/boost/geometry/geometries/multi_polygon.hpp b/boost/geometry/geometries/multi_polygon.hpp
index 94cd922719..87ada7fc75 100644
--- a/boost/geometry/geometries/multi_polygon.hpp
+++ b/boost/geometry/geometries/multi_polygon.hpp
@@ -24,9 +24,9 @@
#include <boost/geometry/geometries/concepts/polygon_concept.hpp>
#include <boost/config.hpp>
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+
#include <initializer_list>
-#endif
+
namespace boost { namespace geometry
{
@@ -56,8 +56,6 @@ class multi_polygon : public Container<Polygon, Allocator<Polygon> >
{
BOOST_CONCEPT_ASSERT( (concepts::Polygon<Polygon>) );
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
-
// default constructor and base_type definitions are required only
// if the constructor taking std::initializer_list is defined
@@ -86,8 +84,6 @@ public:
// return *this;
// }
//#endif
-
-#endif
};
diff --git a/boost/geometry/geometries/point_xyz.hpp b/boost/geometry/geometries/point_xyz.hpp
index 8f8ccf4221..d346b28a55 100644
--- a/boost/geometry/geometries/point_xyz.hpp
+++ b/boost/geometry/geometries/point_xyz.hpp
@@ -70,7 +70,7 @@ public:
/// Set y-value
void y(CoordinateType const& v)
{ this->template set<1>(v); }
-
+
/// Set z-value
void z(CoordinateType const& v)
{ this->template set<2>(v); }
diff --git a/boost/geometry/geometries/polygon.hpp b/boost/geometry/geometries/polygon.hpp
index 76e76cef19..4857c001ae 100644
--- a/boost/geometry/geometries/polygon.hpp
+++ b/boost/geometry/geometries/polygon.hpp
@@ -28,9 +28,9 @@
#include <boost/geometry/geometries/ring.hpp>
#include <boost/config.hpp>
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+
#include <initializer_list>
-#endif
+
namespace boost { namespace geometry
{
@@ -90,8 +90,6 @@ public:
inline ring_type& outer() { return m_outer; }
inline inner_container_type & inners() { return m_inners; }
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
-
// default constructor definition is required only
// if the constructor taking std::initializer_list is defined
@@ -129,8 +127,6 @@ public:
// }
//#endif
-#endif
-
/// Utility method, clears outer and inner rings
inline void clear()
{
diff --git a/boost/geometry/geometries/register/point.hpp b/boost/geometry/geometries/register/point.hpp
index 695ff09069..47da20fb67 100644
--- a/boost/geometry/geometries/register/point.hpp
+++ b/boost/geometry/geometries/register/point.hpp
@@ -18,11 +18,15 @@
#ifndef BOOST_GEOMETRY_GEOMETRIES_REGISTER_POINT_HPP
#define BOOST_GEOMETRY_GEOMETRIES_REGISTER_POINT_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/cs.hpp>
#include <cstddef>
#include <type_traits>
-
#ifndef DOXYGEN_NO_SPECIALIZATIONS
// Starting point, specialize basic traits necessary to register a point
diff --git a/boost/geometry/geometries/ring.hpp b/boost/geometry/geometries/ring.hpp
index fda0be40b4..3921e3a222 100644
--- a/boost/geometry/geometries/ring.hpp
+++ b/boost/geometry/geometries/ring.hpp
@@ -28,9 +28,8 @@
#include <boost/geometry/geometries/concepts/point_concept.hpp>
#include <boost/config.hpp>
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
+
#include <initializer_list>
-#endif
namespace boost { namespace geometry
{
@@ -79,8 +78,6 @@ public :
: base_type(begin, end)
{}
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
-
/// \constructor_initializer_list{ring}
inline ring(std::initializer_list<Point> l)
: base_type(l.begin(), l.end())
@@ -99,7 +96,6 @@ public :
// }
//#endif
-#endif
};
} // namespace model
diff --git a/boost/geometry/geometry.hpp b/boost/geometry/geometry.hpp
index f8b91dfa6c..d0cf39b7e0 100644
--- a/boost/geometry/geometry.hpp
+++ b/boost/geometry/geometry.hpp
@@ -20,13 +20,10 @@
#ifndef BOOST_GEOMETRY_GEOMETRY_HPP
#define BOOST_GEOMETRY_GEOMETRY_HPP
-#if !defined(BOOST_GEOMETRY_DISABLE_DEPRECATED_03_WARNING)
#include <boost/config.hpp>
+
#if defined(BOOST_NO_CXX14_CONSTEXPR)
-#include <boost/config/pragma_message.hpp>
-BOOST_PRAGMA_MESSAGE("CAUTION: Boost.Geometry in Boost 1.73 deprecates support for C++03 and will require C++14 from Boost 1.75 onwards.")
-BOOST_PRAGMA_MESSAGE("CAUTION: Define BOOST_GEOMETRY_DISABLE_DEPRECATED_03_WARNING to suppress this message.")
-#endif
+#error "Use C++14 or higher to compile Boost.Geometry, or use Boost 1.72 or lower."
#endif
// Shortcut to include all header files
@@ -66,6 +63,7 @@ BOOST_PRAGMA_MESSAGE("CAUTION: Define BOOST_GEOMETRY_DISABLE_DEPRECATED_03_WARNI
#include <boost/geometry/algorithms/buffer.hpp>
#include <boost/geometry/algorithms/centroid.hpp>
#include <boost/geometry/algorithms/clear.hpp>
+#include <boost/geometry/algorithms/closest_points.hpp>
#include <boost/geometry/algorithms/comparable_distance.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/convex_hull.hpp>
@@ -84,6 +82,7 @@ BOOST_PRAGMA_MESSAGE("CAUTION: Define BOOST_GEOMETRY_DISABLE_DEPRECATED_03_WARNI
#include <boost/geometry/algorithms/for_each.hpp>
#include <boost/geometry/algorithms/intersection.hpp>
#include <boost/geometry/algorithms/intersects.hpp>
+#include <boost/geometry/algorithms/is_convex.hpp>
#include <boost/geometry/algorithms/is_empty.hpp>
#include <boost/geometry/algorithms/is_simple.hpp>
#include <boost/geometry/algorithms/is_valid.hpp>
@@ -96,6 +95,7 @@ BOOST_PRAGMA_MESSAGE("CAUTION: Define BOOST_GEOMETRY_DISABLE_DEPRECATED_03_WARNI
#include <boost/geometry/algorithms/num_segments.hpp>
#include <boost/geometry/algorithms/overlaps.hpp>
#include <boost/geometry/algorithms/perimeter.hpp>
+#include <boost/geometry/algorithms/point_on_surface.hpp>
#include <boost/geometry/algorithms/relate.hpp>
#include <boost/geometry/algorithms/relation.hpp>
#include <boost/geometry/algorithms/remove_spikes.hpp>
@@ -131,4 +131,7 @@ BOOST_PRAGMA_MESSAGE("CAUTION: Define BOOST_GEOMETRY_DISABLE_DEPRECATED_03_WARNI
#include <boost/geometry/io/wkt/read.hpp>
#include <boost/geometry/io/wkt/write.hpp>
+#include <boost/geometry/algorithms/is_convex.hpp>
+#include <boost/geometry/algorithms/point_on_surface.hpp>
+
#endif // BOOST_GEOMETRY_GEOMETRY_HPP
diff --git a/boost/geometry/index/detail/algorithms/bounds.hpp b/boost/geometry/index/detail/algorithms/bounds.hpp
index 1828a24674..999246d9c9 100644
--- a/boost/geometry/index/detail/algorithms/bounds.hpp
+++ b/boost/geometry/index/detail/algorithms/bounds.hpp
@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019-2020.
-// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2021.
+// Modifications copyright (c) 2019-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,6 +15,11 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_BOUNDS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_BOUNDS_HPP
+#include <boost/geometry/algorithms/convert.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
+#include <boost/geometry/algorithms/detail/envelope/interface.hpp>
+#include <boost/geometry/algorithms/detail/expand/interface.hpp>
+
#include <boost/geometry/index/detail/bounded_view.hpp>
namespace boost { namespace geometry { namespace index { namespace detail
diff --git a/boost/geometry/index/detail/algorithms/comparable_distance_centroid.hpp b/boost/geometry/index/detail/algorithms/comparable_distance_centroid.hpp
index c4e44cae18..97553f7c32 100644
--- a/boost/geometry/index/detail/algorithms/comparable_distance_centroid.hpp
+++ b/boost/geometry/index/detail/algorithms/comparable_distance_centroid.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2021.
+// Modifications copyright (c) 2021 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -11,6 +15,9 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_CENTROID_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_CENTROID_HPP
+#include <boost/geometry/algorithms/detail/comparable_distance/interface.hpp>
+#include <boost/geometry/core/access.hpp>
+
#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>
#include <boost/geometry/index/detail/algorithms/diff_abs.hpp>
@@ -48,7 +55,7 @@ struct sum_for_indexable_dimension<Point, BoxIndexable, box_tag, comparable_dist
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?
diff --git a/boost/geometry/index/detail/algorithms/comparable_distance_far.hpp b/boost/geometry/index/detail/algorithms/comparable_distance_far.hpp
index 214fbf6aaf..102ac545e5 100644
--- a/boost/geometry/index/detail/algorithms/comparable_distance_far.hpp
+++ b/boost/geometry/index/detail/algorithms/comparable_distance_far.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2021.
+// Modifications copyright (c) 2021 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -11,6 +15,9 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_FAR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_FAR_HPP
+#include <boost/geometry/algorithms/detail/comparable_distance/interface.hpp>
+#include <boost/geometry/core/access.hpp>
+
#include <boost/geometry/index/detail/algorithms/diff_abs.hpp>
#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>
diff --git a/boost/geometry/index/detail/algorithms/comparable_distance_near.hpp b/boost/geometry/index/detail/algorithms/comparable_distance_near.hpp
index 15368a7d24..4f2905f3a1 100644
--- a/boost/geometry/index/detail/algorithms/comparable_distance_near.hpp
+++ b/boost/geometry/index/detail/algorithms/comparable_distance_near.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2021.
+// Modifications copyright (c) 2021 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -11,6 +15,9 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_NEAR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_COMPARABLE_DISTANCE_NEAR_HPP
+#include <boost/geometry/algorithms/detail/comparable_distance/interface.hpp>
+#include <boost/geometry/core/access.hpp>
+
#include <boost/geometry/index/detail/algorithms/sum_for_indexable.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
diff --git a/boost/geometry/index/detail/algorithms/content.hpp b/boost/geometry/index/detail/algorithms/content.hpp
index 7833ae3776..f7dfe373d8 100644
--- a/boost/geometry/index/detail/algorithms/content.hpp
+++ b/boost/geometry/index/detail/algorithms/content.hpp
@@ -4,8 +4,9 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2023.
+// Modifications copyright (c) 2020-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,17 +16,24 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_CONTENT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_CONTENT_HPP
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/static_assert.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/select_most_precise.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;
+ using type = typename select_most_precise
+ <
+ typename coordinate_type<Indexable>::type,
+ double
+ >::type;
};
namespace dispatch {
diff --git a/boost/geometry/index/detail/algorithms/diff_abs.hpp b/boost/geometry/index/detail/algorithms/diff_abs.hpp
index 96304acc51..e696ac581d 100644
--- a/boost/geometry/index/detail/algorithms/diff_abs.hpp
+++ b/boost/geometry/index/detail/algorithms/diff_abs.hpp
@@ -4,8 +4,9 @@
//
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2023.
+// Modifications copyright (c) 2020-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,6 +16,7 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_DIFF_ABS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_DIFF_ABS_HPP
+#include <cmath>
#include <type_traits>
namespace boost { namespace geometry { namespace index { namespace detail
diff --git a/boost/geometry/index/detail/algorithms/intersection_content.hpp b/boost/geometry/index/detail/algorithms/intersection_content.hpp
index 880540bc08..1a2cd28bc0 100644
--- a/boost/geometry/index/detail/algorithms/intersection_content.hpp
+++ b/boost/geometry/index/detail/algorithms/intersection_content.hpp
@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2018 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019-2020.
-// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2021.
+// Modifications copyright (c) 2019-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -20,6 +20,9 @@
#include <boost/geometry/index/detail/algorithms/content.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+#include <boost/geometry/strategies/disjoint.hpp>
+
namespace boost { namespace geometry { namespace index { namespace detail {
// Util to distinguish between default and non-default index strategy
diff --git a/boost/geometry/index/detail/algorithms/is_valid.hpp b/boost/geometry/index/detail/algorithms/is_valid.hpp
index 0d57ed57e8..5cd241c29a 100644
--- a/boost/geometry/index/detail/algorithms/is_valid.hpp
+++ b/boost/geometry/index/detail/algorithms/is_valid.hpp
@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2021.
+// Modifications copyright (c) 2020-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -18,6 +18,7 @@
#include <cstddef>
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/static_assert.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
diff --git a/boost/geometry/index/detail/algorithms/margin.hpp b/boost/geometry/index/detail/algorithms/margin.hpp
index 2033f4a531..dc86a511ee 100644
--- a/boost/geometry/index/detail/algorithms/margin.hpp
+++ b/boost/geometry/index/detail/algorithms/margin.hpp
@@ -4,8 +4,9 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2023.
+// Modifications copyright (c) 2020-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,7 +16,13 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MARGIN_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_MARGIN_HPP
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/static_assert.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/select_most_precise.hpp>
// WARNING! comparable_margin() will work only if the same Geometries are compared
// so it shouldn't be used in the case of Variants!
@@ -25,10 +32,11 @@ 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;
+ using type = typename select_most_precise
+ <
+ typename coordinate_type<Box>::type,
+ double
+ >::type;
};
//template <typename Box,
diff --git a/boost/geometry/index/detail/algorithms/minmaxdist.hpp b/boost/geometry/index/detail/algorithms/minmaxdist.hpp
index 508b706196..2f28163a11 100644
--- a/boost/geometry/index/detail/algorithms/minmaxdist.hpp
+++ b/boost/geometry/index/detail/algorithms/minmaxdist.hpp
@@ -56,7 +56,7 @@ struct smallest_for_indexable_dimension<Point, BoxIndexable, box_tag, minmaxdist
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;
diff --git a/boost/geometry/index/detail/algorithms/path_intersection.hpp b/boost/geometry/index/detail/algorithms/path_intersection.hpp
index 4803f59142..831efe5046 100644
--- a/boost/geometry/index/detail/algorithms/path_intersection.hpp
+++ b/boost/geometry/index/detail/algorithms/path_intersection.hpp
@@ -4,8 +4,9 @@
//
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2023.
+// Modifications copyright (c) 2020-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -16,10 +17,14 @@
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_PATH_INTERSECTION_HPP
+#include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
+#include <boost/geometry/algorithms/detail/distance/interface.hpp>
+
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/index/detail/algorithms/segment_intersection.hpp>
+#include <boost/geometry/strategies/default_distance_result.hpp>
#include <boost/geometry/strategies/default_length_result.hpp>
@@ -63,9 +68,9 @@ struct path_intersection<Indexable, Linestring, box_tag, linestring_tag>
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_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 )
diff --git a/boost/geometry/index/detail/algorithms/segment_intersection.hpp b/boost/geometry/index/detail/algorithms/segment_intersection.hpp
index a2717d26ee..674d9f5f89 100644
--- a/boost/geometry/index/detail/algorithms/segment_intersection.hpp
+++ b/boost/geometry/index/detail/algorithms/segment_intersection.hpp
@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2021.
+// Modifications copyright (c) 2020-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,9 +15,14 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SEGMENT_INTERSECTION_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_ALGORITHMS_SEGMENT_INTERSECTION_HPP
+#include <limits>
#include <type_traits>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/static_assert.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
diff --git a/boost/geometry/index/detail/bounded_view.hpp b/boost/geometry/index/detail/bounded_view.hpp
index 6b4d91a64c..b3776416b0 100644
--- a/boost/geometry/index/detail/bounded_view.hpp
+++ b/boost/geometry/index/detail/bounded_view.hpp
@@ -71,7 +71,7 @@ public:
bounded_view_base(Segment const& segment, Strategy const& )
: m_segment(segment)
{}
-
+
template <std::size_t Dimension>
inline coordinate_type get_min() const
{
diff --git a/boost/geometry/index/detail/distance_predicates.hpp b/boost/geometry/index/detail/distance_predicates.hpp
index dcd8d12433..e8420cc6ba 100644
--- a/boost/geometry/index/detail/distance_predicates.hpp
+++ b/boost/geometry/index/detail/distance_predicates.hpp
@@ -5,8 +5,9 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019-2020.
-// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2023.
+// Modifications copyright (c) 2019-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -18,11 +19,18 @@
#include <boost/geometry/core/static_assert.hpp>
+#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/interface.hpp>
+#include <boost/geometry/algorithms/detail/intersects/interface.hpp>
+#include <boost/geometry/algorithms/detail/overlaps/interface.hpp>
+#include <boost/geometry/algorithms/detail/touches/interface.hpp>
+#include <boost/geometry/algorithms/detail/within/interface.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/predicates.hpp>
#include <boost/geometry/index/detail/tags.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
diff --git a/boost/geometry/index/detail/maxmin_heap.hpp b/boost/geometry/index/detail/maxmin_heap.hpp
new file mode 100644
index 0000000000..01ae54ae28
--- /dev/null
+++ b/boost/geometry/index/detail/maxmin_heap.hpp
@@ -0,0 +1,107 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_MAXMIN_HEAP_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_MAXMIN_HEAP_HPP
+
+#include <boost/geometry/index/detail/minmax_heap.hpp>
+
+namespace boost { namespace geometry { namespace index { namespace detail
+{
+
+template <typename It, typename Compare>
+inline void push_maxmin_heap(It first, It last, Compare comp)
+{
+ using namespace minmax_heap_detail;
+ minmax_heap_detail::push_heap<max_call, min_call>(first, last, comp);
+}
+
+template <typename It>
+inline void push_maxmin_heap(It first, It last)
+{
+ using namespace minmax_heap_detail;
+ minmax_heap_detail::push_heap<max_call, min_call>(first, last, std::less<>());
+}
+
+template <typename It, typename Compare>
+inline void pop_top_maxmin_heap(It first, It last, Compare comp)
+{
+ using namespace minmax_heap_detail;
+ pop_heap<max_call, min_call>(first, first, last, comp);
+}
+
+template <typename It>
+inline void pop_top_maxmin_heap(It first, It last)
+{
+ using namespace minmax_heap_detail;
+ pop_heap<max_call, min_call>(first, first, last, std::less<>());
+}
+
+template <typename It, typename Compare>
+inline void pop_bottom_maxmin_heap(It first, It last, Compare comp)
+{
+ using namespace minmax_heap_detail;
+ It bottom = minmax_heap_detail::bottom_heap<max_call>(first, last, comp);
+ pop_heap<max_call, min_call>(first, bottom, last, comp);
+}
+
+template <typename It>
+inline void pop_bottom_maxmin_heap(It first, It last)
+{
+ using namespace minmax_heap_detail;
+ auto&& comp = std::less<>();
+ It bottom = minmax_heap_detail::bottom_heap<max_call>(first, last, comp);
+ pop_heap<max_call, min_call>(first, bottom, last, comp);
+}
+
+template <typename It, typename Compare>
+inline void make_maxmin_heap(It first, It last, Compare comp)
+{
+ using namespace minmax_heap_detail;
+ return minmax_heap_detail::make_heap<max_call, min_call>(first, last, comp);
+}
+
+template <typename It>
+inline void make_maxmin_heap(It first, It last)
+{
+ using namespace minmax_heap_detail;
+ return minmax_heap_detail::make_heap<max_call, min_call>(first, last, std::less<>());
+}
+
+template <typename It, typename Compare>
+inline bool is_maxmin_heap(It first, It last, Compare comp)
+{
+ using namespace minmax_heap_detail;
+ return minmax_heap_detail::is_heap<max_call>(first, last, comp);
+}
+
+template <typename It>
+inline bool is_maxmin_heap(It first, It last)
+{
+ using namespace minmax_heap_detail;
+ return minmax_heap_detail::is_heap<max_call>(first, last, std::less<>());
+}
+
+template <typename It, typename Compare>
+inline decltype(auto) bottom_maxmin_heap(It first, It last, Compare comp)
+{
+ using namespace minmax_heap_detail;
+ return *minmax_heap_detail::bottom_heap<max_call>(first, last, comp);
+}
+
+template <typename It>
+inline decltype(auto) bottom_maxmin_heap(It first, It last)
+{
+ using namespace minmax_heap_detail;
+ return *minmax_heap_detail::bottom_heap<max_call>(first, last, std::less<>());
+}
+
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_MAXMIN_HEAP_HPP
diff --git a/boost/geometry/index/detail/minmax_heap.hpp b/boost/geometry/index/detail/minmax_heap.hpp
new file mode 100644
index 0000000000..4864ce8f5f
--- /dev/null
+++ b/boost/geometry/index/detail/minmax_heap.hpp
@@ -0,0 +1,521 @@
+// Boost.Geometry
+
+// Copyright (c) 2021-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_MINMAX_HEAP_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_MINMAX_HEAP_HPP
+
+#include <iterator>
+#include <limits.h>
+#include <type_traits>
+#include <utility>
+
+#ifdef _MSC_VER // msvc and clang-win
+#include <intrin.h>
+#endif
+
+namespace boost { namespace geometry { namespace index { namespace detail
+{
+
+// Resources:
+// https://en.wikipedia.org/wiki/Min-max_heap
+// http://akira.ruc.dk/~keld/teaching/algoritmedesign_f03/Artikler/02/Atkinson86.pdf
+// https://probablydance.com/2020/08/31/on-modern-hardware-the-min-max-heap-beats-a-binary-heap/
+// https://stackoverflow.com/questions/6531543/efficient-implementation-of-binary-heaps
+// https://stackoverflow.com/questions/994593/how-to-do-an-integer-log2-in-c
+
+namespace minmax_heap_detail
+{
+
+template <typename T>
+using bitsize = std::integral_constant<std::size_t, sizeof(T) * CHAR_BIT>;
+
+template <typename It>
+using diff_t = typename std::iterator_traits<It>::difference_type;
+template <typename It>
+using val_t = typename std::iterator_traits<It>::value_type;
+
+// TODO: In C++20 use std::bit_width()
+
+template <typename T, std::enable_if_t<!std::is_integral<T>::value || (bitsize<T>::value != 32 && bitsize<T>::value != 64), int> = 0>
+inline int level(T i)
+{
+ ++i;
+ int r = 0;
+ while (i >>= 1) { ++r; }
+ return r;
+}
+
+//template <typename T>
+//inline int level(T i)
+//{
+// using std::log2;
+// return int(log2(i + 1));
+//}
+
+#ifdef _MSC_VER // msvc and clang-win
+
+template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 32, int> = 0>
+inline int level(T i)
+{
+ unsigned long r = 0;
+ _BitScanReverse(&r, (unsigned long)(i + 1));
+ return int(r);
+}
+
+template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 64, int> = 0>
+inline int level(T i)
+{
+ unsigned long r = 0;
+#ifdef _WIN64
+ _BitScanReverse64(&r, (unsigned long long)(i + 1));
+#else
+ if (_BitScanReverse(&r, (unsigned long)((i + 1) >> 32))) { r += 32; }
+ else { _BitScanReverse(&r, (unsigned long)(i + 1)); }
+#endif
+ return int(r);
+}
+
+#elif defined(__clang__) || defined(__GNUC__)
+// Only available in gcc-10 and clang-10
+//#elif defined(__has_builtin) && __has_builtin(__builtin_clzl) && __has_builtin(__builtin_clzll)
+
+template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 32, int> = 0>
+inline int level(T i)
+{
+ return 31 - __builtin_clzl((unsigned long)(i + 1));
+}
+
+template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 64, int> = 0>
+inline int level(T i)
+{
+ return 63 - __builtin_clzll((unsigned long long)(i + 1));
+}
+
+#else
+
+template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 32, int> = 0>
+inline int level(T i)
+{
+ ++i;
+ int r = 0;
+ if (i >= 65536) { r += 16; i >>= 16; }
+ if (i >= 256) { r += 8; i >>= 8; }
+ if (i >= 16) { r += 4; i >>= 4; }
+ if (i >= 4) { r += 2; i >>= 2; }
+ if (i >= 2) { r += 1; i >>= 1; }
+ return r;
+}
+
+template <typename T, std::enable_if_t<std::is_integral<T>::value && bitsize<T>::value == 64, int> = 0>
+inline int level(T i)
+{
+ ++i;
+ int r = 0;
+ if (i >= 4294967296ll) { r += 32; i >>= 32; }
+ if (i >= 65536ll) { r += 16; i >>= 16; }
+ if (i >= 256ll) { r += 8; i >>= 8; }
+ if (i >= 16ll) { r += 4; i >>= 4; }
+ if (i >= 4ll) { r += 2; i >>= 2; }
+ if (i >= 2ll) { r += 1; i >>= 1; }
+ return r;
+}
+
+#endif
+
+
+// min/max functions only differ in the order of arguments in comp
+struct min_call
+{
+ template <typename Compare, typename T1, typename T2>
+ bool operator()(Compare&& comp, T1 const& v1, T2 const& v2) const
+ {
+ return comp(v1, v2);
+ }
+};
+
+struct max_call
+{
+ template <typename Compare, typename T1, typename T2>
+ bool operator()(Compare&& comp, T1 const& v1, T2 const& v2) const
+ {
+ return comp(v2, v1);
+ }
+};
+
+
+template <typename Call, typename It, typename Compare>
+inline void push_heap2(It first, diff_t<It> c, val_t<It> val, Compare comp)
+{
+ while (c > 2)
+ {
+ diff_t<It> const g = (c - 3) >> 2; // grandparent index
+ if (! Call()(comp, val, *(first + g)))
+ {
+ break;
+ }
+ *(first + c) = std::move(*(first + g));
+ c = g;
+ }
+
+ *(first + c) = std::move(val);
+}
+
+template <typename MinCall, typename MaxCall, typename It, typename Compare>
+inline void push_heap1(It first, diff_t<It> c, val_t<It> val, Compare comp)
+{
+ diff_t<It> const p = (c - 1) >> 1; // parent index
+ if (MinCall()(comp, *(first + p), val))
+ {
+ *(first + c) = std::move(*(first + p));
+ return push_heap2<MaxCall>(first, p, std::move(val), comp);
+ }
+ else
+ {
+ return push_heap2<MinCall>(first, c, std::move(val), comp);
+ }
+}
+
+template <typename MinCall, typename MaxCall, typename It, typename Compare>
+inline void push_heap(It first, It last, Compare comp)
+{
+ diff_t<It> const size = last - first;
+ if (size < 2)
+ {
+ return;
+ }
+
+ diff_t<It> c = size - 1; // back index
+ val_t<It> val = std::move(*(first + c));
+ if (level(c) % 2 == 0) // is min level
+ {
+ push_heap1<MinCall, MaxCall>(first, c, std::move(val), comp);
+ }
+ else
+ {
+ push_heap1<MaxCall, MinCall>(first, c, std::move(val), comp);
+ }
+}
+
+
+template <typename Call, typename It, typename Compare>
+inline diff_t<It> pick_grandchild4(It first, diff_t<It> f, Compare comp)
+{
+ It it = first + f;
+ diff_t<It> m1 = Call()(comp, *(it), *(it + 1)) ? f : f + 1;
+ diff_t<It> m2 = Call()(comp, *(it + 2), *(it + 3)) ? f + 2 : f + 3;
+ return Call()(comp, *(first + m1), *(first + m2)) ? m1 : m2;
+}
+
+//template <typename Call, typename It, typename Compare>
+//inline diff_t<It> pick_descendant(It first, diff_t<It> f, diff_t<It> l, Compare comp)
+//{
+// diff_t<It> m = f;
+// for (++f; f != l; ++f)
+// {
+// if (Call()(comp, *(first + f), *(first + m)))
+// {
+// m = f;
+// }
+// }
+// return m;
+//}
+
+template <typename Call, typename It, typename Compare>
+inline void pop_heap1(It first, diff_t<It> p, diff_t<It> size, val_t<It> val, Compare comp)
+{
+ if (size >= 7) // grandparent of 4 grandchildren is possible
+ {
+ diff_t<It> const last_g = (size - 3) >> 2; // grandparent of the element behind back
+ while (p < last_g) // p is grandparent of 4 grandchildren
+ {
+ diff_t<It> const ll = 4 * p + 3;
+ diff_t<It> const m = pick_grandchild4<Call>(first, ll, comp);
+
+ if (! Call()(comp, *(first + m), val))
+ {
+ break;
+ }
+
+ *(first + p) = std::move(*(first + m));
+
+ diff_t<It> par = (m - 1) >> 1;
+ if (Call()(comp, *(first + par), val))
+ {
+ using std::swap;
+ swap(*(first + par), val);
+ }
+
+ p = m;
+ }
+ }
+
+ if (size >= 2 && p <= ((size - 2) >> 1)) // at least one child
+ {
+ diff_t<It> const l = 2 * p + 1;
+ diff_t<It> m = l; // left child
+ if (size >= 3 && p <= ((size - 3) >> 1)) // at least two children
+ {
+ // m = left child
+ diff_t<It> m2 = l + 1; // right child
+ if (size >= 4 && p <= ((size - 4) >> 2)) // at least two children and one grandchild
+ {
+ diff_t<It> const ll = 2 * l + 1;
+ m = ll; // left most grandchild
+ // m2 = right child
+ if (size >= 5 && p <= ((size - 5) >> 2)) // at least two children and two grandchildren
+ {
+ m = Call()(comp, *(first + ll), *(first + ll + 1)) ? ll : (ll + 1); // greater of the left grandchildren
+ // m2 = right child
+ if (size >= 6 && p <= ((size - 6) >> 2)) // at least two children and three grandchildren
+ {
+ // m = greater of the left grandchildren
+ m2 = ll + 2; // third grandchild
+ }
+ }
+ }
+
+ m = Call()(comp, *(first + m), *(first + m2)) ? m : m2;
+ }
+
+ if (Call()(comp, *(first + m), val))
+ {
+ *(first + p) = std::move(*(first + m));
+
+ if (m >= 3 && p <= ((m - 3) >> 2)) // is p grandparent of m
+ {
+ diff_t<It> par = (m - 1) >> 1;
+ if (Call()(comp, *(first + par), val))
+ {
+ using std::swap;
+ swap(*(first + par), val);
+ }
+ }
+
+ p = m;
+ }
+ }
+
+ *(first + p) = std::move(val);
+}
+
+template <typename MinCall, typename MaxCall, typename It, typename Compare>
+inline void pop_heap(It first, It el, It last, Compare comp)
+{
+ diff_t<It> size = last - first;
+ if (size < 2)
+ {
+ return;
+ }
+
+ --last;
+ val_t<It> val = std::move(*last);
+ *last = std::move(*el);
+
+ // Ignore the last element
+ --size;
+
+ diff_t<It> p = el - first;
+ if (level(p) % 2 == 0) // is min level
+ {
+ pop_heap1<MinCall>(first, p, size, std::move(val), comp);
+ }
+ else
+ {
+ pop_heap1<MaxCall>(first, p, size, std::move(val), comp);
+ }
+}
+
+template <typename MinCall, typename MaxCall, typename It, typename Compare>
+inline void make_heap(It first, It last, Compare comp)
+{
+ diff_t<It> size = last - first;
+ diff_t<It> p = size / 2;
+ if (p <= 0)
+ {
+ return;
+ }
+
+ int level_p = level(p - 1);
+ diff_t<It> level_f = (diff_t<It>(1) << level_p) - 1;
+ while (p > 0)
+ {
+ --p;
+ val_t<It> val = std::move(*(first + p));
+ if (level_p % 2 == 0) // is min level
+ {
+ pop_heap1<MinCall>(first, p, size, std::move(val), comp);
+ }
+ else
+ {
+ pop_heap1<MaxCall>(first, p, size, std::move(val), comp);
+ }
+
+ if (p == level_f)
+ {
+ --level_p;
+ level_f >>= 1;
+ }
+ }
+}
+
+template <typename Call, typename It, typename Compare>
+inline bool is_heap(It first, It last, Compare comp)
+{
+ diff_t<It> const size = last - first;
+ diff_t<It> pow2 = 4;
+ bool is_min_level = false;
+ for (diff_t<It> i = 1; i < size; ++i)
+ {
+ if (i == pow2 - 1)
+ {
+ pow2 *= 2;
+ is_min_level = ! is_min_level;
+ }
+
+ diff_t<It> const p = (i - 1) >> 1;
+ if (is_min_level)
+ {
+ if (Call()(comp, *(first + p), *(first + i)))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (Call()(comp, *(first + i), *(first + p)))
+ {
+ return false;
+ }
+ }
+
+ if (i >= 3)
+ {
+ diff_t<It> const g = (p - 1) >> 1;
+ if (is_min_level)
+ {
+ if (Call()(comp, *(first + i), *(first + g)))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (Call()(comp, *(first + g), *(first + i)))
+ {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+template <typename Call, typename It, typename Compare>
+inline It bottom_heap(It first, It last, Compare comp)
+{
+ diff_t<It> const size = last - first;
+ return size <= 1 ? first :
+ size == 2 ? (first + 1) :
+ Call()(comp, *(first + 1), *(first + 2)) ? (first + 2) : (first + 1);
+}
+
+} // namespace minmax_heap_detail
+
+
+template <typename It, typename Compare>
+inline void push_minmax_heap(It first, It last, Compare comp)
+{
+ using namespace minmax_heap_detail;
+ minmax_heap_detail::push_heap<min_call, max_call>(first, last, comp);
+}
+
+template <typename It>
+inline void push_minmax_heap(It first, It last)
+{
+ using namespace minmax_heap_detail;
+ minmax_heap_detail::push_heap<min_call, max_call>(first, last, std::less<>());
+}
+
+template <typename It, typename Compare>
+inline void pop_top_minmax_heap(It first, It last, Compare comp)
+{
+ using namespace minmax_heap_detail;
+ pop_heap<min_call, max_call>(first, first, last, comp);
+}
+
+template <typename It>
+inline void pop_top_minmax_heap(It first, It last)
+{
+ using namespace minmax_heap_detail;
+ pop_heap<min_call, max_call>(first, first, last, std::less<>());
+}
+
+template <typename It, typename Compare>
+inline void pop_bottom_minmax_heap(It first, It last, Compare comp)
+{
+ using namespace minmax_heap_detail;
+ It bottom = minmax_heap_detail::bottom_heap<min_call>(first, last, comp);
+ pop_heap<min_call, max_call>(first, bottom, last, comp);
+}
+
+template <typename It>
+inline void pop_bottom_minmax_heap(It first, It last)
+{
+ using namespace minmax_heap_detail;
+ auto&& comp = std::less<>();
+ It bottom = minmax_heap_detail::bottom_heap<min_call>(first, last, comp);
+ pop_heap<min_call, max_call>(first, bottom, last, comp);
+}
+
+template <typename It, typename Compare>
+inline void make_minmax_heap(It first, It last, Compare comp)
+{
+ using namespace minmax_heap_detail;
+ return minmax_heap_detail::make_heap<min_call, max_call>(first, last, comp);
+}
+
+template <typename It>
+inline void make_minmax_heap(It first, It last)
+{
+ using namespace minmax_heap_detail;
+ return minmax_heap_detail::make_heap<min_call, max_call>(first, last, std::less<>());
+}
+
+template <typename It, typename Compare>
+inline bool is_minmax_heap(It first, It last, Compare comp)
+{
+ using namespace minmax_heap_detail;
+ return minmax_heap_detail::is_heap<min_call>(first, last, comp);
+}
+
+template <typename It>
+inline bool is_minmax_heap(It first, It last)
+{
+ using namespace minmax_heap_detail;
+ return minmax_heap_detail::is_heap<min_call>(first, last, std::less<>());
+}
+
+template <typename It, typename Compare>
+inline decltype(auto) bottom_minmax_heap(It first, It last, Compare comp)
+{
+ using namespace minmax_heap_detail;
+ return *minmax_heap_detail::bottom_heap<min_call>(first, last, comp);
+}
+
+template <typename It>
+inline decltype(auto) bottom_minmax_heap(It first, It last)
+{
+ using namespace minmax_heap_detail;
+ return *minmax_heap_detail::bottom_heap<min_call>(first, last, std::less<>());
+}
+
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_MINMAX_HEAP_HPP
diff --git a/boost/geometry/index/detail/predicates.hpp b/boost/geometry/index/detail/predicates.hpp
index 0ae8defe8d..e6f2401982 100644
--- a/boost/geometry/index/detail/predicates.hpp
+++ b/boost/geometry/index/detail/predicates.hpp
@@ -4,8 +4,9 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019-2021.
-// Modifications copyright (c) 2019-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2023.
+// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -19,10 +20,21 @@
#include <type_traits>
//#include <utility>
+#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
+#include <boost/geometry/algorithms/detail/disjoint/interface.hpp>
+#include <boost/geometry/algorithms/detail/intersects/interface.hpp>
+#include <boost/geometry/algorithms/detail/overlaps/interface.hpp>
+#include <boost/geometry/algorithms/detail/touches/interface.hpp>
+#include <boost/geometry/algorithms/detail/within/interface.hpp>
+
#include <boost/geometry/core/static_assert.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/index/detail/tags.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
+
namespace boost { namespace geometry { namespace index { namespace detail {
namespace predicates {
@@ -31,10 +43,10 @@ namespace predicates {
// predicates
// ------------------------------------------------------------------ //
-template <typename Fun, bool IsFunction>
+template <typename Fun, bool IsFunction = std::is_function<Fun>::value>
struct satisfies_impl
{
- satisfies_impl() : fun(NULL) {}
+ satisfies_impl() : fun(nullptr) {}
satisfies_impl(Fun f) : fun(f) {}
Fun * fun;
};
@@ -42,20 +54,19 @@ struct satisfies_impl
template <typename Fun>
struct satisfies_impl<Fun, false>
{
- satisfies_impl() {}
+ satisfies_impl() = default;
satisfies_impl(Fun const& f) : fun(f) {}
Fun fun;
};
template <typename Fun, bool Negated>
-struct satisfies
- : satisfies_impl<Fun, ::boost::is_function<Fun>::value>
+struct satisfies : satisfies_impl<Fun>
{
- typedef satisfies_impl<Fun, ::boost::is_function<Fun>::value> base;
+ using base_t = satisfies_impl<Fun>;
- satisfies() {}
- satisfies(Fun const& f) : base(f) {}
- satisfies(base const& b) : base(b) {}
+ satisfies() = default;
+ satisfies(Fun const& f) : base_t(f) {}
+ satisfies(base_t const& b) : base_t(b) {}
};
// ------------------------------------------------------------------ //
@@ -619,11 +630,13 @@ struct predicates_check_impl<std::tuple<Ts...>, Tag, First, Last>
}
};
-template <typename Tag, std::size_t First, std::size_t Last, typename Predicates, typename Value, typename Indexable, typename Strategy>
+template <typename Tag, typename Predicates, typename Value, typename Indexable, typename Strategy>
inline bool predicates_check(Predicates const& p, Value const& v, Indexable const& i, Strategy const& s)
{
- return detail::predicates_check_impl<Predicates, Tag, First, Last>
- ::apply(p, v, i, s);
+ return detail::predicates_check_impl
+ <
+ Predicates, Tag, 0, predicates_length<Predicates>::value
+ >::apply(p, v, i, s);
}
// ------------------------------------------------------------------ //
diff --git a/boost/geometry/index/detail/priority_dequeue.hpp b/boost/geometry/index/detail/priority_dequeue.hpp
new file mode 100644
index 0000000000..bbe563abad
--- /dev/null
+++ b/boost/geometry/index/detail/priority_dequeue.hpp
@@ -0,0 +1,150 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_PRIORITY_DEQUEUE_HPP
+#define BOOST_GEOMETRY_INDEX_DETAIL_PRIORITY_DEQUEUE_HPP
+
+#include <vector>
+
+#include <boost/geometry/index/detail/maxmin_heap.hpp>
+
+namespace boost { namespace geometry { namespace index { namespace detail
+{
+
+template
+<
+ typename T,
+ typename Container = std::vector<T>,
+ typename Compare = std::less<typename Container::value_type>
+>
+class priority_dequeue
+{
+public:
+ using container_type = Container;
+ using value_compare = Compare;
+ using value_type = typename Container::value_type;
+ using size_type = typename Container::size_type;
+ using reference = typename Container::reference;
+ using const_reference = typename Container::const_reference;
+
+ priority_dequeue()
+ : c(), comp()
+ {}
+
+ explicit priority_dequeue(Compare const& compare)
+ : c(), comp(compare)
+ {}
+
+ priority_dequeue(Compare const& compare, Container const& cont)
+ : c(cont), comp(compare)
+ {
+ make_maxmin_heap(c.begin(), c.end(), comp);
+ }
+
+ priority_dequeue(Compare const& compare, Container&& cont)
+ : c(std::move(cont)), comp(compare)
+ {
+ make_maxmin_heap(c.begin(), c.end(), comp);
+ }
+
+ template <typename It>
+ priority_dequeue(It first, It last)
+ : c(first, last), comp()
+ {
+ make_maxmin_heap(c.begin(), c.end(), comp);
+ }
+
+ template <typename It>
+ priority_dequeue(It first, It last, Compare const& compare)
+ : c(first, last), comp(compare)
+ {
+ make_maxmin_heap(c.begin(), c.end(), comp);
+ }
+
+ template <typename It>
+ priority_dequeue(It first, It last, Compare const& compare, Container const& cont)
+ : c(cont), comp(compare)
+ {
+ c.insert(first, last);
+ make_maxmin_heap(c.begin(), c.end(), comp);
+ }
+
+ template <typename It>
+ priority_dequeue(It first, It last, Compare const& compare, Container&& cont)
+ : c(std::move(cont)), comp(compare)
+ {
+ c.insert(first, last);
+ make_maxmin_heap(c.begin(), c.end(), comp);
+ }
+
+ const_reference top() const
+ {
+ return *c.begin();
+ }
+
+ const_reference bottom() const
+ {
+ return bottom_maxmin_heap(c.begin(), c.end(), comp);
+ }
+
+ void push(const value_type& value)
+ {
+ c.push_back(value);
+ push_maxmin_heap(c.begin(), c.end(), comp);
+ }
+
+ void push(value_type&& value)
+ {
+ c.push_back(std::move(value));
+ push_maxmin_heap(c.begin(), c.end(), comp);
+ }
+
+ template <typename ...Args>
+ void emplace(Args&& ...args)
+ {
+ c.emplace_back(std::forward<Args>(args)...);
+ push_maxmin_heap(c.begin(), c.end(), comp);
+ }
+
+ void pop_top()
+ {
+ pop_top_maxmin_heap(c.begin(), c.end(), comp);
+ c.pop_back();
+ }
+
+ void pop_bottom()
+ {
+ pop_bottom_maxmin_heap(c.begin(), c.end(), comp);
+ c.pop_back();
+ }
+
+ bool empty() const
+ {
+ return c.empty();
+ }
+
+ size_t size() const
+ {
+ return c.size();
+ }
+
+ void swap(priority_dequeue& other)
+ {
+ using std::swap;
+ std::swap(c, other.c);
+ std::swap(comp, other.comp);
+ }
+
+protected:
+ Container c;
+ Compare comp;
+};
+
+}}}} // namespace boost::geometry::index::detail
+
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_PRIORITY_DEQUEUE_HPP
diff --git a/boost/geometry/index/detail/rtree/adaptors.hpp b/boost/geometry/index/detail/rtree/adaptors.hpp
index 4e0eb9ba0a..4da3d7b944 100644
--- a/boost/geometry/index/detail/rtree/adaptors.hpp
+++ b/boost/geometry/index/detail/rtree/adaptors.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2021.
+// Modifications copyright (c) 2021 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -11,13 +15,13 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ADAPTORS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ADAPTORS_HPP
-#include <deque>
-#include <boost/static_assert.hpp>
+#include <vector>
#include <boost/geometry/index/adaptors/query.hpp>
namespace boost { namespace geometry { namespace index {
+// Forward declaration
template <typename Value, typename Options, typename IndexableGetter, typename EqualTo, typename Allocator>
class rtree;
diff --git a/boost/geometry/index/detail/rtree/iterators.hpp b/boost/geometry/index/detail/rtree/iterators.hpp
index a47dd7ea43..5ab04a541c 100644
--- a/boost/geometry/index/detail/rtree/iterators.hpp
+++ b/boost/geometry/index/detail/rtree/iterators.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2021.
+// Modifications copyright (c) 2021 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -11,6 +15,10 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ITERATORS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_ITERATORS_HPP
+#include <iterator>
+
+#include <boost/geometry/index/detail/rtree/visitors/iterator.hpp>
+
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
template <typename Value, typename Allocators>
@@ -112,7 +120,7 @@ public:
{
return r.m_visitor.is_end();
}
-
+
private:
visitor_type m_visitor;
};
diff --git a/boost/geometry/index/detail/rtree/kmeans/kmeans.hpp b/boost/geometry/index/detail/rtree/kmeans/kmeans.hpp
index 3f61482b27..34edcfa7c0 100644
--- a/boost/geometry/index/detail/rtree/kmeans/kmeans.hpp
+++ b/boost/geometry/index/detail/rtree/kmeans/kmeans.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2021.
+// Modifications copyright (c) 2021 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -11,6 +15,6 @@
#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>
+#include <boost/geometry/index/detail/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
index f19654972e..aa9dfbba49 100644
--- a/boost/geometry/index/detail/rtree/kmeans/split.hpp
+++ b/boost/geometry/index/detail/rtree/kmeans/split.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2021.
+// Modifications copyright (c) 2021 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -11,13 +15,17 @@
#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>
+#include <boost/geometry/index/detail/rtree/node/concept.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
+// TODO: This should be defined in options.hpp
+// For now it's defined here to satisfy Boost header policy
+struct split_kmeans_tag {};
+
namespace kmeans {
// some details
@@ -56,25 +64,34 @@ namespace kmeans {
// 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>
+template <typename MembersHolder>
+class split<MembersHolder, 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 MembersHolder::parameters_type parameters_type;
+ typedef typename MembersHolder::box_type box_type;
+ typedef typename MembersHolder::translator_type translator_type;
+ typedef typename MembersHolder::allocators_type allocators_type;
+ typedef typename MembersHolder::size_type size_type;
- typedef typename Options::parameters_type parameters_type;
+ typedef typename MembersHolder::node node;
+ typedef typename MembersHolder::internal_node internal_node;
+ typedef typename MembersHolder::leaf leaf;
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(node* & root_node,
- size_t & leafs_level,
+ static inline void apply(nodes_container_type & additional_nodes,
Node & n,
- internal_node *parent_node,
- size_t current_child_index,
- Translator const& tr,
- Allocators & allocators)
+ box_type & n_box,
+ parameters_type const& parameters,
+ translator_type const& translator,
+ allocators_type & allocators)
{
}
diff --git a/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp b/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp
index ea684332d0..b698f18e96 100644
--- a/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp
+++ b/boost/geometry/index/detail/rtree/linear/redistribute_elements.hpp
@@ -3,7 +3,7 @@
// R-tree linear split algorithm implementation
//
// Copyright (c) 2008 Federico J. Fernandez.
-// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2022 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2020.
// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
@@ -114,50 +114,52 @@ struct find_greatest_normalized_separation
BOOST_GEOMETRY_INDEX_ASSERT(elements.size() == elements_count, "unexpected number of elements");
BOOST_GEOMETRY_INDEX_ASSERT(2 <= elements_count, "unexpected number of elements");
- typename index::detail::strategy_type<Parameters>::type const&
- strategy = index::detail::get_strategy(parameters);
+ auto const& strategy = index::detail::get_strategy(parameters);
// find the lowest low, highest high
- bounded_view_type bounded_indexable_0(rtree::element_indexable(elements[0], translator),
- strategy);
+ indexable_type const& indexable_0 = rtree::element_indexable(elements[0], translator);
+ bounded_view_type const bounded_indexable_0(indexable_0, strategy);
coordinate_type lowest_low = geometry::get<min_corner, DimensionIndex>(bounded_indexable_0);
coordinate_type highest_high = geometry::get<max_corner, DimensionIndex>(bounded_indexable_0);
// 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 )
+ for (size_t i = 1 ; i < elements_count ; ++i)
{
- bounded_view_type bounded_indexable(rtree::element_indexable(elements[i], translator),
- strategy);
+ indexable_type const& indexable_i = rtree::element_indexable(elements[i], translator);
+ bounded_view_type const bounded_indexable(indexable_i, strategy);
coordinate_type min_coord = geometry::get<min_corner, DimensionIndex>(bounded_indexable);
coordinate_type max_coord = geometry::get<max_corner, DimensionIndex>(bounded_indexable);
- if ( max_coord < lowest_high )
+ if (max_coord < lowest_high)
{
lowest_high = max_coord;
lowest_high_index = i;
}
- if ( min_coord < lowest_low )
+ if (min_coord < lowest_low)
+ {
lowest_low = min_coord;
+ }
- if ( highest_high < max_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;
- bounded_view_type bounded_indexable_hl(rtree::element_indexable(elements[highest_low_index], translator),
- strategy);
+ indexable_type const& indexable_hl = rtree::element_indexable(elements[highest_low_index], translator);
+ bounded_view_type const bounded_indexable_hl(indexable_hl, strategy);
coordinate_type highest_low = geometry::get<min_corner, DimensionIndex>(bounded_indexable_hl);
- for ( size_t i = highest_low_index ; i < elements_count ; ++i )
+ for (size_t i = highest_low_index ; i < elements_count ; ++i)
{
- bounded_view_type bounded_indexable(rtree::element_indexable(elements[i], translator),
- strategy);
+ indexable_type const& indexable = rtree::element_indexable(elements[i], translator);
+ bounded_view_type const bounded_indexable(indexable, strategy);
coordinate_type min_coord = geometry::get<min_corner, DimensionIndex>(bounded_indexable);
- if ( highest_low < min_coord &&
- i != lowest_high_index )
+ if (highest_low < min_coord && i != lowest_high_index)
{
highest_low = min_coord;
highest_low_index = i;
@@ -165,12 +167,14 @@ struct find_greatest_normalized_separation
}
coordinate_type const width = highest_high - lowest_low;
-
+
// highest_low - lowest_high
separation = difference<separation_type>(lowest_high, highest_low);
// BOOST_GEOMETRY_INDEX_ASSERT(0 <= width);
- if ( std::numeric_limits<coordinate_type>::epsilon() < width )
+ if (std::numeric_limits<coordinate_type>::epsilon() < width)
+ {
separation /= width;
+ }
seed1 = highest_low_index;
seed2 = lowest_high_index;
@@ -446,7 +450,7 @@ struct redistribute_elements<MembersHolder, linear_tag>
content2 = enlarged_content2;
}
}
-
+
BOOST_GEOMETRY_INDEX_ASSERT(0 < remaining, "unexpected value");
--remaining;
}
diff --git a/boost/geometry/index/detail/rtree/node/node.hpp b/boost/geometry/index/detail/rtree/node/node.hpp
index 4b789c87e4..fba76efb1c 100644
--- a/boost/geometry/index/detail/rtree/node/node.hpp
+++ b/boost/geometry/index/detail/rtree/node/node.hpp
@@ -2,7 +2,7 @@
//
// R-tree nodes
//
-// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2023 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2020.
// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
@@ -55,7 +55,7 @@ inline Box elements_box(FwdIter first, FwdIter last, Translator const& tr,
Strategy const& strategy)
{
Box result;
-
+
// Only here to suppress 'uninitialized local variable used' warning
// until the suggestion below is not implemented
geometry::assign_inverse(result);
@@ -218,7 +218,7 @@ void move_from_back(Container & container, Iterator it)
--back_it;
if ( it != back_it )
{
- *it = boost::move(*back_it); // MAY THROW (copy)
+ *it = std::move(*back_it); // MAY THROW (copy)
}
}
diff --git a/boost/geometry/index/detail/rtree/node/node_elements.hpp b/boost/geometry/index/detail/rtree/node/node_elements.hpp
index 0e5848987e..ca034a8d71 100644
--- a/boost/geometry/index/detail/rtree/node/node_elements.hpp
+++ b/boost/geometry/index/detail/rtree/node/node_elements.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2021.
+// Modifications copyright (c) 2021 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -15,6 +19,7 @@
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
#include <boost/geometry/index/detail/varray.hpp>
#include <boost/geometry/index/detail/rtree/node/pairs.hpp>
+#include <boost/geometry/index/detail/translator.hpp>
namespace boost { namespace geometry { namespace index {
diff --git a/boost/geometry/index/detail/rtree/node/pairs.hpp b/boost/geometry/index/detail/rtree/node/pairs.hpp
index dc088ec29b..57702617fa 100644
--- a/boost/geometry/index/detail/rtree/node/pairs.hpp
+++ b/boost/geometry/index/detail/rtree/node/pairs.hpp
@@ -2,7 +2,7 @@
//
// Pairs intended to be used internally in nodes.
//
-// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2023 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
@@ -11,8 +11,6 @@
#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 {
@@ -24,46 +22,17 @@ 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)
+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
diff --git a/boost/geometry/index/detail/rtree/node/scoped_deallocator.hpp b/boost/geometry/index/detail/rtree/node/scoped_deallocator.hpp
index 0062402d45..a63aad8841 100644
--- a/boost/geometry/index/detail/rtree/node/scoped_deallocator.hpp
+++ b/boost/geometry/index/detail/rtree/node/scoped_deallocator.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2018 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2021.
+// Modifications copyright (c) 2021 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -11,6 +15,8 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SCOPED_DEALLOCATOR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_SCOPED_DEALLOCATOR_HPP
+#include <boost/container/allocator_traits.hpp>
+
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
diff --git a/boost/geometry/index/detail/rtree/node/variant_dynamic.hpp b/boost/geometry/index/detail/rtree/node/variant_dynamic.hpp
index 52b253ccf6..c545a4160a 100644
--- a/boost/geometry/index/detail/rtree/node/variant_dynamic.hpp
+++ b/boost/geometry/index/detail/rtree/node/variant_dynamic.hpp
@@ -2,7 +2,12 @@
//
// R-tree nodes based on Boost.Variant, storing dynamic-size containers
//
-// Copyright (c) 2011-2018 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2023 Adam Wulkiewicz, Lodz, Poland.
+//
+// This file was modified by Oracle on 2021-2023.
+// Modifications copyright (c) 2021-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -11,7 +16,16 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_DYNAMIC_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_DYNAMIC_HPP
+#include <boost/container/allocator_traits.hpp>
+#include <boost/container/vector.hpp>
#include <boost/core/pointer_traits.hpp>
+#include <boost/variant/static_visitor.hpp>
+#include <boost/variant/variant.hpp>
+
+#include <boost/geometry/index/detail/rtree/options.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/scoped_deallocator.hpp>
namespace boost { namespace geometry { namespace index {
@@ -130,7 +144,7 @@ private:
node_allocator_type // node_allocator_type for consistency with variant_leaf
>::template rebind_alloc<Value> value_allocator_type;
typedef boost::container::allocator_traits<value_allocator_type> value_allocator_traits;
-
+
public:
typedef Allocator allocator_type;
@@ -152,23 +166,21 @@ public:
: node_allocator_type(alloc)
{}
- inline allocators(BOOST_FWD_REF(allocators) a)
- : node_allocator_type(boost::move(a.node_allocator()))
+ inline allocators(allocators&& a)
+ : node_allocator_type(std::move(a.node_allocator()))
{}
- inline allocators & operator=(BOOST_FWD_REF(allocators) a)
+ inline allocators & operator=(allocators&& a)
{
- node_allocator() = boost::move(a.node_allocator());
+ node_allocator() = std::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)
{
diff --git a/boost/geometry/index/detail/rtree/node/variant_static.hpp b/boost/geometry/index/detail/rtree/node/variant_static.hpp
index c30998d683..c1612b9853 100644
--- a/boost/geometry/index/detail/rtree/node/variant_static.hpp
+++ b/boost/geometry/index/detail/rtree/node/variant_static.hpp
@@ -2,7 +2,11 @@
//
// R-tree nodes based on Boost.Variant, storing static-size containers
//
-// Copyright (c) 2011-2018 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2023 Adam Wulkiewicz, Lodz, Poland.
+//
+// This file was modified by Oracle on 2021.
+// Modifications copyright (c) 2021 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -11,6 +15,9 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_STATIC_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_VARIANT_STATIC_HPP
+#include <boost/geometry/index/detail/rtree/node/variant_dynamic.hpp>
+#include <boost/geometry/index/detail/varray.hpp>
+
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
@@ -121,23 +128,21 @@ public:
: node_allocator_type(alloc)
{}
- inline allocators(BOOST_FWD_REF(allocators) a)
- : node_allocator_type(boost::move(a.node_allocator()))
+ inline allocators(allocators&& a)
+ : node_allocator_type(std::move(a.node_allocator()))
{}
- inline allocators & operator=(BOOST_FWD_REF(allocators) a)
+ inline allocators & operator=(allocators&& a)
{
- node_allocator() = boost::move(a.node_allocator());
+ node_allocator() = std::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)
{
diff --git a/boost/geometry/index/detail/rtree/node/weak_dynamic.hpp b/boost/geometry/index/detail/rtree/node/weak_dynamic.hpp
index eadda62a9d..8c2ec41475 100644
--- a/boost/geometry/index/detail/rtree/node/weak_dynamic.hpp
+++ b/boost/geometry/index/detail/rtree/node/weak_dynamic.hpp
@@ -2,7 +2,12 @@
//
// R-tree nodes based on static conversion, storing dynamic-size containers
//
-// Copyright (c) 2011-2018 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2023 Adam Wulkiewicz, Lodz, Poland.
+//
+// This file was modified by Oracle on 2021-2023.
+// Modifications copyright (c) 2021-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -11,10 +16,26 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_DYNAMIC_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_DYNAMIC_HPP
+#include <boost/container/allocator_traits.hpp>
+#include <boost/container/vector.hpp>
+#include <boost/core/pointer_traits.hpp>
+#include <boost/core/swap.hpp>
+
+#include <boost/geometry/index/detail/rtree/options.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/scoped_deallocator.hpp>
+#include <boost/geometry/index/detail/rtree/node/weak_visitor.hpp>
+
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
+// TODO: This should be defined in options.hpp
+// For now it's defined here to satisfy Boost header policy
+struct node_weak_dynamic_tag {};
+struct node_weak_static_tag {};
+
template <typename Value, typename Parameters, typename Box, typename Allocators, typename Tag>
struct weak_internal_node
: public weak_node<Value, Parameters, Box, Allocators, Tag>
@@ -87,7 +108,7 @@ struct visitor<Value, Parameters, Box, Allocators, node_weak_dynamic_tag, IsVisi
template <typename Allocator, typename Value, typename Parameters, typename Box, typename Tag>
struct internal_node_alloc
{
- typedef typename internal_nod
+ typedef typename internal_node
<
Value, Parameters, Box,
allocators<Allocator, Value, Parameters, Box, Tag>,
@@ -116,6 +137,22 @@ struct leaf_alloc
>::template rebind_alloc<node_type> type;
};
+template <typename Allocator, typename Value, typename Parameters, typename Box, typename Tag>
+struct node_alloc
+{
+ typedef typename weak_node
+ <
+ Value, Parameters, Box,
+ allocators<Allocator, Value, Parameters, Box, Tag>,
+ Tag
+ >::type node_type;
+
+ typedef typename ::boost::container::allocator_traits
+ <
+ Allocator
+ >::template rebind_alloc<node_type> type;
+};
+
template <typename Allocator, typename Value, typename Parameters, typename Box>
class allocators<Allocator, Value, Parameters, Box, node_weak_dynamic_tag>
: public internal_node_alloc<Allocator, Value, Parameters, Box, node_weak_dynamic_tag>::type
@@ -147,10 +184,10 @@ private:
leaf_allocator_type // leaf_allocator_type for consistency with weak_leaf
>::template rebind_alloc<Value> value_allocator_type;
typedef boost::container::allocator_traits<value_allocator_type> value_allocator_traits;
-
+
public:
typedef Allocator allocator_type;
-
+
typedef Value value_type;
typedef typename value_allocator_traits::reference reference;
typedef typename value_allocator_traits::const_reference const_reference;
@@ -170,26 +207,24 @@ public:
, 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(allocators&& a)
+ : internal_node_allocator_type(std::move(a.internal_node_allocator()))
+ , leaf_allocator_type(std::move(a.leaf_allocator()))
{}
- inline allocators & operator=(BOOST_FWD_REF(allocators) a)
+ inline allocators & operator=(allocators&& a)
{
- internal_node_allocator() = ::boost::move(a.internal_node_allocator());
- leaf_allocator() = ::boost::move(a.leaf_allocator());
+ internal_node_allocator() = std::move(a.internal_node_allocator());
+ leaf_allocator() = std::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)
{
diff --git a/boost/geometry/index/detail/rtree/node/weak_static.hpp b/boost/geometry/index/detail/rtree/node/weak_static.hpp
index ac9e69cecc..a1a5988643 100644
--- a/boost/geometry/index/detail/rtree/node/weak_static.hpp
+++ b/boost/geometry/index/detail/rtree/node/weak_static.hpp
@@ -2,7 +2,11 @@
//
// R-tree nodes based on static conversion, storing static-size containers
//
-// Copyright (c) 2011-2018 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2023 Adam Wulkiewicz, Lodz, Poland.
+//
+// This file was modified by Oracle on 2021.
+// Modifications copyright (c) 2021 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -11,6 +15,9 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_STATIC_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_STATIC_HPP
+#include <boost/geometry/index/detail/rtree/node/weak_dynamic.hpp>
+#include <boost/geometry/index/detail/varray.hpp>
+
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
@@ -127,26 +134,24 @@ public:
, 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(allocators&& a)
+ : internal_node_allocator_type(std::move(a.internal_node_allocator()))
+ , leaf_allocator_type(std::move(a.leaf_allocator()))
{}
- inline allocators & operator=(BOOST_FWD_REF(allocators) a)
+ inline allocators & operator=(allocators&& a)
{
- internal_node_allocator() = ::boost::move(a.internal_node_allocator());
- leaf_allocator() = ::boost::move(a.leaf_allocator());
+ internal_node_allocator() = std::move(a.internal_node_allocator());
+ leaf_allocator() = std::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)
{
diff --git a/boost/geometry/index/detail/rtree/node/weak_visitor.hpp b/boost/geometry/index/detail/rtree/node/weak_visitor.hpp
index 08d84778e6..a6beaf0905 100644
--- a/boost/geometry/index/detail/rtree/node/weak_visitor.hpp
+++ b/boost/geometry/index/detail/rtree/node/weak_visitor.hpp
@@ -4,6 +4,10 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2021.
+// Modifications copyright (c) 2021 Oracle and/or its affiliates.
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -11,6 +15,8 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_VISITOR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_NODE_WEAK_VISITOR_HPP
+#include <boost/geometry/index/detail/assert.hpp>
+
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree {
diff --git a/boost/geometry/index/detail/rtree/pack_create.hpp b/boost/geometry/index/detail/rtree/pack_create.hpp
index 4cfd39669d..33600a4c93 100644
--- a/boost/geometry/index/detail/rtree/pack_create.hpp
+++ b/boost/geometry/index/detail/rtree/pack_create.hpp
@@ -2,11 +2,12 @@
//
// R-tree initial packing
//
-// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2023 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2020 Caian Benedicto, Campinas, Brazil.
//
-// This file was modified by Oracle on 2019.
-// Modifications copyright (c) 2019 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2023.
+// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -18,12 +19,17 @@
#include <boost/core/ignore_unused.hpp>
+#include <boost/geometry/algorithms/centroid.hpp>
+#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
#include <boost/geometry/algorithms/expand.hpp>
+
#include <boost/geometry/index/detail/algorithms/bounds.hpp>
+#include <boost/geometry/index/detail/algorithms/content.hpp>
+#include <boost/geometry/index/detail/algorithms/is_valid.hpp>
#include <boost/geometry/index/detail/algorithms/nth_element.hpp>
+#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
#include <boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp>
-
-#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
+#include <boost/geometry/index/parameters.hpp>
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree {
@@ -72,23 +78,28 @@ template <std::size_t I, std::size_t Dimension>
struct nth_element_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)
+ 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 )
+ if (I == dim_index)
{
index::detail::nth_element(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);
+ auto const mi = geometry::get<min_corner, I>(box);
+ auto const ma = geometry::get<max_corner, I>(box);
+ auto const center = mi + (ma - mi) / 2;
+ geometry::set<max_corner, I>(left, center);
+ geometry::set<min_corner, I>(right, center);
}
else
- nth_element_and_half_boxes<I+1, Dimension>::apply(first, median, last, box, left, right, dim_index);
+ {
+ nth_element_and_half_boxes
+ <
+ I + 1, Dimension
+ >::apply(first, median, last, box, left, right, dim_index);
+ }
}
};
@@ -182,7 +193,7 @@ public:
TmpAlloc const& temp_allocator)
{
typedef typename std::iterator_traits<InIt>::difference_type diff_type;
-
+
diff_type diff = std::distance(first, last);
if ( diff <= 0 )
return node_pointer(0);
@@ -198,7 +209,7 @@ public:
entries.reserve(values_count);
auto const& strategy = index::detail::get_strategy(parameters);
-
+
expandable_box<box_type, strategy_type> hint_box(strategy);
for ( ; first != last ; ++first )
{
@@ -320,7 +331,7 @@ private:
{
// NOTE: push_back() must be called at the end in order to support move_iterator.
// The iterator is dereferenced 2x (no temporary reference) to support
- // non-true reference types and move_iterator without boost::forward<>.
+ // non-true reference types and move_iterator without std::forward<>.
elements_box.expand(translator(*(first->second)));
rtree::elements(l).push_back(*(first->second)); // MAY THROW (A?,C)
}
@@ -361,7 +372,7 @@ private:
rtree::elements(in).reserve(nodes_count); // MAY THROW (A)
// calculate values box and copy values
expandable_box<box_type, strategy_type> elements_box(detail::get_strategy(parameters));
-
+
per_level_packets(first, last, hint_box, values_count, subtree_counts, next_subtree_counts,
rtree::elements(in), elements_box,
parameters, translator, allocators);
@@ -406,7 +417,7 @@ private:
elements_box.expand(el.first);
return;
}
-
+
size_type median_count = calculate_median_count(values_count, subtree_counts);
EIt median = first + median_count;
@@ -416,7 +427,7 @@ private:
box_type left, right;
pack_utils::nth_element_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,
diff --git a/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp b/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp
index 05e71fb0e7..23de98c161 100644
--- a/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp
+++ b/boost/geometry/index/detail/rtree/quadratic/redistribute_elements.hpp
@@ -77,7 +77,7 @@ inline void pick_seeds(Elements const& elements,
content_type free_content = ( index::detail::content(enlarged_box)
- index::detail::content(bounded_ind1) )
- index::detail::content(bounded_ind2);
-
+
if ( greatest_free_content < free_content )
{
greatest_free_content = free_content;
@@ -121,7 +121,7 @@ struct redistribute_elements<MembersHolder, quadratic_tag>
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 - use in-memory storage (std::allocator)
@@ -130,7 +130,7 @@ struct redistribute_elements<MembersHolder, quadratic_tag>
container_type;
container_type elements_copy(elements1.begin(), elements1.end()); // MAY THROW, STRONG (alloc, copy)
container_type elements_backup(elements1.begin(), elements1.end()); // MAY THROW, STRONG (alloc, copy)
-
+
// calculate initial seeds
size_t seed1 = 0;
size_t seed2 = 0;
@@ -277,7 +277,7 @@ struct redistribute_elements<MembersHolder, quadratic_tag>
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 )
{
diff --git a/boost/geometry/index/detail/rtree/query_iterators.hpp b/boost/geometry/index/detail/rtree/query_iterators.hpp
index 8822bcf04f..170c3ac9b1 100644
--- a/boost/geometry/index/detail/rtree/query_iterators.hpp
+++ b/boost/geometry/index/detail/rtree/query_iterators.hpp
@@ -2,10 +2,10 @@
//
// R-tree query iterators
//
-// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2023 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019.
-// Modifications copyright (c) 2019 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2021.
+// Modifications copyright (c) 2019-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,9 +15,11 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_QUERY_ITERATORS_HPP
-#include <boost/scoped_ptr.hpp>
+#include <memory>
-//#define BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
+#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/distance_query.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/spatial_query.hpp>
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace iterators {
@@ -65,13 +67,8 @@ struct end_query_iterator
template <typename MembersHolder, typename Predicates>
class spatial_query_iterator
{
- typedef typename MembersHolder::parameters_type parameters_type;
- typedef typename MembersHolder::translator_type translator_type;
typedef typename MembersHolder::allocators_type allocators_type;
- typedef visitors::spatial_query_incremental<MembersHolder, Predicates> visitor_type;
- typedef typename visitor_type::node_pointer node_pointer;
-
public:
typedef std::forward_iterator_tag iterator_category;
typedef typename MembersHolder::value_type value_type;
@@ -79,32 +76,31 @@ public:
typedef typename allocators_type::difference_type difference_type;
typedef typename allocators_type::const_pointer pointer;
- inline spatial_query_iterator()
- {}
+ spatial_query_iterator() = default;
- inline spatial_query_iterator(parameters_type const& par, translator_type const& t, Predicates const& p)
- : m_visitor(par, t, p)
+ explicit spatial_query_iterator(Predicates const& pred)
+ : m_impl(pred)
{}
- inline spatial_query_iterator(node_pointer root, parameters_type const& par, translator_type const& t, Predicates const& p)
- : m_visitor(par, t, p)
+ spatial_query_iterator(MembersHolder const& members, Predicates const& pred)
+ : m_impl(members, pred)
{
- m_visitor.initialize(root);
+ m_impl.initialize(members);
}
reference operator*() const
{
- return m_visitor.dereference();
+ return m_impl.dereference();
}
const value_type * operator->() const
{
- return boost::addressof(m_visitor.dereference());
+ return boost::addressof(m_impl.dereference());
}
spatial_query_iterator & operator++()
{
- m_visitor.increment();
+ m_impl.increment();
return *this;
}
@@ -117,33 +113,28 @@ public:
friend bool operator==(spatial_query_iterator const& l, spatial_query_iterator const& r)
{
- return l.m_visitor == r.m_visitor;
+ return l.m_impl == r.m_impl;
}
friend bool operator==(spatial_query_iterator const& l, end_query_iterator<value_type, allocators_type> const& /*r*/)
{
- return l.m_visitor.is_end();
+ return l.m_impl.is_end();
}
friend bool operator==(end_query_iterator<value_type, allocators_type> const& /*l*/, spatial_query_iterator const& r)
{
- return r.m_visitor.is_end();
+ return r.m_impl.is_end();
}
-
+
private:
- visitor_type m_visitor;
+ visitors::spatial_query_incremental<MembersHolder, Predicates> m_impl;
};
-template <typename MembersHolder, typename Predicates, unsigned NearestPredicateIndex>
+template <typename MembersHolder, typename Predicates>
class distance_query_iterator
{
- typedef typename MembersHolder::parameters_type parameters_type;
- typedef typename MembersHolder::translator_type translator_type;
typedef typename MembersHolder::allocators_type allocators_type;
- typedef visitors::distance_query_incremental<MembersHolder, Predicates, NearestPredicateIndex> visitor_type;
- typedef typename visitor_type::node_pointer node_pointer;
-
public:
typedef std::forward_iterator_tag iterator_category;
typedef typename MembersHolder::value_type value_type;
@@ -151,32 +142,31 @@ public:
typedef typename allocators_type::difference_type difference_type;
typedef typename allocators_type::const_pointer pointer;
- inline distance_query_iterator()
- {}
+ distance_query_iterator() = default;
- inline distance_query_iterator(parameters_type const& par, translator_type const& t, Predicates const& p)
- : m_visitor(par, t, p)
+ explicit distance_query_iterator(Predicates const& pred)
+ : m_impl(pred)
{}
- inline distance_query_iterator(node_pointer root, parameters_type const& par, translator_type const& t, Predicates const& p)
- : m_visitor(par, t, p)
+ distance_query_iterator(MembersHolder const& members, Predicates const& pred)
+ : m_impl(members, pred)
{
- m_visitor.initialize(root);
+ m_impl.initialize(members);
}
reference operator*() const
{
- return m_visitor.dereference();
+ return m_impl.dereference();
}
const value_type * operator->() const
{
- return boost::addressof(m_visitor.dereference());
+ return boost::addressof(m_impl.dereference());
}
distance_query_iterator & operator++()
{
- m_visitor.increment();
+ m_impl.increment();
return *this;
}
@@ -189,21 +179,21 @@ public:
friend bool operator==(distance_query_iterator const& l, distance_query_iterator const& r)
{
- return l.m_visitor == r.m_visitor;
+ return l.m_impl == r.m_impl;
}
friend bool operator==(distance_query_iterator const& l, end_query_iterator<value_type, allocators_type> const& /*r*/)
{
- return l.m_visitor.is_end();
+ return l.m_impl.is_end();
}
friend bool operator==(end_query_iterator<value_type, allocators_type> const& /*l*/, distance_query_iterator const& r)
{
- return r.m_visitor.is_end();
+ return r.m_impl.is_end();
}
private:
- visitor_type m_visitor;
+ visitors::distance_query_incremental<MembersHolder, Predicates> m_impl;
};
@@ -227,7 +217,7 @@ public:
virtual ~query_iterator_base() {}
virtual query_iterator_base * clone() const = 0;
-
+
virtual bool is_end() const = 0;
virtual reference dereference() const = 0;
virtual void increment() = 0;
@@ -271,7 +261,7 @@ template <typename Value, typename Allocators>
class query_iterator
{
typedef query_iterator_base<Value, Allocators> iterator_base;
- typedef boost::scoped_ptr<iterator_base> iterator_ptr;
+ typedef std::unique_ptr<iterator_base> iterator_ptr;
public:
typedef std::forward_iterator_tag iterator_category;
@@ -280,8 +270,7 @@ public:
typedef typename Allocators::difference_type difference_type;
typedef typename Allocators::const_pointer pointer;
- query_iterator()
- {}
+ query_iterator() = default;
template <typename It>
query_iterator(It const& it)
@@ -296,7 +285,8 @@ public:
: m_ptr(o.m_ptr.get() ? o.m_ptr->clone() : 0)
{}
-#ifndef BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
+ query_iterator(query_iterator&&) = default;
+
query_iterator & operator=(query_iterator const& o)
{
if ( this != boost::addressof(o) )
@@ -305,49 +295,8 @@ public:
}
return *this;
}
-#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
- query_iterator(query_iterator && o)
- : m_ptr(0)
- {
- m_ptr.swap(o.m_ptr);
- }
- query_iterator & operator=(query_iterator && o)
- {
- if ( this != boost::addressof(o) )
- {
- m_ptr.swap(o.m_ptr);
- o.m_ptr.reset();
- }
- return *this;
- }
-#endif
-#else // !BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
-private:
- BOOST_COPYABLE_AND_MOVABLE(query_iterator)
-public:
- query_iterator & operator=(BOOST_COPY_ASSIGN_REF(query_iterator) o)
- {
- if ( this != boost::addressof(o) )
- {
- m_ptr.reset(o.m_ptr.get() ? o.m_ptr->clone() : 0);
- }
- return *this;
- }
- query_iterator(BOOST_RV_REF(query_iterator) o)
- : m_ptr(0)
- {
- m_ptr.swap(o.m_ptr);
- }
- query_iterator & operator=(BOOST_RV_REF(query_iterator) o)
- {
- if ( this != boost::addressof(o) )
- {
- m_ptr.swap(o.m_ptr);
- o.m_ptr.reset();
- }
- return *this;
- }
-#endif // BOOST_GEOMETRY_INDEX_DETAIL_QUERY_ITERATORS_USE_MOVE
+
+ query_iterator& operator=(query_iterator &&) = default;
reference operator*() const
{
diff --git a/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp b/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp
index 7ba5f0f996..8032a2626e 100644
--- a/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp
+++ b/boost/geometry/index/detail/rtree/rstar/choose_next_node.hpp
@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2019 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019.
-// Modifications copyright (c) 2019 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2021.
+// Modifications copyright (c) 2019-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -27,6 +27,8 @@
#include <boost/geometry/index/detail/algorithms/union_content.hpp>
#include <boost/geometry/index/detail/rtree/node/node.hpp>
+#include <boost/geometry/index/detail/rtree/options.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 {
@@ -58,7 +60,7 @@ public:
::boost::ignore_unused(parameters);
children_type & children = rtree::elements(n);
-
+
// children are leafs
if ( node_relative_level <= 1 )
{
diff --git a/boost/geometry/index/detail/rtree/rstar/insert.hpp b/boost/geometry/index/detail/rtree/rstar/insert.hpp
index 8517b7f1b0..b3ad01c345 100644
--- a/boost/geometry/index/detail/rtree/rstar/insert.hpp
+++ b/boost/geometry/index/detail/rtree/rstar/insert.hpp
@@ -4,8 +4,9 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019-2021.
-// Modifications copyright (c) 2019-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2023.
+// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -19,7 +20,13 @@
#include <boost/core/ignore_unused.hpp>
+#include <boost/geometry/algorithms/centroid.hpp>
+#include <boost/geometry/algorithms/detail/comparable_distance/interface.hpp>
+
#include <boost/geometry/index/detail/algorithms/content.hpp>
+#include <boost/geometry/index/detail/rtree/node/concept.hpp>
+#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
namespace boost { namespace geometry { namespace index {
@@ -117,7 +124,7 @@ public:
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 )
{
@@ -181,7 +188,7 @@ private:
{
return d1.first < d2.first;
}
-
+
template <typename Distance, typename El>
static inline bool distances_dsc(
std::pair<Distance, El> const& d1,
@@ -458,7 +465,7 @@ struct level_insert<InsertIndex, Value, MembersHolder, true>
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)
@@ -474,7 +481,7 @@ struct level_insert<InsertIndex, Value, MembersHolder, true>
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)
@@ -532,7 +539,7 @@ struct level_insert<0, Value, MembersHolder, true>
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);
}
};
@@ -594,7 +601,7 @@ public:
visitors::insert<Element, MembersHolder, 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);
+ rtree::apply_visitor(ins_v, *m_root);
}
}
@@ -619,7 +626,7 @@ public:
visitors::insert<Element, MembersHolder, 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);
+ rtree::apply_visitor(ins_v, *m_root);
}
}
diff --git a/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp b/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp
index db08ef3f7c..9dcb3db382 100644
--- a/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp
+++ b/boost/geometry/index/detail/rtree/rstar/redistribute_elements.hpp
@@ -2,7 +2,7 @@
//
// R-tree R*-tree split algorithm implementation
//
-// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2022 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2020.
// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
@@ -55,11 +55,10 @@ public:
bool operator()(Element const& e1, Element const& e2) const
{
- bounded_view_type bounded_ind1(rtree::element_indexable(e1, m_tr), m_strategy);
- bounded_view_type bounded_ind2(rtree::element_indexable(e2, m_tr), m_strategy);
-
- return geometry::get<Corner, AxisIndex>(bounded_ind1)
- < geometry::get<Corner, AxisIndex>(bounded_ind2);
+ indexable_type const& ind1 = rtree::element_indexable(e1, m_tr);
+ indexable_type const& ind2 = rtree::element_indexable(e2, m_tr);
+ return geometry::get<Corner, AxisIndex>(bounded_view_type(ind1, m_strategy))
+ < geometry::get<Corner, AxisIndex>(bounded_view_type(ind2, m_strategy));
}
private:
@@ -133,7 +132,7 @@ struct choose_split_axis_and_index_for_corner
// copy elements
Elements elements_copy(elements); // MAY THROW, STRONG (alloc, copy)
-
+
size_t const index_first = parameters.get_min_elements();
size_t const index_last = parameters.get_max_elements() - parameters.get_min_elements() + 2;
@@ -168,7 +167,7 @@ struct choose_split_axis_and_index_for_corner
translator, strategy);
Box box2 = rtree::elements_box<Box>(elements_copy.begin() + i, elements_copy.end(),
translator, strategy);
-
+
sum_of_margins += index::detail::comparable_margin(box1) + index::detail::comparable_margin(box2);
content_type ovl = index::detail::intersection_content(box1, box2, strategy);
@@ -428,7 +427,7 @@ struct redistribute_elements<MembersHolder, rstar_tag>
{
typedef typename rtree::elements_type<Node>::type elements_type;
typedef typename elements_type::value_type element_type;
-
+
elements_type & elements1 = rtree::elements(n);
elements_type & elements2 = rtree::elements(second_node);
diff --git a/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp b/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp
index 64c4d7470d..377089fde1 100644
--- a/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp
+++ b/boost/geometry/index/detail/rtree/utilities/are_boxes_ok.hpp
@@ -70,7 +70,7 @@ public:
box_type box_exp = rtree::elements_box<box_type>(elements.begin(), elements.end(), m_tr,
index::detail::get_strategy(m_parameters));
-
+
if ( m_exact_match )
result = m_is_root || geometry::equals(box_exp, m_box);
else
@@ -90,7 +90,7 @@ public:
result = false;
return;
}
-
+
box_type box_exp = rtree::values_box<box_type>(elements.begin(), elements.end(), m_tr,
index::detail::get_strategy(m_parameters));
@@ -124,7 +124,7 @@ bool are_boxes_ok(Rtree const& tree, bool exact_match = true)
visitors::are_boxes_ok<
typename RTV::members_holder
> v(tree.parameters(), rtv.translator(), exact_match);
-
+
rtv.apply_visitor(v);
return v.result;
diff --git a/boost/geometry/index/detail/rtree/utilities/are_counts_ok.hpp b/boost/geometry/index/detail/rtree/utilities/are_counts_ok.hpp
index 5c8fc9ef26..30a55dd4f5 100644
--- a/boost/geometry/index/detail/rtree/utilities/are_counts_ok.hpp
+++ b/boost/geometry/index/detail/rtree/utilities/are_counts_ok.hpp
@@ -4,8 +4,9 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019.
-// Modifications copyright (c) 2019 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2023.
+// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -16,6 +17,7 @@
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_COUNTS_OK_HPP
#include <boost/geometry/index/detail/rtree/node/node.hpp>
+#include <boost/geometry/index/detail/rtree/utilities/view.hpp>
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace utilities {
@@ -26,7 +28,7 @@ class are_counts_ok
: public MembersHolder::visitor_const
{
typedef typename MembersHolder::parameters_type parameters_type;
-
+
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
@@ -105,7 +107,7 @@ bool are_counts_ok(Rtree const& tree, bool check_min = true)
visitors::are_counts_ok<
typename RTV::members_holder
> v(tree.parameters(), check_min);
-
+
rtv.apply_visitor(v);
return v.result;
diff --git a/boost/geometry/index/detail/rtree/utilities/are_levels_ok.hpp b/boost/geometry/index/detail/rtree/utilities/are_levels_ok.hpp
index a76cf38bf6..c107e91138 100644
--- a/boost/geometry/index/detail/rtree/utilities/are_levels_ok.hpp
+++ b/boost/geometry/index/detail/rtree/utilities/are_levels_ok.hpp
@@ -4,8 +4,9 @@
//
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019.
-// Modifications copyright (c) 2019 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2023.
+// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -16,6 +17,7 @@
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_ARE_LEVELS_OK_HPP
#include <boost/geometry/index/detail/rtree/node/node.hpp>
+#include <boost/geometry/index/detail/rtree/utilities/view.hpp>
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace utilities {
@@ -99,7 +101,7 @@ bool are_levels_ok(Rtree const& tree)
visitors::are_levels_ok<
typename RTV::members_holder
> v;
-
+
rtv.apply_visitor(v);
return v.result;
diff --git a/boost/geometry/index/detail/rtree/utilities/gl_draw.hpp b/boost/geometry/index/detail/rtree/utilities/gl_draw.hpp
index bdabebf225..051337a276 100644
--- a/boost/geometry/index/detail/rtree/utilities/gl_draw.hpp
+++ b/boost/geometry/index/detail/rtree/utilities/gl_draw.hpp
@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019-2020.
-// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2021.
+// Modifications copyright (c) 2019-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,7 +15,16 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_UTILITIES_GL_DRAW_HPP
+#include <limits>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/static_assert.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
@@ -172,7 +181,7 @@ struct gl_draw
detail::utilities::gl_draw_indexable(it->first, level_rel * z_mul);
}
}
-
+
size_t level_backup = level;
++level;
diff --git a/boost/geometry/index/detail/rtree/utilities/print.hpp b/boost/geometry/index/detail/rtree/utilities/print.hpp
index 2ed71a6b85..ddb2d9cb5c 100644
--- a/boost/geometry/index/detail/rtree/utilities/print.hpp
+++ b/boost/geometry/index/detail/rtree/utilities/print.hpp
@@ -4,8 +4,9 @@
//
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019-2020.
-// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2023.
+// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -17,10 +18,18 @@
#include <iostream>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/static_assert.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
+#include <boost/geometry/index/detail/rtree/node/variant_visitor.hpp>
+#include <boost/geometry/index/detail/rtree/utilities/view.hpp>
namespace boost { namespace geometry { namespace index { namespace detail {
-
+
namespace utilities {
namespace dispatch {
@@ -156,7 +165,7 @@ struct print
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)
{
diff --git a/boost/geometry/index/detail/rtree/utilities/statistics.hpp b/boost/geometry/index/detail/rtree/utilities/statistics.hpp
index 17c2c20337..53be32cca5 100644
--- a/boost/geometry/index/detail/rtree/utilities/statistics.hpp
+++ b/boost/geometry/index/detail/rtree/utilities/statistics.hpp
@@ -5,8 +5,9 @@
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2013 Mateusz Loskot, London, UK.
//
-// This file was modified by Oracle on 2019-2020.
-// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2023.
+// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -19,6 +20,10 @@
#include <algorithm>
#include <tuple>
+#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
+#include <boost/geometry/index/detail/rtree/node/variant_visitor.hpp>
+#include <boost/geometry/index/detail/rtree/utilities/view.hpp>
+
namespace boost { namespace geometry { namespace index { namespace detail { namespace rtree { namespace utilities {
namespace visitors {
@@ -44,37 +49,37 @@ struct statistics
{
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;
@@ -98,7 +103,7 @@ statistics(Rtree const& tree)
> stats_v;
rtv.apply_visitor(stats_v);
-
+
return std::make_tuple(stats_v.levels, stats_v.nodes, stats_v.leaves, stats_v.values, stats_v.values_min, stats_v.values_max);
}
diff --git a/boost/geometry/index/detail/rtree/utilities/view.hpp b/boost/geometry/index/detail/rtree/utilities/view.hpp
index edaa045ac3..8fadc55b45 100644
--- a/boost/geometry/index/detail/rtree/utilities/view.hpp
+++ b/boost/geometry/index/detail/rtree/utilities/view.hpp
@@ -31,7 +31,7 @@ public:
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;
+ typedef typename Rtree::allocators_type allocators_type;
view(Rtree const& rt) : m_rtree(rt) {}
diff --git a/boost/geometry/index/detail/rtree/visitors/children_box.hpp b/boost/geometry/index/detail/rtree/visitors/children_box.hpp
index 1dde1408c9..61bf7d69af 100644
--- a/boost/geometry/index/detail/rtree/visitors/children_box.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/children_box.hpp
@@ -4,8 +4,9 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019.
-// Modifications copyright (c) 2019 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2023.
+// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,6 +16,9 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_CHILDREN_BOX_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_CHILDREN_BOX_HPP
+#include <boost/geometry/index/detail/rtree/node/node.hpp>
+#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
+
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
diff --git a/boost/geometry/index/detail/rtree/visitors/copy.hpp b/boost/geometry/index/detail/rtree/visitors/copy.hpp
index 1dee43d63f..447eba2f18 100644
--- a/boost/geometry/index/detail/rtree/visitors/copy.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/copy.hpp
@@ -53,7 +53,7 @@ public:
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)
+ rtree::apply_visitor(*this, *it->second); // MAY THROW (V, E: alloc, copy, N: alloc)
// for exception safety
subtree_destroyer auto_result(result, m_allocators);
diff --git a/boost/geometry/index/detail/rtree/visitors/count.hpp b/boost/geometry/index/detail/rtree/visitors/count.hpp
index c166fe3e36..2e4353fe52 100644
--- a/boost/geometry/index/detail/rtree/visitors/count.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/count.hpp
@@ -4,8 +4,9 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019.
-// Modifications copyright (c) 2019 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2023.
+// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,6 +16,12 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COUNT_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_COUNT_HPP
+#include <boost/geometry/index/equal_to.hpp>
+#include <boost/geometry/index/detail/algorithms/bounds.hpp>
+#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
+#include <boost/geometry/index/detail/rtree/node/variant_visitor.hpp>
+#include <boost/geometry/index/parameters.hpp>
+
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
diff --git a/boost/geometry/index/detail/rtree/visitors/destroy.hpp b/boost/geometry/index/detail/rtree/visitors/destroy.hpp
index 4afb867cdf..f217a4ab1b 100644
--- a/boost/geometry/index/detail/rtree/visitors/destroy.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/destroy.hpp
@@ -4,8 +4,9 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019.
-// Modifications copyright (c) 2019 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2023.
+// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,6 +16,10 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DELETE_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DELETE_HPP
+#include <boost/geometry/index/detail/rtree/node/concept.hpp>
+#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
+#include <boost/geometry/index/detail/rtree/node/weak_visitor.hpp>
+
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
diff --git a/boost/geometry/index/detail/rtree/visitors/distance_query.hpp b/boost/geometry/index/detail/rtree/visitors/distance_query.hpp
index a40dbfe842..de2f68f88a 100644
--- a/boost/geometry/index/detail/rtree/visitors/distance_query.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/distance_query.hpp
@@ -4,8 +4,9 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019-2021.
-// Modifications copyright (c) 2019-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2023.
+// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,6 +16,16 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_DISTANCE_QUERY_HPP
+#include <queue>
+
+#include <boost/geometry/index/detail/distance_predicates.hpp>
+#include <boost/geometry/index/detail/predicates.hpp>
+#include <boost/geometry/index/detail/priority_dequeue.hpp>
+#include <boost/geometry/index/detail/rtree/node/weak_visitor.hpp>
+#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
+#include <boost/geometry/index/detail/translator.hpp>
+#include <boost/geometry/index/parameters.hpp>
+
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
@@ -40,90 +51,114 @@ struct pair_first_greater
}
};
+template <typename T, typename Comp>
+struct priority_dequeue : index::detail::priority_dequeue<T, std::vector<T>, Comp>
+{
+ priority_dequeue() = default;
+ //void reserve(typename std::vector<T>::size_type n)
+ //{
+ // this->c.reserve(n);
+ //}
+ //void clear()
+ //{
+ // this->c.clear();
+ //}
+};
-template <typename Value, typename Translator, typename DistanceType, typename OutIt>
-class distance_query_result
+template <typename T, typename Comp>
+struct priority_queue : std::priority_queue<T, std::vector<T>, Comp>
{
-public:
- typedef DistanceType distance_type;
+ priority_queue() = default;
+ //void reserve(typename std::vector<T>::size_type n)
+ //{
+ // this->c.reserve(n);
+ //}
+ void clear()
+ {
+ this->c.clear();
+ }
+};
- inline explicit distance_query_result(size_t k, OutIt out_it)
- : m_count(k), m_out_it(out_it)
+struct branch_data_comp
+{
+ template <typename BranchData>
+ bool operator()(BranchData const& b1, BranchData const& b2) const
{
- BOOST_GEOMETRY_INDEX_ASSERT(0 < m_count, "Number of neighbors should be greater than 0");
+ return b1.distance > b2.distance || (b1.distance == b2.distance && b1.reverse_level > b2.reverse_level);
+ }
+};
+template <typename DistanceType, typename Value>
+class distance_query_result
+{
+ using neighbor_data = std::pair<DistanceType, const Value *>;
+ using neighbors_type = std::vector<neighbor_data>;
+ using size_type = typename neighbors_type::size_type;
+
+public:
+ inline distance_query_result(size_type k)
+ : m_count(k)
+ {
m_neighbors.reserve(m_count);
}
- inline void store(Value const& val, distance_type const& curr_comp_dist)
+ // NOTE: Do not call if max_count() == 0
+ inline void store(DistanceType const& distance, const Value * value_ptr)
{
- if ( m_neighbors.size() < m_count )
+ if (m_neighbors.size() < m_count)
{
- m_neighbors.push_back(std::make_pair(curr_comp_dist, val));
+ m_neighbors.push_back(std::make_pair(distance, value_ptr));
- if ( m_neighbors.size() == m_count )
+ if (m_neighbors.size() == m_count)
+ {
std::make_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
+ }
}
- else
+ else if (distance < m_neighbors.front().first)
{
- if ( curr_comp_dist < m_neighbors.front().first )
- {
- std::pop_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
- m_neighbors.back().first = curr_comp_dist;
- m_neighbors.back().second = val;
- std::push_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
- }
+ std::pop_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
+ m_neighbors.back().first = distance;
+ m_neighbors.back().second = value_ptr;
+ std::push_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
}
}
- inline bool has_enough_neighbors() const
+ // NOTE: Do not call if max_count() == 0
+ inline bool ignore_branch(DistanceType const& distance) const
{
- return m_count <= m_neighbors.size();
+ return m_neighbors.size() == m_count
+ && m_neighbors.front().first <= distance;
}
- inline distance_type greatest_comparable_distance() const
+ template <typename OutIt>
+ inline size_type finish(OutIt out_it) 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;
+ for (auto const& p : m_neighbors)
+ {
+ *out_it = *(p.second);
+ ++out_it;
+ }
+
+ return m_neighbors.size();
}
- inline size_t finish()
+ size_type max_count() const
{
- 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();
+ return m_count;
}
private:
- size_t m_count;
- OutIt m_out_it;
-
- std::vector< std::pair<distance_type, Value> > m_neighbors;
+ size_type m_count;
+ neighbors_type m_neighbors;
};
-template
-<
- typename MembersHolder,
- typename Predicates,
- std::size_t DistancePredicateIndex,
- typename OutIter
->
+template <typename MembersHolder, typename Predicates>
class distance_query
- : public MembersHolder::visitor_const
{
-public:
typedef typename MembersHolder::value_type value_type;
typedef typename MembersHolder::box_type box_type;
typedef typename MembersHolder::parameters_type parameters_type;
typedef typename MembersHolder::translator_type translator_type;
- typedef typename MembersHolder::allocators_type allocators_type;
typedef typename index::detail::strategy_type<parameters_type>::type strategy_type;
@@ -131,7 +166,10 @@ public:
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
- typedef index::detail::predicates_element<DistancePredicateIndex, Predicates> nearest_predicate_access;
+ typedef index::detail::predicates_element
+ <
+ index::detail::predicates_find_distance<Predicates>::value, Predicates
+ > nearest_predicate_access;
typedef typename nearest_predicate_access::type nearest_predicate_type;
typedef typename indexable_type<translator_type>::type indexable_type;
@@ -140,147 +178,141 @@ public:
typedef typename calculate_value_distance::result_type value_distance_type;
typedef typename calculate_node_distance::result_type node_distance_type;
- static const std::size_t predicates_len = index::detail::predicates_length<Predicates>::value;
+ typedef typename MembersHolder::size_type size_type;
+ typedef typename MembersHolder::node_pointer node_pointer;
- inline distance_query(parameters_type const& parameters, translator_type const& translator, Predicates const& pred, OutIter out_it)
- : m_parameters(parameters), m_translator(translator)
+ using neighbor_data = std::pair<value_distance_type, const value_type *>;
+ using neighbors_type = std::vector<neighbor_data>;
+
+ struct branch_data
+ {
+ branch_data(node_distance_type d, size_type rl, node_pointer p)
+ : distance(d), reverse_level(rl), ptr(p)
+ {}
+
+ node_distance_type distance;
+ size_type reverse_level;
+ node_pointer ptr;
+ };
+ using branches_type = priority_queue<branch_data, branch_data_comp>;
+
+public:
+ distance_query(MembersHolder const& members, Predicates const& pred)
+ : m_tr(members.translator())
+ , m_strategy(index::detail::get_strategy(members.parameters()))
, m_pred(pred)
- , m_result(nearest_predicate_access::get(m_pred).count, out_it)
- , m_strategy(index::detail::get_strategy(parameters))
- {}
+ {
+ m_neighbors.reserve((std::min)(members.values_count, size_type(max_count())));
+ //m_branches.reserve(members.parameters().get_min_elements() * members.leafs_level); ?
+ // min, max or average?
+ }
- inline void operator()(internal_node const& n)
+ template <typename OutIter>
+ size_type apply(MembersHolder const& members, OutIter out_it)
{
- 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_type::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)
+ return apply(members.root, members.leafs_level, out_it);
+ }
+
+private:
+ template <typename OutIter>
+ size_type apply(node_pointer ptr, size_type reverse_level, OutIter out_it)
+ {
+ namespace id = index::detail;
+
+ if (max_count() <= 0)
{
- // 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, m_strategy) )
+ return 0;
+ }
+
+ for (;;)
+ {
+ if (reverse_level > 0)
{
- // 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,
- m_strategy, node_distance) )
+ internal_node& n = rtree::get<internal_node>(*ptr);
+ // fill array of nodes meeting predicates
+ for (auto const& p : rtree::elements(n))
{
- continue;
+ node_distance_type node_distance; // for distance predicate
+
+ // if current node meets predicates (0 is dummy value)
+ if (id::predicates_check<id::bounds_tag>(m_pred, 0, p.first, m_strategy)
+ // and if distance is ok
+ && calculate_node_distance::apply(predicate(), p.first, m_strategy, node_distance)
+ // and if current node is closer than the furthest neighbor
+ && ! ignore_branch(node_distance))
+ {
+ // add current node's data into the list
+ m_branches.push(branch_data(node_distance, reverse_level - 1, p.second));
+ }
}
-
- // 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) )
+ }
+ else
+ {
+ leaf& n = rtree::get<leaf>(*ptr);
+ // search leaf for closest value meeting predicates
+ for (auto const& v : rtree::elements(n))
{
- continue;
+ value_distance_type value_distance; // for distance predicate
+
+ // if value meets predicates
+ if (id::predicates_check<id::value_tag>(m_pred, v, m_tr(v), m_strategy)
+ // and if distance is ok
+ && calculate_value_distance::apply(predicate(), m_tr(v), m_strategy, value_distance))
+ {
+ // store value
+ store_value(value_distance, boost::addressof(v));
+ }
}
+ }
- // add current node's data into the list
- active_branch_list.push_back( std::make_pair(node_distance, it->second) );
+ if (m_branches.empty()
+ || ignore_branch(m_branches.top().distance))
+ {
+ break;
}
- }
- // 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(), pair_first_less());
+ ptr = m_branches.top().ptr;
+ reverse_level = m_branches.top().reverse_level;
+ m_branches.pop();
+ }
- // recursively visit nodes
- for ( typename active_branch_list_type::const_iterator it = active_branch_list.begin();
- it != active_branch_list.end() ; ++it )
+ for (auto const& p : m_neighbors)
{
- // 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));
+ *out_it = *(p.second);
+ ++out_it;
}
- // ALTERNATIVE VERSION - use heap instead of sorted container
- // It seems to be faster for greater MaxElements and slower otherwise
- // CONSIDER: using one global container/heap for active branches
- // instead of a sorted container per level
- // This would also change the way how branches are traversed!
- // The same may be applied to the iterative version which btw suffers
- // from the copying of the whole containers on resize of the ABLs container
-
- //// make a heap
- //std::make_heap(active_branch_list.begin(), active_branch_list.end(), pair_first_greater());
-
- //// recursively visit nodes
- //while ( !active_branch_list.empty() )
- //{
- // //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(), active_branch_list.front().first) )
- // {
- // break;
- // }
-
- // rtree::apply_visitor(*this, *(active_branch_list.front().second));
-
- // std::pop_heap(active_branch_list.begin(), active_branch_list.end(), pair_first_greater());
- // active_branch_list.pop_back();
- //}
+ return m_neighbors.size();
+ }
+
+ bool ignore_branch(node_distance_type const& node_distance) const
+ {
+ return m_neighbors.size() == max_count()
+ && m_neighbors.front().first <= node_distance;
}
- inline void operator()(leaf const& n)
+ void store_value(value_distance_type value_distance, const value_type * value_ptr)
{
- 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 (m_neighbors.size() < max_count())
{
- // if value meets predicates
- if ( index::detail::predicates_check
- <
- index::detail::value_tag, 0, predicates_len
- >(m_pred, *it, m_translator(*it), m_strategy) )
+ m_neighbors.push_back(std::make_pair(value_distance, value_ptr));
+
+ if (m_neighbors.size() == max_count())
{
- // calculate values distance for distance predicate
- value_distance_type value_distance;
- // if distance is ok
- if ( calculate_value_distance::apply(predicate(), m_translator(*it),
- m_strategy, value_distance) )
- {
- // store value
- m_result.store(*it, value_distance);
- }
+ std::make_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
}
}
+ else if (value_distance < m_neighbors.front().first)
+ {
+ std::pop_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
+ m_neighbors.back() = std::make_pair(value_distance, value_ptr);
+ std::push_heap(m_neighbors.begin(), m_neighbors.end(), pair_first_less());
+ }
}
- inline size_t finish()
- {
- return m_result.finish();
- }
-
-private:
- template <typename Distance>
- static inline bool is_node_prunable(Distance const& greatest_dist, node_distance_type const& d)
+ std::size_t max_count() const
{
- return greatest_dist <= d;
+ return nearest_predicate_access::get(m_pred).count;
}
nearest_predicate_type const& predicate() const
@@ -288,24 +320,18 @@ private:
return nearest_predicate_access::get(m_pred);
}
- parameters_type const& m_parameters;
- translator_type const& m_translator;
+ translator_type const& m_tr;
+ strategy_type m_strategy;
- Predicates m_pred;
- distance_query_result<value_type, translator_type, value_distance_type, OutIter> m_result;
+ Predicates const& m_pred;
- strategy_type m_strategy;
+ branches_type m_branches;
+ neighbors_type m_neighbors;
};
-template <
- typename MembersHolder,
- typename Predicates,
- std::size_t DistancePredicateIndex
->
+template <typename MembersHolder, typename Predicates>
class distance_query_incremental
- : public MembersHolder::visitor_const
{
-public:
typedef typename MembersHolder::value_type value_type;
typedef typename MembersHolder::box_type box_type;
typedef typename MembersHolder::parameters_type parameters_type;
@@ -318,10 +344,13 @@ public:
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
- typedef index::detail::predicates_element<DistancePredicateIndex, Predicates> nearest_predicate_access;
+ typedef index::detail::predicates_element
+ <
+ index::detail::predicates_find_distance<Predicates>::value, Predicates
+ > nearest_predicate_access;
typedef typename nearest_predicate_access::type nearest_predicate_type;
typedef typename indexable_type<translator_type>::type indexable_type;
-
+
typedef index::detail::calculate_distance<nearest_predicate_type, indexable_type, strategy_type, value_tag> calculate_value_distance;
typedef index::detail::calculate_distance<nearest_predicate_type, box_type, strategy_type, bounds_tag> calculate_node_distance;
typedef typename calculate_value_distance::result_type value_distance_type;
@@ -331,90 +360,114 @@ public:
typedef typename allocators_type::const_reference const_reference;
typedef typename allocators_type::node_pointer node_pointer;
- static const std::size_t 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 std::vector<branch_data> internal_heap_type;
+ using neighbor_data = std::pair<value_distance_type, const value_type *>;
+ using neighbors_type = priority_dequeue<neighbor_data, pair_first_greater>;
+
+ struct branch_data
+ {
+ branch_data(node_distance_type d, size_type rl, node_pointer p)
+ : distance(d), reverse_level(rl), ptr(p)
+ {}
+ node_distance_type distance;
+ size_type reverse_level;
+ node_pointer ptr;
+ };
+ using branches_type = priority_queue<branch_data, branch_data_comp>;
+
+public:
inline distance_query_incremental()
- : m_translator(NULL)
+ : m_tr(nullptr)
+// , m_strategy()
// , m_pred()
- , current_neighbor((std::numeric_limits<size_type>::max)())
-// , m_strategy_type()
+ , m_neighbors_count(0)
+ , m_neighbor_ptr(nullptr)
{}
- inline distance_query_incremental(parameters_type const& params, translator_type const& translator, Predicates const& pred)
- : m_translator(::boost::addressof(translator))
+ inline distance_query_incremental(Predicates const& pred)
+ : m_tr(nullptr)
+// , m_strategy()
, m_pred(pred)
- , current_neighbor((std::numeric_limits<size_type>::max)())
- , m_strategy(index::detail::get_strategy(params))
- {
- BOOST_GEOMETRY_INDEX_ASSERT(0 < max_count(), "k must be greather than 0");
- }
+ , m_neighbors_count(0)
+ , m_neighbor_ptr(nullptr)
+ {}
+
+ inline distance_query_incremental(MembersHolder const& members, Predicates const& pred)
+ : m_tr(::boost::addressof(members.translator()))
+ , m_strategy(index::detail::get_strategy(members.parameters()))
+ , m_pred(pred)
+ , m_neighbors_count(0)
+ , m_neighbor_ptr(nullptr)
+ {}
const_reference dereference() const
{
- return *(neighbors[current_neighbor].second);
+ return *m_neighbor_ptr;
}
- void initialize(node_pointer root)
+ void initialize(MembersHolder const& members)
{
- rtree::apply_visitor(*this, *root);
- increment();
+ if (0 < max_count())
+ {
+ apply(members.root, members.leafs_level);
+ increment();
+ }
}
void increment()
{
for (;;)
{
- size_type new_neighbor = current_neighbor == (std::numeric_limits<size_type>::max)() ? 0 : current_neighbor + 1;
-
- if ( internal_heap.empty() )
+ if (m_branches.empty())
{
- if ( new_neighbor < neighbors.size() )
- current_neighbor = new_neighbor;
+ // there exists a next closest neighbor so we can increment
+ if (! m_neighbors.empty())
+ {
+ m_neighbor_ptr = m_neighbors.top().second;
+ ++m_neighbors_count;
+ m_neighbors.pop_top();
+ }
else
{
- current_neighbor = (std::numeric_limits<size_type>::max)();
- // clear() is used to disable the condition above
- neighbors.clear();
+ // there aren't any neighbors left, end
+ m_neighbor_ptr = nullptr;
+ m_neighbors_count = max_count();
}
return;
}
else
{
- branch_data const& closest_branch = internal_heap.front();
- node_distance_type const& closest_distance = closest_branch.first;
+ branch_data const& closest_branch = m_branches.top();
- // if there are no nodes which can have closer values, set new value
- if ( new_neighbor < neighbors.size() &&
- // NOTE: In order to use <= current neighbor can't be sorted again
- neighbors[new_neighbor].first <= closest_distance )
+ // if next neighbor is closer or as close as the closest branch, set next neighbor
+ if (! m_neighbors.empty() && m_neighbors.top().first <= closest_branch.distance )
{
- current_neighbor = new_neighbor;
+ m_neighbor_ptr = m_neighbors.top().second;
+ ++m_neighbors_count;
+ m_neighbors.pop_top();
return;
}
- // if node is further than the furthest neighbor, following nodes will also be further
- BOOST_GEOMETRY_INDEX_ASSERT(neighbors.size() <= max_count(), "unexpected neighbors count");
- if ( max_count() <= neighbors.size() &&
- neighbors.back().first <= closest_distance )
+ BOOST_GEOMETRY_INDEX_ASSERT(m_neighbors_count + m_neighbors.size() <= max_count(), "unexpected neighbors count");
+
+ // if there is enough neighbors and there is no closer branch
+ if (ignore_branch_or_value(closest_branch.distance))
{
- internal_heap.clear();
+ m_branches.clear();
continue;
}
else
{
- node_pointer ptr = closest_branch.second;
- std::pop_heap(internal_heap.begin(), internal_heap.end(), pair_first_greater());
- internal_heap.pop_back();
+ node_pointer ptr = closest_branch.ptr;
+ size_type reverse_level = closest_branch.reverse_level;
+ m_branches.pop();
- rtree::apply_visitor(*this, *ptr);
+ apply(ptr, reverse_level);
}
}
}
@@ -422,112 +475,80 @@ public:
bool is_end() const
{
- return (std::numeric_limits<size_type>::max)() == current_neighbor;
+ return m_neighbor_ptr == nullptr;
}
friend bool operator==(distance_query_incremental const& l, distance_query_incremental const& r)
{
- BOOST_GEOMETRY_INDEX_ASSERT(l.current_neighbor != r.current_neighbor ||
- (std::numeric_limits<size_type>::max)() == l.current_neighbor ||
- (std::numeric_limits<size_type>::max)() == r.current_neighbor ||
- l.neighbors[l.current_neighbor].second == r.neighbors[r.current_neighbor].second,
- "not corresponding iterators");
- return l.current_neighbor == r.current_neighbor;
+ return l.m_neighbors_count == r.m_neighbors_count;
}
- // 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)
+private:
+ void apply(node_pointer ptr, size_type reverse_level)
{
- typedef typename rtree::elements_type<internal_node>::type elements_type;
- elements_type const& elements = rtree::elements(n);
-
- // fill active branch list array of nodes meeting predicates
- for ( typename elements_type::const_iterator it = elements.begin() ; it != elements.end() ; ++it )
+ namespace id = index::detail;
+ // 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)
+ if (reverse_level > 0)
{
- // 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, m_strategy) )
+ internal_node& n = rtree::get<internal_node>(*ptr);
+ // fill active branch list array of nodes meeting predicates
+ for (auto const& p : rtree::elements(n))
{
- // 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,
- m_strategy, node_distance) )
- {
- continue;
- }
-
- // if current node is further than found neighbors - don't analyze it
- if ( max_count() <= neighbors.size() &&
- neighbors.back().first <= node_distance )
+ node_distance_type node_distance; // for distance predicate
+
+ // if current node meets predicates (0 is dummy value)
+ if (id::predicates_check<id::bounds_tag>(m_pred, 0, p.first, m_strategy)
+ // and if distance is ok
+ && calculate_node_distance::apply(predicate(), p.first, m_strategy, node_distance)
+ // and if current node is closer than the furthest neighbor
+ && ! ignore_branch_or_value(node_distance))
{
- continue;
+ // add current node into the queue
+ m_branches.push(branch_data(node_distance, reverse_level - 1, p.second));
}
-
- // add current node's data into the queue
- internal_heap.push_back(std::make_pair(node_distance, it->second));
- std::push_heap(internal_heap.begin(), internal_heap.end(), pair_first_greater());
}
}
- }
-
- // 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)
+ // 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)
+ else
{
- // if value meets predicates
- if ( index::detail::predicates_check
- <
- index::detail::value_tag, 0, predicates_len
- >(m_pred, *it, (*m_translator)(*it), m_strategy) )
+ leaf& n = rtree::get<leaf>(*ptr);
+ // search leaf for closest value meeting predicates
+ for (auto const& v : rtree::elements(n))
{
- // calculate values distance for distance predicate
- value_distance_type value_distance;
- // if distance is ok
- if ( calculate_value_distance::apply(predicate(), (*m_translator)(*it),
- m_strategy, value_distance) )
+ value_distance_type value_distance; // for distance predicate
+
+ // if value meets predicates
+ if (id::predicates_check<id::value_tag>(m_pred, v, (*m_tr)(v), m_strategy)
+ // and if distance is ok
+ && calculate_value_distance::apply(predicate(), (*m_tr)(v), m_strategy, value_distance)
+ // and if current value is closer than the furthest neighbor
+ && ! ignore_branch_or_value(value_distance))
{
- // if there is not enough values or current value is closer than furthest neighbour
- if ( not_enough_neighbors || value_distance < greatest_distance )
+ // add current value into the queue
+ m_neighbors.push(std::make_pair(value_distance, boost::addressof(v)));
+
+ // remove unneeded value
+ if (m_neighbors_count + m_neighbors.size() > max_count())
{
- neighbors.push_back(std::make_pair(value_distance, boost::addressof(*it)));
+ m_neighbors.pop_bottom();
}
}
}
}
+ }
- // TODO: sort is probably suboptimal.
- // An alternative would be std::set, but it'd probably add constant cost.
- // Ideally replace this with double-ended priority queue, e.g. min-max heap.
- // NOTE: A condition in increment() relies on the fact that current neighbor doesn't
- // participate in sorting anymore.
-
- // sort array
- size_type sort_first = current_neighbor == (std::numeric_limits<size_type>::max)() ? 0 : current_neighbor + 1;
- std::sort(neighbors.begin() + sort_first, neighbors.end(), pair_first_less());
- // remove furthest values
- if ( max_count() < neighbors.size() )
- neighbors.resize(max_count());
+ template <typename Distance>
+ bool ignore_branch_or_value(Distance const& distance)
+ {
+ return m_neighbors_count + m_neighbors.size() == max_count()
+ && (m_neighbors.empty() || m_neighbors.bottom().first <= distance);
}
-private:
- inline std::size_t max_count() const
+ std::size_t max_count() const
{
return nearest_predicate_access::get(m_pred).count;
}
@@ -537,15 +558,15 @@ private:
return nearest_predicate_access::get(m_pred);
}
- const translator_type * m_translator;
+ const translator_type * m_tr;
+ strategy_type m_strategy;
Predicates m_pred;
-
- internal_heap_type internal_heap;
- std::vector< std::pair<value_distance_type, const value_type *> > neighbors;
- size_type current_neighbor;
- strategy_type m_strategy;
+ branches_type m_branches;
+ neighbors_type m_neighbors;
+ size_type m_neighbors_count;
+ const value_type * m_neighbor_ptr;
};
}}} // namespace detail::rtree::visitors
diff --git a/boost/geometry/index/detail/rtree/visitors/insert.hpp b/boost/geometry/index/detail/rtree/visitors/insert.hpp
index 8b32c81763..2d87e21a17 100644
--- a/boost/geometry/index/detail/rtree/visitors/insert.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/insert.hpp
@@ -2,10 +2,11 @@
//
// R-tree inserting visitor implementation
//
-// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2023 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019-2020.
-// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2023.
+// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -21,12 +22,15 @@
#include <boost/geometry/algorithms/detail/expand_by_epsilon.hpp>
#include <boost/geometry/core/static_assert.hpp>
-#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/index/detail/algorithms/bounds.hpp>
#include <boost/geometry/index/detail/algorithms/content.hpp>
-
+#include <boost/geometry/index/detail/rtree/node/node.hpp>
+#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
#include <boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp>
+#include <boost/geometry/index/detail/rtree/options.hpp>
+
+#include <boost/geometry/util/condition.hpp>
namespace boost { namespace geometry { namespace index {
@@ -178,7 +182,7 @@ public:
// 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.
+ // it will be possible to throw from std::move() in the case of e.g. static size nodes.
// redistribute elements
box_type box2;
@@ -618,7 +622,7 @@ public:
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)
diff --git a/boost/geometry/index/detail/rtree/visitors/iterator.hpp b/boost/geometry/index/detail/rtree/visitors/iterator.hpp
index 621231ae9a..1a08f2b3f0 100644
--- a/boost/geometry/index/detail/rtree/visitors/iterator.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/iterator.hpp
@@ -4,6 +4,11 @@
//
// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
//
+// This file was modified by Oracle on 2021-2023.
+// Modifications copyright (c) 2021-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -11,6 +16,10 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ITERATOR_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_ITERATOR_HPP
+#include <boost/geometry/index/detail/rtree/node/concept.hpp>
+#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
+#include <boost/geometry/index/detail/rtree/node/variant_visitor.hpp>
+
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
diff --git a/boost/geometry/index/detail/rtree/visitors/remove.hpp b/boost/geometry/index/detail/rtree/visitors/remove.hpp
index 59f486163d..4e8e9078f2 100644
--- a/boost/geometry/index/detail/rtree/visitors/remove.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/remove.hpp
@@ -4,8 +4,9 @@
//
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019.
-// Modifications copyright (c) 2019 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2023.
+// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,11 +16,17 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_REMOVE_HPP
+#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
+
+#include <boost/geometry/index/parameters.hpp>
+#include <boost/geometry/index/detail/algorithms/bounds.hpp>
+#include <boost/geometry/index/detail/rtree/node/node.hpp>
+#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
+#include <boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp>
#include <boost/geometry/index/detail/rtree/visitors/destroy.hpp>
+#include <boost/geometry/index/detail/rtree/visitors/insert.hpp>
#include <boost/geometry/index/detail/rtree/visitors/is_leaf.hpp>
-#include <boost/geometry/algorithms/detail/covered_by/interface.hpp>
-
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
@@ -155,7 +162,7 @@ public:
{
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 )
{
diff --git a/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp b/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp
index f0d30162ce..678f9ddd74 100644
--- a/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp
+++ b/boost/geometry/index/detail/rtree/visitors/spatial_query.hpp
@@ -4,8 +4,9 @@
//
// Copyright (c) 2011-2014 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019-2021.
-// Modifications copyright (c) 2019-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2023.
+// Modifications copyright (c) 2019-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,13 +16,17 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_SPATIAL_QUERY_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_RTREE_VISITORS_SPATIAL_QUERY_HPP
+#include <boost/geometry/index/detail/rtree/node/node_elements.hpp>
+#include <boost/geometry/index/detail/rtree/node/weak_visitor.hpp>
+#include <boost/geometry/index/detail/predicates.hpp>
+#include <boost/geometry/index/parameters.hpp>
+
namespace boost { namespace geometry { namespace index {
namespace detail { namespace rtree { namespace visitors {
template <typename MembersHolder, typename Predicates, typename OutIter>
struct spatial_query
- : public MembersHolder::visitor_const
{
typedef typename MembersHolder::parameters_type parameters_type;
typedef typename MembersHolder::translator_type translator_type;
@@ -33,71 +38,69 @@ struct spatial_query
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
+ typedef typename allocators_type::node_pointer node_pointer;
typedef typename allocators_type::size_type size_type;
- static const std::size_t predicates_len = index::detail::predicates_length<Predicates>::value;
-
- inline spatial_query(parameters_type const& par, translator_type const& t, Predicates const& p, OutIter out_it)
- : tr(t), pred(p), out_iter(out_it), found_count(0), strategy(index::detail::get_strategy(par))
+ spatial_query(MembersHolder const& members, Predicates const& p, OutIter out_it)
+ : m_tr(members.translator())
+ , m_strategy(index::detail::get_strategy(members.parameters()))
+ , m_pred(p)
+ , m_out_iter(out_it)
+ , m_found_count(0)
{}
- inline void operator()(internal_node const& n)
+ size_type apply(node_pointer ptr, size_type reverse_level)
{
- 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)
+ namespace id = index::detail;
+ if (reverse_level > 0)
{
- // if node meets predicates
- // 0 - dummy value
- if ( index::detail::predicates_check
- <
- index::detail::bounds_tag, 0, predicates_len
- >(pred, 0, it->first, strategy) )
+ internal_node& n = rtree::get<internal_node>(*ptr);
+ // traverse nodes meeting predicates
+ for (auto const& p : rtree::elements(n))
{
- rtree::apply_visitor(*this, *it->second);
+ // if node meets predicates (0 is dummy value)
+ if (id::predicates_check<id::bounds_tag>(m_pred, 0, p.first, m_strategy))
+ {
+ apply(p.second, reverse_level - 1);
+ }
}
}
- }
-
- 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)
+ else
{
- // if value meets predicates
- if ( index::detail::predicates_check
- <
- index::detail::value_tag, 0, predicates_len
- >(pred, *it, tr(*it), strategy) )
+ leaf& n = rtree::get<leaf>(*ptr);
+ // get all values meeting predicates
+ for (auto const& v : rtree::elements(n))
{
- *out_iter = *it;
- ++out_iter;
-
- ++found_count;
+ // if value meets predicates
+ if (id::predicates_check<id::value_tag>(m_pred, v, m_tr(v), m_strategy))
+ {
+ *m_out_iter = v;
+ ++m_out_iter;
+ ++m_found_count;
+ }
}
}
+
+ return m_found_count;
}
- translator_type const& tr;
+ size_type apply(MembersHolder const& members)
+ {
+ return apply(members.root, members.leafs_level);
+ }
- Predicates pred;
+private:
+ translator_type const& m_tr;
+ strategy_type m_strategy;
- OutIter out_iter;
- size_type found_count;
+ Predicates const& m_pred;
+ OutIter m_out_iter;
- strategy_type strategy;
+ size_type m_found_count;
};
template <typename MembersHolder, typename Predicates>
class spatial_query_incremental
- : public MembersHolder::visitor_const
{
typedef typename MembersHolder::value_type value_type;
typedef typename MembersHolder::parameters_type parameters_type;
@@ -106,7 +109,6 @@ class spatial_query_incremental
typedef typename index::detail::strategy_type<parameters_type>::type strategy_type;
-public:
typedef typename MembersHolder::node node;
typedef typename MembersHolder::internal_node internal_node;
typedef typename MembersHolder::leaf leaf;
@@ -119,37 +121,40 @@ public:
typedef typename rtree::elements_type<leaf>::type leaf_elements;
typedef typename rtree::elements_type<leaf>::type::const_iterator leaf_iterator;
- static const std::size_t predicates_len = index::detail::predicates_length<Predicates>::value;
+ struct internal_data
+ {
+ internal_data(internal_iterator f, internal_iterator l, size_type rl)
+ : first(f), last(l), reverse_level(rl)
+ {}
+ internal_iterator first;
+ internal_iterator last;
+ size_type reverse_level;
+ };
- inline spatial_query_incremental()
- : m_translator(NULL)
+public:
+ spatial_query_incremental()
+ : m_translator(nullptr)
+// , m_strategy()
// , m_pred()
- , m_values(NULL)
+ , m_values(nullptr)
, m_current()
-// , m_strategy()
{}
- inline spatial_query_incremental(parameters_type const& params, translator_type const& t, Predicates const& p)
- : m_translator(::boost::addressof(t))
+ spatial_query_incremental(Predicates const& p)
+ : m_translator(nullptr)
+// , m_strategy()
, m_pred(p)
- , m_values(NULL)
+ , m_values(nullptr)
, m_current()
- , m_strategy(index::detail::get_strategy(params))
{}
- 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();
- }
+ spatial_query_incremental(MembersHolder const& members, Predicates const& p)
+ : m_translator(::boost::addressof(members.translator()))
+ , m_strategy(index::detail::get_strategy(members.parameters()))
+ , m_pred(p)
+ , m_values(nullptr)
+ , m_current()
+ {}
const_reference dereference() const
{
@@ -157,9 +162,9 @@ public:
return *m_current;
}
- void initialize(node_pointer root)
+ void initialize(MembersHolder const& members)
{
- rtree::apply_visitor(*this, *root);
+ apply(members.root, members.leafs_level);
search_value();
}
@@ -169,8 +174,38 @@ public:
search_value();
}
+ 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:
+ void apply(node_pointer ptr, size_type reverse_level)
+ {
+ namespace id = index::detail;
+
+ if (reverse_level > 0)
+ {
+ internal_node& n = rtree::get<internal_node>(*ptr);
+ auto const& elements = rtree::elements(n);
+ m_internal_stack.push_back(internal_data(elements.begin(), elements.end(), reverse_level - 1));
+ }
+ else
+ {
+ leaf& n = rtree::get<leaf>(*ptr);
+ m_values = ::boost::addressof(rtree::elements(n));
+ m_current = rtree::elements(n).begin();
+ }
+ }
+
void search_value()
{
+ namespace id = index::detail;
for (;;)
{
// if leaf is choosen, move to the next value in leaf
@@ -180,10 +215,7 @@ public:
{
// return if next value is found
value_type const& v = *m_current;
- if (index::detail::predicates_check
- <
- index::detail::value_tag, 0, predicates_len
- >(m_pred, v, (*m_translator)(v), m_strategy))
+ if (id::predicates_check<id::value_tag>(m_pred, v, (*m_translator)(v), m_strategy))
{
return;
}
@@ -200,52 +232,40 @@ public:
else
{
// return if there is no more nodes to traverse
- if ( m_internal_stack.empty() )
+ if (m_internal_stack.empty())
+ {
return;
+ }
+
+ internal_data& current_data = m_internal_stack.back();
// no more children in current node, remove it from stack
- if ( m_internal_stack.back().first == m_internal_stack.back().second )
+ if (current_data.first == current_data.last)
{
m_internal_stack.pop_back();
continue;
}
- internal_iterator it = m_internal_stack.back().first;
- ++m_internal_stack.back().first;
+ internal_iterator it = current_data.first;
+ ++current_data.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, m_strategy))
+ if (id::predicates_check<id::bounds_tag>(m_pred, 0, it->first, m_strategy))
{
- rtree::apply_visitor(*this, *(it->second));
+ apply(it->second, current_data.reverse_level);
}
}
}
}
- 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_type * m_translator;
+ strategy_type m_strategy;
Predicates m_pred;
- std::vector< std::pair<internal_iterator, internal_iterator> > m_internal_stack;
+ std::vector<internal_data> m_internal_stack;
const leaf_elements * m_values;
leaf_iterator m_current;
-
- strategy_type m_strategy;
};
}}} // namespace detail::rtree::visitors
diff --git a/boost/geometry/index/detail/serialization.hpp b/boost/geometry/index/detail/serialization.hpp
index 71902d19f7..acb8cde2aa 100644
--- a/boost/geometry/index/detail/serialization.hpp
+++ b/boost/geometry/index/detail/serialization.hpp
@@ -1,6 +1,11 @@
// Boost.Geometry Index
//
-// Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2023 Adam Wulkiewicz, Lodz, Poland.
+//
+// This file was modified by Oracle on 2021-2023.
+// Modifications copyright (c) 2021-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -9,10 +14,20 @@
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_SERIALIZATION_HPP
-//#include <boost/serialization/serialization.hpp>
+#include <boost/type_traits/alignment_of.hpp>
+#include <boost/type_traits/aligned_storage.hpp>
+
+#include <boost/serialization/serialization.hpp>
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/version.hpp>
-//#include <boost/serialization/nvp.hpp>
+#include <boost/serialization/nvp.hpp>
+
+#include <boost/geometry/geometries/point.hpp>
+#include <boost/geometry/geometries/box.hpp>
+
+#include <boost/geometry/index/parameters.hpp>
+#include <boost/geometry/index/detail/rtree/node/concept.hpp>
+#include <boost/geometry/index/detail/rtree/node/subtree_destroyer.hpp>
// TODO
// how about using the unsigned type capable of storing Max in compile-time versions?
@@ -26,9 +41,15 @@
// each geometry save without this info
// TODO - move to index/detail/serialization.hpp
-namespace boost { namespace geometry { namespace index { namespace detail {
+namespace boost { namespace geometry { namespace index {
+
+// Forward declaration
+template <typename Value, typename Options, typename IndexableGetter, typename EqualTo, typename Allocator>
+class rtree;
-// TODO - use boost::move?
+namespace detail {
+
+// TODO - use std::move?
template<typename T>
class serialization_storage
{
@@ -57,7 +78,7 @@ private:
template <typename T, typename Archive> inline
T serialization_load(const char * name, Archive & ar)
{
- namespace bs = boost::serialization;
+ namespace bs = boost::serialization;
serialization_storage<T> storage(ar, bs::version<T>::value); // load_construct_data
ar >> boost::serialization::make_nvp(name, *storage.address()); // serialize
//ar >> *storage.address(); // serialize
@@ -72,7 +93,7 @@ void serialization_save(T const& t, const char * name, Archive & ar)
ar << boost::serialization::make_nvp(name, t); // serialize
//ar << t; // serialize
}
-
+
}}}}
// TODO - move to index/serialization/rtree.hpp
@@ -391,15 +412,17 @@ private:
size_t elements_count;
ar >> boost::serialization::make_nvp("s", elements_count);
- // leafs_level == 0 implies current_level == 0
- if ( (elements_count < parameters.get_min_elements() && leafs_level > 0)
+ // root may contain count < min but shouldn't contain count > max
+ if ( (elements_count < parameters.get_min_elements() && current_level > 0)
|| parameters.get_max_elements() < elements_count )
+ {
BOOST_THROW_EXCEPTION(std::runtime_error("rtree loading error"));
+ }
if ( current_level < leafs_level )
{
node_pointer n = rtree::create_node<allocators_type, internal_node>::apply(allocators); // MAY THROW (A)
- subtree_destroyer auto_remover(n, allocators);
+ subtree_destroyer auto_remover(n, allocators);
internal_node & in = rtree::get<internal_node>(*n);
elements_type & elements = rtree::elements(in);
@@ -460,7 +483,7 @@ public:
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;
+ typedef typename Rtree::allocators_type allocators_type;
const_private_view(Rtree const& rt) : m_rtree(rt) {}
@@ -485,7 +508,7 @@ public:
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;
+ typedef typename Rtree::allocators_type allocators_type;
private_view(Rtree & rt) : m_rtree(rt) {}
diff --git a/boost/geometry/index/detail/translator.hpp b/boost/geometry/index/detail/translator.hpp
index 34960d2268..900be6e73d 100644
--- a/boost/geometry/index/detail/translator.hpp
+++ b/boost/geometry/index/detail/translator.hpp
@@ -2,8 +2,8 @@
//
// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019-2020.
-// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2021.
+// Modifications copyright (c) 2019-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,6 +15,8 @@
#include <type_traits>
+#include <boost/geometry/strategies/default_strategy.hpp>
+
namespace boost { namespace geometry { namespace index {
namespace detail {
diff --git a/boost/geometry/index/detail/utilities.hpp b/boost/geometry/index/detail/utilities.hpp
index c45775513e..9060071b33 100644
--- a/boost/geometry/index/detail/utilities.hpp
+++ b/boost/geometry/index/detail/utilities.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry Index
//
-// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2023 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020 Oracle and/or its affiliates.
@@ -12,7 +12,7 @@
#include <type_traits>
-#include <boost/swap.hpp>
+#include <boost/core/swap.hpp>
#ifndef BOOST_GEOMETRY_INDEX_DETAIL_UTILITIES_HPP
#define BOOST_GEOMETRY_INDEX_DETAIL_UTILITIES_HPP
@@ -31,7 +31,7 @@ static inline void assign_cond(T &, T const&, std::false_type) {}
template<class T>
static inline void move_cond(T & l, T & r, std::true_type)
{
- l = ::boost::move(r);
+ l = std::move(r);
}
template<class T>
diff --git a/boost/geometry/index/detail/varray.hpp b/boost/geometry/index/detail/varray.hpp
index 8a00e361e6..9911520bbb 100644
--- a/boost/geometry/index/detail/varray.hpp
+++ b/boost/geometry/index/detail/varray.hpp
@@ -1,7 +1,7 @@
// Boost.Container varray
//
// Copyright (c) 2011-2013 Andrew Hundt.
-// Copyright (c) 2012-2015 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2012-2023 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020, Oracle and/or its affiliates.
@@ -18,14 +18,10 @@
#include <boost/container/detail/config_begin.hpp>
#include <boost/container/detail/workaround.hpp>
-#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
-#include <boost/move/detail/fwd_macros.hpp>
-#endif
-
#include <boost/concept_check.hpp>
#include <boost/config.hpp>
#include <boost/core/ignore_unused.hpp>
-#include <boost/swap.hpp>
+#include <boost/core/swap.hpp>
#include <boost/integer.hpp>
// TODO - use std::reverse_iterator and std::iterator_traits
@@ -49,7 +45,7 @@
*/
namespace boost { namespace geometry { namespace index { namespace detail {
-
+
namespace varray_detail {
template <typename Value, std::size_t Capacity>
@@ -58,10 +54,10 @@ 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 Value* pointer;
+ typedef const Value* const_pointer;
+ typedef Value& reference;
+ typedef const Value& const_reference;
typedef std::false_type use_memop_in_swap_and_move;
typedef std::false_type use_optimized_swap;
@@ -99,7 +95,7 @@ struct checker
static inline void check_not_empty(Varray const& v)
{
BOOST_GEOMETRY_INDEX_ASSERT(!v.empty(), "the container is empty");
-
+
::boost::ignore_unused(v);
}
@@ -127,12 +123,12 @@ varray is a sequence container like boost::container::vector with contiguous sto
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
+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
+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
+elements in cases with complex object lifetime requirements that would otherwise not be trivially
possible.
\par Error Handling
@@ -172,19 +168,6 @@ class varray
template <typename V, std::size_t C>
friend class varray;
- BOOST_COPYABLE_AND_MOVABLE(varray)
-
-#ifdef BOOST_NO_CXX11_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;
@@ -284,7 +267,7 @@ public:
: m_size(0)
{
BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal<Iterator>)); // Make sure you passed a ForwardIterator
-
+
this->assign(first, last); // may throw
}
@@ -323,7 +306,7 @@ public:
: 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
}
@@ -337,7 +320,7 @@ public:
//!
//! @par Complexity
//! Linear O(N).
- varray & operator=(BOOST_COPY_ASSIGN_REF(varray) other)
+ varray& operator=(varray const& other)
{
this->assign(other.begin(), other.end()); // may throw
@@ -359,7 +342,7 @@ public:
//! @par Complexity
//! Linear O(N).
template <std::size_t C>
- varray & operator=(BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(varray, value_type, C) other)
+ varray& operator=(varray<value_type, C> const& other)
{
this->assign(other.begin(), other.end()); // may throw
@@ -371,15 +354,15 @@ public:
//! @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.
+ //! @li If \c std::is_nothrow_move_constructible<Value>::value is \c true and Value's move constructor throws.
+ //! @li If \c std::is_nothrow_move_constructible<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)
+ varray(varray&& other)
{
typedef typename
vt::use_memop_in_swap_and_move use_memop_in_swap_and_move;
@@ -394,8 +377,8 @@ public:
//! @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.
+ //! @li If \c std::is_nothrow_move_constructible<Value>::value is \c true and Value's move constructor throws.
+ //! @li If \c std::is_nothrow_move_constructible<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
@@ -406,7 +389,7 @@ public:
//! @par Complexity
//! Linear O(N).
template <std::size_t C>
- varray(BOOST_RV_REF_2_TEMPL_ARGS(varray, value_type, C) other)
+ varray(varray<value_type, C>&& other)
: m_size(other.m_size)
{
errh::check_capacity(*this, other.size()); // may throw
@@ -422,15 +405,15 @@ public:
//! @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.
+ //! @li If \c std::is_nothrow_move_constructible<Value>::value is \c true and Value's move constructor or move assignment throws.
+ //! @li If \c std::is_nothrow_move_constructible<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)
+ varray& operator=(varray&& other)
{
if ( &other == this )
return *this;
@@ -450,8 +433,8 @@ public:
//! @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.
+ //! @li If \c std::is_nothrow_move_constructible<Value>::value is \c true and Value's move constructor or move assignment throws.
+ //! @li If \c std::is_nothrow_move_constructible<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
@@ -462,7 +445,7 @@ public:
//! @par Complexity
//! Linear O(N).
template <std::size_t C>
- varray & operator=(BOOST_RV_REF_2_TEMPL_ARGS(varray, value_type, C) other)
+ varray& operator=(varray<value_type, C>&& other)
{
errh::check_capacity(*this, other.size()); // may throw
@@ -492,15 +475,15 @@ public:
//! @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,
+ //! @li If \c std::is_nothrow_move_constructible<Value>::value is \c true and Value's move constructor or move assignment throws,
+ //! @li If \c std::is_nothrow_move_constructible<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)
+ void swap(varray& other)
{
typedef typename
vt::use_optimized_swap use_optimized_swap;
@@ -515,8 +498,8 @@ public:
//! @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,
+ //! @li If \c std::is_nothrow_move_constructible<Value>::value is \c true and Value's move constructor or move assignment throws,
+ //! @li If \c std::is_nothrow_move_constructible<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
@@ -527,7 +510,7 @@ public:
//! @par Complexity
//! Linear O(N).
template <std::size_t C>
- void swap(varray<value_type, C> & other)
+ void swap(varray<value_type, C>& other)
{
errh::check_capacity(*this, other.size());
errh::check_capacity(other, this->size());
@@ -535,7 +518,7 @@ public:
typedef typename
vt::use_optimized_swap use_optimized_swap;
- this->swap_dispatch(other, use_optimized_swap());
+ this->swap_dispatch(other, use_optimized_swap());
}
//! @pre <tt>count <= capacity()</tt>
@@ -597,7 +580,7 @@ public:
else
{
errh::check_capacity(*this, count); // may throw
-
+
std::uninitialized_fill(this->end(), this->begin() + count, value); // may throw
}
m_size = count; // update end
@@ -641,7 +624,7 @@ public:
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
@@ -661,14 +644,14 @@ public:
//!
//! @par Complexity
//! Constant O(1).
- void push_back(BOOST_RV_REF(value_type) value)
+ void push_back(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
+ sv::construct(dti(), this->end(), std::move(value)); // may throw
++m_size; // update end
}
@@ -724,8 +707,8 @@ public:
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
+ value_type& r = *(this->end() - 1);
+ sv::construct(dti(), this->end(), std::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
@@ -751,7 +734,7 @@ public:
//!
//! @par Complexity
//! Constant or linear.
- iterator insert(iterator position, BOOST_RV_REF(value_type) value)
+ iterator insert(iterator position, value_type&& value)
{
typedef typename vt::disable_trivial_init dti;
namespace sv = varray_detail;
@@ -761,17 +744,17 @@ public:
if ( position == this->end() )
{
- sv::construct(dti(), position, boost::move(value)); // may throw
+ sv::construct(dti(), position, std::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
+ value_type& r = *(this->end() - 1);
+ sv::construct(dti(), this->end(), std::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
+ sv::assign(position, std::move(value)); // may throw
}
return position;
@@ -811,7 +794,7 @@ public:
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) )
@@ -912,9 +895,9 @@ public:
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_GEOMETRY_INDEX_ASSERT(0 <= n, "invalid range");
//TODO - add this->size() check?
@@ -979,8 +962,6 @@ public:
m_size = count; // update end
}
-#if !defined(BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE)
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
//! @pre <tt>size() < capacity()</tt>
//!
//! @brief Inserts a Value constructed with
@@ -997,14 +978,14 @@ public:
//! @par Complexity
//! Constant O(1).
template<class ...Args>
- void emplace_back(BOOST_FWD_REF(Args) ...args)
+ void emplace_back(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
+ sv::construct(dti(), this->end(), std::forward<Args>(args)...); // may throw
++m_size; // update end
}
@@ -1027,7 +1008,7 @@ public:
//! @par Complexity
//! Constant or linear.
template<class ...Args>
- iterator emplace(iterator position, BOOST_FWD_REF(Args) ...args)
+ iterator emplace(iterator position, Args&& ...args)
{
typedef typename vt::disable_trivial_init dti;
@@ -1038,7 +1019,7 @@ public:
if ( position == this->end() )
{
- sv::construct(dti(), position, ::boost::forward<Args>(args)...); // may throw
+ sv::construct(dti(), position, std::forward<Args>(args)...); // may throw
++m_size; // update end
}
else
@@ -1046,76 +1027,21 @@ public:
// 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
+ value_type& r = *(this->end() - 1);
+ sv::construct(dti(), this->end(), std::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
+ value_type* val_p = static_cast<value_type*>(temp_storage.address());
+ sv::construct(dti(), val_p, std::forward<Args>(args)...); // may throw
sv::scoped_destructor<value_type> d(val_p);
- sv::assign(position, ::boost::move(*val_p)); // may throw
+ sv::assign(position, std::move(*val_p)); // may throw
}
return position;
}
-#else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
-
- #define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_EMPLACE(N) \
- BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- void emplace_back(BOOST_MOVE_UREF##N) \
- { \
- 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_I##N BOOST_MOVE_FWD##N ); /*may throw*/\
- ++m_size; /*update end*/ \
- } \
- \
- BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
- iterator emplace(iterator position BOOST_MOVE_I##N BOOST_MOVE_UREF##N) \
- { \
- 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_I##N BOOST_MOVE_FWD##N ); /*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_MOVE_I##N BOOST_MOVE_FWD##N ); /*may throw*/\
- sv::scoped_destructor<value_type> d(val_p); \
- sv::assign(position, ::boost::move(*val_p)); /*may throw*/\
- } \
- \
- return position; \
- } \
-
- BOOST_MOVE_ITERATE_0TO9(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_EMPLACE)
- #undef BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_EMPLACE
-
-#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
-#endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE
-
//! @brief Removes all elements from the container.
//!
//! @par Throws
@@ -1309,7 +1235,7 @@ public:
return boost::addressof(*(this->ptr()));
}
-
+
//! @brief Returns iterator to the first element.
//!
//! @return iterator to the first element contained in the vector.
@@ -1500,19 +1426,19 @@ private:
// @par Complexity
// Linear O(N).
template <std::size_t C>
- void move_ctor_dispatch(varray<value_type, C> & other, std::true_type /*use_memop*/)
+ void move_ctor_dispatch(varray<value_type, C>& other, std::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.
+ // @li If std::is_nothrow_move_constructible<Value>::value is true and Value's move constructor throws
+ // @li If std::is_nothrow_move_constructible<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, std::false_type /*use_memop*/)
+ void move_ctor_dispatch(varray<value_type, C>& other, std::false_type /*use_memop*/)
{
namespace sv = varray_detail;
sv::uninitialized_move_if_noexcept(other.begin(), other.end(), this->begin()); // may throw
@@ -1524,7 +1450,7 @@ private:
// @par Complexity
// Linear O(N).
template <std::size_t C>
- void move_assign_dispatch(varray<value_type, C> & other, std::true_type /*use_memop*/)
+ void move_assign_dispatch(varray<value_type, C>& other, std::true_type /*use_memop*/)
{
this->clear();
@@ -1533,12 +1459,12 @@ private:
}
// @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.
+ // @li If std::is_nothrow_move_constructible<Value>::value is true and Value's move constructor or move assignment throws
+ // @li If std::is_nothrow_move_constructible<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, std::false_type /*use_memop*/)
+ void move_assign_dispatch(varray<value_type, C>& other, std::false_type /*use_memop*/)
{
namespace sv = varray_detail;
if ( m_size <= static_cast<size_type>(other.size()) )
@@ -1560,7 +1486,7 @@ private:
// @par Complexity
// Linear O(N).
template <std::size_t C>
- void swap_dispatch(varray<value_type, C> & other, std::true_type /*use_optimized_swap*/)
+ void swap_dispatch(varray<value_type, C>& other, std::true_type /*use_optimized_swap*/)
{
typedef std::conditional_t
<
@@ -1568,9 +1494,9 @@ private:
aligned_storage_type,
typename varray<value_type, C>::aligned_storage_type
> storage_type;
-
+
storage_type temp;
- Value * temp_ptr = reinterpret_cast<Value*>(temp.address());
+ 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());
@@ -1585,7 +1511,7 @@ private:
// @par Complexity
// Linear O(N).
template <std::size_t C>
- void swap_dispatch(varray<value_type, C> & other, std::false_type /*use_optimized_swap*/)
+ void swap_dispatch(varray<value_type, C>& other, std::false_type /*use_optimized_swap*/)
{
namespace sv = varray_detail;
@@ -1615,7 +1541,7 @@ private:
sizeof(value_type),
boost::alignment_of<value_type>::value
> temp_storage;
- value_type * temp_ptr = reinterpret_cast<value_type*>(temp_storage.address());
+ 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));
@@ -1635,12 +1561,15 @@ private:
// "incompatible ranges");
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
+ //std::iter_swap(first_sm, first_la);
+ //std::swap(*first_sm, *first_la); // may throw
+ //boost::swap(*first_sm, *first_la);
+ value_type temp(std::move(*first_sm)); // may throw
+ *first_sm = std::move(*first_la); // may throw
+ *first_la = std::move(temp); // may throw
}
sv::uninitialized_move(first_la, last_la, first_sm); // may throw
sv::destroy(first_la, last_la);
@@ -1657,9 +1586,9 @@ private:
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);
@@ -1694,7 +1623,7 @@ private:
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;
@@ -1703,7 +1632,7 @@ private:
{
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
@@ -1872,7 +1801,7 @@ public:
}
// basic
- varray & operator=(varray const& /*other*/)
+ varray& operator=(varray const& /*other*/)
{
//errh::check_capacity(*this, other.size());
return *this;
@@ -1880,7 +1809,7 @@ public:
// basic
template <size_t C>
- varray & operator=(varray<value_type, C> const& other)
+ varray& operator=(varray<value_type, C> const& other)
{
errh::check_capacity(*this, other.size()); // may throw
return *this;
@@ -1901,7 +1830,7 @@ public:
errh::check_capacity(*this, count); // may throw
}
-
+
// nothrow
void reserve(size_type count)
{
@@ -2031,8 +1960,8 @@ public:
}
// nothrow
- Value * data() { return boost::addressof(*(this->ptr())); }
- const Value * data() const { return boost::addressof(*(this->ptr())); }
+ Value* data() { return boost::addressof(*(this->ptr())); }
+ const Value* data() const { return boost::addressof(*(this->ptr())); }
// nothrow
iterator begin() { return this->ptr(); }
@@ -2183,7 +2112,7 @@ bool operator>= (varray<V, C1> const& x, varray<V, C2> const& y)
//! @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)
+inline void swap(varray<V, C1>& x, varray<V, C2>& y)
{
x.swap(y);
}
diff --git a/boost/geometry/index/detail/varray_detail.hpp b/boost/geometry/index/detail/varray_detail.hpp
index c66185f9a7..cd9ff6b88e 100644
--- a/boost/geometry/index/detail/varray_detail.hpp
+++ b/boost/geometry/index/detail/varray_detail.hpp
@@ -3,7 +3,7 @@
// varray details
//
// Copyright (c) 2011-2013 Andrew Hundt.
-// Copyright (c) 2012-2020 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2012-2023 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2020.
// Modifications copyright (c) 2020, Oracle and/or its affiliates.
@@ -25,15 +25,10 @@
#include <boost/config.hpp>
-#include <boost/core/no_exceptions_support.hpp>
-#include <boost/move/move.hpp>
#include <boost/core/addressof.hpp>
+#include <boost/core/no_exceptions_support.hpp>
#include <boost/iterator/iterator_traits.hpp>
-#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
-#include <boost/move/detail/fwd_macros.hpp>
-#endif
-
// 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)
@@ -48,13 +43,13 @@ namespace boost { namespace geometry { namespace index { namespace detail { name
template <typename I>
struct are_elements_contiguous : std::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>
@@ -68,7 +63,7 @@ struct are_elements_contiguous<
{};
#if defined(BOOST_DINKUMWARE_STDLIB)
-
+
template <typename T>
struct are_elements_contiguous<
std::_Vector_const_iterator<T>
@@ -101,7 +96,7 @@ struct are_elements_contiguous<
#else // OTHER_STDLIB
// TODO - add other iterators implementations
-
+
#endif // STDLIB
#endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_ENABLE_VECTOR_OPTIMIZATION && !BOOST_NO_EXCEPTIONS
@@ -284,7 +279,7 @@ O uninitialized_move_dispatch(I first, I last, O dst,
{
typedef typename std::iterator_traits<O>::value_type value_type;
for (; first != last; ++first, ++o )
- new (boost::addressof(*o)) value_type(boost::move(*first));
+ new (boost::addressof(*o)) value_type(std::move(*first));
}
BOOST_CATCH(...)
{
@@ -324,7 +319,7 @@ inline
O move_dispatch(I first, I last, O dst,
std::false_type /*use_memmove*/)
{
- return boost::move(first, last, dst); // may throw
+ return std::move(first, last, dst); // may throw
}
template <typename I, typename O>
@@ -354,7 +349,7 @@ inline
BDO move_backward_dispatch(BDI first, BDI last, BDO dst,
std::false_type /*use_memmove*/)
{
- return boost::move_backward(first, last, dst); // may throw
+ return std::move_backward(first, last, dst); // may throw
}
template <typename BDI, typename BDO>
@@ -364,17 +359,6 @@ BDO move_backward(BDI first, BDI last, BDO dst)
return move_backward_dispatch(first, last, dst, is_memop_safe_for_range<BDI, BDO>()); // may throw
}
-template <typename T>
-struct has_nothrow_move
- : std::integral_constant
- <
- bool,
- ::boost::has_nothrow_move<std::remove_const_t<T> >::value
- ||
- ::boost::has_nothrow_move<T>::value
- >
-{};
-
// uninitialized_move_if_noexcept(I, I, O)
template <typename I, typename O>
@@ -397,7 +381,7 @@ template <typename I, typename O>
inline
O uninitialized_move_if_noexcept(I first, I last, O dst)
{
- typedef has_nothrow_move<
+ typedef std::is_nothrow_move_constructible<
typename ::boost::iterator_value<O>::type
> use_move;
@@ -426,7 +410,7 @@ template <typename I, typename O>
inline
O move_if_noexcept(I first, I last, O dst)
{
- typedef has_nothrow_move<
+ typedef std::is_nothrow_move_constructible<
typename ::boost::iterator_value<O>::type
> use_move;
@@ -495,7 +479,7 @@ inline
void construct_dispatch(std::false_type /*dont_init*/, I pos)
{
typedef typename ::boost::iterator_value<I>::type value_type;
- new (static_cast<void*>(::boost::addressof(*pos))) value_type(); // may throw
+ new (static_cast<void*>(boost::addressof(*pos))) value_type(); // may throw
}
template <typename DisableTrivialInit, typename I>
@@ -553,61 +537,32 @@ void construct_move_dispatch(I pos, V const& v,
template <typename I, typename P>
inline
-void construct_move_dispatch(I pos, BOOST_RV_REF(P) p,
+void construct_move_dispatch(I pos, P&& p,
std::false_type const& /*use_memcpy*/)
{
typedef typename boost::iterator_value<I>::type V;
- new (static_cast<void*>(boost::addressof(*pos))) V(::boost::move(p)); // may throw
+ new (static_cast<void*>(boost::addressof(*pos))) V(std::move(p)); // may throw
}
template <typename DisableTrivialInit, typename I, typename P>
inline
-void construct(DisableTrivialInit const&, I pos, BOOST_RV_REF(P) p)
+void construct(DisableTrivialInit const&, I pos, P&& p)
{
- construct_move_dispatch(pos, ::boost::move(p), is_memop_safe_for_value<I, P>()); // may throw
+ construct_move_dispatch(pos, std::move(p), is_memop_safe_for_value<I, P>()); // may throw
}
// Needed by emplace_back() and emplace()
-#if !defined(BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE)
-#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
-
template <typename DisableTrivialInit, typename I, class ...Args>
inline
void construct(DisableTrivialInit const&,
I pos,
- BOOST_FWD_REF(Args) ...args)
+ Args&& ...args)
{
typedef typename boost::iterator_value<I>::type V;
- new (static_cast<void*>(boost::addressof(*pos))) V(::boost::forward<Args>(args)...); // may throw
+ new (static_cast<void*>(boost::addressof(*pos))) V(std::forward<Args>(args)...); // may throw
}
-#else // !BOOST_NO_CXX11_VARIADIC_TEMPLATES
-
-// BOOST_NO_CXX11_RVALUE_REFERENCES -> P0 const& p0
-// !BOOST_NO_CXX11_RVALUE_REFERENCES -> P0 && p0
-// which means that version with one parameter may take V const& v
-
-#define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_CONSTRUCT(N) \
-template <typename DisableTrivialInit, typename I, typename P BOOST_MOVE_I##N BOOST_MOVE_CLASS##N > \
-inline \
-void construct(DisableTrivialInit const&, \
- I pos, \
- BOOST_FWD_REF(P) p \
- BOOST_MOVE_I##N BOOST_MOVE_UREF##N) \
-{ \
- typedef typename boost::iterator_value<I>::type V; \
- new \
- (static_cast<void*>(boost::addressof(*pos))) \
- V(boost::forward<P>(p) BOOST_MOVE_I##N BOOST_MOVE_FWD##N); /*may throw*/ \
-} \
-
-BOOST_MOVE_ITERATE_1TO9(BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_CONSTRUCT)
-#undef BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_DETAIL_CONSTRUCT
-
-#endif // !BOOST_NO_CXX11_VARIADIC_TEMPLATES
-#endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE
-
// assign(I, V)
template <typename I, typename V>
@@ -645,17 +600,17 @@ void assign_move_dispatch(I pos, V const& v,
template <typename I, typename V>
inline
-void assign_move_dispatch(I pos, BOOST_RV_REF(V) v,
+void assign_move_dispatch(I pos, V&& v,
std::false_type /*use_memcpy*/)
{
- *pos = boost::move(v); // may throw
+ *pos = std::move(v); // may throw
}
template <typename I, typename V>
inline
-void assign(I pos, BOOST_RV_REF(V) v)
+void assign(I pos, V&& v)
{
- assign_move_dispatch(pos, ::boost::move(v), is_memop_safe_for_value<I, V>());
+ assign_move_dispatch(pos, std::move(v), is_memop_safe_for_value<I, V>());
}
// uninitialized_copy_s
diff --git a/boost/geometry/index/distance_predicates.hpp b/boost/geometry/index/distance_predicates.hpp
index 59b32af475..00fc663cb3 100644
--- a/boost/geometry/index/distance_predicates.hpp
+++ b/boost/geometry/index/distance_predicates.hpp
@@ -2,7 +2,7 @@
//
// Spatial index distance predicates, calculators and checkers used in nearest neighbor query
//
-// Copyright (c) 2011-2013 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2022 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
@@ -11,6 +11,12 @@
#ifndef BOOST_GEOMETRY_INDEX_DISTANCE_PREDICATES_HPP
#define BOOST_GEOMETRY_INDEX_DISTANCE_PREDICATES_HPP
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_PREDICATES
+#define BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_PREDICATES
+#endif
+#endif
+
#include <boost/geometry/index/detail/distance_predicates.hpp>
/*!
@@ -21,7 +27,7 @@ namespace boost { namespace geometry { namespace index {
// relations generators
-#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_PREDICATES
/*!
\brief Generate to_nearest() relationship.
@@ -91,7 +97,7 @@ detail::to_furthest<T> to_furthest(T const& v)
return detail::to_furthest<T>(v);
}
-#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_PREDICATES
// distance predicates generators
diff --git a/boost/geometry/index/equal_to.hpp b/boost/geometry/index/equal_to.hpp
index 3ce2e1e4cd..0a360ba387 100644
--- a/boost/geometry/index/equal_to.hpp
+++ b/boost/geometry/index/equal_to.hpp
@@ -16,6 +16,8 @@
#include <boost/geometry/algorithms/detail/equals/interface.hpp>
#include <boost/geometry/index/indexable.hpp>
+#include <tuple>
+
namespace boost { namespace geometry { namespace index { namespace detail
{
@@ -151,10 +153,10 @@ 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.
@@ -183,7 +185,7 @@ struct equal_to<std::pair<T1, T2>, false>
/*!
\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.
@@ -214,7 +216,7 @@ struct equal_to<boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>, false>
/*!
\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.
@@ -231,10 +233,6 @@ struct equal_to<boost::tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>, false>
}}}} // namespace boost::geometry::index::detail
-#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>
@@ -277,7 +275,7 @@ struct equal_to<std::tuple<Args...>, false>
/*!
\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.
@@ -293,7 +291,6 @@ struct equal_to<std::tuple<Args...>, false>
}}}} // namespace boost::geometry::index::detail
-#endif // !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
namespace boost { namespace geometry { namespace index {
@@ -313,10 +310,10 @@ struct equal_to
{
/*! \brief The type of result returned by function object. */
typedef typename detail::equal_to<Value>::result_type result_type;
-
+
/*!
\brief Compare Values.
-
+
\param l First value.
\param r Second value.
\return true if Values are equal.
diff --git a/boost/geometry/index/indexable.hpp b/boost/geometry/index/indexable.hpp
index 2b9f3d0f11..84cf05face 100644
--- a/boost/geometry/index/indexable.hpp
+++ b/boost/geometry/index/indexable.hpp
@@ -21,6 +21,8 @@
#include <boost/geometry/util/type_traits.hpp>
+#include <tuple>
+
namespace boost { namespace geometry { namespace index { namespace detail
{
@@ -63,7 +65,7 @@ struct indexable
/*!
\brief Return indexable extracted from the value.
-
+
\param v The value.
\return The indexable.
*/
@@ -105,7 +107,7 @@ struct indexable<std::pair<Indexable, Second>, false>
/*!
\brief Return indexable extracted from the value.
-
+
\param v The value.
\return The indexable.
*/
@@ -164,7 +166,7 @@ struct indexable_boost_tuple
/*!
\brief Return indexable extracted from the value.
-
+
\param v The value.
\return The indexable.
*/
@@ -251,10 +253,6 @@ struct indexable<boost::tuples::cons<Indexable, Tail>, false>
}}}} // namespace boost::geometry::index::detail
-#if !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
-
-#include <tuple>
-
namespace boost { namespace geometry { namespace index { namespace detail {
/*!
@@ -280,7 +278,7 @@ struct indexable<std::tuple<Indexable, Args...>, false>
/*!
\brief Return indexable extracted from the value.
-
+
\param v The value.
\return The indexable.
*/
@@ -317,7 +315,6 @@ struct indexable<std::tuple<Indexable, Args...>, false>
}}}} // namespace boost::geometry::index::detail
-#endif // !defined(BOOST_NO_CXX11_HDR_TUPLE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
namespace boost { namespace geometry { namespace index {
@@ -339,7 +336,7 @@ struct indexable
/*!
\brief Return indexable extracted from the value.
-
+
\param v The value.
\return The indexable.
*/
diff --git a/boost/geometry/index/inserter.hpp b/boost/geometry/index/inserter.hpp
index 30280d4cb0..8ef2a4606d 100644
--- a/boost/geometry/index/inserter.hpp
+++ b/boost/geometry/index/inserter.hpp
@@ -34,7 +34,7 @@ public:
inline explicit insert_iterator(Container & c)
: container(&c)
{}
-
+
insert_iterator & operator=(typename Container::value_type const& value)
{
container->insert(value);
diff --git a/boost/geometry/index/parameters.hpp b/boost/geometry/index/parameters.hpp
index fdaef9284b..d5d8d87fe1 100644
--- a/boost/geometry/index/parameters.hpp
+++ b/boost/geometry/index/parameters.hpp
@@ -4,8 +4,8 @@
//
// Copyright (c) 2011-2017 Adam Wulkiewicz, Lodz, Poland.
//
-// This file was modified by Oracle on 2019-2020.
-// Modifications copyright (c) 2019-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2019-2021.
+// Modifications copyright (c) 2019-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
//
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,17 +15,17 @@
#ifndef BOOST_GEOMETRY_INDEX_PARAMETERS_HPP
#define BOOST_GEOMETRY_INDEX_PARAMETERS_HPP
-
#include <limits>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/index/detail/exception.hpp>
+#include <boost/geometry/strategies/default_strategy.hpp>
namespace boost { namespace geometry { namespace index {
-namespace detail {
+namespace detail {
template <size_t MaxElements>
struct default_min_elements_s
@@ -46,7 +46,7 @@ inline size_t default_min_elements_d_calc(size_t max_elements, size_t min_elemen
size_t raw_value = (max_elements * 3) / 10;
return 1 <= raw_value ? raw_value : 1;
}
-
+
return min_elements;
}
@@ -67,7 +67,7 @@ inline size_t default_rstar_reinserted_elements_d_calc(size_t max_elements, size
{
return (max_elements * 3) / 10;
}
-
+
return reinserted_elements;
}
diff --git a/boost/geometry/index/predicates.hpp b/boost/geometry/index/predicates.hpp
index 6da0d0ec5d..9adf3fa853 100644
--- a/boost/geometry/index/predicates.hpp
+++ b/boost/geometry/index/predicates.hpp
@@ -2,7 +2,7 @@
//
// Spatial query predicates
//
-// Copyright (c) 2011-2018 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2022 Adam Wulkiewicz, Lodz, Poland.
//
// This file was modified by Oracle on 2019-2021.
// Modifications copyright (c) 2019-2021 Oracle and/or its affiliates.
@@ -15,6 +15,12 @@
#ifndef BOOST_GEOMETRY_INDEX_PREDICATES_HPP
#define BOOST_GEOMETRY_INDEX_PREDICATES_HPP
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_PREDICATES
+#define BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_PREDICATES
+#endif
+#endif
+
#include <boost/geometry/index/detail/predicates.hpp>
#include <boost/geometry/util/tuples.hpp>
@@ -212,7 +218,7 @@ overlaps(Geometry const& g)
>(g);
}
-#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_PREDICATES
/*!
\brief Generate \c touches() predicate.
@@ -240,7 +246,7 @@ touches(Geometry const& g)
>(g);
}
-#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_PREDICATES
/*!
\brief Generate \c within() predicate.
@@ -294,10 +300,8 @@ 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
@@ -343,7 +347,7 @@ nearest(Geometry const& geometry, std::size_t k)
return detail::predicates::nearest<Geometry>(geometry, k);
}
-#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_PREDICATES
/*!
\brief Generate path() predicate.
@@ -373,7 +377,7 @@ path(SegmentOrLinestring const& linestring, std::size_t k)
return detail::predicates::path<SegmentOrLinestring>(linestring, k);
}
-#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+#endif // BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_PREDICATES
namespace detail { namespace predicates {
@@ -417,7 +421,7 @@ operator&&(std::tuple<Preds...> const& t, Pred const& p)
std::tuple<Preds...>, Pred
>::apply(t, p);
}
-
+
}} // namespace detail::predicates
}}} // namespace boost::geometry::index
diff --git a/boost/geometry/index/rtree.hpp b/boost/geometry/index/rtree.hpp
index 2b7e3811d5..425dae965a 100644
--- a/boost/geometry/index/rtree.hpp
+++ b/boost/geometry/index/rtree.hpp
@@ -3,7 +3,7 @@
// R-tree implementation
//
// Copyright (c) 2008 Federico J. Fernandez.
-// Copyright (c) 2011-2019 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2011-2023 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2020 Caian Benedicto, Campinas, Brazil.
//
// This file was modified by Oracle on 2019-2021.
@@ -23,7 +23,6 @@
// Boost
#include <boost/container/new_allocator.hpp>
-#include <boost/move/move.hpp>
#include <boost/tuple/tuple.hpp>
// Boost.Geometry
@@ -90,7 +89,15 @@
#include <boost/geometry/index/detail/rtree/query_iterators.hpp>
#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
-// serialization
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_SERIALIZATION
+#define BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_SERIALIZATION
+#endif
+#ifndef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_ITERATORS
+#define BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_ITERATORS
+#endif
+#endif
+
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_SERIALIZATION
#include <boost/geometry/index/detail/serialization.hpp>
#endif
@@ -129,10 +136,9 @@ Predefined algorithms with run-time parameters are:
\li \c boost::geometry::index::dynamic_rstar.
\par IndexableGetter
-The object of IndexableGetter type translates from Value to Indexable each time
-r-tree requires it. This means that this operation is done for each Value
-access. Therefore the IndexableGetter should return the Indexable by
-a reference type. The Indexable should not be calculated since it could harm
+An object of IndexableGetter type translates from Value to Indexable each time
+r-tree requires it. This operation is done for each Value access.
+The Indexable should not be calculated each time since it could harm
the performance. The default IndexableGetter can translate all types adapted
to Point, Box or Segment concepts (called Indexables). Furthermore, it can
handle <tt>std::pair<Indexable, T></tt>, <tt>std::tuple<Indexable, ...></tt>
@@ -165,8 +171,6 @@ template
>
class rtree
{
- BOOST_COPYABLE_AND_MOVABLE(rtree)
-
public:
/*! \brief The type of Value stored in the container. */
typedef Value value_type;
@@ -264,10 +268,10 @@ private:
members_holder(IndGet const& ind_get,
ValEq const& val_eq,
Parameters const& parameters,
- BOOST_FWD_REF(Alloc) alloc)
+ Alloc&& alloc)
: translator_type(ind_get, val_eq)
, Parameters(parameters)
- , allocators_type(boost::forward<Alloc>(alloc))
+ , allocators_type(std::forward<Alloc>(alloc))
, values_count(0)
, leafs_level(0)
, root(0)
@@ -301,7 +305,7 @@ private:
node_pointer root;
};
- typedef typename members_holder::translator_type translator_type;
+ typedef typename members_holder::translator_type translator_type;
typedef typename members_holder::options_type options_type;
typedef typename members_holder::allocators_type allocators_type;
typedef typename members_holder::node node;
@@ -312,7 +316,7 @@ private:
typedef typename members_holder::allocator_traits_type allocator_traits_type;
friend class detail::rtree::utilities::view<rtree>;
-#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_SERIALIZATION
friend class detail::rtree::private_view<rtree>;
friend class detail::rtree::const_private_view<rtree>;
#endif
@@ -598,7 +602,7 @@ public:
/*!
\brief The copy constructor.
- It uses parameters, translator and allocator from the source tree.
+ It uses parameters, observers and allocator from the source tree.
\param src The rtree which content will be copied.
@@ -619,7 +623,7 @@ public:
/*!
\brief The copy constructor.
- It uses Parameters and translator from the source tree.
+ It uses parameters and observers from the source tree.
\param src The rtree which content will be copied.
\param allocator The allocator which will be used.
@@ -640,18 +644,18 @@ public:
/*!
\brief The moving constructor.
- It uses parameters, translator and allocator from the source tree.
+ It uses parameters, observers 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)
+ inline rtree(rtree&& src)
: m_members(src.m_members.indexable_getter(),
src.m_members.equal_to(),
src.m_members.parameters(),
- boost::move(src.m_members.allocators()))
+ std::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);
@@ -661,7 +665,7 @@ public:
/*!
\brief The moving constructor.
- It uses parameters and translator from the source tree.
+ It uses parameters and observers from the source tree.
\param src The rtree which content will be moved.
\param allocator The allocator.
@@ -671,7 +675,7 @@ public:
\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)
+ inline rtree(rtree&& src, allocator_type const& allocator)
: m_members(src.m_members.indexable_getter(),
src.m_members.equal_to(),
src.m_members.parameters(),
@@ -692,7 +696,7 @@ public:
/*!
\brief The assignment operator.
- It uses parameters and translator from the source tree.
+ It uses parameters and observers from the source tree.
\param src The rtree which content will be copied.
@@ -701,7 +705,7 @@ public:
\li If allocation throws.
\li If allocation throws or returns invalid value.
*/
- inline rtree & operator=(BOOST_COPY_ASSIGN_REF(rtree) src)
+ inline rtree & operator=(rtree const& src)
{
if ( &src != this )
{
@@ -711,11 +715,11 @@ public:
// 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 std::integral_constant<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());
@@ -730,7 +734,7 @@ public:
/*!
\brief The moving assignment.
- It uses parameters and translator from the source tree.
+ It uses parameters and observers from the source tree.
\param src The rtree which content will be moved.
@@ -739,13 +743,13 @@ public:
\li If Value copy constructor throws.
\li If allocation throws or returns invalid value.
*/
- inline rtree & operator=(BOOST_RV_REF(rtree) src)
+ inline rtree & operator=(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);
@@ -761,7 +765,7 @@ public:
// 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 std::integral_constant<bool,
allocator_traits_type::propagate_on_container_move_assignment::value
> propagate;
@@ -782,7 +786,7 @@ public:
/*!
\brief Swaps contents of two rtrees.
- Parameters, translator and allocators are swapped as well.
+ Parameters, observers and allocators are swapped as well.
\param other The rtree which content will be swapped with this rtree content.
@@ -794,11 +798,11 @@ public:
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 std::integral_constant<bool,
allocator_traits_type::propagate_on_container_swap::value
> propagate;
@@ -995,7 +999,7 @@ public:
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::contains(),
\li \c boost::geometry::index::covered_by(),
@@ -1015,7 +1019,7 @@ public:
\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().
@@ -1026,7 +1030,7 @@ public:
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&&().
@@ -1079,17 +1083,9 @@ public:
template <typename Predicates, typename OutIter>
size_type query(Predicates const& predicates, OutIter out_it) const
{
- if ( !m_members.root )
- return 0;
-
- static const std::size_t distance_predicates_count = detail::predicates_count_distance<Predicates>::value;
- static const bool is_distance_predicate = 0 < distance_predicates_count;
- BOOST_GEOMETRY_STATIC_ASSERT((distance_predicates_count <= 1),
- "Only one distance predicate can be passed.",
- Predicates);
-
- return query_dispatch(predicates, out_it,
- std::integral_constant<bool, is_distance_predicate>());
+ return m_members.root
+ ? query_dispatch(predicates, out_it)
+ : 0;
}
/*!
@@ -1099,7 +1095,7 @@ public:
For the information about predicates which may be passed to this method see query().
\par Example
- \verbatim
+ \verbatim
for ( Rtree::const_query_iterator it = tree.qbegin(bgi::nearest(pt, 10000)) ;
it != tree.qend() ; ++it )
{
@@ -1131,7 +1127,7 @@ public:
The modification of the rtree may invalidate the iterators.
\param predicates Predicates.
-
+
\return The iterator pointing at the begin of the query range.
*/
template <typename Predicates>
@@ -1146,7 +1142,7 @@ public:
This method returns an iterator which may be used to check if the query has ended.
\par Example
- \verbatim
+ \verbatim
for ( Rtree::const_query_iterator it = tree.qbegin(bgi::nearest(pt, 10000)) ;
it != tree.qend() ; ++it )
{
@@ -1175,7 +1171,7 @@ public:
\warning
The modification of the rtree may invalidate the iterators.
-
+
\return The iterator pointing at the end of the query range.
*/
const_query_iterator qend() const
@@ -1183,7 +1179,18 @@ public:
return const_query_iterator();
}
-#ifndef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL
+private:
+ template <typename Predicates>
+ using query_iterator_t = std::conditional_t
+ <
+ detail::predicates_count_distance<Predicates>::value == 0,
+ detail::rtree::iterators::spatial_query_iterator<members_holder, Predicates>,
+ detail::rtree::iterators::distance_query_iterator<members_holder, Predicates>
+ >;
+
+#ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL_ITERATORS
+public:
+#else
private:
#endif
/*!
@@ -1191,7 +1198,7 @@ private:
This method returns an iterator which may be used to perform iterative queries.
For the information about predicates which may be passed to this method see query().
-
+
The type of the returned iterator depends on the type of passed Predicates but the iterator of this type
may be assigned to the variable of const_query_iterator type. If you'd like to use the type of the iterator
returned by this method you may get the type e.g. by using C++11 decltype or Boost.Typeof library.
@@ -1236,42 +1243,19 @@ private:
The modification of the rtree may invalidate the iterators.
\param predicates Predicates.
-
+
\return The iterator pointing at the begin of the query range.
*/
template <typename Predicates>
- std::conditional_t
- <
- detail::predicates_count_distance<Predicates>::value == 0,
- detail::rtree::iterators::spatial_query_iterator<members_holder, Predicates>,
- detail::rtree::iterators::distance_query_iterator
- <
- members_holder, Predicates,
- detail::predicates_find_distance<Predicates>::value
- >
- >
- qbegin_(Predicates const& predicates) const
+ query_iterator_t<Predicates> qbegin_(Predicates const& predicates) const
{
- static const std::size_t distance_predicates_count = detail::predicates_count_distance<Predicates>::value;
- BOOST_GEOMETRY_STATIC_ASSERT((distance_predicates_count <= 1),
+ BOOST_GEOMETRY_STATIC_ASSERT((detail::predicates_count_distance<Predicates>::value <= 1),
"Only one distance predicate can be passed.",
Predicates);
- typedef std::conditional_t
- <
- detail::predicates_count_distance<Predicates>::value == 0,
- detail::rtree::iterators::spatial_query_iterator<members_holder, Predicates>,
- detail::rtree::iterators::distance_query_iterator
- <
- members_holder, Predicates,
- detail::predicates_find_distance<Predicates>::value
- >
- > iterator_type;
-
- if ( !m_members.root )
- return iterator_type(m_members.parameters(), m_members.translator(), predicates);
-
- return iterator_type(m_members.root, m_members.parameters(), m_members.translator(), predicates);
+ return m_members.root
+ ? query_iterator_t<Predicates>(m_members, predicates)
+ : query_iterator_t<Predicates>(predicates);
}
/*!
@@ -1279,7 +1263,7 @@ private:
This method returns the iterator which may be used to perform iterative queries. For the information
about the predicates which may be passed to this method see query().
-
+
The type of the returned iterator depends on the type of passed Predicates but the iterator of this type
may be assigned to the variable of const_query_iterator type. If you'd like to use the type of the iterator
returned by this method you may get the type e.g. by using C++11 decltype or Boost.Typeof library.
@@ -1303,39 +1287,17 @@ private:
The modification of the rtree may invalidate the iterators.
\param predicates Predicates.
-
+
\return The iterator pointing at the end of the query range.
*/
template <typename Predicates>
- std::conditional_t
- <
- detail::predicates_count_distance<Predicates>::value == 0,
- detail::rtree::iterators::spatial_query_iterator<members_holder, Predicates>,
- detail::rtree::iterators::distance_query_iterator
- <
- members_holder, Predicates,
- detail::predicates_find_distance<Predicates>::value
- >
- >
- qend_(Predicates const& predicates) const
+ query_iterator_t<Predicates> qend_(Predicates const& predicates) const
{
- static const std::size_t distance_predicates_count = detail::predicates_count_distance<Predicates>::value;
- BOOST_GEOMETRY_STATIC_ASSERT((distance_predicates_count <= 1),
+ BOOST_GEOMETRY_STATIC_ASSERT((detail::predicates_count_distance<Predicates>::value <= 1),
"Only one distance predicate can be passed.",
Predicates);
- typedef std::conditional_t
- <
- detail::predicates_count_distance<Predicates>::value == 0,
- detail::rtree::iterators::spatial_query_iterator<members_holder, Predicates>,
- detail::rtree::iterators::distance_query_iterator
- <
- members_holder, Predicates,
- detail::predicates_find_distance<Predicates>::value
- >
- > iterator_type;
-
- return iterator_type(m_members.parameters(), m_members.translator(), predicates);
+ return query_iterator_t<Predicates>(m_members.parameters(), m_members.translator(), predicates);
}
/*!
@@ -1343,7 +1305,7 @@ private:
This method returns the iterator which may be compared with the iterator returned by qbegin() in order to
check if the query has ended.
-
+
The type of the returned iterator is different than the type returned by qbegin() but the iterator of this type
may be assigned to the variable of const_query_iterator type. If you'd like to use the type of the iterator returned by this
method, which most certainly will be faster than the type-erased iterator, you may get the type
@@ -1384,7 +1346,7 @@ private:
\warning
The modification of the rtree may invalidate the iterators.
-
+
\return The iterator pointing at the end of the query range.
*/
detail::rtree::iterators::end_query_iterator<value_type, allocators_type>
@@ -1436,10 +1398,9 @@ public:
*/
const_iterator begin() const
{
- if ( !m_members.root )
- return const_iterator();
-
- return const_iterator(m_members.root);
+ return m_members.root
+ ? const_iterator(m_members.root)
+ : const_iterator();
}
/*!
@@ -1546,7 +1507,7 @@ public:
/*!
\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.
@@ -1894,15 +1855,16 @@ private:
\par Exception-safety
strong
*/
- template <typename Predicates, typename OutIter>
- size_type query_dispatch(Predicates const& predicates, OutIter out_it, std::false_type /*is_distance_predicate*/) const
+ template
+ <
+ typename Predicates, typename OutIter,
+ std::enable_if_t<(detail::predicates_count_distance<Predicates>::value == 0), int> = 0
+ >
+ size_type query_dispatch(Predicates const& predicates, OutIter out_it) const
{
detail::rtree::visitors::spatial_query<members_holder, Predicates, OutIter>
- find_v(m_members.parameters(), m_members.translator(), predicates, out_it);
-
- detail::rtree::apply_visitor(find_v, *m_members.root);
-
- return find_v.found_count;
+ query(m_members, predicates, out_it);
+ return query.apply(m_members);
}
/*!
@@ -1911,24 +1873,23 @@ private:
\par Exception-safety
strong
*/
- template <typename Predicates, typename OutIter>
- size_type query_dispatch(Predicates const& predicates, OutIter out_it, std::true_type /*is_distance_predicate*/) const
+ template
+ <
+ typename Predicates, typename OutIter,
+ std::enable_if_t<(detail::predicates_count_distance<Predicates>::value > 0), int> = 0
+ >
+ size_type query_dispatch(Predicates const& predicates, OutIter out_it) const
{
- BOOST_GEOMETRY_INDEX_ASSERT(m_members.root, "The root must exist");
-
- static const std::size_t distance_predicate_index = detail::predicates_find_distance<Predicates>::value;
- detail::rtree::visitors::distance_query<
- members_holder,
- Predicates,
- distance_predicate_index,
- OutIter
- > distance_v(m_members.parameters(), m_members.translator(), predicates, out_it);
+ BOOST_GEOMETRY_STATIC_ASSERT((detail::predicates_count_distance<Predicates>::value == 1),
+ "Only one distance predicate can be passed.",
+ Predicates);
- detail::rtree::apply_visitor(distance_v, *m_members.root);
+ detail::rtree::visitors::distance_query<members_holder, Predicates>
+ distance_v(m_members, predicates);
- return distance_v.finish();
+ return distance_v.apply(m_members, out_it);
}
-
+
/*!
\brief Count elements corresponding to value or indexable.
@@ -2117,7 +2078,7 @@ This query function performs spatial and k-nearest neighbor searches. It allows
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::contains(),
\li \c boost::geometry::index::covered_by(),
@@ -2148,7 +2109,7 @@ If the nearest predicate is passed a k-nearest neighbor search will be performed
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&&().
@@ -2198,7 +2159,7 @@ query(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree,
This method returns the iterator which may be used to perform iterative queries. For the information
about the predicates which may be passed to this method see query().
-
+
\par Example
\verbatim
std::for_each(bgi::qbegin(tree, bgi::nearest(pt, 3)), bgi::qend(tree), do_something());
@@ -2218,7 +2179,7 @@ The modification of the rtree may invalidate the iterators.
\param tree The rtree.
\param predicates Predicates.
-
+
\return The iterator pointing at the begin of the query range.
*/
template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator,
@@ -2234,7 +2195,7 @@ qbegin(rtree<Value, Parameters, IndexableGetter, EqualTo, Allocator> const& tree
\brief Returns the query iterator pointing at the end of the query range.
This method returns the iterator which may be used to check if the query has ended.
-
+
\par Example
\verbatim
std::for_each(bgi::qbegin(tree, bgi::nearest(pt, 3)), bgi::qend(tree), do_something());
@@ -2250,7 +2211,7 @@ Nothing
The modification of the rtree may invalidate the iterators.
\ingroup rtree_functions
-
+
\return The iterator pointing at the end of the query range.
*/
template <typename Value, typename Parameters, typename IndexableGetter, typename EqualTo, typename Allocator> inline
diff --git a/boost/geometry/io/dsv/write.hpp b/boost/geometry/io/dsv/write.hpp
index d24255d4a9..5870d21c58 100644
--- a/boost/geometry/io/dsv/write.hpp
+++ b/boost/geometry/io/dsv/write.hpp
@@ -28,8 +28,6 @@
#include <boost/range/end.hpp>
#include <boost/range/value_type.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
-
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/ring_type.hpp>
@@ -170,15 +168,11 @@ struct dsv_range
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)
+ for (auto it = boost::begin(range); it != boost::end(range); ++it)
{
os << (first ? "" : settings.point_separator)
<< settings.point_open;
@@ -218,10 +212,8 @@ struct dsv_poly
dsv_range<ring>::apply(os, exterior_ring(poly), settings);
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(poly);
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ auto const& rings = interior_rings(poly);
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
{
os << settings.list_separator;
dsv_range<ring>::apply(os, *it, settings);
@@ -362,12 +354,6 @@ struct dsv_multi
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,
@@ -376,9 +362,7 @@ struct dsv_multi
os << settings.list_open;
bool first = true;
- for(iterator it = boost::begin(multi);
- it != boost::end(multi);
- ++it, first = false)
+ for(auto it = boost::begin(multi); it != boost::end(multi); ++it, first = false)
{
os << (first ? "" : settings.list_separator);
dispatch_one::apply(os, *it, settings);
diff --git a/boost/geometry/io/svg/svg_mapper.hpp b/boost/geometry/io/svg/svg_mapper.hpp
index aaac850442..76be933c08 100644
--- a/boost/geometry/io/svg/svg_mapper.hpp
+++ b/boost/geometry/io/svg/svg_mapper.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2009-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2015-2021.
// Modifications copyright (c) 2015-2020, Oracle and/or its affiliates.
@@ -18,6 +19,7 @@
#define BOOST_GEOMETRY_IO_SVG_MAPPER_HPP
#include <cstdio>
+#include <memory>
#include <type_traits>
#include <vector>
@@ -25,7 +27,6 @@
#include <boost/algorithm/string/split.hpp>
#include <boost/config.hpp>
#include <boost/noncopyable.hpp>
-#include <boost/scoped_ptr.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -160,10 +161,7 @@ struct svg_map<multi_tag, Multi, SvgPoint>
std::string const& style, double size,
Multi const& multi, TransformStrategy const& strategy)
{
- for (typename boost::range_iterator<Multi const>::type it
- = boost::begin(multi);
- it != boost::end(multi);
- ++it)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
svg_map
<
@@ -290,7 +288,7 @@ class svg_mapper : boost::noncopyable
> transformer_type;
model::box<Point> m_bounding_box;
- boost::scoped_ptr<transformer_type> m_matrix;
+ std::unique_ptr<transformer_type> m_matrix;
std::ostream& m_stream;
SvgCoordinateType const m_width;
@@ -343,7 +341,7 @@ class svg_mapper : boost::noncopyable
}
public :
-
+
/*!
\brief Constructor, initializing the SVG map. Opens and initializes the SVG.
Should be called explicitly.
@@ -466,19 +464,17 @@ public :
{
// 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)
+ std::vector<std::string> split;
+ boost::split(split, s, boost::is_any_of("\n"));
+ for (auto const& item : split)
{
m_stream
<< "<tspan x=\"" << get<0>(map_point) + offset_x
<< "\""
<< " y=\"" << get<1>(map_point) + offset_y
<< "\""
- << ">" << *it << "</tspan>";
+ << ">" << item << "</tspan>";
+ offset_y += lineheight;
}
}
m_stream << "</text>" << std::endl;
diff --git a/boost/geometry/io/svg/write.hpp b/boost/geometry/io/svg/write.hpp
index f372b7adff..a8be963fdf 100644
--- a/boost/geometry/io/svg/write.hpp
+++ b/boost/geometry/io/svg/write.hpp
@@ -29,8 +29,6 @@
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/variant_fwd.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
-
#include <boost/geometry/core/exterior_ring.hpp>
#include <boost/geometry/core/interior_rings.hpp>
#include <boost/geometry/core/ring_type.hpp>
@@ -99,7 +97,7 @@ struct svg_segment
ct y1 = geometry::get<0, 1>(segment);
ct x2 = geometry::get<1, 0>(segment);
ct y2 = geometry::get<1, 1>(segment);
-
+
os << "<line x1=\"" << x1 << "\" y1=\"" << y1
<< "\" x2=\"" << x2 << "\" y2=\"" << y2
<< "\" style=\"" << style << "\"/>";
@@ -117,15 +115,11 @@ struct svg_range
static inline void apply(std::basic_ostream<Char, Traits>& os,
Range const& range, std::string const& style, double)
{
- 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)
+ for (auto it = boost::begin(range); it != boost::end(range); ++it, first = false)
{
os << (first ? "" : " " )
<< geometry::get<0>(*it)
@@ -146,15 +140,12 @@ struct svg_poly
Polygon const& polygon, std::string const& style, double)
{
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)
+ for (auto it = boost::begin(ring); it != boost::end(ring); ++it, first = false)
{
os << (first ? "M" : " L") << " "
<< geometry::get<0>(*it)
@@ -164,15 +155,11 @@ struct svg_poly
// Inner rings:
{
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(polygon);
- for (typename detail::interior_iterator<Polygon const>::type
- rit = boost::begin(rings); rit != boost::end(rings); ++rit)
+ auto const& rings = interior_rings(polygon);
+ for (auto rit = boost::begin(rings); rit != boost::end(rings); ++rit)
{
first = true;
- for (typename detail::interior_ring_iterator<Polygon const>::type
- it = boost::begin(*rit); it != boost::end(*rit);
- ++it, first = false)
+ for (auto it = boost::begin(*rit); it != boost::end(*rit); ++it, first = false)
{
os << (first ? "M" : " L") << " "
<< geometry::get<0>(*it)
@@ -209,14 +196,10 @@ struct svg_multi
static inline void apply(std::basic_ostream<Char, Traits>& os,
MultiGeometry const& multi, std::string const& style, double size)
{
- for (typename boost::range_iterator<MultiGeometry const>::type
- it = boost::begin(multi);
- it != boost::end(multi);
- ++it)
+ for (auto it = boost::begin(multi); it != boost::end(multi); ++it)
{
Policy::apply(os, *it, style, size);
}
-
}
};
diff --git a/boost/geometry/io/wkt/detail/prefix.hpp b/boost/geometry/io/wkt/detail/prefix.hpp
index b566e02aa6..a61b8ae0f6 100644
--- a/boost/geometry/io/wkt/detail/prefix.hpp
+++ b/boost/geometry/io/wkt/detail/prefix.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2007-2022 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
@@ -57,6 +57,20 @@ struct prefix_multipolygon
static inline const char* apply() { return "MULTIPOLYGON"; }
};
+struct prefix_segment
+{
+ static inline const char* apply() { return "SEGMENT"; }
+};
+struct prefix_box
+{
+ static inline const char* apply() { return "BOX"; }
+};
+struct prefix_geometrycollection
+{
+ static inline const char* apply() { return "GEOMETRYCOLLECTION"; }
+};
+
+
}} // namespace wkt::impl
#endif
diff --git a/boost/geometry/io/wkt/detail/wkt_multi.hpp b/boost/geometry/io/wkt/detail/wkt_multi.hpp
index 2b2d1946ad..f332752160 100644
--- a/boost/geometry/io/wkt/detail/wkt_multi.hpp
+++ b/boost/geometry/io/wkt/detail/wkt_multi.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2007-2022 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
@@ -11,46 +11,13 @@
// 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
+#ifndef BOOST_GEOMETRY_IO_WKT_MULTI_HPP
+#define BOOST_GEOMETRY_IO_WKT_MULTI_HPP
#include <boost/geometry/core/tags.hpp>
#include <boost/geometry/domains/gis/io/wkt/write.hpp>
+#include <boost/config/pragma_message.hpp>
+BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
-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
+#endif // BOOST_GEOMETRY_IO_WKT_MULTI_HPP
diff --git a/boost/geometry/io/wkt/read.hpp b/boost/geometry/io/wkt/read.hpp
index ccfb4352cb..a8d0f6a484 100644
--- a/boost/geometry/io/wkt/read.hpp
+++ b/boost/geometry/io/wkt/read.hpp
@@ -1,14 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2007-2022 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2017-2023 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2020 Baidyanath Kundu, Haldia, India
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
-
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -24,14 +23,13 @@
#include <cstddef>
#include <string>
+#include <boost/algorithm/string/predicate.hpp>
#include <boost/lexical_cast.hpp>
-#include <boost/tokenizer.hpp>
-
-#include <boost/algorithm/string.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
+#include <boost/tokenizer.hpp>
#include <boost/throw_exception.hpp>
#include <boost/geometry/algorithms/assign.hpp>
@@ -117,19 +115,26 @@ private :
namespace detail { namespace wkt
{
-typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
+inline auto make_tokenizer(std::string const& wkt)
+{
+ using separator = boost::char_separator<char>;
+ using tokenizer = boost::tokenizer<separator>;
+ const tokenizer tokens(wkt, separator(" \n\t\r", ",()"));
+ return tokens;
+}
template <typename Point,
std::size_t Dimension = 0,
std::size_t DimensionCount = geometry::dimension<Point>::value>
struct parsing_assigner
{
- static inline void apply(tokenizer::iterator& it,
- tokenizer::iterator const& end,
+ template <typename TokenizerIterator>
+ static inline void apply(TokenizerIterator& it,
+ TokenizerIterator const& end,
Point& point,
std::string const& wkt)
{
- typedef typename coordinate_type<Point>::type coordinate_type;
+ using coordinate_type = typename coordinate_type<Point>::type;
// Stop at end of tokens, or at "," ot ")"
bool finished = (it == end || *it == "," || *it == ")");
@@ -167,8 +172,9 @@ struct parsing_assigner
template <typename Point, std::size_t DimensionCount>
struct parsing_assigner<Point, DimensionCount, DimensionCount>
{
- static inline void apply(tokenizer::iterator&,
- tokenizer::iterator const&,
+ template <typename TokenizerIterator>
+ static inline void apply(TokenizerIterator&,
+ TokenizerIterator const&,
Point&,
std::string const&)
{
@@ -226,9 +232,9 @@ template <typename Point>
struct container_inserter
{
// Version with output iterator
- template <typename OutputIterator>
- static inline void apply(tokenizer::iterator& it,
- tokenizer::iterator const& end,
+ template <typename TokenizerIterator, typename OutputIterator>
+ static inline void apply(TokenizerIterator& it,
+ TokenizerIterator const& end,
std::string const& wkt,
OutputIterator out)
{
@@ -258,10 +264,8 @@ template <typename Geometry,
closure_selector Closure = closure<Geometry>::value>
struct stateful_range_appender
{
- typedef typename geometry::point_type<Geometry>::type point_type;
-
// NOTE: Geometry is a reference
- inline void append(Geometry geom, point_type const& point, bool)
+ inline void append(Geometry geom, typename geometry::point_type<Geometry>::type const& point, bool)
{
geometry::append(geom, point);
}
@@ -270,13 +274,13 @@ struct stateful_range_appender
template <typename Geometry>
struct stateful_range_appender<Geometry, open>
{
- typedef typename geometry::point_type<Geometry>::type point_type;
- typedef typename boost::range_size
+ using point_type = typename geometry::point_type<Geometry>::type;
+ using size_type = typename boost::range_size
<
typename util::remove_cptrref<Geometry>::type
- >::type size_type;
+ >::type;
- BOOST_STATIC_ASSERT(( util::is_ring<Geometry>::value ));
+ BOOST_STATIC_ASSERT((util::is_ring<Geometry>::value));
inline stateful_range_appender()
: pt_index(0)
@@ -290,11 +294,10 @@ struct stateful_range_appender<Geometry, open>
if (pt_index == 0)
{
first_point = point;
- //should_append = true;
}
else
{
- // NOTE: if there is not enough Points, they're always appended
+ // NOTE: if there are not enough Points, they're always appended
should_append
= is_next_expected
|| pt_index < core_detail::closure::minimum_ring_size<open>::value
@@ -312,10 +315,10 @@ private:
static inline bool disjoint(point_type const& p1, point_type const& p2)
{
// TODO: pass strategy
- typedef typename strategies::io::services::default_strategy
+ using strategy_type = typename strategies::io::services::default_strategy
<
point_type
- >::type strategy_type;
+ >::type;
return detail::disjoint::disjoint_point_point(p1, p2, strategy_type());
}
@@ -328,10 +331,11 @@ private:
template <typename Geometry>
struct container_appender
{
- typedef typename geometry::point_type<Geometry>::type point_type;
+ using point_type = typename geometry::point_type<Geometry>::type;
- static inline void apply(tokenizer::iterator& it,
- tokenizer::iterator const& end,
+ template <typename TokenizerIterator>
+ static inline void apply(TokenizerIterator& it,
+ TokenizerIterator const& end,
std::string const& wkt,
Geometry out)
{
@@ -367,8 +371,9 @@ struct container_appender
template <typename P>
struct point_parser
{
- static inline void apply(tokenizer::iterator& it,
- tokenizer::iterator const& end,
+ template <typename TokenizerIterator>
+ static inline void apply(TokenizerIterator& it,
+ TokenizerIterator const& end,
std::string const& wkt,
P& point)
{
@@ -382,8 +387,9 @@ struct point_parser
template <typename Geometry>
struct linestring_parser
{
- static inline void apply(tokenizer::iterator& it,
- tokenizer::iterator const& end,
+ template <typename TokenizerIterator>
+ static inline void apply(TokenizerIterator& it,
+ TokenizerIterator const& end,
std::string const& wkt,
Geometry& geometry)
{
@@ -395,8 +401,9 @@ struct linestring_parser
template <typename Ring>
struct ring_parser
{
- static inline void apply(tokenizer::iterator& it,
- tokenizer::iterator const& end,
+ template <typename TokenizerIterator>
+ static inline void apply(TokenizerIterator& it,
+ TokenizerIterator const& end,
std::string const& wkt,
Ring& ring)
{
@@ -417,11 +424,12 @@ struct ring_parser
template <typename Polygon>
struct polygon_parser
{
- typedef typename ring_return_type<Polygon>::type ring_return_type;
- typedef container_appender<ring_return_type> appender;
+ using ring_return_type = typename ring_return_type<Polygon>::type;
+ using appender = container_appender<ring_return_type>;
- static inline void apply(tokenizer::iterator& it,
- tokenizer::iterator const& end,
+ template <typename TokenizerIterator>
+ static inline void apply(TokenizerIterator& it,
+ TokenizerIterator const& end,
std::string const& wkt,
Polygon& poly)
{
@@ -457,7 +465,8 @@ struct polygon_parser
};
-inline bool one_of(tokenizer::iterator const& it,
+template <typename TokenizerIterator>
+inline bool one_of(TokenizerIterator const& it,
std::string const& value,
bool& is_present)
{
@@ -469,7 +478,8 @@ inline bool one_of(tokenizer::iterator const& it,
return false;
}
-inline bool one_of(tokenizer::iterator const& it,
+template <typename TokenizerIterator>
+inline bool one_of(TokenizerIterator const& it,
std::string const& value,
bool& present1,
bool& present2)
@@ -484,8 +494,9 @@ inline bool one_of(tokenizer::iterator const& it,
}
-inline void handle_empty_z_m(tokenizer::iterator& it,
- tokenizer::iterator const& end,
+template <typename TokenizerIterator>
+inline void handle_empty_z_m(TokenizerIterator& it,
+ TokenizerIterator const& end,
bool& has_empty,
bool& has_z,
bool& has_m)
@@ -535,9 +546,9 @@ struct dimension<Geometry, geometry_collection_tag>
\brief Internal, starts parsing
\param geometry_name string to compare with first token
*/
-template <typename Geometry>
-inline bool initialize(tokenizer::iterator& it,
- tokenizer::iterator const& end,
+template <typename Geometry, typename TokenizerIterator>
+inline bool initialize(TokenizerIterator& it,
+ TokenizerIterator const& end,
std::string const& wkt,
std::string const& geometry_name)
{
@@ -552,8 +563,8 @@ inline bool initialize(tokenizer::iterator& it,
// Silence warning C4127: conditional expression is constant
#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable : 4127)
+#pragma warning(push)
+#pragma warning(disable : 4127)
#endif
if (has_z && dimension<Geometry>::value < 3)
@@ -570,7 +581,7 @@ inline bool initialize(tokenizer::iterator& it,
return false;
}
// M is ignored at all.
-
+
return true;
}
@@ -582,17 +593,18 @@ struct geometry_parser
{
geometry::clear(geometry);
- tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
- tokenizer::iterator it = tokens.begin();
- tokenizer::iterator const end = tokens.end();
+ auto const tokens{make_tokenizer(wkt)};
+ auto it = tokens.begin();
+ auto const end = tokens.end();
apply(it, end, wkt, geometry);
check_end(it, end, wkt);
}
- static inline void apply(tokenizer::iterator& it,
- tokenizer::iterator const& end,
+ template <typename TokenizerIterator>
+ static inline void apply(TokenizerIterator& it,
+ TokenizerIterator const& end,
std::string const& wkt,
Geometry& geometry)
{
@@ -611,17 +623,18 @@ struct multi_parser
{
traits::clear<MultiGeometry>::apply(geometry);
- tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
- tokenizer::iterator it = tokens.begin();
- tokenizer::iterator const end = tokens.end();
+ auto const tokens{make_tokenizer(wkt)};
+ auto it = tokens.begin();
+ auto const end = tokens.end();
apply(it, end, wkt, geometry);
check_end(it, end, wkt);
}
- static inline void apply(tokenizer::iterator& it,
- tokenizer::iterator const& end,
+ template <typename TokenizerIterator>
+ static inline void apply(TokenizerIterator& it,
+ TokenizerIterator const& end,
std::string const& wkt,
MultiGeometry& geometry)
{
@@ -652,8 +665,9 @@ struct multi_parser
template <typename P>
struct noparenthesis_point_parser
{
- static inline void apply(tokenizer::iterator& it,
- tokenizer::iterator const& end,
+ template <typename TokenizerIterator>
+ static inline void apply(TokenizerIterator& it,
+ TokenizerIterator const& end,
std::string const& wkt,
P& point)
{
@@ -668,17 +682,18 @@ struct multi_point_parser
{
traits::clear<MultiGeometry>::apply(geometry);
- tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
- tokenizer::iterator it = tokens.begin();
- tokenizer::iterator const end = tokens.end();
+ auto const tokens{make_tokenizer(wkt)};
+ auto it = tokens.begin();
+ auto const end = tokens.end();
apply(it, end, wkt, geometry);
check_end(it, end, wkt);
}
- static inline void apply(tokenizer::iterator& it,
- tokenizer::iterator const& end,
+ template <typename TokenizerIterator>
+ static inline void apply(TokenizerIterator& it,
+ TokenizerIterator const& end,
std::string const& wkt,
MultiGeometry& geometry)
{
@@ -735,17 +750,18 @@ struct box_parser
{
static inline void apply(std::string const& wkt, Box& box)
{
- tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
- tokenizer::iterator it = tokens.begin();
- tokenizer::iterator end = tokens.end();
+ auto const tokens{make_tokenizer(wkt)};
+ auto it = tokens.begin();
+ auto const end = tokens.end();
apply(it, end, wkt, box);
check_end(it, end, wkt);
}
- static inline void apply(tokenizer::iterator& it,
- tokenizer::iterator const& end,
+ template <typename TokenizerIterator>
+ static inline void apply(TokenizerIterator& it,
+ TokenizerIterator const& end,
std::string const& wkt,
Box& box)
{
@@ -772,7 +788,7 @@ struct box_parser
BOOST_THROW_EXCEPTION(read_wkt_exception("Should start with 'POLYGON' or 'BOX'", wkt));
}
- typedef typename point_type<Box>::type point_type;
+ using point_type = typename point_type<Box>::type;
std::vector<point_type> points;
container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points));
@@ -815,21 +831,24 @@ 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();
+ auto const tokens{make_tokenizer(wkt)};
+ auto it = tokens.begin();
+ auto const end = tokens.end();
apply(it, end, wkt, segment);
check_end(it, end, wkt);
}
- static inline void apply(tokenizer::iterator& it,
- tokenizer::iterator const& end,
+ template <typename TokenizerIterator>
+ static inline void apply(TokenizerIterator& it,
+ TokenizerIterator const& end,
std::string const& wkt,
Segment& segment)
{
- if (it != end && (boost::iequals(*it, "SEGMENT") || boost::iequals(*it, "LINESTRING")))
+ if (it != end
+ && (boost::iequals(*it, prefix_segment::apply())
+ || boost::iequals(*it, prefix_linestring::apply())))
{
++it;
}
@@ -838,7 +857,7 @@ struct segment_parser
BOOST_THROW_EXCEPTION(read_wkt_exception("Should start with 'LINESTRING' or 'SEGMENT'", wkt));
}
- typedef typename point_type<Segment>::type point_type;
+ using point_type = typename point_type<Segment>::type;
std::vector<point_type> points;
container_inserter<point_type>::apply(it, end, wkt, std::back_inserter(points));
@@ -881,54 +900,67 @@ template
>
struct dynamic_readwkt_caller
{
- static inline void apply(tokenizer::iterator& it,
- tokenizer::iterator const& end,
+ template <typename TokenizerIterator>
+ static inline void apply(TokenizerIterator& it,
+ TokenizerIterator const& end,
std::string const& wkt,
Geometry& geometry)
{
- if (boost::iequals(*it, "POINT"))
+ static const char* tag_point = prefix_point::apply();
+ static const char* tag_linestring = prefix_linestring::apply();
+ static const char* tag_polygon = prefix_polygon::apply();
+
+ static const char* tag_multi_point = prefix_multipoint::apply();
+ static const char* tag_multi_linestring = prefix_multilinestring::apply();
+ static const char* tag_multi_polygon = prefix_multipolygon::apply();
+
+ static const char* tag_segment = prefix_segment::apply();
+ static const char* tag_box = prefix_box::apply();
+ static const char* tag_gc = prefix_geometrycollection::apply();
+
+ if (boost::iequals(*it, tag_point))
{
- parse_geometry<util::is_point>("POINT", it, end, wkt, geometry);
+ parse_geometry<util::is_point>(tag_point, it, end, wkt, geometry);
}
- else if (boost::iequals(*it, "MULTIPOINT"))
+ else if (boost::iequals(*it, tag_multi_point))
{
- parse_geometry<util::is_multi_point>("MULTIPOINT", it, end, wkt, geometry);
+ parse_geometry<util::is_multi_point>(tag_multi_point, it, end, wkt, geometry);
}
- else if (boost::iequals(*it, "SEGMENT"))
+ else if (boost::iequals(*it, tag_segment))
{
- parse_geometry<util::is_segment>("SEGMENT", it, end, wkt, geometry);
+ parse_geometry<util::is_segment>(tag_segment, it, end, wkt, geometry);
}
- else if (boost::iequals(*it, "LINESTRING"))
+ else if (boost::iequals(*it, tag_linestring))
{
- parse_geometry<util::is_linestring>("LINESTRING", it, end, wkt, geometry, false)
- || parse_geometry<util::is_segment>("LINESTRING", it, end, wkt, geometry);
+ parse_geometry<util::is_linestring>(tag_linestring, it, end, wkt, geometry, false)
+ || parse_geometry<util::is_segment>(tag_linestring, it, end, wkt, geometry);
}
- else if (boost::iequals(*it, "MULTILINESTRING"))
+ else if (boost::iequals(*it, tag_multi_linestring))
{
- parse_geometry<util::is_multi_linestring>("MULTILINESTRING", it, end, wkt, geometry);
+ parse_geometry<util::is_multi_linestring>(tag_multi_linestring, it, end, wkt, geometry);
}
- else if (boost::iequals(*it, "BOX"))
+ else if (boost::iequals(*it, tag_box))
{
- parse_geometry<util::is_box>("BOX", it, end, wkt, geometry);
+ parse_geometry<util::is_box>(tag_box, it, end, wkt, geometry);
}
- else if (boost::iequals(*it, "POLYGON"))
+ else if (boost::iequals(*it, tag_polygon))
{
- parse_geometry<util::is_polygon>("POLYGON", it, end, wkt, geometry, false)
- || parse_geometry<util::is_ring>("POLYGON", it, end, wkt, geometry, false)
- || parse_geometry<util::is_box>("POLYGON", it, end, wkt, geometry);
+ parse_geometry<util::is_polygon>(tag_polygon, it, end, wkt, geometry, false)
+ || parse_geometry<util::is_ring>(tag_polygon, it, end, wkt, geometry, false)
+ || parse_geometry<util::is_box>(tag_polygon, it, end, wkt, geometry);
}
- else if (boost::iequals(*it, "MULTIPOLYGON"))
+ else if (boost::iequals(*it, tag_multi_polygon))
{
- parse_geometry<util::is_multi_polygon>("MULTIPOLYGON", it, end, wkt, geometry);
+ parse_geometry<util::is_multi_polygon>(tag_multi_polygon, it, end, wkt, geometry);
}
- else if (boost::iequals(*it, "GEOMETRYCOLLECTION"))
+ else if (boost::iequals(*it, tag_gc))
{
- parse_geometry<util::is_geometry_collection>("GEOMETRYCOLLECTION", it, end, wkt, geometry);
+ parse_geometry<util::is_geometry_collection>(tag_gc, it, end, wkt, geometry);
}
else
{
BOOST_THROW_EXCEPTION(read_wkt_exception(
- "Should start with geometry's name, e.g. 'POINT', 'LINESTRING', 'POLYGON', etc.",
+ "Should start with geometry's type, for example 'POINT', 'LINESTRING', 'POLYGON'",
wkt));
}
}
@@ -937,6 +969,7 @@ private:
template
<
template <typename> class UnaryPred,
+ typename TokenizerIterator,
typename Geom = typename util::sequence_find_if
<
typename traits::geometry_types<Geometry>::type, UnaryPred
@@ -944,8 +977,8 @@ private:
std::enable_if_t<! std::is_void<Geom>::value, int> = 0
>
static bool parse_geometry(const char * ,
- tokenizer::iterator& it,
- tokenizer::iterator const& end,
+ TokenizerIterator& it,
+ TokenizerIterator const& end,
std::string const& wkt,
Geometry& geometry,
bool = true)
@@ -959,6 +992,7 @@ private:
template
<
template <typename> class UnaryPred,
+ typename TokenizerIterator,
typename Geom = typename util::sequence_find_if
<
typename traits::geometry_types<Geometry>::type, UnaryPred
@@ -966,8 +1000,8 @@ private:
std::enable_if_t<std::is_void<Geom>::value, int> = 0
>
static bool parse_geometry(const char * name,
- tokenizer::iterator& ,
- tokenizer::iterator const& ,
+ TokenizerIterator& ,
+ TokenizerIterator const& ,
std::string const& wkt,
Geometry& ,
bool throw_on_misfit = true)
@@ -1084,13 +1118,13 @@ struct read_wkt<DynamicGeometry, dynamic_geometry_tag>
{
static inline void apply(std::string const& wkt, DynamicGeometry& dynamic_geometry)
{
- detail::wkt::tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
- detail::wkt::tokenizer::iterator it = tokens.begin();
- detail::wkt::tokenizer::iterator end = tokens.end();
+ auto tokens{detail::wkt::make_tokenizer(wkt)};
+ auto it = tokens.begin();
+ auto const end = tokens.end();
if (it == end)
{
BOOST_THROW_EXCEPTION(read_wkt_exception(
- "Should start with geometry's name, e.g. 'POINT', 'LINESTRING', 'POLYGON', etc.",
+ "Should start with geometry's type, for example 'POINT', 'LINESTRING', 'POLYGON'",
wkt));
}
@@ -1111,21 +1145,23 @@ struct read_wkt<Geometry, geometry_collection_tag>
{
range::clear(geometry);
- detail::wkt::tokenizer tokens(wkt, boost::char_separator<char>(" ", ",()"));
- detail::wkt::tokenizer::iterator it = tokens.begin();
- detail::wkt::tokenizer::iterator const end = tokens.end();
+ auto tokens{detail::wkt::make_tokenizer(wkt)};
+ auto it = tokens.begin();
+ auto const end = tokens.end();
apply(it, end, wkt, geometry);
detail::wkt::check_end(it, end, wkt);
}
- static inline void apply(detail::wkt::tokenizer::iterator& it,
- detail::wkt::tokenizer::iterator const& end,
+ template <typename TokenizerIterator>
+ static inline void apply(TokenizerIterator& it,
+ TokenizerIterator const& end,
std::string const& wkt,
Geometry& geometry)
{
- if (detail::wkt::initialize<Geometry>(it, end, wkt, "GEOMETRYCOLLECTION"))
+ if (detail::wkt::initialize<Geometry>(it, end, wkt,
+ detail::wkt::prefix_geometrycollection::apply()))
{
detail::wkt::handle_open_parenthesis(it, end, wkt);
diff --git a/boost/geometry/io/wkt/write.hpp b/boost/geometry/io/wkt/write.hpp
index aa52d072f3..90f69a54a2 100644
--- a/boost/geometry/io/wkt/write.hpp
+++ b/boost/geometry/io/wkt/write.hpp
@@ -1,14 +1,13 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2007-2017 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2007-2022 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2017 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2017 Mateusz Loskot, London, UK.
-// Copyright (c) 2014-2017 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2014-2023 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2020 Baidyanath Kundu, Haldia, India.
// This file was modified by Oracle on 2015-2021.
// Modifications copyright (c) 2015-2021, Oracle and/or its affiliates.
-
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -22,16 +21,15 @@
#ifndef BOOST_GEOMETRY_IO_WKT_WRITE_HPP
#define BOOST_GEOMETRY_IO_WKT_WRITE_HPP
+#include <array>
#include <ostream>
#include <string>
-#include <boost/array.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
-#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/convert.hpp>
#include <boost/geometry/algorithms/detail/disjoint/point_point.hpp>
@@ -52,7 +50,7 @@
#include <boost/geometry/strategies/io/geographic.hpp>
#include <boost/geometry/strategies/io/spherical.hpp>
-#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/constexpr.hpp>
#include <boost/geometry/util/type_traits.hpp>
@@ -61,8 +59,8 @@ 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)
+#pragma warning(push)
+#pragma warning(disable : 4512)
#endif
#ifndef DOXYGEN_NO_DETAIL
@@ -88,32 +86,6 @@ struct stream_coordinate<P, Count, Count>
{}
};
-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
*/
@@ -131,14 +103,13 @@ struct wkt_point
/*!
\brief Stream ranges as WKT
-\note policy is used to stream prefix/postfix, enabling derived classes to override this
*/
template
<
typename Range,
- bool ForceClosurePossible,
typename PrefixPolicy,
- typename SuffixPolicy
+ bool ForceClosurePossible = false,
+ bool WriteDoubleBrackets = false
>
struct wkt_range
{
@@ -146,52 +117,62 @@ struct wkt_range
static inline void apply(std::basic_ostream<Char, Traits>& os,
Range const& range, bool force_closure = ForceClosurePossible)
{
- typedef typename boost::range_iterator<Range const>::type iterator_type;
-
- typedef stream_coordinate
+ using stream_type = stream_coordinate
<
point_type, 0, dimension<point_type>::type::value
- > stream_type;
+ >;
bool first = true;
os << PrefixPolicy::apply();
+ os << "(";
- // TODO: check EMPTY here
-
- iterator_type begin = boost::begin(range);
- iterator_type end = boost::end(range);
- for (iterator_type it = begin; it != end; ++it)
+ if (boost::size(range) > 0)
{
- os << (first ? "" : ",");
- stream_type::apply(os, *it);
- first = false;
- }
+ if BOOST_GEOMETRY_CONSTEXPR (WriteDoubleBrackets)
+ {
+ os << "(";
+ }
+ auto begin = boost::begin(range);
+ auto const end = boost::end(range);
+ for (auto it = begin; it != end; ++it)
+ {
+ os << (first ? "" : ",");
+ stream_type::apply(os, *it);
+ first = false;
+ }
- // optionally, close range to ring by repeating the first point
- if (BOOST_GEOMETRY_CONDITION(ForceClosurePossible)
- && force_closure
- && boost::size(range) > 1
- && wkt_range::disjoint(*begin, *(end - 1)))
- {
- os << ",";
- stream_type::apply(os, *begin);
+ // optionally, close range to ring by repeating the first point
+ if BOOST_GEOMETRY_CONSTEXPR (ForceClosurePossible)
+ {
+ if (force_closure
+ && boost::size(range) > 1
+ && wkt_range::disjoint(*begin, *(end - 1)))
+ {
+ os << ",";
+ stream_type::apply(os, *begin);
+ }
+ }
+ if BOOST_GEOMETRY_CONSTEXPR (WriteDoubleBrackets)
+ {
+ os << ")";
+ }
}
- os << SuffixPolicy::apply();
+ os << ")";
}
private:
- typedef typename boost::range_value<Range>::type point_type;
+ using point_type = typename boost::range_value<Range>::type;
static inline bool disjoint(point_type const& p1, point_type const& p2)
{
// TODO: pass strategy
- typedef typename strategies::io::services::default_strategy
+ using strategy_type = typename strategies::io::services::default_strategy
<
point_type
- >::type strategy_type;
+ >::type;
return detail::disjoint::disjoint_point_point(p1, p2, strategy_type());
}
@@ -206,9 +187,8 @@ struct wkt_sequence
: wkt_range
<
Range,
- ForceClosurePossible,
- opening_parenthesis,
- closing_parenthesis
+ prefix_null,
+ ForceClosurePossible
>
{};
@@ -219,20 +199,29 @@ struct wkt_poly
static inline void apply(std::basic_ostream<Char, Traits>& os,
Polygon const& poly, bool force_closure)
{
- typedef typename ring_type<Polygon const>::type ring;
+ using ring = typename ring_type<Polygon const>::type;
+
+ auto const& exterior = exterior_ring(poly);
+ auto const& rings = interior_rings(poly);
+
+ std::size_t point_count = boost::size(exterior);
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
+ {
+ point_count += boost::size(*it);
+ }
os << PrefixPolicy::apply();
- // TODO: check EMPTY here
- os << "(";
- wkt_sequence<ring>::apply(os, exterior_ring(poly), force_closure);
- typename interior_return_type<Polygon const>::type
- rings = interior_rings(poly);
- for (typename detail::interior_iterator<Polygon const>::type
- it = boost::begin(rings); it != boost::end(rings); ++it)
+ os << "(";
+ if (point_count > 0)
{
- os << ",";
- wkt_sequence<ring>::apply(os, *it, force_closure);
+ wkt_sequence<ring>::apply(os, exterior, force_closure);
+
+ for (auto it = boost::begin(rings); it != boost::end(rings); ++it)
+ {
+ os << ",";
+ wkt_sequence<ring>::apply(os, *it, force_closure);
+ }
}
os << ")";
}
@@ -247,13 +236,9 @@ struct wkt_multi
Multi const& geometry, bool force_closure)
{
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)
+ for (auto it = boost::begin(geometry); it != boost::end(geometry); ++it)
{
if (it != boost::begin(geometry))
{
@@ -269,7 +254,7 @@ struct wkt_multi
template <typename Box>
struct wkt_box
{
- typedef typename point_type<Box>::type point_type;
+ using point_type = typename point_type<Box>::type;
template <typename Char, typename Traits>
static inline void apply(std::basic_ostream<Char, Traits>& os,
@@ -313,14 +298,14 @@ struct wkt_box
template <typename Segment>
struct wkt_segment
{
- typedef typename point_type<Segment>::type point_type;
+ using point_type = typename point_type<Segment>::type;
template <typename Char, typename Traits>
static inline void apply(std::basic_ostream<Char, Traits>& os,
Segment const& segment, bool)
{
// Convert to two points, then stream
- typedef boost::array<point_type, 2> sequence;
+ using sequence = std::array<point_type, 2>;
sequence points;
geometry::detail::assign_point_from_index<0>(segment, points[0]);
@@ -363,9 +348,7 @@ struct wkt<Linestring, linestring_tag>
: detail::wkt::wkt_range
<
Linestring,
- false,
- detail::wkt::prefix_linestring_par,
- detail::wkt::closing_parenthesis
+ detail::wkt::prefix_linestring
>
{};
@@ -395,9 +378,9 @@ struct wkt<Ring, ring_tag>
: detail::wkt::wkt_range
<
Ring,
+ detail::wkt::prefix_polygon,
true,
- detail::wkt::prefix_ring_par_par,
- detail::wkt::double_closing_parenthesis
+ true
>
{};
@@ -478,9 +461,10 @@ struct wkt<Geometry, geometry_collection_tag>
static inline void apply(OutputStream& os, Geometry const& geometry,
bool force_closure)
{
- output_or_recursive_call(os, geometry, force_closure);
+ wkt::output_or_recursive_call(os, geometry, force_closure);
}
+private:
template
<
typename OutputStream, typename Geom,
@@ -501,7 +485,7 @@ struct wkt<Geometry, geometry_collection_tag>
traits::iter_visit<Geom>::apply([&](auto const& g)
{
- output_or_recursive_call(os, g, force_closure);
+ wkt::output_or_recursive_call(os, g, force_closure);
}, it);
}
@@ -605,7 +589,7 @@ inline std::string to_wkt(Geometry const& geometry, int significant_digits)
}
#if defined(_MSC_VER)
-#pragma warning(pop)
+#pragma warning(pop)
#endif
}} // namespace boost::geometry
diff --git a/boost/geometry/iterators/detail/point_iterator/inner_range_type.hpp b/boost/geometry/iterators/detail/point_iterator/inner_range_type.hpp
index edeebee744..8e93cf56eb 100644
--- a/boost/geometry/iterators/detail/point_iterator/inner_range_type.hpp
+++ b/boost/geometry/iterators/detail/point_iterator/inner_range_type.hpp
@@ -31,7 +31,7 @@ namespace detail { namespace point_iterator
template
<
- typename Geometry,
+ typename Geometry,
typename Tag = typename tag<Geometry>::type
>
struct inner_range_type
diff --git a/boost/geometry/iterators/flatten_iterator.hpp b/boost/geometry/iterators/flatten_iterator.hpp
index cfe232b4e9..cdfb5ab1bd 100644
--- a/boost/geometry/iterators/flatten_iterator.hpp
+++ b/boost/geometry/iterators/flatten_iterator.hpp
@@ -211,7 +211,7 @@ private:
}
while ( empty(m_outer_it) );
m_inner_it = AccessInnerEnd::apply(*m_outer_it);
- }
+ }
--m_inner_it;
}
};
diff --git a/boost/geometry/multi/io/wkt/detail/prefix.hpp b/boost/geometry/multi/io/wkt/detail/prefix.hpp
index 34e2b241d0..ee6b37e592 100644
--- a/boost/geometry/multi/io/wkt/detail/prefix.hpp
+++ b/boost/geometry/multi/io/wkt/detail/prefix.hpp
@@ -14,8 +14,7 @@
#ifndef BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP
#define BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP
-
-#include <boost/geometry/io/wkt/detail/prefix.hpp>
-
+#include <boost/config/pragma_message.hpp>
+BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
#endif // BOOST_GEOMETRY_MULTI_IO_WKT_DETAIL_PREFIX_HPP
diff --git a/boost/geometry/policies/compare.hpp b/boost/geometry/policies/compare.hpp
index 6a081af837..9dd8a694cc 100644
--- a/boost/geometry/policies/compare.hpp
+++ b/boost/geometry/policies/compare.hpp
@@ -2,9 +2,10 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2017, 2019.
-// Modifications copyright (c) 2017, 2019, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2023.
+// Modifications copyright (c) 2017-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -18,6 +19,7 @@
#include <cstddef>
#include <boost/geometry/strategies/compare.hpp>
+#include <boost/geometry/strategies/spherical/compare.hpp>
#include <boost/geometry/util/math.hpp>
@@ -36,92 +38,244 @@ namespace boost { namespace geometry
on equal x-es then on y, etc.
If a dimension is specified, only that dimension is considered
*/
+
template
<
typename Point = void,
int Dimension = -1,
- typename CSTag = void
+ typename StrategyOrTag = void
+>
+struct less_exact
+{
+ using first_argument_type = Point;
+ using second_argument_type = Point;
+ using result_type = bool;
+
+ inline bool operator()(Point const& left, Point const& right) const
+ {
+ return StrategyOrTag::template compare_type
+ <
+ strategy::compare::less,
+ strategy::compare::equals_exact
+ >::apply(left, right);
+ }
+};
+
+template
+<
+ typename Point = void,
+ int Dimension = -1,
+ typename StrategyOrTag = void
>
struct less
{
- typedef Point first_argument_type;
- typedef Point second_argument_type;
- typedef bool result_type;
+ using first_argument_type = Point;
+ using second_argument_type = Point;
+ using result_type = bool;
+
+ inline bool operator()(Point const& left, Point const& right) const
+ {
+ return StrategyOrTag::template compare_type
+ <
+ strategy::compare::less,
+ strategy::compare::equals_epsilon
+ >::apply(left, right);
+ }
+};
+
+
+template <typename Point, int Dimension>
+struct less<Point, Dimension, void>
+{
+ using first_argument_type = Point;
+ using second_argument_type = Point;
+ using result_type = bool;
inline bool operator()(Point const& left, Point const& right) const
{
- typedef typename strategy::compare::services::default_strategy
+ using strategy_type = typename strategy::compare::services::default_strategy
<
strategy::compare::less,
+ strategy::compare::equals_epsilon,
Point, Point,
- Dimension,
- CSTag, CSTag
- >::type strategy_type;
+ Dimension
+ >::type;
return strategy_type::apply(left, right);
}
};
-template <int Dimension, typename CSTag>
-struct less<void, Dimension, CSTag>
+template <int Dimension, typename Strategy>
+struct less<void, Dimension, Strategy>
{
- typedef bool result_type;
+ using result_type = bool;
template <typename Point1, typename Point2>
inline bool operator()(Point1 const& left, Point2 const& right) const
{
- typedef typename strategy::compare::services::default_strategy
+ return Strategy::template compare_type
<
strategy::compare::less,
- Point1, Point2,
+ strategy::compare::equals_epsilon
+ >::apply(left, right);
+ }
+};
+
+// for backward compatibility
+
+template <typename Point, int Dimension>
+struct less<Point, Dimension, boost::geometry::cartesian_tag>
+{
+ using first_argument_type = Point;
+ using second_argument_type = Point;
+ using result_type = bool;
+
+ inline bool operator()(Point const& left, Point const& right) const
+ {
+ using strategy_type = typename strategy::compare::services::default_strategy
+ <
+ strategy::compare::less,
+ strategy::compare::equals_epsilon,
+ Point, Point,
Dimension,
- CSTag, CSTag
- >::type strategy_type;
+ boost::geometry::cartesian_tag, boost::geometry::cartesian_tag
+ >::type;
return strategy_type::apply(left, right);
}
};
template <typename Point, int Dimension>
-struct less<Point, Dimension, void>
+struct less<Point, Dimension, boost::geometry::spherical_tag>
{
- typedef Point first_argument_type;
- typedef Point second_argument_type;
- typedef bool result_type;
+ using first_argument_type = Point;
+ using second_argument_type = Point;
+ using result_type = bool;
inline bool operator()(Point const& left, Point const& right) const
{
- typedef typename strategy::compare::services::default_strategy
+ using strategy_type = typename strategy::compare::services::default_strategy
<
strategy::compare::less,
+ strategy::compare::equals_epsilon,
Point, Point,
- Dimension
- >::type strategy_type;
+ Dimension,
+ boost::geometry::spherical_tag, boost::geometry::spherical_tag
+ >::type;
+
+ return strategy_type::apply(left, right);
+ }
+};
+
+template <typename Point, int Dimension>
+struct less<Point, Dimension, boost::geometry::geographic_tag>
+{
+ using first_argument_type = Point;
+ using second_argument_type = Point;
+ using result_type = bool;
+
+ inline bool operator()(Point const& left, Point const& right) const
+ {
+ using strategy_type = typename strategy::compare::services::default_strategy
+ <
+ strategy::compare::less,
+ strategy::compare::equals_epsilon,
+ Point, Point,
+ Dimension,
+ boost::geometry::geographic_tag, boost::geometry::geographic_tag
+ >::type;
+
+ return strategy_type::apply(left, right);
+ }
+};
+
+template <int Dimension>
+struct less<void, Dimension, boost::geometry::cartesian_tag>
+{
+ using result_type = bool;
+
+ template <typename Point1, typename Point2>
+ inline bool operator()(Point1 const& left, Point2 const& right) const
+ {
+ using strategy_type = typename strategy::compare::services::default_strategy
+ <
+ strategy::compare::less,
+ strategy::compare::equals_epsilon,
+ Point1, Point2,
+ Dimension,
+ boost::geometry::cartesian_tag, boost::geometry::cartesian_tag
+ >::type;
return strategy_type::apply(left, right);
}
};
template <int Dimension>
+struct less<void, Dimension, boost::geometry::spherical_tag>
+{
+ using result_type = bool;
+
+ template <typename Point1, typename Point2>
+ inline bool operator()(Point1 const& left, Point2 const& right) const
+ {
+ using strategy_type = typename strategy::compare::services::default_strategy
+ <
+ strategy::compare::less,
+ strategy::compare::equals_epsilon,
+ Point1, Point2,
+ Dimension,
+ boost::geometry::spherical_tag, boost::geometry::spherical_tag
+ >::type;
+
+ return strategy_type::apply(left, right);
+ }
+};
+
+template <int Dimension>
+struct less<void, Dimension, boost::geometry::geographic_tag>
+{
+ using result_type = bool;
+
+ template <typename Point1, typename Point2>
+ inline bool operator()(Point1 const& left, Point2 const& right) const
+ {
+ using strategy_type = typename strategy::compare::services::default_strategy
+ <
+ strategy::compare::less,
+ strategy::compare::equals_epsilon,
+ Point1, Point2,
+ Dimension,
+ boost::geometry::geographic_tag, boost::geometry::geographic_tag
+ >::type;
+
+ return strategy_type::apply(left, right);
+ }
+};
+
+
+template <int Dimension>
struct less<void, Dimension, void>
{
- typedef bool result_type;
+ using result_type = bool;
template <typename Point1, typename Point2>
inline bool operator()(Point1 const& left, Point2 const& right) const
{
- typedef typename strategy::compare::services::default_strategy
+ using strategy_type = typename strategy::compare::services::default_strategy
<
strategy::compare::less,
+ strategy::compare::equals_epsilon,
Point1, Point2,
Dimension
- >::type strategy_type;
+ >::type;
return strategy_type::apply(left, right);
}
};
+
+
/*!
\brief Greater functor
\ingroup compare
@@ -136,19 +290,20 @@ template
>
struct greater
{
- typedef Point first_argument_type;
- typedef Point second_argument_type;
- typedef bool result_type;
+ using first_argument_type = Point;
+ using second_argument_type = Point;
+ using result_type = bool;
bool operator()(Point const& left, Point const& right) const
{
- typedef typename strategy::compare::services::default_strategy
+ using strategy_type = typename strategy::compare::services::default_strategy
<
strategy::compare::greater,
+ strategy::compare::equals_epsilon,
Point, Point,
Dimension,
CSTag, CSTag
- >::type strategy_type;
+ >::type;
return strategy_type::apply(left, right);
}
@@ -157,18 +312,19 @@ struct greater
template <int Dimension, typename CSTag>
struct greater<void, Dimension, CSTag>
{
- typedef bool result_type;
+ using result_type = bool;
template <typename Point1, typename Point2>
bool operator()(Point1 const& left, Point2 const& right) const
{
- typedef typename strategy::compare::services::default_strategy
+ using strategy_type = typename strategy::compare::services::default_strategy
<
strategy::compare::greater,
+ strategy::compare::equals_epsilon,
Point1, Point2,
Dimension,
CSTag, CSTag
- >::type strategy_type;
+ >::type;
return strategy_type::apply(left, right);
}
@@ -177,18 +333,19 @@ struct greater<void, Dimension, CSTag>
template <typename Point, int Dimension>
struct greater<Point, Dimension, void>
{
- typedef Point first_argument_type;
- typedef Point second_argument_type;
- typedef bool result_type;
+ using first_argument_type = Point;
+ using second_argument_type = Point;
+ using result_type = bool;
bool operator()(Point const& left, Point const& right) const
{
- typedef typename strategy::compare::services::default_strategy
+ using strategy_type = typename strategy::compare::services::default_strategy
<
strategy::compare::greater,
+ strategy::compare::equals_epsilon,
Point, Point,
Dimension
- >::type strategy_type;
+ >::type;
return strategy_type::apply(left, right);
}
@@ -197,17 +354,18 @@ struct greater<Point, Dimension, void>
template <int Dimension>
struct greater<void, Dimension, void>
{
- typedef bool result_type;
+ using result_type = bool;
template <typename Point1, typename Point2>
bool operator()(Point1 const& left, Point2 const& right) const
{
- typedef typename strategy::compare::services::default_strategy
+ using strategy_type = typename strategy::compare::services::default_strategy
<
strategy::compare::greater,
+ strategy::compare::equals_epsilon,
Point1, Point2,
Dimension
- >::type strategy_type;
+ >::type;
return strategy_type::apply(left, right);
}
@@ -230,19 +388,20 @@ template
>
struct equal_to
{
- typedef Point first_argument_type;
- typedef Point second_argument_type;
- typedef bool result_type;
+ using first_argument_type = Point;
+ using second_argument_type = Point;
+ using result_type = bool;
bool operator()(Point const& left, Point const& right) const
{
- typedef typename strategy::compare::services::default_strategy
+ using strategy_type = typename strategy::compare::services::default_strategy
<
strategy::compare::equal_to,
+ strategy::compare::equals_epsilon,
Point, Point,
Dimension,
CSTag, CSTag
- >::type strategy_type;
+ >::type;
return strategy_type::apply(left, right);
}
@@ -251,18 +410,19 @@ struct equal_to
template <int Dimension, typename CSTag>
struct equal_to<void, Dimension, CSTag>
{
- typedef bool result_type;
+ using result_type = bool;
template <typename Point1, typename Point2>
bool operator()(Point1 const& left, Point2 const& right) const
{
- typedef typename strategy::compare::services::default_strategy
+ using strategy_type = typename strategy::compare::services::default_strategy
<
strategy::compare::equal_to,
+ strategy::compare::equals_epsilon,
Point1, Point2,
Dimension,
CSTag, CSTag
- >::type strategy_type;
+ >::type;
return strategy_type::apply(left, right);
}
@@ -271,18 +431,19 @@ struct equal_to<void, Dimension, CSTag>
template <typename Point, int Dimension>
struct equal_to<Point, Dimension, void>
{
- typedef Point first_argument_type;
- typedef Point second_argument_type;
- typedef bool result_type;
+ using first_argument_type = Point;
+ using second_argument_type = Point;
+ using result_type = bool;
bool operator()(Point const& left, Point const& right) const
{
- typedef typename strategy::compare::services::default_strategy
+ using strategy_type = typename strategy::compare::services::default_strategy
<
strategy::compare::equal_to,
+ strategy::compare::equals_epsilon,
Point, Point,
Dimension
- >::type strategy_type;
+ >::type;
return strategy_type::apply(left, right);
}
@@ -291,17 +452,18 @@ struct equal_to<Point, Dimension, void>
template <int Dimension>
struct equal_to<void, Dimension, void>
{
- typedef bool result_type;
+ using result_type = bool;
template <typename Point1, typename Point2>
bool operator()(Point1 const& left, Point2 const& right) const
{
- typedef typename strategy::compare::services::default_strategy
+ using strategy_type = typename strategy::compare::services::default_strategy
<
strategy::compare::equal_to,
+ strategy::compare::equals_epsilon,
Point1, Point2,
Dimension
- >::type strategy_type;
+ >::type;
return strategy_type::apply(left, right);
}
diff --git a/boost/geometry/policies/is_valid/failing_reason_policy.hpp b/boost/geometry/policies/is_valid/failing_reason_policy.hpp
index bb28091d98..701e72c2d3 100644
--- a/boost/geometry/policies/is_valid/failing_reason_policy.hpp
+++ b/boost/geometry/policies/is_valid/failing_reason_policy.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2015, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2015, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -14,7 +15,7 @@
#include <sstream>
#include <boost/geometry/io/dsv/write.hpp>
-#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/constexpr.hpp>
#include <boost/geometry/util/range.hpp>
#include <boost/geometry/algorithms/validity_failure_type.hpp>
#include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
@@ -69,10 +70,12 @@ private:
static inline
validity_failure_type transform_failure_type(validity_failure_type failure)
{
- if (BOOST_GEOMETRY_CONDITION(
- AllowDuplicates && failure == failure_duplicate_points))
+ if BOOST_GEOMETRY_CONSTEXPR (AllowDuplicates)
{
- return no_failure;
+ if (failure == failure_duplicate_points)
+ {
+ return no_failure;
+ }
}
return failure;
}
@@ -81,10 +84,12 @@ private:
validity_failure_type transform_failure_type(validity_failure_type failure,
bool is_linear)
{
- if (BOOST_GEOMETRY_CONDITION(
- is_linear && AllowSpikes && failure == failure_spikes))
+ if BOOST_GEOMETRY_CONSTEXPR (AllowSpikes)
{
- return no_failure;
+ if (is_linear && failure == failure_spikes)
+ {
+ return no_failure;
+ }
}
return transform_failure_type(failure);
}
@@ -123,9 +128,12 @@ private:
bool is_linear,
SpikePoint const& spike_point)
{
- if (BOOST_GEOMETRY_CONDITION(is_linear && AllowSpikes))
+ if BOOST_GEOMETRY_CONSTEXPR (AllowSpikes)
{
- return;
+ if (is_linear)
+ {
+ return;
+ }
}
oss << ". A spike point was found with apex at "
@@ -173,7 +181,7 @@ private:
static inline void apply(std::ostringstream& oss,
Point const& point)
{
- if (BOOST_GEOMETRY_CONDITION(AllowDuplicates))
+ if BOOST_GEOMETRY_CONSTEXPR (AllowDuplicates)
{
return;
}
diff --git a/boost/geometry/policies/predicate_based_interrupt_policy.hpp b/boost/geometry/policies/predicate_based_interrupt_policy.hpp
index 6d3d5be016..79f420790e 100644
--- a/boost/geometry/policies/predicate_based_interrupt_policy.hpp
+++ b/boost/geometry/policies/predicate_based_interrupt_policy.hpp
@@ -1,6 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2014-2020, Oracle and/or its affiliates.
+// Copyright (c) 2014-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -10,11 +12,12 @@
#ifndef BOOST_GEOMETRY_ALGORITHMS_POLICIES_PREDICATE_BASED_INTERRUPT_POLICY_HPP
#define BOOST_GEOMETRY_ALGORITHMS_POLICIES_PREDICATE_BASED_INTERRUPT_POLICY_HPP
+#include <algorithm>
+
#include <boost/range/begin.hpp>
+#include <boost/range/empty.hpp>
#include <boost/range/end.hpp>
-#include <boost/geometry/algorithms/detail/check_iterator_range.hpp>
-
namespace boost { namespace geometry
{
@@ -43,12 +46,14 @@ struct stateless_predicate_based_interrupt_policy
template <typename Range>
inline bool apply(Range const& range)
{
- // if there is at least one unacceptable turn in the range, return false
- has_intersections = !detail::check_iterator_range
- <
- IsAcceptableTurnPredicate,
- AllowEmptyTurnRange
- >::apply(boost::begin(range), boost::end(range));
+ // if there is at least one unacceptable turn in the range, return true
+ bool const has_unacceptable_turn = std::any_of(boost::begin(range), boost::end(range),
+ [](auto const& turn) {
+ return ! IsAcceptableTurnPredicate::apply(turn);
+ });
+
+ has_intersections = has_unacceptable_turn
+ && !(AllowEmptyTurnRange && boost::empty(range));
return has_intersections;
}
@@ -78,12 +83,15 @@ struct predicate_based_interrupt_policy
template <typename Range>
inline bool apply(Range const& range)
{
- // if there is at least one unacceptable turn in the range, return false
- has_intersections = !detail::check_iterator_range
- <
- IsAcceptableTurnPredicate,
- AllowEmptyTurnRange
- >::apply(boost::begin(range), boost::end(range), m_predicate);
+ // if there is at least one unacceptable turn in the range, return true
+ bool const has_unacceptable_turn = std::any_of(boost::begin(range),
+ boost::end(range),
+ [&]( auto const& turn ) {
+ return ! m_predicate.apply(turn);
+ });
+
+ has_intersections = has_unacceptable_turn
+ && !(AllowEmptyTurnRange && boost::empty(range));
return has_intersections;
}
diff --git a/boost/geometry/policies/relate/intersection_points.hpp b/boost/geometry/policies/relate/intersection_points.hpp
index 1ba08452fd..1d7671ddfd 100644
--- a/boost/geometry/policies/relate/intersection_points.hpp
+++ b/boost/geometry/policies/relate/intersection_points.hpp
@@ -2,8 +2,9 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2016.
-// Modifications copyright (c) 2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2016, 2022.
+// Modifications copyright (c) 2016-2022 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -68,7 +69,7 @@ struct segments_intersection_points
Ratio const& rb_from_wrt_a, Ratio const& rb_to_wrt_a)
{
return_type result;
- unsigned int index = 0, count_a = 0, count_b = 0;
+ unsigned int index = 0;
Ratio on_a[2];
// The conditions "index < 2" are necessary for non-robust handling,
@@ -87,7 +88,6 @@ struct segments_intersection_points
result.fractions[index].assign(Ratio::zero(), ra_from_wrt_b);
on_a[index] = Ratio::zero();
index++;
- count_a++;
}
if (b1_wrt_a == 2 //rb_from_wrt_a.in_segment()
&& index < 2)
@@ -103,7 +103,6 @@ struct segments_intersection_points
result.fractions[index].assign(rb_from_wrt_a, Ratio::zero());
on_a[index] = rb_from_wrt_a;
index++;
- count_b++;
}
if (a2_wrt_b >= 1 && a2_wrt_b <= 3 //ra_to_wrt_b.on_segment()
@@ -116,7 +115,6 @@ struct segments_intersection_points
result.fractions[index].assign(Ratio::one(), ra_to_wrt_b);
on_a[index] = Ratio::one();
index++;
- count_a++;
}
if (b2_wrt_a == 2 // rb_to_wrt_a.in_segment()
&& index < 2)
@@ -125,7 +123,6 @@ struct segments_intersection_points
result.fractions[index].assign(rb_to_wrt_a, Ratio::one());
on_a[index] = rb_to_wrt_a;
index++;
- count_b++;
}
// TEMPORARY
diff --git a/boost/geometry/policies/robustness/get_rescale_policy.hpp b/boost/geometry/policies/robustness/get_rescale_policy.hpp
index 66f949fe4a..5e1dd5e4d0 100644
--- a/boost/geometry/policies/robustness/get_rescale_policy.hpp
+++ b/boost/geometry/policies/robustness/get_rescale_policy.hpp
@@ -24,6 +24,7 @@
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/core/config.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
#include <boost/geometry/core/tag_cast.hpp>
#include <boost/geometry/algorithms/envelope.hpp>
@@ -37,7 +38,6 @@
#include <boost/geometry/policies/robustness/no_rescale_policy.hpp>
#include <boost/geometry/policies/robustness/rescale_policy.hpp>
#include <boost/geometry/policies/robustness/robust_type.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/type_traits.hpp>
// TEMP
diff --git a/boost/geometry/policies/robustness/segment_ratio.hpp b/boost/geometry/policies/robustness/segment_ratio.hpp
index 07c74cc431..9a3914a756 100644
--- a/boost/geometry/policies/robustness/segment_ratio.hpp
+++ b/boost/geometry/policies/robustness/segment_ratio.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2013 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2016-2020.
-// Modifications copyright (c) 2016-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2016-2021.
+// Modifications copyright (c) 2016-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -19,8 +19,8 @@
#include <boost/rational.hpp>
#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
namespace boost { namespace geometry
{
@@ -53,8 +53,8 @@ struct less<Type, false>
template <typename Ratio>
static inline bool apply(Ratio const& lhs, Ratio const& rhs)
{
- BOOST_GEOMETRY_ASSERT(lhs.denominator() != 0);
- BOOST_GEOMETRY_ASSERT(rhs.denominator() != 0);
+ BOOST_GEOMETRY_ASSERT(lhs.denominator() != Type(0));
+ BOOST_GEOMETRY_ASSERT(rhs.denominator() != Type(0));
Type const a = lhs.numerator() / lhs.denominator();
Type const b = rhs.numerator() / rhs.denominator();
return ! geometry::math::equals(a, b)
@@ -86,8 +86,8 @@ struct equal<Type, false>
template <typename Ratio>
static inline bool apply(Ratio const& lhs, Ratio const& rhs)
{
- BOOST_GEOMETRY_ASSERT(lhs.denominator() != 0);
- BOOST_GEOMETRY_ASSERT(rhs.denominator() != 0);
+ BOOST_GEOMETRY_ASSERT(lhs.denominator() != Type(0));
+ BOOST_GEOMETRY_ASSERT(rhs.denominator() != Type(0));
Type const a = lhs.numerator() / lhs.denominator();
Type const b = rhs.numerator() / rhs.denominator();
return geometry::math::equals(a, b);
@@ -119,7 +119,8 @@ struct possibly_collinear<Type, false>
template <typename Ratio, typename Threshold>
static inline bool apply(Ratio const& ratio, Threshold)
{
- return ratio.denominator() == 0;
+ static Type const zero = 0;
+ return ratio.denominator() == zero;
}
};
@@ -135,11 +136,16 @@ struct possibly_collinear<Type, false>
template <typename Type>
class segment_ratio
{
-public :
- typedef Type numeric_type;
+ // Type used for the approximation (a helper value)
+ // and for the edge value (0..1) (a helper function).
+ using floating_point_type =
+ typename detail::promoted_to_floating_point<Type>::type;
// Type-alias for the type itself
- typedef segment_ratio<Type> thistype;
+ using thistype = segment_ratio<Type>;
+
+public:
+ using int_type = Type;
inline segment_ratio()
: m_numerator(0)
@@ -158,7 +164,7 @@ public :
segment_ratio& operator=(segment_ratio const&) = default;
segment_ratio(segment_ratio&&) = default;
segment_ratio& operator=(segment_ratio&&) = default;
-
+
// These are needed because in intersection strategies ratios are assigned
// in fractions and if a user passes CalculationType then ratio Type in
// turns is taken from geometry coordinate_type and the one used in
@@ -212,31 +218,31 @@ public :
{
// Minimal normalization
// 1/-4 => -1/4, -1/-4 => 1/4
- if (m_denominator < 0)
+ if (m_denominator < zero_instance())
{
m_numerator = -m_numerator;
m_denominator = -m_denominator;
}
m_approximation =
- m_denominator == 0 ? 0
+ m_denominator == zero_instance() ? floating_point_type{0}
: (
- boost::numeric_cast<fp_type>(m_numerator) * scale()
- / boost::numeric_cast<fp_type>(m_denominator)
+ boost::numeric_cast<floating_point_type>(m_numerator) * scale()
+ / boost::numeric_cast<floating_point_type>(m_denominator)
);
}
- inline bool is_zero() const { return math::equals(m_numerator, 0); }
+ inline bool is_zero() const { return math::equals(m_numerator, Type(0)); }
inline bool is_one() const { return math::equals(m_numerator, m_denominator); }
inline bool on_segment() const
{
// e.g. 0/4 or 4/4 or 2/4
- return m_numerator >= 0 && m_numerator <= m_denominator;
+ return m_numerator >= zero_instance() && m_numerator <= m_denominator;
}
inline bool in_segment() const
{
// e.g. 1/4
- return m_numerator > 0 && m_numerator < m_denominator;
+ return m_numerator > zero_instance() && m_numerator < m_denominator;
}
inline bool on_end() const
{
@@ -246,7 +252,7 @@ public :
inline bool left() const
{
// e.g. -1/4
- return m_numerator < 0;
+ return m_numerator < zero_instance();
}
inline bool right() const
{
@@ -254,21 +260,16 @@ public :
return m_numerator > m_denominator;
}
- inline bool near_end() const
- {
- if (left() || right())
- {
- return false;
- }
-
- static fp_type const small_part_of_scale = scale() / 100;
- return m_approximation < small_part_of_scale
- || m_approximation > scale() - small_part_of_scale;
- }
-
- inline bool close_to(thistype const& other) const
+ //! Returns a value between 0.0 and 1.0
+ //! 0.0 means: exactly in the middle
+ //! 1.0 means: exactly on one of the edges (or even over it)
+ inline floating_point_type edge_value() const
{
- return geometry::math::abs(m_approximation - other.m_approximation) < 50;
+ using fp = floating_point_type;
+ fp const one{1.0};
+ floating_point_type const result
+ = fp(2) * geometry::math::abs(fp(0.5) - m_approximation / scale());
+ return result > one ? one : result;
}
template <typename Threshold>
@@ -313,19 +314,7 @@ public :
}
#endif
-
-
private :
- // NOTE: if this typedef is used then fp_type is non-fundamental type
- // if Type is non-fundamental type
- //typedef typename promote_floating_point<Type>::type fp_type;
-
- // TODO: What with user-defined numeric types?
- // Shouldn't here is_integral be checked?
- typedef std::conditional_t
- <
- std::is_floating_point<Type>::value, Type, double
- > fp_type;
Type m_numerator;
Type m_denominator;
@@ -335,12 +324,24 @@ private :
// Boost.Rational is used if the approximations are close.
// Reason: performance, Boost.Rational does a GCD by default and also the
// comparisons contain while-loops.
- fp_type m_approximation;
+ floating_point_type m_approximation;
+ inline bool close_to(thistype const& other) const
+ {
+ static floating_point_type const threshold{50.0};
+ return geometry::math::abs(m_approximation - other.m_approximation)
+ < threshold;
+ }
+
+ static inline floating_point_type scale()
+ {
+ static floating_point_type const fp_scale{1000000.0};
+ return fp_scale;
+ }
- static inline fp_type scale()
+ static inline Type zero_instance()
{
- return 1000000.0;
+ return 0;
}
};
diff --git a/boost/geometry/srs/epsg.hpp b/boost/geometry/srs/epsg.hpp
index f26c2e0c42..7a636e5664 100644
--- a/boost/geometry/srs/epsg.hpp
+++ b/boost/geometry/srs/epsg.hpp
@@ -19,7 +19,7 @@
namespace boost { namespace geometry
{
-
+
namespace projections
{
diff --git a/boost/geometry/srs/esri.hpp b/boost/geometry/srs/esri.hpp
index 086a2f0592..194ae853bb 100644
--- a/boost/geometry/srs/esri.hpp
+++ b/boost/geometry/srs/esri.hpp
@@ -19,7 +19,7 @@
namespace boost { namespace geometry
{
-
+
namespace projections
{
diff --git a/boost/geometry/srs/iau2000.hpp b/boost/geometry/srs/iau2000.hpp
index 82f2d21769..4e15930728 100644
--- a/boost/geometry/srs/iau2000.hpp
+++ b/boost/geometry/srs/iau2000.hpp
@@ -19,7 +19,7 @@
namespace boost { namespace geometry
{
-
+
namespace projections
{
diff --git a/boost/geometry/srs/projection.hpp b/boost/geometry/srs/projection.hpp
index cbb91642a4..9025952c0d 100644
--- a/boost/geometry/srs/projection.hpp
+++ b/boost/geometry/srs/projection.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017-2020.
// Modifications copyright (c) 2017-2020, Oracle and/or its affiliates.
@@ -14,10 +15,10 @@
#define BOOST_GEOMETRY_SRS_PROJECTION_HPP
+#include <memory>
#include <string>
#include <type_traits>
-#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/throw_exception.hpp>
#include <boost/geometry/algorithms/convert.hpp>
@@ -41,7 +42,7 @@
namespace boost { namespace geometry
{
-
+
namespace projections
{
@@ -378,7 +379,7 @@ private:
return result;
}
- boost::shared_ptr<vprj_t> m_ptr;
+ std::shared_ptr<vprj_t> m_ptr;
};
template <typename StaticParameters, typename CT>
@@ -392,7 +393,7 @@ class static_proj_wrapper_base
<
StaticParameters
>::type proj_tag;
-
+
typedef typename projections::detail::static_projection_type
<
proj_tag,
@@ -498,7 +499,7 @@ public:
namespace srs
{
-
+
/*!
\brief Representation of projection
\details Either dynamic or static projection representation
diff --git a/boost/geometry/srs/projections/dpar.hpp b/boost/geometry/srs/projections/dpar.hpp
index 18a0971a1e..696246c18f 100644
--- a/boost/geometry/srs/projections/dpar.hpp
+++ b/boost/geometry/srs/projections/dpar.hpp
@@ -1,6 +1,9 @@
// Boost.Geometry
-// Copyright (c) 2017-2020, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+
+// Copyright (c) 2017-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -30,7 +33,8 @@
#include <boost/range/end.hpp>
#include <boost/range/size.hpp>
#include <boost/range/value_type.hpp>
-#include <boost/tuple/tuple.hpp>
+
+#include <boost/variant/get.hpp>
#include <boost/variant/variant.hpp>
@@ -208,6 +212,7 @@ enum value_proj
proj_cc,
proj_cea,
proj_chamb,
+ proj_col_urban,
proj_collg,
proj_crast,
proj_denoy,
@@ -292,6 +297,7 @@ enum value_proj
proj_wag2,
proj_wag3,
proj_wag7,
+ proj_webmerc,
proj_wink1,
proj_wink2
};
@@ -334,7 +340,7 @@ enum name_f
es,
f,
h,
- //h_0, // currently not used
+ h_0,
k = 7,
k_0,
m, // also used for M
@@ -411,7 +417,10 @@ enum name_be
r_h, // originally R_h
r_v, // originally R_V
rescale, // 70
- south
+ south,
+ variant_c, // BG specific
+ no_off,
+ hyperbolic
};
/*enum name_catalog
@@ -481,6 +490,11 @@ enum name_units
vunits
};
+enum name_axis
+{
+ axis = 86 // 3 element list of numbers
+};
+
template <typename T>
struct parameter
{
@@ -576,12 +590,10 @@ struct parameter
, m_value(srs::detail::nadgrids(boost::begin(v), boost::end(v)))
{}
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
parameter(name_nadgrids id, std::initializer_list<std::string> v)
: m_id(id)
, m_value(srs::detail::nadgrids(v))
{}
-#endif
parameter(name_orient id, value_orient v)
: m_id(id), m_value(int(v))
@@ -641,7 +653,6 @@ struct parameter
}
}
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
parameter(name_towgs84 id, std::initializer_list<T> v)
: m_id(id)
, m_value(srs::detail::towgs84<T>(v))
@@ -652,7 +663,17 @@ struct parameter
BOOST_THROW_EXCEPTION( projection_exception("Invalid number of towgs84 elements. Should be 3 or 7.") );
}
}
-#endif
+
+ parameter(name_axis id, std::initializer_list<int> v)
+ : m_id(id)
+ , m_value(srs::detail::axis(v))
+ {
+ std::size_t n = v.size();
+ if (n != 3)
+ {
+ BOOST_THROW_EXCEPTION( projection_exception("Invalid number of axis elements. Should be 3.") );
+ }
+ }
parameter(name_units id, value_units v)
: m_id(id), m_value(int(v))
@@ -661,7 +682,7 @@ struct parameter
parameter(value_units v)
: m_id(units), m_value(int(v))
{}
-
+
private:
typedef boost::variant
<
@@ -688,6 +709,7 @@ public:
bool is_id_equal(name_sweep const& id) const { return m_id == int(id); }
bool is_id_equal(name_towgs84 const& id) const { return m_id == int(id); }
bool is_id_equal(name_units const& id) const { return m_id == int(id); }
+ bool is_id_equal(name_axis const& id) const { return m_id == int(id); }
template <typename V>
V const& get_value() const
@@ -700,7 +722,7 @@ public:
{
return m_value.which() == srs::detail::find_type_index<variant_type, V>::value;
}
-
+
private:
int m_id;
variant_type m_value;
@@ -719,66 +741,6 @@ public:
BOOST_DEFAULTED_FUNCTION(parameters(), {})
-#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
- template <typename Id>
- explicit parameters(Id id)
- {
- add(id);
- }
-
- template <typename Id>
- parameters & add(Id id)
- {
- m_params.push_back(parameter<T>(id));
- return *this;
- }
-
- template <typename Id>
- parameters & operator()(Id id)
- {
- return add(id);
- }
-
- template <typename Id, typename V>
- parameters(Id id, V const& value)
- {
- add(id, value);
- }
-
- template <typename Id, typename V>
- parameters & add(Id id, V const& value)
- {
- m_params.push_back(parameter<T>(id, value));
- return *this;
- }
-
- template <typename Id, typename V>
- parameters & operator()(Id id, V const& value)
- {
- return add(id, value);
- }
-
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
- template <typename Id, typename V>
- parameters(Id id, std::initializer_list<V> value)
- {
- add(id, value);
- }
-
- template <typename Id, typename V>
- parameters & add(Id id, std::initializer_list<V> value)
- {
- m_params.push_back(parameter<T>(id, value));
- return *this;
- }
-
- template <typename Id, typename V>
- parameters & operator()(Id id, std::initializer_list<V> value)
- {
- return add(id, value);
- }
-#endif // BOOST_NO_CXX11_HDR_INITIALIZER_LIST
-#else // BOOST_NO_CXX11_RVALUE_REFERENCES || BOOST_NO_CXX11_RVALUE_REFERENCES
template <typename Id>
explicit parameters(Id id)
{
@@ -817,7 +779,6 @@ public:
return add(id, std::forward<V>(value));
}
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
template <typename Id, typename V>
parameters(Id id, std::initializer_list<V> value)
{
@@ -836,8 +797,6 @@ public:
{
return add(id, value);
}
-#endif // BOOST_NO_CXX11_HDR_INITIALIZER_LIST
-#endif // BOOST_NO_CXX11_RVALUE_REFERENCES || BOOST_NO_CXX11_RVALUE_REFERENCES
const_iterator begin() const { return m_params.begin(); }
const_iterator end() const { return m_params.end(); }
diff --git a/boost/geometry/srs/projections/epsg.hpp b/boost/geometry/srs/projections/epsg.hpp
index 29cb03dbd2..0178c0f3e1 100644
--- a/boost/geometry/srs/projections/epsg.hpp
+++ b/boost/geometry/srs/projections/epsg.hpp
@@ -2,8 +2,9 @@
// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2017, 2018, 2020.
-// Modifications copyright (c) 2017-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017, 2018, 2020, 2022.
+// Modifications copyright (c) 2017-2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -1609,7 +1610,7 @@ namespace detail
{3584, srs::dpar::parameters<>(proj_lcc)(lat_1,41.48333333333333)(lat_2,41.28333333333333)(lat_0,41)(lon_0,-70.5)(x_0,500000.0001016001)(y_0,0)(ellps_grs80)(towgs84,srs::detail::towgs84<>(0,0,0,0,0,0,0))(to_meter,0.3048006096012192)(no_defs)},
{3585, srs::dpar::parameters<>(proj_lcc)(lat_1,42.68333333333333)(lat_2,41.71666666666667)(lat_0,41)(lon_0,-71.5)(x_0,200000)(y_0,750000)(ellps_grs80)(towgs84,srs::detail::towgs84<>(0,0,0,0,0,0,0))(units_m)(no_defs)},
{3586, srs::dpar::parameters<>(proj_lcc)(lat_1,42.68333333333333)(lat_2,41.71666666666667)(lat_0,41)(lon_0,-71.5)(x_0,200000.0001016002)(y_0,750000)(ellps_grs80)(towgs84,srs::detail::towgs84<>(0,0,0,0,0,0,0))(to_meter,0.3048006096012192)(no_defs)},
- {3587, srs::dpar::parameters<>(proj_lcc)(lat_1,45.7)(lat_2,44.18333333333333)(lat_0,43.31666666666667)(lon_0,-84.36666666666666)(x_0,6000000)(y_0,0)(ellps_grs80)(towgs84,srs::detail::towgs84<>(0,0,0,0,0,0,0))(units_m)(no_defs)},
+ {3587, srs::dpar::parameters<>(proj_webmerc)(lon_0,0)(x_0,0)(y_0,0)(ellps_wgs84)(srs::dpar::datum_wgs84)(units_m)(no_defs)},
{3588, srs::dpar::parameters<>(proj_lcc)(lat_1,45.7)(lat_2,44.18333333333333)(lat_0,43.31666666666667)(lon_0,-84.36666666666666)(x_0,5999999.999976001)(y_0,0)(ellps_grs80)(towgs84,srs::detail::towgs84<>(0,0,0,0,0,0,0))(to_meter,0.3048)(no_defs)},
{3589, srs::dpar::parameters<>(proj_lcc)(lat_1,47.08333333333334)(lat_2,45.48333333333333)(lat_0,44.78333333333333)(lon_0,-87)(x_0,8000000)(y_0,0)(ellps_grs80)(towgs84,srs::detail::towgs84<>(0,0,0,0,0,0,0))(units_m)(no_defs)},
{3590, srs::dpar::parameters<>(proj_lcc)(lat_1,47.08333333333334)(lat_2,45.48333333333333)(lat_0,44.78333333333333)(lon_0,-87)(x_0,7999999.999968001)(y_0,0)(ellps_grs80)(towgs84,srs::detail::towgs84<>(0,0,0,0,0,0,0))(to_meter,0.3048)(no_defs)},
@@ -1807,7 +1808,7 @@ namespace detail
{3782, srs::dpar::parameters<>(proj_tmerc)(lat_0,0)(lon_0,-120)(k,0.9999)(x_0,0)(y_0,0)(ellps_grs80)(units_m)(no_defs)},
{3783, srs::dpar::parameters<>(proj_tmerc)(lat_0,-25.06855261111111)(lon_0,-130.1129671111111)(k,1)(x_0,14200)(y_0,15500)(ellps_wgs84)(towgs84,srs::detail::towgs84<>(0,0,0,0,0,0,0))(units_m)(no_defs)},
{3784, srs::dpar::parameters<>(proj_utm)(zone,9)(south)(ellps_intl)(towgs84,srs::detail::towgs84<>(185,165,42,0,0,0,0))(units_m)(no_defs)},
- {3785, srs::dpar::parameters<>(proj_merc)(lat_ts,0)(lon_0,0)(k,1)(x_0,0)(y_0,0)(r,6378137)(units_m)(no_defs)},
+ {3785, srs::dpar::parameters<>(proj_webmerc)(lon_0,0)(x_0,0)(y_0,0)(ellps_wgs84)(srs::dpar::datum_wgs84)(units_m)(no_defs)},
{3786, srs::dpar::parameters<>(proj_eqc)(lat_ts,0)(lat_0,0)(lon_0,0)(x_0,0)(y_0,0)(r,6371007)(units_m)(no_defs)},
{3787, srs::dpar::parameters<>(proj_tmerc)(lat_0,0)(lon_0,15)(k,0.9999)(x_0,500000)(y_0,-5000000)(ellps_bessel)(towgs84,srs::detail::towgs84<>(577.326,90.129,463.919,5.137,1.474,5.297,2.4232))(units_m)(no_defs)},
{3788, srs::dpar::parameters<>(proj_tmerc)(lat_0,0)(lon_0,166)(k,1)(x_0,3500000)(y_0,10000000)(ellps_grs80)(towgs84,srs::detail::towgs84<>(0,0,0,0,0,0,0))(units_m)(no_defs)},
@@ -1857,6 +1858,7 @@ namespace detail
//{3848},
//{3849},
//{3850},
+ {3857, srs::dpar::parameters<>(proj_webmerc)(lon_0,0)(x_0,0)(y_0,0)(ellps_wgs84)(srs::dpar::datum_wgs84)(units_m)(no_defs)},
{3920, srs::dpar::parameters<>(proj_utm)(zone,20)(ellps_clrk66)(towgs84,srs::detail::towgs84<>(11,72,-101,0,0,0,0))(units_m)(no_defs)},
{3942, srs::dpar::parameters<>(proj_lcc)(lat_1,41.25)(lat_2,42.75)(lat_0,42)(lon_0,3)(x_0,1700000)(y_0,1200000)(ellps_grs80)(towgs84,srs::detail::towgs84<>(0,0,0,0,0,0,0))(units_m)(no_defs)},
{3943, srs::dpar::parameters<>(proj_lcc)(lat_1,42.25)(lat_2,43.75)(lat_0,43)(lon_0,3)(x_0,1700000)(y_0,2200000)(ellps_grs80)(towgs84,srs::detail::towgs84<>(0,0,0,0,0,0,0))(units_m)(no_defs)},
@@ -2610,6 +2612,7 @@ namespace detail
//{5819},
//{5820},
//{5821},
+ {6247, srs::dpar::parameters<>(proj_col_urban)(lon_0,-74.1465916666667)(lat_0,4.68048611111111)(x_0,92334.879)(y_0,109320.965)(h_0,2550)(ellps_grs80)(srs::dpar::datum_wgs84)(units_m)(no_defs)},
//{7400},
//{7401},
//{7402},
diff --git a/boost/geometry/srs/projections/epsg_params.hpp b/boost/geometry/srs/projections/epsg_params.hpp
index e9572bf25d..ba04f89c03 100644
--- a/boost/geometry/srs/projections/epsg_params.hpp
+++ b/boost/geometry/srs/projections/epsg_params.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry
-// Copyright (c) 2017, Oracle and/or its affiliates.
+// Copyright (c) 2017-2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -18,7 +19,7 @@
namespace boost { namespace geometry
{
-
+
namespace srs
{
diff --git a/boost/geometry/srs/projections/epsg_traits.hpp b/boost/geometry/srs/projections/epsg_traits.hpp
index ce9125a7ce..53bdcc560d 100644
--- a/boost/geometry/srs/projections/epsg_traits.hpp
+++ b/boost/geometry/srs/projections/epsg_traits.hpp
@@ -2,8 +2,9 @@
// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2017, 2018, 2020.
-// Modifications copyright (c) 2017-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017, 2018, 2020, 2022.
+// Copyright (c) 2017-2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -1821,7 +1822,7 @@ BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3781) srs::spar::paramet
BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3782) srs::spar::parameters<srs::spar::proj_tmerc,srs::spar::lat_0<>,srs::spar::lon_0<>,srs::spar::k<>,srs::spar::x_0<>,srs::spar::y_0<>,srs::spar::ellps_grs80,srs::spar::units_m,srs::spar::no_defs> BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_MID() (srs::spar::proj_tmerc(),srs::spar::lat_0<>(0),srs::spar::lon_0<>(-120),srs::spar::k<>(0.9999),srs::spar::x_0<>(0),srs::spar::y_0<>(0)) BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_END()
BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3783) srs::spar::parameters<srs::spar::proj_tmerc,srs::spar::lat_0<>,srs::spar::lon_0<>,srs::spar::k<>,srs::spar::x_0<>,srs::spar::y_0<>,srs::spar::ellps_wgs84,srs::spar::towgs84<>,srs::spar::units_m,srs::spar::no_defs> BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_MID() (srs::spar::proj_tmerc(),srs::spar::lat_0<>(-25.06855261111111),srs::spar::lon_0<>(-130.1129671111111),srs::spar::k<>(1),srs::spar::x_0<>(14200),srs::spar::y_0<>(15500),srs::spar::ellps_wgs84(),srs::spar::towgs84<>(0,0,0,0,0,0,0)) BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_END()
BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3784) srs::spar::parameters<srs::spar::proj_utm,srs::spar::zone<9>,srs::spar::south,srs::spar::ellps_intl,srs::spar::towgs84<>,srs::spar::units_m,srs::spar::no_defs> BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_MID() (srs::spar::proj_utm(),srs::spar::zone<9>(),srs::spar::south(),srs::spar::ellps_intl(),srs::spar::towgs84<>(185,165,42,0,0,0,0)) BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_END()
-BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3785) srs::spar::parameters<srs::spar::proj_merc,srs::spar::lat_ts<>,srs::spar::lon_0<>,srs::spar::k<>,srs::spar::x_0<>,srs::spar::y_0<>,srs::spar::r<>,srs::spar::units_m,srs::spar::no_defs> BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_MID() (srs::spar::proj_merc(),srs::spar::lat_ts<>(0),srs::spar::lon_0<>(0),srs::spar::k<>(1),srs::spar::x_0<>(0),srs::spar::y_0<>(0),srs::spar::r<>(6378137)) BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_END()
+BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3785) srs::spar::parameters<srs::spar::proj_webmerc,srs::spar::lon_0<>,srs::spar::x_0<>,srs::spar::y_0<>,srs::spar::ellps_wgs84,srs::spar::datum_wgs84,srs::spar::units_m,srs::spar::no_defs> BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_MID() (srs::spar::proj_webmerc(),srs::spar::lon_0<>(0),srs::spar::x_0<>(0),srs::spar::y_0<>(0)) BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_END()
BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3786) srs::spar::parameters<srs::spar::proj_eqc,srs::spar::lat_ts<>,srs::spar::lat_0<>,srs::spar::lon_0<>,srs::spar::x_0<>,srs::spar::y_0<>,srs::spar::r<>,srs::spar::units_m,srs::spar::no_defs> BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_MID() (srs::spar::proj_eqc(),srs::spar::lat_ts<>(0),srs::spar::lat_0<>(0),srs::spar::lon_0<>(0),srs::spar::x_0<>(0),srs::spar::y_0<>(0),srs::spar::r<>(6371007)) BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_END()
BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3787) srs::spar::parameters<srs::spar::proj_tmerc,srs::spar::lat_0<>,srs::spar::lon_0<>,srs::spar::k<>,srs::spar::x_0<>,srs::spar::y_0<>,srs::spar::ellps_bessel,srs::spar::towgs84<>,srs::spar::units_m,srs::spar::no_defs> BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_MID() (srs::spar::proj_tmerc(),srs::spar::lat_0<>(0),srs::spar::lon_0<>(15),srs::spar::k<>(0.9999),srs::spar::x_0<>(500000),srs::spar::y_0<>(-5000000),srs::spar::ellps_bessel(),srs::spar::towgs84<>(577.326,90.129,463.919,5.137,1.474,5.297,2.4232)) BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_END()
BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3788) srs::spar::parameters<srs::spar::proj_tmerc,srs::spar::lat_0<>,srs::spar::lon_0<>,srs::spar::k<>,srs::spar::x_0<>,srs::spar::y_0<>,srs::spar::ellps_grs80,srs::spar::towgs84<>,srs::spar::units_m,srs::spar::no_defs> BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_MID() (srs::spar::proj_tmerc(),srs::spar::lat_0<>(0),srs::spar::lon_0<>(166),srs::spar::k<>(1),srs::spar::x_0<>(3500000),srs::spar::y_0<>(10000000),srs::spar::ellps_grs80(),srs::spar::towgs84<>(0,0,0,0,0,0,0)) BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_END()
@@ -1871,6 +1872,7 @@ BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3824) srs::spar::paramet
//BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3848)
//BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3849)
//BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3850)
+BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3857) srs::spar::parameters<srs::spar::proj_webmerc,srs::spar::lon_0<>,srs::spar::x_0<>,srs::spar::y_0<>,srs::spar::ellps_wgs84,srs::spar::datum_wgs84,srs::spar::units_m,srs::spar::no_defs> BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_MID() (srs::spar::proj_webmerc(),srs::spar::lon_0<>(0),srs::spar::x_0<>(0),srs::spar::y_0<>(0)) BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_END()
BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3920) srs::spar::parameters<srs::spar::proj_utm,srs::spar::zone<20>,srs::spar::ellps_clrk66,srs::spar::towgs84<>,srs::spar::units_m,srs::spar::no_defs> BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_MID() (srs::spar::proj_utm(),srs::spar::zone<20>(),srs::spar::ellps_clrk66(),srs::spar::towgs84<>(11,72,-101,0,0,0,0)) BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_END()
BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3942) srs::spar::parameters<srs::spar::proj_lcc,srs::spar::lat_1<>,srs::spar::lat_2<>,srs::spar::lat_0<>,srs::spar::lon_0<>,srs::spar::x_0<>,srs::spar::y_0<>,srs::spar::ellps_grs80,srs::spar::towgs84<>,srs::spar::units_m,srs::spar::no_defs> BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_MID() (srs::spar::proj_lcc(),srs::spar::lat_1<>(41.25),srs::spar::lat_2<>(42.75),srs::spar::lat_0<>(42),srs::spar::lon_0<>(3),srs::spar::x_0<>(1700000),srs::spar::y_0<>(1200000),srs::spar::ellps_grs80(),srs::spar::towgs84<>(0,0,0,0,0,0,0)) BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_END()
BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 3943) srs::spar::parameters<srs::spar::proj_lcc,srs::spar::lat_1<>,srs::spar::lat_2<>,srs::spar::lat_0<>,srs::spar::lon_0<>,srs::spar::x_0<>,srs::spar::y_0<>,srs::spar::ellps_grs80,srs::spar::towgs84<>,srs::spar::units_m,srs::spar::no_defs> BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_MID() (srs::spar::proj_lcc(),srs::spar::lat_1<>(42.25),srs::spar::lat_2<>(43.75),srs::spar::lat_0<>(43),srs::spar::lon_0<>(3),srs::spar::x_0<>(1700000),srs::spar::y_0<>(2200000),srs::spar::ellps_grs80(),srs::spar::towgs84<>(0,0,0,0,0,0,0)) BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_END()
@@ -2624,6 +2626,7 @@ BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 4999) srs::spar::paramet
//BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 5819)
//BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 5820)
//BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 5821)
+BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 6247) srs::spar::parameters<srs::spar::proj_col_urban,srs::spar::lon_0<>,srs::spar::lat_0<>,srs::spar::x_0<>,srs::spar::y_0<>,srs::spar::h_0<>,srs::spar::ellps_grs80,srs::spar::datum_wgs84,srs::spar::units_m,srs::spar::no_defs> BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_MID() (srs::spar::proj_col_urban(),srs::spar::lon_0<>(-74.1465916666667),srs::spar::lat_0<>(4.68048611111111),srs::spar::x_0<>(92334.879),srs::spar::y_0<>(109320.965),srs::spar::h_0<>(2550)) BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_END()
//BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 7400)
//BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 7401)
//BOOST_GEOMETRY_PROJECTIONS_DETAIL_SRID_TRAITS_BEG(epsg, 7402)
diff --git a/boost/geometry/srs/projections/esri_params.hpp b/boost/geometry/srs/projections/esri_params.hpp
index 01673092f8..741e194b16 100644
--- a/boost/geometry/srs/projections/esri_params.hpp
+++ b/boost/geometry/srs/projections/esri_params.hpp
@@ -18,7 +18,7 @@
namespace boost { namespace geometry
{
-
+
namespace srs
{
diff --git a/boost/geometry/srs/projections/factory.hpp b/boost/geometry/srs/projections/factory.hpp
index 156fece801..acea3b5125 100644
--- a/boost/geometry/srs/projections/factory.hpp
+++ b/boost/geometry/srs/projections/factory.hpp
@@ -1,9 +1,11 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017-2021.
-// Modifications copyright (c) 2017-2021, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2022.
+// Modifications copyright (c) 2017-2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -14,10 +16,9 @@
#define BOOST_GEOMETRY_PROJECTIONS_FACTORY_HPP
#include <map>
+#include <memory>
#include <string>
-#include <boost/shared_ptr.hpp>
-
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/srs/projections/dpar.hpp>
@@ -36,6 +37,7 @@
#include <boost/geometry/srs/projections/proj/cc.hpp>
#include <boost/geometry/srs/projections/proj/cea.hpp>
#include <boost/geometry/srs/projections/proj/chamb.hpp>
+#include <boost/geometry/srs/projections/proj/col_urban.hpp>
#include <boost/geometry/srs/projections/proj/collg.hpp>
#include <boost/geometry/srs/projections/proj/crast.hpp>
#include <boost/geometry/srs/projections/proj/denoy.hpp>
@@ -180,7 +182,7 @@ private:
typedef factory_key<Params> key;
typedef typename key::type key_type;
- typedef boost::shared_ptr<entry_base> entry_ptr;
+ typedef std::shared_ptr<entry_base> entry_ptr;
typedef std::map<key_type, entry_ptr> entries_map;
@@ -203,6 +205,7 @@ public:
detail::cc_init(*this);
detail::cea_init(*this);
detail::chamb_init(*this);
+ detail::col_urban_init(*this);
detail::collg_init(*this);
detail::crast_init(*this);
detail::denoy_init(*this);
diff --git a/boost/geometry/srs/projections/iau2000_params.hpp b/boost/geometry/srs/projections/iau2000_params.hpp
index 1cc8539a05..2782f2ae05 100644
--- a/boost/geometry/srs/projections/iau2000_params.hpp
+++ b/boost/geometry/srs/projections/iau2000_params.hpp
@@ -18,7 +18,7 @@
namespace boost { namespace geometry
{
-
+
namespace srs
{
diff --git a/boost/geometry/srs/projections/impl/base_dynamic.hpp b/boost/geometry/srs/projections/impl/base_dynamic.hpp
index 74fbffa742..de94bade04 100644
--- a/boost/geometry/srs/projections/impl/base_dynamic.hpp
+++ b/boost/geometry/srs/projections/impl/base_dynamic.hpp
@@ -146,7 +146,7 @@ public:
dynamic_wrapper_fi(Params const& params, P const& par, P3 const& p3)
: base_t(params, par, p3)
{}
-
+
virtual void inv(P const& par, CT const& xy_x, CT const& xy_y, CT& lp_lon, CT& lp_lat) const
{
this->prj().inv(par, xy_x, xy_y, lp_lon, lp_lat);
diff --git a/boost/geometry/srs/projections/impl/dms_parser.hpp b/boost/geometry/srs/projections/impl/dms_parser.hpp
index ee9c8db3d1..02e26b7287 100644
--- a/boost/geometry/srs/projections/impl/dms_parser.hpp
+++ b/boost/geometry/srs/projections/impl/dms_parser.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017, 2018.
// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates.
@@ -39,9 +40,10 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
+#include <algorithm>
#include <string>
+#include <ostream>
-#include <boost/algorithm/string.hpp>
#include <boost/static_assert.hpp>
#include <boost/geometry/core/config.hpp>
@@ -123,16 +125,10 @@ struct dms_parser
bool has_dms[3];
dms_value()
-#ifdef BOOST_GEOMETRY_CXX11_ARRAY_UNIFIED_INITIALIZATION
- : dms{0, 0, 0}
- , has_dms{false, false, false}
- {}
-#else
{
std::fill(dms, dms + 3, T(0));
std::fill(has_dms, has_dms + 3, false);
}
-#endif
};
diff --git a/boost/geometry/srs/projections/impl/geocent.hpp b/boost/geometry/srs/projections/impl/geocent.hpp
index 8ae2f393ce..a4846c2d86 100644
--- a/boost/geometry/srs/projections/impl/geocent.hpp
+++ b/boost/geometry/srs/projections/impl/geocent.hpp
@@ -28,7 +28,7 @@
* ERROR HANDLING
*
* This component checks parameters for valid values. If an invalid value
- * is found, the error code is combined with the current error code using
+ * is found, the error code is combined with the current error code using
* the bitwise or. This combining allows multiple error codes to be
* returned. The possible error codes are:
*
@@ -47,13 +47,13 @@
* GEOCENTRIC is intended for reuse by any application that performs
* coordinate conversions between geodetic coordinates and geocentric
* coordinates.
- *
+ *
*
* REFERENCES
- *
+ *
* An Improved Algorithm for Geocentric to Geodetic Coordinate Conversion,
* Ralph Toms, February 1996 UCRL-JC-123138.
- *
+ *
* Further information on GEOCENTRIC can be found in the Reuse Manual.
*
* GEOCENTRIC originated from : U.S. Army Topographic Engineering Center
@@ -135,11 +135,11 @@ inline T AD_C()
/***************************************************************************/
/*
- * FUNCTIONS
+ * FUNCTIONS
*/
template <typename T>
-inline long pj_Set_Geocentric_Parameters (GeocentricInfo<T> & gi, T const& a, T const& b)
+inline long pj_Set_Geocentric_Parameters (GeocentricInfo<T> & gi, T const& a, T const& b)
{ /* BEGIN Set_Geocentric_Parameters */
/*
@@ -172,7 +172,7 @@ inline long pj_Set_Geocentric_Parameters (GeocentricInfo<T> & gi, T const& a, T
template <typename T>
inline void pj_Get_Geocentric_Parameters (GeocentricInfo<T> const& gi,
- T & a,
+ T & a,
T & b)
{ /* BEGIN Get_Geocentric_Parameters */
/*
@@ -246,7 +246,7 @@ inline long pj_Convert_Geodetic_To_Geocentric (GeocentricInfo<T> const& gi,
/*
* The function Convert_Geocentric_To_Geodetic converts geocentric
- * coordinates (X, Y, Z) to geodetic coordinates (latitude, longitude,
+ * coordinates (X, Y, Z) to geodetic coordinates (latitude, longitude,
* and height), according to the current ellipsoid parameters.
*
* X : Geocentric X coordinate, in meters. (input)
@@ -326,7 +326,7 @@ inline void pj_Convert_Geocentric_To_Geodetic (GeocentricInfo<T> const& gi,
Latitude = PI_OVER_2;
Height = -Geocent_b;
return;
- }
+ }
}
}
W2 = X*X + Y*Y;
diff --git a/boost/geometry/srs/projections/impl/pj_apply_gridshift.hpp b/boost/geometry/srs/projections/impl/pj_apply_gridshift.hpp
index e9e4c9e5bd..3d1db4c065 100644
--- a/boost/geometry/srs/projections/impl/pj_apply_gridshift.hpp
+++ b/boost/geometry/srs/projections/impl/pj_apply_gridshift.hpp
@@ -338,7 +338,7 @@ inline bool pj_apply_gridshift_3(StreamPolicy const& stream_policy,
grids_tag)
{
typedef typename boost::range_size<Range>::type size_type;
-
+
// If the grids are empty the indexes are as well
if (gridindexes.empty())
{
@@ -356,7 +356,7 @@ inline bool pj_apply_gridshift_3(StreamPolicy const& stream_policy,
CalcT in_lon = geometry::get_as_radian<0>(point);
CalcT in_lat = geometry::get_as_radian<1>(point);
-
+
pj_gi * gip = find_grid(in_lon, in_lat, grids.gridinfo, gridindexes);
if ( gip != NULL )
@@ -369,7 +369,7 @@ inline bool pj_apply_gridshift_3(StreamPolicy const& stream_policy,
CalcT out_lat = HUGE_VAL;
nad_cvt<Inverse>(in_lon, in_lat, out_lon, out_lat, *gip);
-
+
// TODO: check differently
if ( out_lon != HUGE_VAL )
{
@@ -392,7 +392,7 @@ inline bool pj_apply_gridshift_3(StreamPolicy const& stream_policy,
shared_grids_tag)
{
typedef typename boost::range_size<Range>::type size_type;
-
+
// If the grids are empty the indexes are as well
if (gridindexes.empty())
{
diff --git a/boost/geometry/srs/projections/impl/pj_datum_set.hpp b/boost/geometry/srs/projections/impl/pj_datum_set.hpp
index e44491e25a..2f119bdf08 100644
--- a/boost/geometry/srs/projections/impl/pj_datum_set.hpp
+++ b/boost/geometry/srs/projections/impl/pj_datum_set.hpp
@@ -2,6 +2,7 @@
// This file is manually converted from PROJ4
// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017-2020.
// Modifications copyright (c) 2017-2020, Oracle and/or its affiliates.
@@ -43,7 +44,8 @@
#include <string>
#include <vector>
-#include <boost/algorithm/string.hpp>
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/algorithm/string/split.hpp>
#include <boost/geometry/srs/projections/dpar.hpp>
#include <boost/geometry/srs/projections/exception.hpp>
@@ -103,7 +105,7 @@ inline const pj_datums_type<T>* pj_datum_find_datum(srs::dpar::parameters<T> con
{
typename srs::dpar::parameters<T>::const_iterator
it = pj_param_find(params, srs::dpar::datum);
-
+
if (it != params.end())
{
const pj_datums_type<T>* pj_datums = pj_get_datums<T>().first;
@@ -184,7 +186,7 @@ inline bool pj_datum_find_nadgrids(srs::detail::proj4_parameters const& params,
{
std::string::size_type end = snadgrids.find(',', i);
std::string name = snadgrids.substr(i, end - i);
-
+
i = end;
if (end != std::string::npos)
++i;
@@ -207,7 +209,7 @@ inline bool pj_datum_find_nadgrids(srs::dpar::parameters<T> const& params,
{
out = it->template get_value<srs::detail::nadgrids>();
}
-
+
return ! out.empty();
}
@@ -284,7 +286,7 @@ inline bool pj_datum_find_towgs84(srs::dpar::parameters<T> const& params,
{
typename srs::dpar::parameters<T>::const_iterator
it = pj_param_find(params, srs::dpar::towgs84);
-
+
if (it != params.end())
{
srs::detail::towgs84<T> const&
diff --git a/boost/geometry/srs/projections/impl/pj_ell_set.hpp b/boost/geometry/srs/projections/impl/pj_ell_set.hpp
index 18b4aa1164..128c70e689 100644
--- a/boost/geometry/srs/projections/impl/pj_ell_set.hpp
+++ b/boost/geometry/srs/projections/impl/pj_ell_set.hpp
@@ -129,7 +129,7 @@ inline bool pj_ell_init_ellps(srs::dpar::parameters<T> const& params, T &a, T &b
const pj_ellps_type<T>* pj_ellps = pj_get_ellps<T>().first;
const int n = pj_get_ellps<T>().second;
int i = it->template get_value<int>();
-
+
if (i < 0 || i >= n) {
BOOST_THROW_EXCEPTION( projection_exception(error_unknown_ellp_param) );
}
@@ -244,7 +244,7 @@ inline void pj_ell_init(Params const& params, T &a, T &es)
} else if (pj_param_f<srs::spar::rf>(params, "rf", srs::dpar::rf, es)) { /* recip flattening */
if (es == 0.0) {
BOOST_THROW_EXCEPTION( projection_exception(error_rev_flattening_is_zero) );
- }
+ }
es = 1./ es;
es = es * (2. - es);
is_ell_set = true;
diff --git a/boost/geometry/srs/projections/impl/pj_fwd.hpp b/boost/geometry/srs/projections/impl/pj_fwd.hpp
index 01b7b97a2d..786be4bc0c 100644
--- a/boost/geometry/srs/projections/impl/pj_fwd.hpp
+++ b/boost/geometry/srs/projections/impl/pj_fwd.hpp
@@ -92,8 +92,14 @@ inline void pj_fwd(Prj const& prj, P const& par, LL const& ll, XY& xy)
prj.fwd(par, lp_lon, lp_lat, x, y);
- geometry::set<0>(xy, par.fr_meter * (par.a * x + par.x0));
- geometry::set<1>(xy, par.fr_meter * (par.a * y + par.y0));
+ if (par.axis[0] == 0)
+ {
+ geometry::set<0>(xy, par.sign[0] * par.fr_meter * (par.a * x + par.x0));
+ geometry::set<1>(xy, par.sign[1] * par.fr_meter * (par.a * y + par.y0));
+ } else {
+ geometry::set<1>(xy, par.sign[1] * par.fr_meter * (par.a * x + par.x0));
+ geometry::set<0>(xy, par.sign[0] * par.fr_meter * (par.a * y + par.y0));
+ }
}
} // namespace detail
diff --git a/boost/geometry/srs/projections/impl/pj_generic_inverse.hpp b/boost/geometry/srs/projections/impl/pj_generic_inverse.hpp
new file mode 100644
index 0000000000..d54dbc40a2
--- /dev/null
+++ b/boost/geometry/srs/projections/impl/pj_generic_inverse.hpp
@@ -0,0 +1,163 @@
+// Boost.Geometry
+
+// Copyright (c) 2022 Adam Wulkiewicz, Lodz, Poland.
+
+// Copyright (c) 2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Use, modification and distribution is subject to the 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 file is converted from PROJ, https://github.com/OSGeo/PROJ
+
+// Last updated version of proj: 9.0.0
+
+// Original copyright notice:
+
+/******************************************************************************
+ *
+ * Project: PROJ
+ * Purpose: Generic method to compute inverse projection from forward method
+ * Author: Even Rouault <even dot rouault at spatialys dot com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifndef BOOST_GEOMETRY_PROJECTIONS_IMPL_PJ_GENERIC_INVERSE_HPP
+#define BOOST_GEOMETRY_PROJECTIONS_IMPL_PJ_GENERIC_INVERSE_HPP
+
+#include <algorithm>
+#include <cmath>
+
+#include <boost/geometry/util/math.hpp>
+
+/** Compute (lam, phi) corresponding to input (xy_x, xy_y) for projection P.
+ *
+ * Uses Newton-Raphson method, extended to 2D variables, that is using
+ * inversion of the Jacobian 2D matrix of partial derivatives. The derivatives
+ * are estimated numerically from the P->fwd method evaluated at close points.
+ *
+ * Note: thresholds used have been verified to work with adams_ws2 and wink2
+ *
+ * Starts with initial guess provided by user in lpInitial
+ */
+
+
+namespace boost { namespace geometry { namespace projections
+{
+
+namespace detail
+{
+
+template <typename T, typename Parameters, typename Projection>
+void pj_generic_inverse_2d(T const& xy_x,
+ T const& xy_y,
+ Parameters const& par,
+ Projection const& proj,
+ T& lp_lat,
+ T& lp_lon)
+{
+ T deriv_lam_X = 0;
+ T deriv_lam_Y = 0;
+ T deriv_phi_X = 0;
+ T deriv_phi_Y = 0;
+
+ for (int i = 0; i < 15; i++)
+ {
+ T xyApprox_x;
+ T xyApprox_y;
+ proj->fwd(par, lp_lon, lp_lat, xyApprox_x, xyApprox_y);
+ T const deltaX = xyApprox_x - xy_x;
+ T const deltaY = xyApprox_y - xy_y;
+ if (fabs(deltaX) < 1e-10 && fabs(deltaY) < 1e-10) return;
+
+ if (fabs(deltaX) > 1e-6 || fabs(deltaY) > 1e-6)
+ {
+ // Compute Jacobian matrix (only if we aren't close to the final
+ // result to speed things a bit)
+ T lp2_lat;
+ T lp2_lon;
+ T xy2_x;
+ T xy2_y;
+ T const dLam = lp_lat > 0 ? -1e-6 : 1e-6;
+ lp2_lat = lp_lat + dLam;
+ lp2_lon = lp_lon;
+ proj->fwd(par, lp2_lon, lp2_lat, xy2_x, xy2_y);
+ //xy2 = P->fwd(lp2, P);
+ T const deriv_X_lam = (xy2_x - xyApprox_x) / dLam;
+ T const deriv_Y_lam = (xy2_y - xyApprox_y) / dLam;
+
+ T const dPhi = lp_lon > 0 ? -1e-6 : 1e-6;
+ lp2_lat = lp_lat;
+ lp2_lon = lp_lon + dPhi;
+ proj->fwd(par, lp2_lon, lp2_lat, xy2_x, xy2_y);
+ //xy2 = P->fwd(lp2, P);
+ T const deriv_X_phi = (xy2_x - xyApprox_x) / dPhi;
+ T const deriv_Y_phi = (xy2_y - xyApprox_y) / dPhi;
+
+ // Inverse of Jacobian matrix
+ T const det = deriv_X_lam * deriv_Y_phi - deriv_X_phi * deriv_Y_lam;
+ if (det != 0)
+ {
+ deriv_lam_X = deriv_Y_phi / det;
+ deriv_lam_Y = -deriv_X_phi / det;
+ deriv_phi_X = -deriv_Y_lam / det;
+ deriv_phi_Y = deriv_X_lam / det;
+ }
+ }
+
+ if (xy_x != 0)
+ {
+ // Limit the amplitude of correction to avoid overshoots due to
+ // bad initial guess
+ T const delta_lam = (std::max)(
+ (std::min)(deltaX * deriv_lam_X + deltaY * deriv_lam_Y, 0.3),
+ -0.3);
+ lp_lat -= delta_lam;
+ if (lp_lat < -math::pi<T>())
+ lp_lat = -math::pi<T>();
+ else if (lp_lat > math::pi<T>())
+ lp_lat = math::pi<T>();
+ }
+
+ if (xy_y != 0)
+ {
+ T const delta_phi = (std::max)(
+ (std::min)(deltaX * deriv_phi_X + deltaY * deriv_phi_Y, 0.3),
+ -0.3);
+ lp_lon -= delta_phi;
+ static T const half_pi = math::half_pi<T>();
+ if (lp_lon < -half_pi)
+ lp_lon = -half_pi;
+ else if (lp_lon > half_pi)
+ lp_lon = half_pi;
+ }
+ }
+ //pj_ctx_set_errno(P->ctx, PJD_ERR_NON_CONVERGENT);
+}
+
+} // namespace detail
+
+}}} // namespace boost::geometry::projections
+
+#endif // BOOST_GEOMETRY_PROJECTIONS_IMPL_PJ_GENERIC_INVERSE_HPP
diff --git a/boost/geometry/srs/projections/impl/pj_gridinfo.hpp b/boost/geometry/srs/projections/impl/pj_gridinfo.hpp
index 0d297b1cb8..2822fe6959 100644
--- a/boost/geometry/srs/projections/impl/pj_gridinfo.hpp
+++ b/boost/geometry/srs/projections/impl/pj_gridinfo.hpp
@@ -1,6 +1,8 @@
// Boost.Geometry
// This file is manually converted from PROJ4
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+
// This file was modified by Oracle on 2018, 2019.
// Modifications copyright (c) 2018-2019, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -41,11 +43,11 @@
#define BOOST_GEOMETRY_SRS_PROJECTIONS_IMPL_PJ_GRIDINFO_HPP
-#include <boost/algorithm/string.hpp>
-
#include <boost/geometry/core/assert.hpp>
#include <boost/geometry/util/math.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/algorithm/string/trim.hpp>
#include <boost/cstdint.hpp>
#include <algorithm>
@@ -190,18 +192,18 @@ template <typename IStream>
bool pj_gridinfo_load_ctable(IStream & is, pj_gi_load & gi)
{
pj_ctable & ct = gi.ct;
-
+
// Move the input stream by the size of the proj4 original CTABLE
std::size_t header_size = 80
+ 2 * sizeof(pj_ctable::lp_t)
+ sizeof(pj_ctable::ilp_t)
+ sizeof(pj_ctable::flp_t*);
is.seekg(header_size);
-
+
// read all the actual shift values
std::size_t a_size = ct.lim.lam * ct.lim.phi;
ct.cvs.resize(a_size);
-
+
std::size_t ch_size = sizeof(pj_ctable::flp_t) * a_size;
is.read(reinterpret_cast<char*>(&ct.cvs[0]), ch_size);
@@ -213,7 +215,7 @@ bool pj_gridinfo_load_ctable(IStream & is, pj_gi_load & gi)
}
return true;
-}
+}
/************************************************************************/
/* pj_gridinfo_load_ctable2() */
@@ -274,7 +276,7 @@ inline bool pj_gridinfo_load_ntv1(IStream & is, pj_gi_load & gi)
std::vector<double> row_buf(r_size);
gi.ct.cvs.resize(gi.ct.lim.lam * gi.ct.lim.phi);
-
+
for (boost::int32_t row = 0; row < gi.ct.lim.phi; row++ )
{
is.read(reinterpret_cast<char*>(&row_buf[0]), ch_size);
@@ -366,7 +368,7 @@ inline bool pj_gridinfo_load_gtx(IStream & is, pj_gi_load & gi)
{
boost::int32_t words = gi.ct.lim.lam * gi.ct.lim.phi;
std::size_t const ch_size = sizeof(float) * words;
-
+
is.seekg(gi.grid_offset);
// TODO: Consider changing this unintuitive code
@@ -827,12 +829,12 @@ inline bool pj_gridinfo_init_ctable2(std::string const& gridname,
memcpy( &ct.ll, header + 96, 40 );
// do some minimal validation to ensure the structure isn't corrupt
- if ( (ct.lim.lam < 1) || (ct.lim.lam > 100000)
+ if ( (ct.lim.lam < 1) || (ct.lim.lam > 100000)
|| (ct.lim.phi < 1) || (ct.lim.phi > 100000) )
{
return false;
}
-
+
// trim white space and newlines off id
boost::trim_right_if(ct.id, is_trimmable_char());
@@ -879,12 +881,12 @@ inline bool pj_gridinfo_init_ctable(std::string const& gridname,
memcpy( &ct.ll, header + 80, 40 );
// do some minimal validation to ensure the structure isn't corrupt
- if ( (ct.lim.lam < 1) || (ct.lim.lam > 100000)
+ if ( (ct.lim.lam < 1) || (ct.lim.lam > 100000)
|| (ct.lim.phi < 1) || (ct.lim.phi > 100000) )
{
return false;
}
-
+
// trim white space and newlines off id
boost::trim_right_if(ct.id, is_trimmable_char());
@@ -923,7 +925,7 @@ inline bool pj_gridinfo_init(std::string const& gridname,
if ( is.fail() ) {
return false;
}
-
+
is.seekg(0);
// Determine file type.
diff --git a/boost/geometry/srs/projections/impl/pj_gridlist.hpp b/boost/geometry/srs/projections/impl/pj_gridlist.hpp
index 6407142f9b..06904238f5 100644
--- a/boost/geometry/srs/projections/impl/pj_gridlist.hpp
+++ b/boost/geometry/srs/projections/impl/pj_gridlist.hpp
@@ -101,7 +101,7 @@ inline bool pj_gridlist_merge_gridfile(std::string const& gridname,
{
// Try to find in the existing list of loaded grids. Add all
// matching grids as with NTv2 we can get many grids from one
- // file (one shared gridname).
+ // file (one shared gridname).
if (pj_gridlist_find_all(gridname, grids.gridinfo, gridindexes))
return true;
@@ -118,7 +118,7 @@ inline bool pj_gridlist_merge_gridfile(std::string const& gridname,
// Add the grid now that it is loaded.
pj_gridlist_add_seq_inc(gridindexes, orig_size, grids.gridinfo.size());
-
+
return true;
}
@@ -132,10 +132,10 @@ inline bool pj_gridlist_merge_gridfile(std::string const& gridname,
{
// Try to find in the existing list of loaded grids. Add all
// matching grids as with NTv2 we can get many grids from one
- // file (one shared gridname).
+ // file (one shared gridname).
{
typename SharedGrids::read_locked lck_grids(grids);
-
+
if (pj_gridlist_find_all(gridname, lck_grids.gridinfo, gridindexes))
return true;
}
@@ -145,7 +145,7 @@ inline bool pj_gridlist_merge_gridfile(std::string const& gridname,
stream_policy.open(is, gridname);
pj_gridinfo new_grids;
-
+
if (! pj_gridinfo_init(gridname, is, new_grids))
{
return false;
@@ -171,9 +171,9 @@ inline bool pj_gridlist_merge_gridfile(std::string const& gridname,
for (std::size_t i = 0 ; i < new_grids.size() ; ++ i)
new_grids[i].swap(lck_grids.gridinfo[i + orig_size]);
}
-
+
pj_gridlist_add_seq_inc(gridindexes, orig_size, new_size);
-
+
return true;
}
@@ -200,7 +200,7 @@ inline void pj_gridlist_from_nadgrids(srs::detail::nadgrids const& nadgrids,
it != nadgrids.end() ; ++it)
{
bool required = (*it)[0] != '@';
-
+
std::string name(it->begin() + (required ? 0 : 1), it->end());
if ( ! pj_gridlist_merge_gridfile(name, stream_policy, grids, gridindexes,
diff --git a/boost/geometry/srs/projections/impl/pj_init.hpp b/boost/geometry/srs/projections/impl/pj_init.hpp
index 9f8119e4ff..66aa7ba0df 100644
--- a/boost/geometry/srs/projections/impl/pj_init.hpp
+++ b/boost/geometry/srs/projections/impl/pj_init.hpp
@@ -2,6 +2,7 @@
// This file is manually converted from PROJ4
// Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017-2020.
// Modifications copyright (c) 2017-2020, Oracle and/or its affiliates.
@@ -44,9 +45,6 @@
#include <type_traits>
#include <vector>
-#include <boost/algorithm/string.hpp>
-#include <boost/tuple/tuple.hpp>
-
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/srs/projections/dpar.hpp>
@@ -60,8 +58,8 @@
#include <boost/geometry/srs/projections/proj4.hpp>
#include <boost/geometry/srs/projections/spar.hpp>
-#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry { namespace projections
@@ -354,7 +352,7 @@ inline void pj_init_pm(srs::detail::proj4_parameters const& params, T& val)
}
BOOST_CATCH_END
}
-
+
val = 0.0;
}
@@ -428,6 +426,81 @@ inline void pj_init_pm(srs::spar::parameters<Ps...> const& params, T& val)
}
/************************************************************************/
+/* pj_init_axis() */
+/************************************************************************/
+
+template <typename Params, typename T>
+inline void pj_init_axis(Params const& params, parameters<T> & projdef)
+{
+ std::string axis = pj_get_param_s(params, "axis");
+ if(! axis.empty())
+ {
+ for (std::size_t i = 0; i < axis.length(); ++i)
+ {
+ switch(axis[i])
+ {
+ case 'w':
+ projdef.sign[i] = -1;
+ projdef.axis[i] = 0;
+ break;
+ case 'e':
+ projdef.sign[i] = 1;
+ projdef.axis[i] = 0;
+ break;
+ case 's':
+ projdef.sign[i] = -1;
+ projdef.axis[i] = 1;
+ break;
+ case 'n':
+ projdef.sign[i] = 1;
+ projdef.axis[i] = 1;
+ break;
+ case 'd':
+ projdef.sign[i] = -1;
+ projdef.axis[i] = 2;
+ break;
+ case 'u':
+ projdef.sign[i] = 1;
+ projdef.axis[i] = 2;
+ break;
+ default:
+ BOOST_THROW_EXCEPTION( projection_exception(error_axis) );
+ }
+ }
+ // Currently not support elevation
+ if (projdef.axis[0] + projdef.axis[1] != 1)
+ {
+ BOOST_THROW_EXCEPTION( projection_exception(error_axis) );
+ }
+ }
+
+}
+
+// TODO: implement axis support for other types of parameters
+
+template <typename T>
+inline void pj_init_axis(srs::dpar::parameters<T> const& , parameters<T> & )
+{}
+
+template <typename Params>
+struct pj_init_axis_static
+{
+ template <typename T>
+ static void apply(Params const& , parameters<T> & )
+ {}
+};
+
+template <typename T, typename ...Ps>
+inline void pj_init_axis(srs::spar::parameters<Ps...> const& params, parameters<T> & projdef)
+{
+ pj_init_axis_static
+ <
+ srs::spar::parameters<Ps...>
+ >::apply(params, projdef);
+}
+
+
+/************************************************************************/
/* pj_init() */
/* */
/* Main entry point for initialing a PJ projections */
@@ -449,7 +522,7 @@ inline parameters<T> pj_init(Params const& params)
// NOTE: proj4 gets defaults from "proj_def.dat".
// In Boost.Geometry this is emulated by manually setting them in
// pj_ell_init and projections aea, lcc and lagrng
-
+
/* set datum parameters */
pj_datum_init(params, pin);
@@ -515,6 +588,9 @@ inline parameters<T> pj_init(Params const& params)
/* prime meridian */
pj_init_pm(params, pin.from_greenwich);
+ /* set axis orientation */
+ pj_init_axis(params, pin);
+
return pin;
}
diff --git a/boost/geometry/srs/projections/impl/pj_inv.hpp b/boost/geometry/srs/projections/impl/pj_inv.hpp
index aa65af9746..0a3d55cf0d 100644
--- a/boost/geometry/srs/projections/impl/pj_inv.hpp
+++ b/boost/geometry/srs/projections/impl/pj_inv.hpp
@@ -62,12 +62,22 @@ inline void pj_inv(PRJ const& prj, PAR const& par, XY const& xy, LL& ll)
/* can't do as much preliminary checking as with forward */
/* descale and de-offset */
- calc_t xy_x = (geometry::get<0>(xy) * par.to_meter - par.x0) * par.ra;
- calc_t xy_y = (geometry::get<1>(xy) * par.to_meter - par.y0) * par.ra;
- calc_t lon = 0, lat = 0;
+ calc_t lon = 0;
+ calc_t lat = 0;
+ calc_t xy_x = 0;
+ calc_t xy_y = 0;
+
+ if (par.axis[0] == 1)
+ {
+ xy_x = (geometry::get<1>(xy) * par.to_meter * par.sign[1] - par.x0) * par.ra;
+ xy_y = (geometry::get<0>(xy) * par.to_meter * par.sign[0] - par.y0) * par.ra;
+ } else {
+ xy_x = (geometry::get<0>(xy) * par.to_meter * par.sign[0] - par.x0) * par.ra;
+ xy_y = (geometry::get<1>(xy) * par.to_meter * par.sign[1] - par.y0) * par.ra;
+ }
prj.inv(par, xy_x, xy_y, lon, lat); /* inverse project */
-
+
lon += par.lam0; /* reduce from del lp.lam */
if (!par.over)
lon = adjlon(lon); /* adjust longitude to CM */
diff --git a/boost/geometry/srs/projections/impl/pj_mlfn.hpp b/boost/geometry/srs/projections/impl/pj_mlfn.hpp
index 92621875bb..2795c7696d 100644
--- a/boost/geometry/srs/projections/impl/pj_mlfn.hpp
+++ b/boost/geometry/srs/projections/impl/pj_mlfn.hpp
@@ -95,7 +95,7 @@ inline en<T> pj_enfn(T const& es)
en[3] = (t *= es) * (C66 - es * C68);
en[4] = t * es * C88;
}
-
+
return en;
}
diff --git a/boost/geometry/srs/projections/impl/pj_param.hpp b/boost/geometry/srs/projections/impl/pj_param.hpp
index 283a65967c..3ff1b06d15 100644
--- a/boost/geometry/srs/projections/impl/pj_param.hpp
+++ b/boost/geometry/srs/projections/impl/pj_param.hpp
@@ -205,7 +205,7 @@ inline bool _pj_param_i(Params const& params, Name const& name, int & par)
{
set_value(par, *it);
return true;
- }
+ }
return false;
}
@@ -214,12 +214,12 @@ template <typename T, typename Params, typename Name>
inline bool _pj_param_f(Params const& params, Name const& name, T & par)
{
check_name(name);
- typename Params::const_iterator it = pj_param_find(params, name);
+ typename Params::const_iterator it = pj_param_find(params, name);
if (it != params.end())
{
set_value(par, *it);
return true;
- }
+ }
return false;
}
@@ -228,19 +228,19 @@ template <typename T, typename Params, typename Name>
inline bool _pj_param_r(Params const& params, Name const& name, T & par)
{
check_name(name);
- typename Params::const_iterator it = pj_param_find(params, name);
+ typename Params::const_iterator it = pj_param_find(params, name);
if (it != params.end())
{
set_value_r(par, *it);
return true;
- }
+ }
return false;
}
/* bool input */
inline bool _pj_get_param_b(srs::detail::proj4_parameters const& pl, std::string const& name)
{
- srs::detail::proj4_parameters::const_iterator it = pj_param_find(pl, name);
+ srs::detail::proj4_parameters::const_iterator it = pj_param_find(pl, name);
if (it != pl.end())
{
switch (it->value[0])
@@ -253,7 +253,7 @@ inline bool _pj_get_param_b(srs::detail::proj4_parameters const& pl, std::string
BOOST_THROW_EXCEPTION( projection_exception(error_invalid_boolean_param) );
return false;
}
- }
+ }
return false;
}
@@ -270,12 +270,12 @@ inline bool _pj_get_param_b(srs::dpar::parameters<T> const& pl, srs::dpar::name_
/* string input */
inline bool pj_param_s(srs::detail::proj4_parameters const& pl, std::string const& name, std::string & par)
{
- srs::detail::proj4_parameters::const_iterator it = pj_param_find(pl, name);
+ srs::detail::proj4_parameters::const_iterator it = pj_param_find(pl, name);
if (it != pl.end())
{
par = it->value;
return true;
- }
+ }
return false;
}
@@ -363,7 +363,7 @@ inline bool _pj_get_param_b(srs::spar::parameters<Ps...> const& params)
// {
// par = static_cast<Value>(it->template get_value<int>());
// return true;
-// }
+// }
// return false;
//}
diff --git a/boost/geometry/srs/projections/impl/pj_qsfn.hpp b/boost/geometry/srs/projections/impl/pj_qsfn.hpp
index 606fab5e4e..7975fbd478 100644
--- a/boost/geometry/srs/projections/impl/pj_qsfn.hpp
+++ b/boost/geometry/srs/projections/impl/pj_qsfn.hpp
@@ -42,7 +42,7 @@
namespace boost { namespace geometry { namespace projections
{
-
+
namespace detail {
/* determine small q */
diff --git a/boost/geometry/srs/projections/impl/pj_transform.hpp b/boost/geometry/srs/projections/impl/pj_transform.hpp
index 02291649e0..b4f14c80b5 100644
--- a/boost/geometry/srs/projections/impl/pj_transform.hpp
+++ b/boost/geometry/srs/projections/impl/pj_transform.hpp
@@ -1,6 +1,8 @@
// Boost.Geometry
// This file is manually converted from PROJ4
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+
// This file was modified by Oracle on 2017, 2018.
// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -49,6 +51,7 @@
#include <boost/geometry/srs/projections/impl/projects.hpp>
#include <boost/geometry/srs/projections/invalid_point.hpp>
+#include <boost/geometry/util/condition.hpp>
#include <boost/geometry/util/range.hpp>
#include <cstring>
@@ -249,7 +252,7 @@ inline bool pj_transform(SrcPrj const& srcprj, Par const& srcdefn,
/* -------------------------------------------------------------------- */
/* Transform Z to meters if it isn't already. */
/* -------------------------------------------------------------------- */
- if( srcdefn.vto_meter != 1.0 && dimension > 2 )
+ if( BOOST_GEOMETRY_CONDITION(srcdefn.vto_meter != 1.0 && dimension > 2) )
{
for( std::size_t i = 0; i < point_count; i++ )
{
@@ -261,10 +264,10 @@ inline bool pj_transform(SrcPrj const& srcprj, Par const& srcdefn,
/* -------------------------------------------------------------------- */
/* Transform geocentric source coordinates to lat/long. */
/* -------------------------------------------------------------------- */
- if( srcdefn.is_geocent )
+ if( BOOST_GEOMETRY_CONDITION(srcdefn.is_geocent) )
{
// Point should be cartesian 3D (ECEF)
- if (dimension < 3)
+ if ( BOOST_GEOMETRY_CONDITION(dimension < 3) )
BOOST_THROW_EXCEPTION( projection_exception(error_geocentric) );
//return PJD_ERR_GEOCENTRIC;
@@ -454,10 +457,10 @@ inline bool pj_transform(SrcPrj const& srcprj, Par const& srcdefn,
/* -------------------------------------------------------------------- */
/* Transform destination latlong to geocentric if required. */
/* -------------------------------------------------------------------- */
- if( dstdefn.is_geocent )
+ if( BOOST_GEOMETRY_CONDITION(dstdefn.is_geocent) )
{
// Point should be cartesian 3D (ECEF)
- if (dimension < 3)
+ if ( BOOST_GEOMETRY_CONDITION(dimension < 3) )
BOOST_THROW_EXCEPTION( projection_exception(error_geocentric) );
//return PJD_ERR_GEOCENTRIC;
@@ -470,7 +473,7 @@ inline bool pj_transform(SrcPrj const& srcprj, Par const& srcdefn,
result = false;
else
BOOST_THROW_EXCEPTION( projection_exception(err) );
-
+
if( dstdefn.fr_meter != 1.0 )
{
for( std::size_t i = 0; i < point_count; i++ )
@@ -569,7 +572,7 @@ inline bool pj_transform(SrcPrj const& srcprj, Par const& srcdefn,
{
point_type & point = range::at(range, i);
coord_t x = get_as_radian<0>(point);
-
+
if( is_invalid_point(point) )
continue;
@@ -770,7 +773,7 @@ inline int pj_geocentric_to_wgs84( Par const& defn,
for(std::size_t i = 0; i < point_count; i++ )
{
point_type & point = range::at(rng, i);
-
+
if( is_invalid_point(point) )
continue;
@@ -925,7 +928,7 @@ inline bool pj_datum_transform(Par const& srcdefn,
/* -------------------------------------------------------------------- */
/* Create a temporary Z array if one is not provided. */
/* -------------------------------------------------------------------- */
-
+
range_wrapper<Range> z_range(range);
/* -------------------------------------------------------------------- */
diff --git a/boost/geometry/srs/projections/impl/projects.hpp b/boost/geometry/srs/projections/impl/projects.hpp
index 6ca757252b..a3b8a64fbb 100644
--- a/boost/geometry/srs/projections/impl/projects.hpp
+++ b/boost/geometry/srs/projections/impl/projects.hpp
@@ -106,7 +106,7 @@ struct pj_consts
T to_meter, fr_meter; /* cartesian scaling */
T vto_meter, vfr_meter; /* Vertical scaling. Internal unit [m] */
- // D A T U M S A N D H E I G H T S Y S T E M S
+ // D A T U M S A N D H E I G H T S Y S T E M S
T from_greenwich; /* prime meridian offset (in radians) */
T long_wrap_center; /* 0.0 for -180 to 180, actually in radians*/
@@ -128,6 +128,9 @@ struct pj_consts
//enum pj_io_units left; /* Flags for input/output coordinate types */
//enum pj_io_units right;
+ srs::detail::axis axis;
+ srs::detail::axis sign;
+
// Initialize all variables
pj_consts()
: a(0), ra(0)
@@ -140,6 +143,7 @@ struct pj_consts
, datum_type(datum_unknown)
, is_long_wrap_set(false)
, over(false), geoc(false), is_latlong(false), is_geocent(false)
+ , axis(0,1,2), sign(1,1,1) //the default east, northing, elevation
//, need_ellps(true)
//, left(PJ_IO_UNITS_ANGULAR), right(PJ_IO_UNITS_CLASSIC)
{}
diff --git a/boost/geometry/srs/projections/par_data.hpp b/boost/geometry/srs/projections/par_data.hpp
index c867676128..5f485433a8 100644
--- a/boost/geometry/srs/projections/par_data.hpp
+++ b/boost/geometry/srs/projections/par_data.hpp
@@ -36,11 +36,9 @@ struct nadgrids
: base_t(first, last)
{}
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
nadgrids(std::initializer_list<std::string> l)
: base_t(l)
{}
-#endif
nadgrids(std::string const& g0)
: base_t(1)
@@ -88,14 +86,9 @@ struct towgs84
towgs84()
: m_size(0)
-#ifdef BOOST_GEOMETRY_CXX11_ARRAY_UNIFIED_INITIALIZATION
- , m_data{0, 0, 0, 0, 0, 0, 0}
- {}
-#else
{
std::fill(m_data, m_data + 7, T(0));
}
-#endif
template <typename It>
towgs84(It first, It last)
@@ -103,12 +96,10 @@ struct towgs84
assign(first, last);
}
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
towgs84(std::initializer_list<T> l)
{
assign(l.begin(), l.end());
}
-#endif
towgs84(T const& v0, T const& v1, T const& v2)
: m_size(3)
@@ -144,12 +135,10 @@ struct towgs84
m_data[m_size] = *first;
}
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
void assign(std::initializer_list<T> l)
{
assign(l.begin(), l.end());
}
-#endif
const_reference operator[](size_type i) const
{
@@ -188,6 +177,97 @@ private:
T m_data[7];
};
+struct axis
+{
+ static const std::size_t static_capacity = 3;
+
+ typedef std::size_t size_type;
+ typedef int value_type;
+ typedef int* iterator;
+ typedef const int* const_iterator;
+ typedef int& reference;
+ typedef const int& const_reference;
+
+ axis()
+ : m_size(3)
+ , m_data{0, 0, 0}
+ {}
+
+ template <typename It>
+ axis(It first, It last)
+ {
+ assign(first, last);
+ }
+
+ axis(std::initializer_list<int> l)
+ {
+ assign(l.begin(), l.end());
+ }
+
+ axis(int const& v0, int const& v1, int const& v2)
+ : m_size(3)
+ {
+ m_data[0] = v0;
+ m_data[1] = v1;
+ m_data[2] = v2;
+ }
+
+ void push_back(int const& v)
+ {
+ BOOST_GEOMETRY_ASSERT(m_size < static_capacity);
+ m_data[m_size] = v;
+ ++m_size;
+ }
+
+ template <typename It>
+ void assign(It first, It last)
+ {
+ for (m_size = 0 ; first != last && m_size < 3 ; ++first, ++m_size)
+ m_data[m_size] = *first;
+ }
+
+ void assign(std::initializer_list<int> l)
+ {
+ assign(l.begin(), l.end());
+ }
+
+ const_reference operator[](size_type i) const
+ {
+ BOOST_GEOMETRY_ASSERT(i < m_size);
+ return m_data[i];
+ }
+
+ reference operator[](size_type i)
+ {
+ BOOST_GEOMETRY_ASSERT(i < m_size);
+ return m_data[i];
+ }
+
+ size_type size() const
+ {
+ return m_size;
+ }
+
+ bool empty() const
+ {
+ return m_size == 0;
+ }
+
+ void clear()
+ {
+ m_size = 0;
+ }
+
+ iterator begin() { return m_data; }
+ iterator end() { return m_data + m_size; }
+ const_iterator begin() const { return m_data; }
+ const_iterator end() const { return m_data + m_size; }
+
+private:
+ size_type m_size;
+ int m_data[3];
+};
+
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
diff --git a/boost/geometry/srs/projections/proj/aea.hpp b/boost/geometry/srs/projections/proj/aea.hpp
index 00f56316bb..bf319618a5 100644
--- a/boost/geometry/srs/projections/proj/aea.hpp
+++ b/boost/geometry/srs/projections/proj/aea.hpp
@@ -174,7 +174,7 @@ namespace projections
};
template <typename Parameters, typename T>
- inline void setup(Parameters const& par, par_aea<T>& proj_parm)
+ inline void setup(Parameters const& par, par_aea<T>& proj_parm)
{
T cosphi, sinphi;
int secant;
diff --git a/boost/geometry/srs/projections/proj/aeqd.hpp b/boost/geometry/srs/projections/proj/aeqd.hpp
index eeee75f965..ca9f49bdf2 100644
--- a/boost/geometry/srs/projections/proj/aeqd.hpp
+++ b/boost/geometry/srs/projections/proj/aeqd.hpp
@@ -204,7 +204,7 @@ namespace projections
inline void s_forward(T const& lp_lon, T lp_lat, T& xy_x, T& xy_y, Par const& /*par*/, ProjParm const& proj_parm)
{
static const T half_pi = detail::half_pi<T>();
-
+
T coslam, cosphi, sinphi;
sinphi = sin(lp_lat);
@@ -248,7 +248,7 @@ namespace projections
{
static const T pi = detail::pi<T>();
static const T half_pi = detail::half_pi<T>();
-
+
T cosc, c_rh, sinc;
if ((c_rh = boost::math::hypot(xy_x, xy_y)) > pi) {
diff --git a/boost/geometry/srs/projections/proj/airy.hpp b/boost/geometry/srs/projections/proj/airy.hpp
index 00931ae825..0237500c66 100644
--- a/boost/geometry/srs/projections/proj/airy.hpp
+++ b/boost/geometry/srs/projections/proj/airy.hpp
@@ -218,7 +218,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(airy_entry, airy_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(airy_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(airy, airy_entry)
diff --git a/boost/geometry/srs/projections/proj/august.hpp b/boost/geometry/srs/projections/proj/august.hpp
index 4db65c5a23..0b550a54b5 100644
--- a/boost/geometry/srs/projections/proj/august.hpp
+++ b/boost/geometry/srs/projections/proj/august.hpp
@@ -125,7 +125,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(august_entry, august_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(august_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(august, august_entry)
diff --git a/boost/geometry/srs/projections/proj/bipc.hpp b/boost/geometry/srs/projections/proj/bipc.hpp
index 6eb57e8390..bc954ca6bb 100644
--- a/boost/geometry/srs/projections/proj/bipc.hpp
+++ b/boost/geometry/srs/projections/proj/bipc.hpp
@@ -260,7 +260,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(bipc_entry, bipc_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(bipc_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(bipc, bipc_entry)
diff --git a/boost/geometry/srs/projections/proj/cass.hpp b/boost/geometry/srs/projections/proj/cass.hpp
index f87ed312d7..2cca32882c 100644
--- a/boost/geometry/srs/projections/proj/cass.hpp
+++ b/boost/geometry/srs/projections/proj/cass.hpp
@@ -2,8 +2,9 @@
// Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2017, 2018, 2019.
-// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017, 2018, 2019, 2022.
+// Modifications copyright (c) 2017-2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle.
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,7 +16,7 @@
// PROJ4 is maintained by Frank Warmerdam
// PROJ4 is converted to Boost.Geometry by Barend Gehrels
-// Last updated version of proj: 5.0.0
+// Last updated version of proj: 9.0.0
// Original copyright notice:
@@ -44,8 +45,9 @@
#include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
#include <boost/geometry/srs/projections/impl/projects.hpp>
#include <boost/geometry/srs/projections/impl/factory_entry.hpp>
+#include <boost/geometry/srs/projections/impl/pj_generic_inverse.hpp>
#include <boost/geometry/srs/projections/impl/pj_mlfn.hpp>
-
+#include <boost/geometry/srs/projections/impl/pj_param.hpp>
namespace boost { namespace geometry
{
@@ -79,6 +81,7 @@ namespace projections
{
T m0;
detail::en<T> en;
+ bool hyperbolic;
};
template <typename T, typename Parameters>
@@ -88,16 +91,18 @@ namespace projections
// FORWARD(e_forward) ellipsoid
// Project coordinates from geographic (lon, lat) to cartesian (x, y)
- inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
+ inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat,
+ T& xy_x, T& xy_y) const
{
- static const T C1 = cass::C1<T>();
- static const T C2 = cass::C2<T>();
- static const T C3 = cass::C3<T>();
+ static T const C1 = cass::C1<T>();
+ static T const C2 = cass::C2<T>();
+ static T const C3 = cass::C3<T>();
- T n = sin(lp_lat);
+ T sinlplat = sin(lp_lat);
T c = cos(lp_lat);
- xy_y = pj_mlfn(lp_lat, n, c, this->m_proj_parm.en);
- n = 1./sqrt(1. - par.es * n * n);
+ xy_y = pj_mlfn(lp_lat, sinlplat, c, this->m_proj_parm.en);
+ T n_square = 1./(1. - par.es * sinlplat * sinlplat);
+ T n = sqrt(n_square);
T tn = tan(lp_lat);
T t = tn * tn;
T a1 = lp_lon * c;
@@ -107,11 +112,17 @@ namespace projections
(C1 - (8. - t + 8. * c) * a2 * C2));
xy_y -= this->m_proj_parm.m0 - n * tn * a2 *
(.5 + (5. - t + 6. * c) * a2 * C3);
+ if ( this->m_proj_parm.hyperbolic )
+ {
+ T const rho = n_square * (1. - par.es) * n;
+ xy_y -= xy_y * xy_y * xy_y / (6 * rho * n);
+ }
}
// INVERSE(e_inverse) ellipsoid
// Project coordinates from cartesian (x, y) to geographic (lon, lat)
- inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
+ inline void inv(Parameters const& par, T const& xy_x, T const& xy_y,
+ T& lp_lon, T& lp_lat) const
{
static const T C3 = cass::C3<T>();
static const T C4 = cass::C4<T>();
@@ -131,6 +142,13 @@ namespace projections
(.5 - (1. + 3. * t) * d2 * C3);
lp_lon = dd * (1. + t * d2 *
(-C4 + (1. + 3. * t) * d2 * C5)) / cos(ph1);
+ if ( this->m_proj_parm.hyperbolic )
+ {
+ // EPSG guidance note 7-2 suggests a custom approximation for the
+ // 'Vanua Levu 1915 / Vanua Levu Grid' case, but better use the
+ // generic inversion method
+ pj_generic_inverse_2d(xy_x, xy_y, par, this, lp_lat, lp_lon);
+ }
}
static inline std::string get_name()
@@ -147,7 +165,8 @@ namespace projections
// FORWARD(s_forward) spheroid
// Project coordinates from geographic (lon, lat) to cartesian (x, y)
- inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
+ inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat,
+ T& xy_x, T& xy_y) const
{
xy_x = asin(cos(lp_lat) * sin(lp_lon));
xy_y = atan2(tan(lp_lat) , cos(lp_lon)) - par.phi0;
@@ -155,7 +174,8 @@ namespace projections
// INVERSE(s_inverse) spheroid
// Project coordinates from cartesian (x, y) to geographic (lon, lat)
- inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
+ inline void inv(Parameters const& par, T const& xy_x, T const& xy_y,
+ T& lp_lon, T& lp_lat) const
{
T dd = xy_y + par.phi0;
lp_lat = asin(sin(dd) * cos(xy_x));
@@ -170,14 +190,18 @@ namespace projections
};
// Cassini
- template <typename Parameters, typename T>
- inline void setup_cass(Parameters& par, par_cass<T>& proj_parm)
+ template <typename Params, typename Parameters, typename T>
+ inline void setup_cass(Params const& params, Parameters& par, par_cass<T>& proj_parm)
{
if (par.es) {
proj_parm.en = pj_enfn<T>(par.es);
proj_parm.m0 = pj_mlfn(par.phi0, sin(par.phi0), cos(par.phi0), proj_parm.en);
} else {
}
+ proj_parm.hyperbolic = false;
+ if (pj_param_exists<srs::spar::hyperbolic>(params, "hyperbolic", srs::dpar::hyperbolic))
+ proj_parm.hyperbolic = true;
+
}
}} // namespace detail::cass
@@ -200,9 +224,9 @@ namespace projections
struct cass_ellipsoid : public detail::cass::base_cass_ellipsoid<T, Parameters>
{
template <typename Params>
- inline cass_ellipsoid(Params const& , Parameters const& par)
+ inline cass_ellipsoid(Params const& params, Parameters const& par)
{
- detail::cass::setup_cass(par, this->m_proj_parm);
+ detail::cass::setup_cass(params, par, this->m_proj_parm);
}
};
@@ -223,9 +247,9 @@ namespace projections
struct cass_spheroid : public detail::cass::base_cass_spheroid<T, Parameters>
{
template <typename Params>
- inline cass_spheroid(Params const& , Parameters const& par)
+ inline cass_spheroid(Params const& params, Parameters const& par)
{
- detail::cass::setup_cass(par, this->m_proj_parm);
+ detail::cass::setup_cass(params, par, this->m_proj_parm);
}
};
@@ -234,7 +258,8 @@ namespace projections
{
// Static projection
- BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(srs::spar::proj_cass, cass_spheroid, cass_ellipsoid)
+ BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(srs::spar::proj_cass, cass_spheroid,
+ cass_ellipsoid)
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(cass_entry, cass_spheroid, cass_ellipsoid)
diff --git a/boost/geometry/srs/projections/proj/cc.hpp b/boost/geometry/srs/projections/proj/cc.hpp
index 0684efc6b5..400bd2f70e 100644
--- a/boost/geometry/srs/projections/proj/cc.hpp
+++ b/boost/geometry/srs/projections/proj/cc.hpp
@@ -57,7 +57,7 @@ namespace projections
{
static const double epsilon10 = 1.e-10;
-
+
template <typename T, typename Parameters>
struct base_cc_spheroid
{
@@ -130,7 +130,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(cc_entry, cc_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(cc_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(cc, cc_entry);
diff --git a/boost/geometry/srs/projections/proj/cea.hpp b/boost/geometry/srs/projections/proj/cea.hpp
index 53f253aebb..cd37a79981 100644
--- a/boost/geometry/srs/projections/proj/cea.hpp
+++ b/boost/geometry/srs/projections/proj/cea.hpp
@@ -218,7 +218,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(cea_entry, cea_spheroid, cea_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(cea_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(cea, cea_entry);
diff --git a/boost/geometry/srs/projections/proj/chamb.hpp b/boost/geometry/srs/projections/proj/chamb.hpp
index d0e33fde1c..f2e269a6a9 100644
--- a/boost/geometry/srs/projections/proj/chamb.hpp
+++ b/boost/geometry/srs/projections/proj/chamb.hpp
@@ -272,7 +272,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(chamb_entry, chamb_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(chamb_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(chamb, chamb_entry);
diff --git a/boost/geometry/srs/projections/proj/col_urban.hpp b/boost/geometry/srs/projections/proj/col_urban.hpp
new file mode 100644
index 0000000000..f9fd7de63f
--- /dev/null
+++ b/boost/geometry/srs/projections/proj/col_urban.hpp
@@ -0,0 +1,166 @@
+// Boost.Geometry - gis-projections (based on PROJ4)
+
+// Copyright (c) 2022, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle.
+
+// Use, modification and distribution is subject to the 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 file is converted from PROJ4, http://trac.osgeo.org/proj
+// PROJ4 is originally written by Gerald Evenden (then of the USGS)
+// PROJ4 is maintained by Frank Warmerdam
+// PROJ4 is converted to Boost.Geometry by Barend Gehrels
+
+// Last updated version of proj: 9.0.0
+
+// Original copyright notice:
+
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifndef BOOST_GEOMETRY_PROJECTIONS_COL_URBAN_HPP
+#define BOOST_GEOMETRY_PROJECTIONS_COL_URBAN_HPP
+
+#include <boost/geometry/util/math.hpp>
+
+#include <boost/geometry/srs/projections/impl/base_static.hpp>
+#include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
+#include <boost/geometry/srs/projections/impl/pj_param.hpp>
+#include <boost/geometry/srs/projections/impl/projects.hpp>
+#include <boost/geometry/srs/projections/impl/factory_entry.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace projections
+{
+ #ifndef DOXYGEN_NO_DETAIL
+ namespace detail { namespace col_urban
+ {
+ template <typename T>
+ struct par_col_urban
+ {
+ T h0; // height of projection origin, divided by semi-major axis (a)
+ T rho0; // adimensional value, contrary to Guidance note 7.2
+ T A;
+ T B; // adimensional value, contrary to Guidance note 7.2
+ T C;
+ T D; // adimensional value, contrary to Guidance note 7.2
+ };
+
+ template <typename T, typename Parameters>
+ struct base_col_urban_spheroid
+ {
+ par_col_urban<T> m_proj_parm;
+
+ // FORWARD(s_forward) spheroid
+ // Project coordinates from geographic (lon, lat) to cartesian (x, y)
+ inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
+ {
+ const T cosphi = cos(lp_lat);
+ const T sinphi = sin(lp_lat);
+ const T nu = 1. / sqrt(1 - par.es * sinphi * sinphi);
+ const T lam_nu_cosphi = lp_lon * nu * cosphi;
+ xy_x = this->m_proj_parm.A * lam_nu_cosphi;
+ const T sinphi_m = sin(0.5 * (lp_lat + par.phi0));
+ const T rho_m = (1 - par.es) / pow(1 - par.es * sinphi_m * sinphi_m, 1.5);
+ const T G = 1 + this->m_proj_parm.h0 / rho_m;
+ xy_y = G * this->m_proj_parm.rho0 * ((lp_lat - par.phi0) + this->m_proj_parm.B * lam_nu_cosphi * lam_nu_cosphi);
+ }
+
+ // INVERSE(s_inverse) spheroid
+ // Project coordinates from cartesian (x, y) to geographic (lon, lat)
+ inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
+ {
+ lp_lat = par.phi0 + xy_y / this->m_proj_parm.D - this->m_proj_parm.B * (xy_x / this->m_proj_parm.C) * (xy_x / this->m_proj_parm.C);
+ const double sinphi = sin(lp_lat);
+ const double nu = 1. / sqrt(1 - par.es * sinphi * sinphi);
+ lp_lon = xy_x / (this->m_proj_parm.C * nu * cos(lp_lat));
+
+ }
+
+ static inline std::string get_name()
+ {
+ return "col_urban_spheroid";
+ }
+
+ };
+
+ // Colombia Urban
+ template <typename Params, typename Parameters, typename T>
+ inline void setup(Params const& params, Parameters const& par, par_col_urban<T>& proj_parm)
+ {
+ T h0_unscaled;
+ if ( !pj_param_f<srs::spar::h_0>(params, "h_0", srs::dpar::h_0, h0_unscaled) ){
+ h0_unscaled = T(0);
+ }
+ proj_parm.h0 = h0_unscaled / par.a;
+ const T sinphi0 = sin(par.phi0);
+ const T nu0 = 1. / sqrt(1 - par.es * sinphi0 * sinphi0);
+ proj_parm.A = 1 + proj_parm.h0 / nu0;
+ proj_parm.rho0 = (1 - par.es) / pow(1 - par.es * sinphi0 * sinphi0, 1.5);
+ proj_parm.B = tan(par.phi0) / (2 * proj_parm.rho0 * nu0);
+ proj_parm.C = 1 + proj_parm.h0;
+ proj_parm.D = proj_parm.rho0 * (1 + proj_parm.h0 / (1 - par.es));
+ }
+
+ }} // namespace col_urban
+ #endif // doxygen
+
+ /*!
+ \brief Colombia Urban
+ \ingroup projections
+ \tparam Geographic latlong point type
+ \tparam Cartesian xy point type
+ \tparam Parameters parameter type
+ */
+ template <typename T, typename Parameters>
+ struct col_urban_spheroid : public detail::col_urban::base_col_urban_spheroid<T, Parameters>
+ {
+ template <typename Params>
+ inline col_urban_spheroid(Params const& params, Parameters & par)
+ {
+ detail::col_urban::setup(params, par, this->m_proj_parm);
+ }
+ };
+
+ #ifndef DOXYGEN_NO_DETAIL
+ namespace detail
+ {
+
+ // Static projection
+ BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_col_urban, col_urban_spheroid)
+
+ // Factory entry(s)
+ BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(col_urban_entry, col_urban_spheroid)
+
+ BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(col_urban_init)
+ {
+ BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(col_urban, col_urban_entry);
+ }
+
+ } // namespace detail
+ #endif // doxygen
+
+} // namespace projections
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_PROJECTIONS_COL_URBAN_HPP
diff --git a/boost/geometry/srs/projections/proj/collg.hpp b/boost/geometry/srs/projections/proj/collg.hpp
index 06d08a92a9..28a1d1ff1c 100644
--- a/boost/geometry/srs/projections/proj/collg.hpp
+++ b/boost/geometry/srs/projections/proj/collg.hpp
@@ -144,7 +144,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(collg_entry, collg_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(collg_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(collg, collg_entry);
diff --git a/boost/geometry/srs/projections/proj/crast.hpp b/boost/geometry/srs/projections/proj/crast.hpp
index ee8887ba97..55f3aaa0f4 100644
--- a/boost/geometry/srs/projections/proj/crast.hpp
+++ b/boost/geometry/srs/projections/proj/crast.hpp
@@ -132,7 +132,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(crast_entry, crast_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(crast_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(crast, crast_entry);
diff --git a/boost/geometry/srs/projections/proj/denoy.hpp b/boost/geometry/srs/projections/proj/denoy.hpp
index cb5ca29311..1cf89d3469 100644
--- a/boost/geometry/srs/projections/proj/denoy.hpp
+++ b/boost/geometry/srs/projections/proj/denoy.hpp
@@ -131,7 +131,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(denoy_entry, denoy_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(denoy_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(denoy, denoy_entry);
diff --git a/boost/geometry/srs/projections/proj/eck1.hpp b/boost/geometry/srs/projections/proj/eck1.hpp
index 4320176f9a..fad743d402 100644
--- a/boost/geometry/srs/projections/proj/eck1.hpp
+++ b/boost/geometry/srs/projections/proj/eck1.hpp
@@ -124,7 +124,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(eck1_entry, eck1_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(eck1_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(eck1, eck1_entry);
diff --git a/boost/geometry/srs/projections/proj/eck2.hpp b/boost/geometry/srs/projections/proj/eck2.hpp
index b099796683..e80fb071c5 100644
--- a/boost/geometry/srs/projections/proj/eck2.hpp
+++ b/boost/geometry/srs/projections/proj/eck2.hpp
@@ -141,7 +141,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(eck2_entry, eck2_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(eck2_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(eck2, eck2_entry);
diff --git a/boost/geometry/srs/projections/proj/eck3.hpp b/boost/geometry/srs/projections/proj/eck3.hpp
index 85d13ed2d8..20c5bc1bb1 100644
--- a/boost/geometry/srs/projections/proj/eck3.hpp
+++ b/boost/geometry/srs/projections/proj/eck3.hpp
@@ -260,7 +260,7 @@ namespace projections
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(putp1_entry, putp1_spheroid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(wag6_entry, wag6_spheroid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(kav7_entry, kav7_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(eck3_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(eck3, eck3_entry);
diff --git a/boost/geometry/srs/projections/proj/eck4.hpp b/boost/geometry/srs/projections/proj/eck4.hpp
index bdc4311e96..d6364353ac 100644
--- a/boost/geometry/srs/projections/proj/eck4.hpp
+++ b/boost/geometry/srs/projections/proj/eck4.hpp
@@ -152,7 +152,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(eck4_entry, eck4_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(eck4_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(eck4, eck4_entry);
diff --git a/boost/geometry/srs/projections/proj/eck5.hpp b/boost/geometry/srs/projections/proj/eck5.hpp
index ae658ea61b..ea62eeb392 100644
--- a/boost/geometry/srs/projections/proj/eck5.hpp
+++ b/boost/geometry/srs/projections/proj/eck5.hpp
@@ -125,7 +125,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(eck5_entry, eck5_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(eck5_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(eck5, eck5_entry);
diff --git a/boost/geometry/srs/projections/proj/eqc.hpp b/boost/geometry/srs/projections/proj/eqc.hpp
index 93a90dca32..b85480008e 100644
--- a/boost/geometry/srs/projections/proj/eqc.hpp
+++ b/boost/geometry/srs/projections/proj/eqc.hpp
@@ -135,7 +135,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(eqc_entry, eqc_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(eqc_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(eqc, eqc_entry);
diff --git a/boost/geometry/srs/projections/proj/eqdc.hpp b/boost/geometry/srs/projections/proj/eqdc.hpp
index 2919c5d7f2..9fec68c265 100644
--- a/boost/geometry/srs/projections/proj/eqdc.hpp
+++ b/boost/geometry/srs/projections/proj/eqdc.hpp
@@ -201,7 +201,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(eqdc_entry, eqdc_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(eqdc_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(eqdc, eqdc_entry);
diff --git a/boost/geometry/srs/projections/proj/etmerc.hpp b/boost/geometry/srs/projections/proj/etmerc.hpp
index 946ad28135..6d58e7b63e 100644
--- a/boost/geometry/srs/projections/proj/etmerc.hpp
+++ b/boost/geometry/srs/projections/proj/etmerc.hpp
@@ -427,7 +427,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(etmerc_entry, etmerc_ellipsoid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(utm_entry, utm_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(etmerc_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(etmerc, etmerc_entry);
diff --git a/boost/geometry/srs/projections/proj/fahey.hpp b/boost/geometry/srs/projections/proj/fahey.hpp
index e143436f92..1889ddfcd4 100644
--- a/boost/geometry/srs/projections/proj/fahey.hpp
+++ b/boost/geometry/srs/projections/proj/fahey.hpp
@@ -127,7 +127,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(fahey_entry, fahey_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(fahey_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(fahey, fahey_entry);
diff --git a/boost/geometry/srs/projections/proj/fouc_s.hpp b/boost/geometry/srs/projections/proj/fouc_s.hpp
index ec1cd34836..5f2825e226 100644
--- a/boost/geometry/srs/projections/proj/fouc_s.hpp
+++ b/boost/geometry/srs/projections/proj/fouc_s.hpp
@@ -163,7 +163,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(fouc_s_entry, fouc_s_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(fouc_s_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(fouc_s, fouc_s_entry);
diff --git a/boost/geometry/srs/projections/proj/gall.hpp b/boost/geometry/srs/projections/proj/gall.hpp
index 61967ce81c..2eea2c102f 100644
--- a/boost/geometry/srs/projections/proj/gall.hpp
+++ b/boost/geometry/srs/projections/proj/gall.hpp
@@ -126,7 +126,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(gall_entry, gall_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(gall_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(gall, gall_entry);
diff --git a/boost/geometry/srs/projections/proj/geocent.hpp b/boost/geometry/srs/projections/proj/geocent.hpp
index ebb5350dc7..9c10fe1a73 100644
--- a/boost/geometry/srs/projections/proj/geocent.hpp
+++ b/boost/geometry/srs/projections/proj/geocent.hpp
@@ -126,7 +126,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(geocent_entry, geocent_other)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(geocent_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(geocent, geocent_entry);
diff --git a/boost/geometry/srs/projections/proj/geos.hpp b/boost/geometry/srs/projections/proj/geos.hpp
index e27786ee1f..ddc8095ecc 100644
--- a/boost/geometry/srs/projections/proj/geos.hpp
+++ b/boost/geometry/srs/projections/proj/geos.hpp
@@ -88,7 +88,7 @@ namespace projections
/* Calculation of geocentric latitude. */
lp_lat = atan (this->m_proj_parm.radius_p2 * tan (lp_lat));
-
+
/* Calculation of the three components of the vector from satellite to
** position on earth surface (lon,lat).*/
r = (this->m_proj_parm.radius_p) / boost::math::hypot(this->m_proj_parm.radius_p * cos (lp_lat), sin (lp_lat));
@@ -121,7 +121,7 @@ namespace projections
/* Setting three components of vector from satellite to position.*/
Vx = -1.0;
-
+
if(this->m_proj_parm.flip_axis) {
Vz = tan (xy_y / this->m_proj_parm.radius_g_1);
Vy = tan (xy_x / this->m_proj_parm.radius_g_1) * boost::math::hypot(1.0, Vz);
@@ -207,7 +207,7 @@ namespace projections
Vy = tan (xy_x / (this->m_proj_parm.radius_g - 1.0));
Vz = tan (xy_y / (this->m_proj_parm.radius_g - 1.0)) * sqrt (1.0 + Vy * Vy);
}
-
+
/* Calculation of terms in cubic equation and determinant.*/
a = Vy * Vy + Vz * Vz + Vx * Vx;
b = 2 * this->m_proj_parm.radius_g * Vx;
@@ -274,7 +274,7 @@ namespace projections
if (par.phi0 != 0.0)
BOOST_THROW_EXCEPTION( projection_exception(error_unknown_prime_meridian) );
-
+
proj_parm.flip_axis = geos_flip_axis(params);
proj_parm.radius_g_1 = proj_parm.h / par.a;
@@ -353,7 +353,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(geos_entry, geos_spheroid, geos_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(geos_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(geos, geos_entry);
diff --git a/boost/geometry/srs/projections/proj/gins8.hpp b/boost/geometry/srs/projections/proj/gins8.hpp
index b1bb4a74c4..7f2f4062d2 100644
--- a/boost/geometry/srs/projections/proj/gins8.hpp
+++ b/boost/geometry/srs/projections/proj/gins8.hpp
@@ -127,7 +127,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(gins8_entry, gins8_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(gins8_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(gins8, gins8_entry);
diff --git a/boost/geometry/srs/projections/proj/gn_sinu.hpp b/boost/geometry/srs/projections/proj/gn_sinu.hpp
index 7e6903f9b4..9bc9e4d36f 100644
--- a/boost/geometry/srs/projections/proj/gn_sinu.hpp
+++ b/boost/geometry/srs/projections/proj/gn_sinu.hpp
@@ -165,7 +165,7 @@ namespace projections
};
template <typename Parameters, typename T>
- inline void setup(Parameters& par, par_gn_sinu_s<T>& proj_parm)
+ inline void setup(Parameters& par, par_gn_sinu_s<T>& proj_parm)
{
par.es = 0;
@@ -354,7 +354,7 @@ namespace projections
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(sinu_entry, sinu_spheroid, sinu_ellipsoid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(eck6_entry, eck6_spheroid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(mbtfps_entry, mbtfps_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(gn_sinu_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(gn_sinu, gn_sinu_entry);
diff --git a/boost/geometry/srs/projections/proj/gnom.hpp b/boost/geometry/srs/projections/proj/gnom.hpp
index bde8e19063..afee056535 100644
--- a/boost/geometry/srs/projections/proj/gnom.hpp
+++ b/boost/geometry/srs/projections/proj/gnom.hpp
@@ -232,7 +232,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(gnom_entry, gnom_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(gnom_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(gnom, gnom_entry);
diff --git a/boost/geometry/srs/projections/proj/goode.hpp b/boost/geometry/srs/projections/proj/goode.hpp
index f8dd87c372..226c098015 100644
--- a/boost/geometry/srs/projections/proj/goode.hpp
+++ b/boost/geometry/srs/projections/proj/goode.hpp
@@ -67,7 +67,7 @@ namespace projections
{
sinu_spheroid<T, Par> sinu;
moll_spheroid<T, Par> moll;
-
+
// NOTE: It is ok to share parameters between projections because
// the only member that is modified in the constructors of
// spherical sinu and moll projections is es = 0 which is set
@@ -176,7 +176,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(goode_entry, goode_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(goode_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(goode, goode_entry);
diff --git a/boost/geometry/srs/projections/proj/gstmerc.hpp b/boost/geometry/srs/projections/proj/gstmerc.hpp
index a39db181a7..d8999d5552 100644
--- a/boost/geometry/srs/projections/proj/gstmerc.hpp
+++ b/boost/geometry/srs/projections/proj/gstmerc.hpp
@@ -159,7 +159,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(gstmerc_entry, gstmerc_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(gstmerc_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(gstmerc, gstmerc_entry);
diff --git a/boost/geometry/srs/projections/proj/hammer.hpp b/boost/geometry/srs/projections/proj/hammer.hpp
index de2afa55e2..0a8352127c 100644
--- a/boost/geometry/srs/projections/proj/hammer.hpp
+++ b/boost/geometry/srs/projections/proj/hammer.hpp
@@ -164,7 +164,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(hammer_entry, hammer_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(hammer_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(hammer, hammer_entry)
diff --git a/boost/geometry/srs/projections/proj/hatano.hpp b/boost/geometry/srs/projections/proj/hatano.hpp
index 4d444f87e3..a87c52f802 100644
--- a/boost/geometry/srs/projections/proj/hatano.hpp
+++ b/boost/geometry/srs/projections/proj/hatano.hpp
@@ -170,7 +170,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(hatano_entry, hatano_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(hatano_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(hatano, hatano_entry)
diff --git a/boost/geometry/srs/projections/proj/healpix.hpp b/boost/geometry/srs/projections/proj/healpix.hpp
index 670b8b9aff..e84da48282 100644
--- a/boost/geometry/srs/projections/proj/healpix.hpp
+++ b/boost/geometry/srs/projections/proj/healpix.hpp
@@ -276,7 +276,7 @@ namespace projections
**/
template <typename T>
inline void healpix_sphere(T const& lp_lam, T const& lp_phi, T& xy_x, T& xy_y)
- {
+ {
static const T pi = detail::pi<T>();
static const T half_pi = detail::half_pi<T>();
static const T fourth_pi = detail::fourth_pi<T>();
@@ -307,7 +307,7 @@ namespace projections
**/
template <typename T>
inline void healpix_sphere_inverse(T const& xy_x, T const& xy_y, T& lp_lam, T& lp_phi)
- {
+ {
static const T pi = detail::pi<T>();
static const T half_pi = detail::half_pi<T>();
static const T fourth_pi = detail::fourth_pi<T>();
@@ -827,7 +827,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(healpix_entry, healpix_spheroid, healpix_ellipsoid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(rhealpix_entry, rhealpix_spheroid, rhealpix_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(healpix_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(healpix, healpix_entry)
diff --git a/boost/geometry/srs/projections/proj/igh.hpp b/boost/geometry/srs/projections/proj/igh.hpp
index 8e01151c8a..f10cba6c32 100644
--- a/boost/geometry/srs/projections/proj/igh.hpp
+++ b/boost/geometry/srs/projections/proj/igh.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry - gis-projections (based on PROJ4)
// Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017-2021.
// Modifications copyright (c) 2017-2021, Oracle and/or its affiliates.
@@ -49,8 +50,6 @@
#include <boost/geometry/util/math.hpp>
-#include <boost/shared_ptr.hpp>
-
namespace boost { namespace geometry
{
@@ -218,7 +217,7 @@ namespace projections
static const T d180 = igh::d180<T>();
static const T c2 = 2.0;
-
+
const T y90 = this->m_proj_parm.dy0 + sqrt(c2); // lt=90 corresponds to y=y0+sqrt(2.0)
int z = 0;
@@ -317,7 +316,7 @@ namespace projections
+-------+--------+-----------+-----------+
-180 -100 -20 80 180
*/
-
+
T lp_lam = 0, lp_phi = d4044118;
T xy1_x, xy1_y;
T xy3_x, xy3_y;
diff --git a/boost/geometry/srs/projections/proj/imw_p.hpp b/boost/geometry/srs/projections/proj/imw_p.hpp
index 2e018646db..72ac322f82 100644
--- a/boost/geometry/srs/projections/proj/imw_p.hpp
+++ b/boost/geometry/srs/projections/proj/imw_p.hpp
@@ -298,7 +298,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(imw_p_entry, imw_p_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(imw_p_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(imw_p, imw_p_entry)
diff --git a/boost/geometry/srs/projections/proj/isea.hpp b/boost/geometry/srs/projections/proj/isea.hpp
index f1b887ad6b..f2984568c7 100644
--- a/boost/geometry/srs/projections/proj/isea.hpp
+++ b/boost/geometry/srs/projections/proj/isea.hpp
@@ -266,7 +266,7 @@ namespace projections
};
return result;
}
-
+
template <typename T>
inline const isea_geo<T> * vertex()
{
@@ -1240,7 +1240,7 @@ namespace projections
pj_param_i<srs::spar::aperture>(params, "aperture", srs::dpar::aperture, proj_parm.dgg.aperture);
// TODO: this parameter is set below second time
pj_param_i<srs::spar::resolution>(params, "resolution", srs::dpar::resolution, proj_parm.dgg.resolution);
-
+
isea_mode_init(params, proj_parm);
// TODO: pj_param_exists -> pj_get_param_b ?
@@ -1303,7 +1303,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(isea_entry, isea_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(isea_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(isea, isea_entry)
diff --git a/boost/geometry/srs/projections/proj/krovak.hpp b/boost/geometry/srs/projections/proj/krovak.hpp
index d1761f6371..240c51158e 100644
--- a/boost/geometry/srs/projections/proj/krovak.hpp
+++ b/boost/geometry/srs/projections/proj/krovak.hpp
@@ -2,8 +2,9 @@
// Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2017, 2018, 2019.
-// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017, 2018, 2019, 2022.
+// Modifications copyright (c) 2017-2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle.
// Use, modification and distribution is subject to the Boost Software License,
@@ -128,19 +129,17 @@ namespace projections
xy_y *= this->m_proj_parm.czech;
xy_x *= this->m_proj_parm.czech;
+ if (this->m_proj_parm.czech == 1) std::swap(xy_x, xy_y);
}
// INVERSE(e_inverse) ellipsoid
// Project coordinates from cartesian (x, y) to geographic (lon, lat)
inline void inv(Parameters const& par, T xy_x, T xy_y, T& lp_lon, T& lp_lat) const
{
- T u, deltav, s, d, eps, rho, fi1, xy0;
+ T u, deltav, s, d, eps, rho, fi1;
int i;
- // TODO: replace with std::swap()
- xy0 = xy_x;
- xy_x = xy_y;
- xy_y = xy0;
+ if (this->m_proj_parm.czech == -1) std::swap(xy_x, xy_y);
xy_x *= this->m_proj_parm.czech;
xy_y *= this->m_proj_parm.czech;
@@ -261,7 +260,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(krovak_entry, krovak_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(krovak_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(krovak, krovak_entry)
diff --git a/boost/geometry/srs/projections/proj/labrd.hpp b/boost/geometry/srs/projections/proj/labrd.hpp
index 823bd69554..50fcdc586d 100644
--- a/boost/geometry/srs/projections/proj/labrd.hpp
+++ b/boost/geometry/srs/projections/proj/labrd.hpp
@@ -226,7 +226,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(labrd_entry, labrd_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(labrd_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(labrd, labrd_entry)
diff --git a/boost/geometry/srs/projections/proj/laea.hpp b/boost/geometry/srs/projections/proj/laea.hpp
index c6775ed3e1..30f82d07b2 100644
--- a/boost/geometry/srs/projections/proj/laea.hpp
+++ b/boost/geometry/srs/projections/proj/laea.hpp
@@ -408,7 +408,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(laea_entry, laea_spheroid, laea_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(laea_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(laea, laea_entry)
diff --git a/boost/geometry/srs/projections/proj/lagrng.hpp b/boost/geometry/srs/projections/proj/lagrng.hpp
index 439b574714..ad9cf77028 100644
--- a/boost/geometry/srs/projections/proj/lagrng.hpp
+++ b/boost/geometry/srs/projections/proj/lagrng.hpp
@@ -109,7 +109,7 @@ namespace projections
proj_parm.rw = 0.0;
bool is_w_set = pj_param_f<srs::spar::w>(params, "W", srs::dpar::w, proj_parm.rw);
-
+
// Boost.Geometry specific, set default parameters manually
if (! is_w_set) {
bool const use_defaults = ! pj_get_param_b<srs::spar::no_defs>(params, "no_defs", srs::dpar::no_defs);
@@ -170,7 +170,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(lagrng_entry, lagrng_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(lagrng_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(lagrng, lagrng_entry);
diff --git a/boost/geometry/srs/projections/proj/larr.hpp b/boost/geometry/srs/projections/proj/larr.hpp
index a584aa3373..427b9906c7 100644
--- a/boost/geometry/srs/projections/proj/larr.hpp
+++ b/boost/geometry/srs/projections/proj/larr.hpp
@@ -116,7 +116,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(larr_entry, larr_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(larr_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(larr, larr_entry);
diff --git a/boost/geometry/srs/projections/proj/lask.hpp b/boost/geometry/srs/projections/proj/lask.hpp
index 158402de08..270ae73e93 100644
--- a/boost/geometry/srs/projections/proj/lask.hpp
+++ b/boost/geometry/srs/projections/proj/lask.hpp
@@ -130,7 +130,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(lask_entry, lask_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(lask_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(lask, lask_entry);
diff --git a/boost/geometry/srs/projections/proj/latlong.hpp b/boost/geometry/srs/projections/proj/latlong.hpp
index 111075ef2c..2673b9e635 100644
--- a/boost/geometry/srs/projections/proj/latlong.hpp
+++ b/boost/geometry/srs/projections/proj/latlong.hpp
@@ -136,7 +136,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(latlong_entry, latlong_other)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(latlong_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(lonlat, latlong_entry)
diff --git a/boost/geometry/srs/projections/proj/lcc.hpp b/boost/geometry/srs/projections/proj/lcc.hpp
index 7210c3b884..611a6e0301 100644
--- a/boost/geometry/srs/projections/proj/lcc.hpp
+++ b/boost/geometry/srs/projections/proj/lcc.hpp
@@ -248,7 +248,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(lcc_entry, lcc_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(lcc_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(lcc, lcc_entry);
diff --git a/boost/geometry/srs/projections/proj/lcca.hpp b/boost/geometry/srs/projections/proj/lcca.hpp
index e36ece8671..25f3e182df 100644
--- a/boost/geometry/srs/projections/proj/lcca.hpp
+++ b/boost/geometry/srs/projections/proj/lcca.hpp
@@ -180,7 +180,7 @@ namespace projections
T s2p0, N0, R0, tan0;
proj_parm.en = pj_enfn<T>(par.es);
-
+
if (par.phi0 == 0.) {
BOOST_THROW_EXCEPTION( projection_exception(error_lat_0_is_zero) );
}
@@ -232,7 +232,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(lcca_entry, lcca_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(lcca_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(lcca, lcca_entry)
diff --git a/boost/geometry/srs/projections/proj/loxim.hpp b/boost/geometry/srs/projections/proj/loxim.hpp
index d39bf89288..3ad8603d85 100644
--- a/boost/geometry/srs/projections/proj/loxim.hpp
+++ b/boost/geometry/srs/projections/proj/loxim.hpp
@@ -168,7 +168,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(loxim_entry, loxim_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(loxim_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(loxim, loxim_entry)
diff --git a/boost/geometry/srs/projections/proj/lsat.hpp b/boost/geometry/srs/projections/proj/lsat.hpp
index dd6b3ae623..37ffcc5b73 100644
--- a/boost/geometry/srs/projections/proj/lsat.hpp
+++ b/boost/geometry/srs/projections/proj/lsat.hpp
@@ -316,7 +316,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(lsat_entry, lsat_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(lsat_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(lsat, lsat_entry)
diff --git a/boost/geometry/srs/projections/proj/mbt_fps.hpp b/boost/geometry/srs/projections/proj/mbt_fps.hpp
index 282799f842..e48843c37c 100644
--- a/boost/geometry/srs/projections/proj/mbt_fps.hpp
+++ b/boost/geometry/srs/projections/proj/mbt_fps.hpp
@@ -151,7 +151,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(mbt_fps_entry, mbt_fps_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(mbt_fps_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(mbt_fps, mbt_fps_entry)
diff --git a/boost/geometry/srs/projections/proj/mbtfpp.hpp b/boost/geometry/srs/projections/proj/mbtfpp.hpp
index 7b587b7da3..e8383c6cdd 100644
--- a/boost/geometry/srs/projections/proj/mbtfpp.hpp
+++ b/boost/geometry/srs/projections/proj/mbtfpp.hpp
@@ -154,7 +154,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(mbtfpp_entry, mbtfpp_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(mbtfpp_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(mbtfpp, mbtfpp_entry)
diff --git a/boost/geometry/srs/projections/proj/mbtfpq.hpp b/boost/geometry/srs/projections/proj/mbtfpq.hpp
index 6bd850a5e7..2e194e4ab4 100644
--- a/boost/geometry/srs/projections/proj/mbtfpq.hpp
+++ b/boost/geometry/srs/projections/proj/mbtfpq.hpp
@@ -165,7 +165,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(mbtfpq_entry, mbtfpq_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(mbtfpq_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(mbtfpq, mbtfpq_entry)
diff --git a/boost/geometry/srs/projections/proj/merc.hpp b/boost/geometry/srs/projections/proj/merc.hpp
index 398339a695..54c26f7021 100644
--- a/boost/geometry/srs/projections/proj/merc.hpp
+++ b/boost/geometry/srs/projections/proj/merc.hpp
@@ -2,8 +2,9 @@
// Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2017, 2018, 2019.
-// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017, 2018, 2019, 2022.
+// Modifications copyright (c) 2017-2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle.
// Use, modification and distribution is subject to the Boost Software License,
@@ -206,19 +207,46 @@ namespace projections
}
};
+ /*!
+ \brief Web Mercator projection
+ \ingroup projections
+ \tparam Geographic latlong point type
+ \tparam Cartesian xy point type
+ \tparam Parameters parameter type
+ \par Projection characteristics
+ - Cylindrical
+ - Spheroid
+ - Ellipsoid
+ */
+ template <typename T, typename Parameters>
+ struct webmerc_spheroid : public detail::merc::base_merc_spheroid<T, Parameters>
+ {
+ template <typename Params>
+ inline webmerc_spheroid(Params const&, Parameters & par)
+ {
+ par.k0 = 1;
+ }
+ };
+
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
// Static projection
- BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(srs::spar::proj_merc, merc_spheroid, merc_ellipsoid)
+ BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(srs::spar::proj_merc, merc_spheroid,
+ merc_ellipsoid)
+ BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_webmerc,
+ webmerc_spheroid)
// Factory entry(s)
- BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(merc_entry, merc_spheroid, merc_ellipsoid)
-
+ BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(merc_entry, merc_spheroid,
+ merc_ellipsoid)
+ BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(webmerc_entry, webmerc_spheroid)
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(merc_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(merc, merc_entry)
+ BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(webmerc, webmerc_entry)
}
} // namespace detail
@@ -229,4 +257,3 @@ namespace projections
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_PROJECTIONS_MERC_HPP
-
diff --git a/boost/geometry/srs/projections/proj/mill.hpp b/boost/geometry/srs/projections/proj/mill.hpp
index 375f056fb6..789cb13126 100644
--- a/boost/geometry/srs/projections/proj/mill.hpp
+++ b/boost/geometry/srs/projections/proj/mill.hpp
@@ -129,7 +129,7 @@ namespace projections
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(mill, mill_entry)
}
-
+
} // namespace detail
#endif // doxygen
diff --git a/boost/geometry/srs/projections/proj/mod_ster.hpp b/boost/geometry/srs/projections/proj/mod_ster.hpp
index b7fffb3f9c..71df525c7d 100644
--- a/boost/geometry/srs/projections/proj/mod_ster.hpp
+++ b/boost/geometry/srs/projections/proj/mod_ster.hpp
@@ -458,7 +458,7 @@ namespace projections
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(gs48_entry, gs48_ellipsoid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(alsk_entry, alsk_ellipsoid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(gs50_entry, gs50_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(mod_ster_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(mil_os, mil_os_entry)
diff --git a/boost/geometry/srs/projections/proj/moll.hpp b/boost/geometry/srs/projections/proj/moll.hpp
index e00bb2c760..5dc030f60a 100644
--- a/boost/geometry/srs/projections/proj/moll.hpp
+++ b/boost/geometry/srs/projections/proj/moll.hpp
@@ -119,7 +119,7 @@ namespace projections
};
template <typename Parameters, typename T>
- inline void setup(Parameters& par, par_moll<T>& proj_parm, T const& p)
+ inline void setup(Parameters& par, par_moll<T>& proj_parm, T const& p)
{
T r, sp, p2 = p + p;
@@ -239,7 +239,7 @@ namespace projections
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(moll_entry, moll_spheroid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(wag4_entry, wag4_spheroid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(wag5_entry, wag5_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(moll_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(moll, moll_entry);
diff --git a/boost/geometry/srs/projections/proj/nsper.hpp b/boost/geometry/srs/projections/proj/nsper.hpp
index 49b8c85cd9..29ecdc3c95 100644
--- a/boost/geometry/srs/projections/proj/nsper.hpp
+++ b/boost/geometry/srs/projections/proj/nsper.hpp
@@ -202,7 +202,7 @@ namespace projections
};
template <typename Params, typename Parameters, typename T>
- inline void setup(Params const& params, Parameters& par, par_nsper<T>& proj_parm)
+ inline void setup(Params const& params, Parameters& par, par_nsper<T>& proj_parm)
{
proj_parm.height = pj_get_param_f<T, srs::spar::h>(params, "h", srs::dpar::h);
if (proj_parm.height <= 0.)
diff --git a/boost/geometry/srs/projections/proj/ob_tran.hpp b/boost/geometry/srs/projections/proj/ob_tran.hpp
index 0ec9ba3497..c3b5b70de5 100644
--- a/boost/geometry/srs/projections/proj/ob_tran.hpp
+++ b/boost/geometry/srs/projections/proj/ob_tran.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry - gis-projections (based on PROJ4)
// Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2017-2020.
// Modifications copyright (c) 2017-2020, Oracle and/or its affiliates.
@@ -40,19 +41,17 @@
#ifndef BOOST_GEOMETRY_PROJECTIONS_OB_TRAN_HPP
#define BOOST_GEOMETRY_PROJECTIONS_OB_TRAN_HPP
+#include <memory>
#include <type_traits>
-#include <boost/geometry/util/math.hpp>
-#include <boost/shared_ptr.hpp>
-
#include <boost/geometry/core/static_assert.hpp>
-
#include <boost/geometry/srs/projections/impl/aasincos.hpp>
#include <boost/geometry/srs/projections/impl/base_static.hpp>
#include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
#include <boost/geometry/srs/projections/impl/factory_entry.hpp>
#include <boost/geometry/srs/projections/impl/pj_ell_set.hpp>
#include <boost/geometry/srs/projections/impl/projects.hpp>
+#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
@@ -61,7 +60,7 @@ namespace projections
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail {
-
+
// fwd declaration needed below
template <typename T>
inline detail::dynamic_wrapper_b<T, projections::parameters<T> >*
@@ -199,7 +198,7 @@ namespace projections
link->inv(link->params(), xy_x, xy_y, lp_lon, lp_lat);
}
- boost::shared_ptr<dynamic_wrapper_b<T, Parameters> > link;
+ std::shared_ptr<dynamic_wrapper_b<T, Parameters> > link;
T lamp;
T cphip, sphip;
};
@@ -253,7 +252,7 @@ namespace projections
inline void o_forward(T lp_lon, T lp_lat, T& xy_x, T& xy_y, Par const& proj_parm)
{
T coslam, sinphi, cosphi;
-
+
coslam = cos(lp_lon);
sinphi = sin(lp_lat);
cosphi = cos(lp_lat);
@@ -326,7 +325,7 @@ namespace projections
lamc = pj_get_param_r<T, srs::spar::o_lon_c>(params, "o_lon_c", srs::dpar::o_lon_c);
phic = pj_get_param_r<T, srs::spar::o_lon_c>(params, "o_lat_c", srs::dpar::o_lat_c);
//alpha = pj_get_param_r(par.params, "o_alpha");
-
+
if (fabs(fabs(phic) - half_pi) <= tolerance)
BOOST_THROW_EXCEPTION( projection_exception(error_lat_0_or_alpha_eq_90) );
@@ -542,7 +541,7 @@ namespace projections
*/
template <typename T, typename Parameters>
struct ob_tran_transverse : public detail::ob_tran::base_ob_tran_transverse<T, Parameters>
- {
+ {
template <typename Params>
inline ob_tran_transverse(Params const& , Parameters const& ,
detail::ob_tran::par_ob_tran<T, Parameters> const& proj_parm)
diff --git a/boost/geometry/srs/projections/proj/omerc.hpp b/boost/geometry/srs/projections/proj/omerc.hpp
index 9b9f5170fd..5239b3a7e5 100644
--- a/boost/geometry/srs/projections/proj/omerc.hpp
+++ b/boost/geometry/srs/projections/proj/omerc.hpp
@@ -2,8 +2,9 @@
// Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2017, 2018, 2019.
-// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017, 2018, 2019, 2022.
+// Modifications copyright (c) 2017-2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle.
// Use, modification and distribution is subject to the Boost Software License,
@@ -78,14 +79,16 @@ namespace projections
// FORWARD(e_forward) ellipsoid
// Project coordinates from geographic (lon, lat) to cartesian (x, y)
- inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
+ inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x,
+ T& xy_y) const
{
static const T half_pi = detail::half_pi<T>();
T s, t, U, V, W, temp, u, v;
if (fabs(fabs(lp_lat) - half_pi) > epsilon) {
- W = this->m_proj_parm.E / math::pow(pj_tsfn(lp_lat, sin(lp_lat), par.e), this->m_proj_parm.B);
+ W = this->m_proj_parm.E / math::pow(pj_tsfn(lp_lat, sin(lp_lat), par.e),
+ this->m_proj_parm.B);
temp = 1. / W;
s = .5 * (W - temp);
t = .5 * (W + temp);
@@ -99,7 +102,8 @@ namespace projections
if(fabs(temp) < tolerance) {
u = this->m_proj_parm.A * lp_lon;
} else {
- u = this->m_proj_parm.ArB * atan2((s * this->m_proj_parm.cosgam + V * this->m_proj_parm.singam), temp);
+ u = this->m_proj_parm.ArB * atan2((s * this->m_proj_parm.cosgam
+ + V * this->m_proj_parm.singam), temp);
}
} else {
v = lp_lat > 0 ? this->m_proj_parm.v_pole_n : this->m_proj_parm.v_pole_s;
@@ -117,7 +121,8 @@ namespace projections
// INVERSE(e_inverse) ellipsoid
// Project coordinates from cartesian (x, y) to geographic (lon, lat)
- inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
+ inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon,
+ T& lp_lat) const
{
static const T half_pi = detail::half_pi<T>();
@@ -128,7 +133,8 @@ namespace projections
u = xy_x;
} else {
v = xy_x * this->m_proj_parm.cosrot - xy_y * this->m_proj_parm.sinrot;
- u = xy_y * this->m_proj_parm.cosrot + xy_x * this->m_proj_parm.sinrot + this->m_proj_parm.u_0;
+ u = xy_y * this->m_proj_parm.cosrot + xy_x * this->m_proj_parm.sinrot
+ + this->m_proj_parm.u_0;
}
Qp = exp(- this->m_proj_parm.BrA * v);
Sp = .5 * (Qp - 1. / Qp);
@@ -140,7 +146,8 @@ namespace projections
lp_lat = Up < 0. ? -half_pi : half_pi;
} else {
lp_lat = this->m_proj_parm.E / sqrt((1. + Up) / (1. - Up));
- if ((lp_lat = pj_phi2(math::pow(lp_lat, T(1) / this->m_proj_parm.B), par.e)) == HUGE_VAL) {
+ if ((lp_lat = pj_phi2(math::pow(lp_lat, T(1) / this->m_proj_parm.B), par.e))
+ == HUGE_VAL) {
BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
}
lp_lon = - this->m_proj_parm.rB * atan2((Sp * this->m_proj_parm.cosgam -
@@ -168,23 +175,14 @@ namespace projections
gamma0, lamc=0, lam1=0, lam2=0, phi1=0, phi2=0, alpha_c=0;
int alp, gam, no_off = 0;
- proj_parm.no_rot = pj_get_param_b<srs::spar::no_rot>(params, "no_rot", srs::dpar::no_rot);
+ proj_parm.no_rot = pj_get_param_b<srs::spar::no_rot>(params, "no_rot",
+ srs::dpar::no_rot);
alp = pj_param_r<srs::spar::alpha>(params, "alpha", srs::dpar::alpha, alpha_c);
gam = pj_param_r<srs::spar::gamma>(params, "gamma", srs::dpar::gamma, gamma);
if (alp || gam) {
lamc = pj_get_param_r<T, srs::spar::lonc>(params, "lonc", srs::dpar::lonc);
- // NOTE: This is not needed in Boost.Geometry
- //no_off =
- // /* For libproj4 compatability */
- // pj_param_exists(par.params, "no_off")
- // /* for backward compatibility */
- // || pj_param_exists(par.params, "no_uoff");
- //if( no_off )
- //{
- // /* Mark the parameter as used, so that the pj_get_def() return them */
- // pj_get_param_s(par.params, "no_uoff");
- // pj_get_param_s(par.params, "no_off");
- //}
+ // NOTE: This is needed for Hotline Oblique Mercator variant A projection
+ no_off = pj_get_param_b<srs::spar::no_off>(params, "no_off", srs::dpar::no_off);
} else {
lam1 = pj_get_param_r<T, srs::spar::lon_1>(params, "lon_1", srs::dpar::lon_1);
phi1 = pj_get_param_r<T, srs::spar::lat_1>(params, "lat_1", srs::dpar::lat_1);
@@ -281,13 +279,14 @@ namespace projections
- no_rot: No rotation
- alpha: Alpha (degrees)
- gamma: Gamma (degrees)
- - no_off: Only for compatibility with libproj, proj4 (string)
+ - no_off: Do not offset origin to center of projection
+ (useful for Hotline Oblique Mercator variant A).
- lonc: Longitude (only used if alpha (or gamma) is specified) (degrees)
- lon_1 (degrees)
- lat_1: Latitude of first standard parallel (degrees)
- lon_2 (degrees)
- lat_2: Latitude of second standard parallel (degrees)
- - no_uoff (string)
+ - no_uoff: deprecated (string)
\par Example
\image html ex_omerc.gif
*/
diff --git a/boost/geometry/srs/projections/proj/putp3.hpp b/boost/geometry/srs/projections/proj/putp3.hpp
index b7ee613503..e057f70e46 100644
--- a/boost/geometry/srs/projections/proj/putp3.hpp
+++ b/boost/geometry/srs/projections/proj/putp3.hpp
@@ -97,7 +97,7 @@ namespace projections
inline void setup_putp3(Parameters& par, par_putp3<T>& proj_parm)
{
proj_parm.A = 4. * RPISQ;
-
+
par.es = 0.;
}
@@ -106,7 +106,7 @@ namespace projections
inline void setup_putp3p(Parameters& par, par_putp3<T>& proj_parm)
{
proj_parm.A = 2. * RPISQ;
-
+
par.es = 0.;
}
diff --git a/boost/geometry/srs/projections/proj/putp4p.hpp b/boost/geometry/srs/projections/proj/putp4p.hpp
index f510557ca2..3647e7e310 100644
--- a/boost/geometry/srs/projections/proj/putp4p.hpp
+++ b/boost/geometry/srs/projections/proj/putp4p.hpp
@@ -102,7 +102,7 @@ namespace projections
{
proj_parm.C_x = 0.874038744;
proj_parm.C_y = 3.883251825;
-
+
par.es = 0.;
}
@@ -112,7 +112,7 @@ namespace projections
{
proj_parm.C_x = 1.;
proj_parm.C_y = 4.442882938;
-
+
par.es = 0.;
}
diff --git a/boost/geometry/srs/projections/proj/putp5.hpp b/boost/geometry/srs/projections/proj/putp5.hpp
index 6601b9dc9e..8968a11b6e 100644
--- a/boost/geometry/srs/projections/proj/putp5.hpp
+++ b/boost/geometry/srs/projections/proj/putp5.hpp
@@ -90,7 +90,7 @@ namespace projections
}
};
-
+
// Putnins P5
template <typename Parameters, typename T>
@@ -98,7 +98,7 @@ namespace projections
{
proj_parm.A = 2.;
proj_parm.B = 1.;
-
+
par.es = 0.;
}
@@ -108,7 +108,7 @@ namespace projections
{
proj_parm.A = 1.5;
proj_parm.B = 0.5;
-
+
par.es = 0.;
}
diff --git a/boost/geometry/srs/projections/proj/putp6.hpp b/boost/geometry/srs/projections/proj/putp6.hpp
index cf30252479..c7688b47be 100644
--- a/boost/geometry/srs/projections/proj/putp6.hpp
+++ b/boost/geometry/srs/projections/proj/putp6.hpp
@@ -110,7 +110,7 @@ namespace projections
}
};
-
+
// Putnins P6
template <typename Parameters, typename T>
@@ -121,7 +121,7 @@ namespace projections
proj_parm.A = 4.;
proj_parm.B = 2.1471437182129378784;
proj_parm.D = 2.;
-
+
par.es = 0.;
}
@@ -134,7 +134,7 @@ namespace projections
proj_parm.A = 6.;
proj_parm.B = 5.61125;
proj_parm.D = 3.;
-
+
par.es = 0.;
}
diff --git a/boost/geometry/srs/projections/proj/qsc.hpp b/boost/geometry/srs/projections/proj/qsc.hpp
index 49eef3398e..733015e7f3 100644
--- a/boost/geometry/srs/projections/proj/qsc.hpp
+++ b/boost/geometry/srs/projections/proj/qsc.hpp
@@ -189,7 +189,7 @@ namespace projections
T lat, lon;
T theta, phi;
- T t, mu; /* nu; */
+ T t, mu; /* nu; */
area_type area;
/* Convert the geodetic latitude to a geocentric latitude.
diff --git a/boost/geometry/srs/projections/proj/sconics.hpp b/boost/geometry/srs/projections/proj/sconics.hpp
index 465928cbd3..a0a0551def 100644
--- a/boost/geometry/srs/projections/proj/sconics.hpp
+++ b/boost/geometry/srs/projections/proj/sconics.hpp
@@ -163,7 +163,7 @@ namespace projections
};
template <typename Params, typename Parameters, typename T>
- inline void setup(Params const& params, Parameters& par, par_sconics<T>& proj_parm, proj_type type)
+ inline void setup(Params const& params, Parameters& par, par_sconics<T>& proj_parm, proj_type type)
{
static const T half_pi = detail::half_pi<T>();
@@ -256,7 +256,7 @@ namespace projections
inline void setup_murd3(Params const& params, Parameters& par, par_sconics<T>& proj_parm)
{
setup(params, par, proj_parm, proj_murd3);
- }
+ }
// Perspective Conic
template <typename Params, typename Parameters, typename T>
@@ -274,7 +274,7 @@ namespace projections
}} // namespace detail::sconics
#endif // doxygen
-
+
/*!
\brief Tissot projection
\ingroup projections
@@ -462,7 +462,7 @@ namespace projections
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_pconic, pconic_spheroid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_tissot, tissot_spheroid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_vitk1, vitk1_spheroid)
-
+
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(euler_entry, euler_spheroid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(murd1_entry, murd1_spheroid)
diff --git a/boost/geometry/srs/projections/proj/somerc.hpp b/boost/geometry/srs/projections/proj/somerc.hpp
index 6c189726ce..7d84d8f9c8 100644
--- a/boost/geometry/srs/projections/proj/somerc.hpp
+++ b/boost/geometry/srs/projections/proj/somerc.hpp
@@ -183,10 +183,10 @@ namespace projections
// Static projection
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_somerc, somerc_ellipsoid)
-
+
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(somerc_entry, somerc_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(somerc_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(somerc, somerc_entry)
diff --git a/boost/geometry/srs/projections/proj/stere.hpp b/boost/geometry/srs/projections/proj/stere.hpp
index 21b308bb22..793781880b 100644
--- a/boost/geometry/srs/projections/proj/stere.hpp
+++ b/boost/geometry/srs/projections/proj/stere.hpp
@@ -79,6 +79,7 @@ namespace projections
T cosX1;
T akm1;
mode_type mode;
+ bool variant_c;
};
template <typename T>
@@ -137,8 +138,21 @@ namespace projections
sinphi = -sinphi;
BOOST_FALLTHROUGH;
case n_pole:
- xy_x = this->m_proj_parm.akm1 * pj_tsfn(lp_lat, sinphi, par.e);
- xy_y = - xy_x * coslam;
+ // see IOGP Publication 373-7-2 – Geomatics Guidance Note number 7, part 2
+ // December 2021 pg. 82
+ if( m_proj_parm.variant_c )
+ {
+ auto t = pj_tsfn(lp_lat, sinphi, par.e);
+ auto tf = pj_tsfn(this->m_proj_parm.phits,
+ sin(this->m_proj_parm.phits),
+ par.e);
+ xy_x = this->m_proj_parm.akm1 * t;
+ auto mf = this->m_proj_parm.akm1 * tf;
+ xy_y = - xy_x * coslam - mf;
+ } else {
+ xy_x = this->m_proj_parm.akm1 * pj_tsfn(lp_lat, sinphi, par.e);
+ xy_y = - xy_x * coslam;
+ }
break;
}
@@ -152,6 +166,7 @@ namespace projections
static const T half_pi = detail::half_pi<T>();
T cosphi, sinphi, tp=0.0, phi_l=0.0, rho, halfe=0.0, halfpi=0.0;
+ T mf = 0;
int i;
rho = boost::math::hypot(xy_x, xy_y);
@@ -175,6 +190,16 @@ namespace projections
xy_y = -xy_y;
BOOST_FALLTHROUGH;
case s_pole:
+ // see IOGP Publication 373-7-2 – Geomatics Guidance Note number 7, part 2
+ // December 2021 pg. 82
+ if( m_proj_parm.variant_c )
+ {
+ auto tf = pj_tsfn(this->m_proj_parm.phits,
+ sin(this->m_proj_parm.phits),
+ par.e);
+ mf = this->m_proj_parm.akm1 * tf;
+ rho = boost::math::hypot(xy_x, xy_y + mf);
+ }
phi_l = half_pi - 2. * atan(tp = - rho / this->m_proj_parm.akm1);
halfpi = -half_pi;
halfe = -.5 * par.e;
@@ -186,7 +211,7 @@ namespace projections
if (fabs(phi_l - lp_lat) < conv_tolerance) {
if (this->m_proj_parm.mode == s_pole)
lp_lat = -lp_lat;
- lp_lon = (xy_x == 0. && xy_y == 0.) ? 0. : atan2(xy_x, xy_y);
+ lp_lon = (xy_x == 0. && xy_y == 0.) ? 0. : atan2(xy_x, xy_y + mf);
return;
}
}
@@ -362,6 +387,10 @@ namespace projections
if (! pj_param_r<srs::spar::lat_ts>(params, "lat_ts", srs::dpar::lat_ts, proj_parm.phits))
proj_parm.phits = half_pi;
+ proj_parm.variant_c = false;
+ if (pj_param_exists<srs::spar::variant_c>(params, "variant_c", srs::dpar::variant_c))
+ proj_parm.variant_c = true;
+
setup(par, proj_parm);
}
@@ -499,7 +528,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(stere_entry, stere_spheroid, stere_ellipsoid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(ups_entry, ups_spheroid, ups_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(stere_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(stere, stere_entry)
diff --git a/boost/geometry/srs/projections/proj/sterea.hpp b/boost/geometry/srs/projections/proj/sterea.hpp
index c1e6134bde..c3b2a07231 100644
--- a/boost/geometry/srs/projections/proj/sterea.hpp
+++ b/boost/geometry/srs/projections/proj/sterea.hpp
@@ -165,7 +165,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(sterea_entry, sterea_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(sterea_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(sterea, sterea_entry)
diff --git a/boost/geometry/srs/projections/proj/sts.hpp b/boost/geometry/srs/projections/proj/sts.hpp
index deca4d0013..8662afb41a 100644
--- a/boost/geometry/srs/projections/proj/sts.hpp
+++ b/boost/geometry/srs/projections/proj/sts.hpp
@@ -109,7 +109,7 @@ namespace projections
};
template <typename Parameters, typename T>
- inline void setup(Parameters& par, par_sts<T>& proj_parm, T const& p, T const& q, bool mode)
+ inline void setup(Parameters& par, par_sts<T>& proj_parm, T const& p, T const& q, bool mode)
{
par.es = 0.;
proj_parm.C_x = q / p;
@@ -253,7 +253,7 @@ namespace projections
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(qua_aut_entry, qua_aut_spheroid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(mbt_s_entry, mbt_s_spheroid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(fouc_entry, fouc_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(sts_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(kav5, kav5_entry)
diff --git a/boost/geometry/srs/projections/proj/tcc.hpp b/boost/geometry/srs/projections/proj/tcc.hpp
index 8380d94b07..501aa4f9a1 100644
--- a/boost/geometry/srs/projections/proj/tcc.hpp
+++ b/boost/geometry/srs/projections/proj/tcc.hpp
@@ -122,7 +122,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(tcc_entry, tcc_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(tcc_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(tcc, tcc_entry)
diff --git a/boost/geometry/srs/projections/proj/tcea.hpp b/boost/geometry/srs/projections/proj/tcea.hpp
index f442e010b6..7e0acf8850 100644
--- a/boost/geometry/srs/projections/proj/tcea.hpp
+++ b/boost/geometry/srs/projections/proj/tcea.hpp
@@ -93,7 +93,7 @@ namespace projections
}} // namespace detail::tcea
#endif // doxygen
-
+
/*!
\brief Transverse Cylindrical Equal Area projection
\ingroup projections
@@ -125,7 +125,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(tcea_entry, tcea_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(tcea_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(tcea, tcea_entry)
diff --git a/boost/geometry/srs/projections/proj/tmerc.hpp b/boost/geometry/srs/projections/proj/tmerc.hpp
index 7c8ca6464c..6d645ec12c 100644
--- a/boost/geometry/srs/projections/proj/tmerc.hpp
+++ b/boost/geometry/srs/projections/proj/tmerc.hpp
@@ -1,9 +1,11 @@
// Boost.Geometry - gis-projections (based on PROJ4)
// Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2017, 2018, 2019.
-// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017, 2018, 2019, 2022.
+// Modifications copyright (c) 2017-2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle.
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,7 +17,7 @@
// PROJ4 is maintained by Frank Warmerdam
// PROJ4 is converted to Boost.Geometry by Barend Gehrels
-// Last updated version of proj: 5.0.0
+// Last updated version of proj: 8.2.1
// Original copyright notice:
@@ -40,8 +42,6 @@
#ifndef BOOST_GEOMETRY_PROJECTIONS_TMERC_HPP
#define BOOST_GEOMETRY_PROJECTIONS_TMERC_HPP
-#include <boost/geometry/util/math.hpp>
-
#include <boost/geometry/srs/projections/impl/base_static.hpp>
#include <boost/geometry/srs/projections/impl/base_dynamic.hpp>
#include <boost/geometry/srs/projections/impl/projects.hpp>
@@ -49,6 +49,9 @@
#include <boost/geometry/srs/projections/impl/function_overloads.hpp>
#include <boost/geometry/srs/projections/impl/pj_mlfn.hpp>
+#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/util/math.hpp>
+
namespace boost { namespace geometry
{
@@ -59,226 +62,574 @@ namespace projections
namespace detail { namespace tmerc
{
- static const double epsilon10 = 1.e-10;
-
- template <typename T>
- inline T FC1() { return 1.; }
- template <typename T>
- inline T FC2() { return .5; }
- template <typename T>
- inline T FC3() { return .16666666666666666666666666666666666666; }
- template <typename T>
- inline T FC4() { return .08333333333333333333333333333333333333; }
- template <typename T>
- inline T FC5() { return .05; }
- template <typename T>
- inline T FC6() { return .03333333333333333333333333333333333333; }
- template <typename T>
- inline T FC7() { return .02380952380952380952380952380952380952; }
- template <typename T>
- inline T FC8() { return .01785714285714285714285714285714285714; }
-
- template <typename T>
- struct par_tmerc
- {
- T esp;
- T ml0;
- detail::en<T> en;
- };
+ static const double epsilon10 = 1.e-10;
+
+ /* Constant for "exact" transverse mercator */
+ static const int proj_etmerc_order = 6;
+
+ template <typename T>
+ inline T FC1() { return 1.; }
+ template <typename T>
+ inline T FC2() { return .5; }
+ template <typename T>
+ inline T FC3() { return .16666666666666666666666666666666666666; }
+ template <typename T>
+ inline T FC4() { return .08333333333333333333333333333333333333; }
+ template <typename T>
+ inline T FC5() { return .05; }
+ template <typename T>
+ inline T FC6() { return .03333333333333333333333333333333333333; }
+ template <typename T>
+ inline T FC7() { return .02380952380952380952380952380952380952; }
+ template <typename T>
+ inline T FC8() { return .01785714285714285714285714285714285714; }
+
+ template <typename T>
+ struct par_tmerc
+ {
+ T esp;
+ T ml0;
+ detail::en<T> en;
+ };
+
+ // More exact: Poder/Engsager
+ template <typename T>
+ struct par_tmerc_exact
+ {
+ T Qn; /* Merid. quad., scaled to the projection */
+ T Zb; /* Radius vector in polar coord. systems */
+ T cgb[6]; /* Constants for Gauss -> Geo lat */
+ T cbg[6]; /* Constants for Geo lat -> Gauss */
+ T utg[6]; /* Constants for transv. merc. -> geo */
+ T gtu[6]; /* Constants for geo -> transv. merc. */
+ };
+
+ template <typename T, typename Parameters>
+ struct base_tmerc_ellipsoid
+ {
+ par_tmerc<T> m_proj_parm;
- template <typename T, typename Parameters>
- struct base_tmerc_ellipsoid
+ // FORWARD(e_forward) ellipse
+ // Project coordinates from geographic (lon, lat) to cartesian (x, y)
+ inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
{
- par_tmerc<T> m_proj_parm;
-
- // FORWARD(e_forward) ellipse
- // Project coordinates from geographic (lon, lat) to cartesian (x, y)
- inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
+ static const T half_pi = detail::half_pi<T>();
+ static const T FC1 = tmerc::FC1<T>();
+ static const T FC2 = tmerc::FC2<T>();
+ static const T FC3 = tmerc::FC3<T>();
+ static const T FC4 = tmerc::FC4<T>();
+ static const T FC5 = tmerc::FC5<T>();
+ static const T FC6 = tmerc::FC6<T>();
+ static const T FC7 = tmerc::FC7<T>();
+ static const T FC8 = tmerc::FC8<T>();
+
+ T al, als, n, cosphi, sinphi, t;
+
+ /*
+ * Fail if our longitude is more than 90 degrees from the
+ * central meridian since the results are essentially garbage.
+ * Is error -20 really an appropriate return value?
+ *
+ * http://trac.osgeo.org/proj/ticket/5
+ */
+ if( lp_lon < -half_pi || lp_lon > half_pi )
{
- static const T half_pi = detail::half_pi<T>();
- static const T FC1 = tmerc::FC1<T>();
- static const T FC2 = tmerc::FC2<T>();
- static const T FC3 = tmerc::FC3<T>();
- static const T FC4 = tmerc::FC4<T>();
- static const T FC5 = tmerc::FC5<T>();
- static const T FC6 = tmerc::FC6<T>();
- static const T FC7 = tmerc::FC7<T>();
- static const T FC8 = tmerc::FC8<T>();
-
- T al, als, n, cosphi, sinphi, t;
-
- /*
- * Fail if our longitude is more than 90 degrees from the
- * central meridian since the results are essentially garbage.
- * Is error -20 really an appropriate return value?
- *
- * http://trac.osgeo.org/proj/ticket/5
- */
- if( lp_lon < -half_pi || lp_lon > half_pi )
- {
- xy_x = HUGE_VAL;
- xy_y = HUGE_VAL;
- BOOST_THROW_EXCEPTION( projection_exception(error_lat_or_lon_exceed_limit) );
- return;
- }
+ xy_x = HUGE_VAL;
+ xy_y = HUGE_VAL;
+ BOOST_THROW_EXCEPTION( projection_exception(error_lat_or_lon_exceed_limit) );
+ return;
+ }
+ sinphi = sin(lp_lat);
+ cosphi = cos(lp_lat);
+ t = fabs(cosphi) > 1e-10 ? sinphi/cosphi : 0.;
+ t *= t;
+ al = cosphi * lp_lon;
+ als = al * al;
+ al /= sqrt(1. - par.es * sinphi * sinphi);
+ n = this->m_proj_parm.esp * cosphi * cosphi;
+ xy_x = par.k0 * al * (FC1 +
+ FC3 * als * (1. - t + n +
+ FC5 * als * (5. + t * (t - 18.) + n * (14. - 58. * t)
+ + FC7 * als * (61. + t * ( t * (179. - t) - 479. ) )
+ )));
+ xy_y = par.k0 * (pj_mlfn(lp_lat, sinphi, cosphi, this->m_proj_parm.en) - this->m_proj_parm.ml0 +
+ sinphi * al * lp_lon * FC2 * ( 1. +
+ FC4 * als * (5. - t + n * (9. + 4. * n) +
+ FC6 * als * (61. + t * (t - 58.) + n * (270. - 330 * t)
+ + FC8 * als * (1385. + t * ( t * (543. - t) - 3111.) )
+ ))));
+ }
+
+ // INVERSE(e_inverse) ellipsoid
+ // Project coordinates from cartesian (x, y) to geographic (lon, lat)
+ inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
+ {
+ static const T half_pi = detail::half_pi<T>();
+ static const T FC1 = tmerc::FC1<T>();
+ static const T FC2 = tmerc::FC2<T>();
+ static const T FC3 = tmerc::FC3<T>();
+ static const T FC4 = tmerc::FC4<T>();
+ static const T FC5 = tmerc::FC5<T>();
+ static const T FC6 = tmerc::FC6<T>();
+ static const T FC7 = tmerc::FC7<T>();
+ static const T FC8 = tmerc::FC8<T>();
+
+ T n, con, cosphi, d, ds, sinphi, t;
+
+ lp_lat = pj_inv_mlfn(this->m_proj_parm.ml0 + xy_y / par.k0, par.es, this->m_proj_parm.en);
+ if (fabs(lp_lat) >= half_pi) {
+ lp_lat = xy_y < 0. ? -half_pi : half_pi;
+ lp_lon = 0.;
+ } else {
sinphi = sin(lp_lat);
cosphi = cos(lp_lat);
t = fabs(cosphi) > 1e-10 ? sinphi/cosphi : 0.;
- t *= t;
- al = cosphi * lp_lon;
- als = al * al;
- al /= sqrt(1. - par.es * sinphi * sinphi);
n = this->m_proj_parm.esp * cosphi * cosphi;
- xy_x = par.k0 * al * (FC1 +
- FC3 * als * (1. - t + n +
- FC5 * als * (5. + t * (t - 18.) + n * (14. - 58. * t)
- + FC7 * als * (61. + t * ( t * (179. - t) - 479. ) )
+ d = xy_x * sqrt(con = 1. - par.es * sinphi * sinphi) / par.k0;
+ con *= t;
+ t *= t;
+ ds = d * d;
+ lp_lat -= (con * ds / (1.-par.es)) * FC2 * (1. -
+ ds * FC4 * (5. + t * (3. - 9. * n) + n * (1. - 4 * n) -
+ ds * FC6 * (61. + t * (90. - 252. * n +
+ 45. * t) + 46. * n
+ - ds * FC8 * (1385. + t * (3633. + t * (4095. + 1574. * t)) )
)));
- xy_y = par.k0 * (pj_mlfn(lp_lat, sinphi, cosphi, this->m_proj_parm.en) - this->m_proj_parm.ml0 +
- sinphi * al * lp_lon * FC2 * ( 1. +
- FC4 * als * (5. - t + n * (9. + 4. * n) +
- FC6 * als * (61. + t * (t - 58.) + n * (270. - 330 * t)
- + FC8 * als * (1385. + t * ( t * (543. - t) - 3111.) )
- ))));
+ lp_lon = d*(FC1 -
+ ds*FC3*( 1. + 2.*t + n -
+ ds*FC5*(5. + t*(28. + 24.*t + 8.*n) + 6.*n
+ - ds * FC7 * (61. + t * (662. + t * (1320. + 720. * t)) )
+ ))) / cosphi;
}
+ }
- // INVERSE(e_inverse) ellipsoid
- // Project coordinates from cartesian (x, y) to geographic (lon, lat)
- inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
- {
- static const T half_pi = detail::half_pi<T>();
- static const T FC1 = tmerc::FC1<T>();
- static const T FC2 = tmerc::FC2<T>();
- static const T FC3 = tmerc::FC3<T>();
- static const T FC4 = tmerc::FC4<T>();
- static const T FC5 = tmerc::FC5<T>();
- static const T FC6 = tmerc::FC6<T>();
- static const T FC7 = tmerc::FC7<T>();
- static const T FC8 = tmerc::FC8<T>();
-
- T n, con, cosphi, d, ds, sinphi, t;
-
- lp_lat = pj_inv_mlfn(this->m_proj_parm.ml0 + xy_y / par.k0, par.es, this->m_proj_parm.en);
- if (fabs(lp_lat) >= half_pi) {
- lp_lat = xy_y < 0. ? -half_pi : half_pi;
- lp_lon = 0.;
- } else {
- sinphi = sin(lp_lat);
- cosphi = cos(lp_lat);
- t = fabs(cosphi) > 1e-10 ? sinphi/cosphi : 0.;
- n = this->m_proj_parm.esp * cosphi * cosphi;
- d = xy_x * sqrt(con = 1. - par.es * sinphi * sinphi) / par.k0;
- con *= t;
- t *= t;
- ds = d * d;
- lp_lat -= (con * ds / (1.-par.es)) * FC2 * (1. -
- ds * FC4 * (5. + t * (3. - 9. * n) + n * (1. - 4 * n) -
- ds * FC6 * (61. + t * (90. - 252. * n +
- 45. * t) + 46. * n
- - ds * FC8 * (1385. + t * (3633. + t * (4095. + 1574. * t)) )
- )));
- lp_lon = d*(FC1 -
- ds*FC3*( 1. + 2.*t + n -
- ds*FC5*(5. + t*(28. + 24.*t + 8.*n) + 6.*n
- - ds * FC7 * (61. + t * (662. + t * (1320. + 720. * t)) )
- ))) / cosphi;
- }
- }
+ static inline std::string get_name()
+ {
+ return "tmerc_ellipsoid";
+ }
- static inline std::string get_name()
- {
- return "tmerc_ellipsoid";
- }
+ };
- };
+ template <typename T, typename Parameters>
+ struct base_tmerc_ellipsoid_exact
+ {
+ par_tmerc_exact<T> m_proj_parm;
- template <typename T, typename Parameters>
- struct base_tmerc_spheroid
+ static inline std::string get_name()
{
- par_tmerc<T> m_proj_parm;
+ return "tmerc_ellipsoid";
+ }
- // FORWARD(s_forward) sphere
- // Project coordinates from geographic (lon, lat) to cartesian (x, y)
- inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
- {
- static const T half_pi = detail::half_pi<T>();
-
- T b, cosphi;
-
- /*
- * Fail if our longitude is more than 90 degrees from the
- * central meridian since the results are essentially garbage.
- * Is error -20 really an appropriate return value?
- *
- * http://trac.osgeo.org/proj/ticket/5
- */
- if( lp_lon < -half_pi || lp_lon > half_pi )
- {
- xy_x = HUGE_VAL;
- xy_y = HUGE_VAL;
- BOOST_THROW_EXCEPTION( projection_exception(error_lat_or_lon_exceed_limit) );
- return;
- }
+ /* Helper functions for "exact" transverse mercator */
+ inline
+ static T gatg(const T *p1, int len_p1, T B, T cos_2B, T sin_2B)
+ {
+ T h = 0, h1, h2 = 0;
+
+ const T two_cos_2B = 2*cos_2B;
+ const T* p = p1 + len_p1;
+ h1 = *--p;
+ while (p - p1) {
+ h = -h2 + two_cos_2B*h1 + *--p;
+ h2 = h1;
+ h1 = h;
+ }
+ return (B + h*sin_2B);
+ }
- cosphi = cos(lp_lat);
- b = cosphi * sin(lp_lon);
- if (fabs(fabs(b) - 1.) <= epsilon10)
- BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
+ /* Complex Clenshaw summation */
+ inline
+ static T clenS(const T *a, int size,
+ T sin_arg_r, T cos_arg_r,
+ T sinh_arg_i, T cosh_arg_i,
+ T *R, T *I)
+ {
+ T r, i, hr, hr1, hr2, hi, hi1, hi2;
+
+ /* arguments */
+ const T* p = a + size;
+ r = 2*cos_arg_r*cosh_arg_i;
+ i = -2*sin_arg_r*sinh_arg_i;
+
+ /* summation loop */
+ hi1 = hr1 = hi = 0;
+ hr = *--p;
+ for (; a - p;) {
+ hr2 = hr1;
+ hi2 = hi1;
+ hr1 = hr;
+ hi1 = hi;
+ hr = -hr2 + r*hr1 - i*hi1 + *--p;
+ hi = -hi2 + i*hr1 + r*hi1;
+ }
- xy_x = this->m_proj_parm.ml0 * log((1. + b) / (1. - b));
- xy_y = cosphi * cos(lp_lon) / sqrt(1. - b * b);
+ r = sin_arg_r*cosh_arg_i;
+ i = cos_arg_r*sinh_arg_i;
+ *R = r*hr - i*hi;
+ *I = r*hi + i*hr;
+ return *R;
+ }
- b = fabs( xy_y );
- if (b >= 1.) {
- if ((b - 1.) > epsilon10)
- BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
- else xy_y = 0.;
- } else
- xy_y = acos(xy_y);
+ /* Real Clenshaw summation */
+ static T clens(const T *a, int size, T arg_r)
+ {
+ T r, hr, hr1, hr2, cos_arg_r;
+
+ const T* p = a + size;
+ cos_arg_r = cos(arg_r);
+ r = 2*cos_arg_r;
+
+ /* summation loop */
+ hr1 = 0;
+ hr = *--p;
+ for (; a - p;) {
+ hr2 = hr1;
+ hr1 = hr;
+ hr = -hr2 + r*hr1 + *--p;
+ }
+ return sin(arg_r)*hr;
+ }
- if (lp_lat < 0.)
- xy_y = -xy_y;
- xy_y = this->m_proj_parm.esp * (xy_y - par.phi0);
+ /* Ellipsoidal, forward */
+ //static PJ_XY exact_e_fwd (PJ_LP lp, PJ *P)
+ inline void fwd(Parameters const& /*par*/,
+ T const& lp_lon,
+ T const& lp_lat,
+ T& xy_x, T& xy_y) const
+ {
+ //PJ_XY xy = {0.0,0.0};
+ //const auto *Q = &(static_cast<struct tmerc_data*>(par.opaque)->exact);
+
+ /* ell. LAT, LNG -> Gaussian LAT, LNG */
+ T Cn = gatg (this->m_proj_parm.cbg, proj_etmerc_order, lp_lat,
+ cos(2*lp_lat), sin(2*lp_lat));
+ /* Gaussian LAT, LNG -> compl. sph. LAT */
+ const T sin_Cn = sin (Cn);
+ const T cos_Cn = cos (Cn);
+ const T sin_Ce = sin (lp_lon);
+ const T cos_Ce = cos (lp_lon);
+
+ const T cos_Cn_cos_Ce = cos_Cn*cos_Ce;
+ Cn = atan2 (sin_Cn, cos_Cn_cos_Ce);
+
+ const T inv_denom_tan_Ce = 1. / hypot (sin_Cn, cos_Cn_cos_Ce);
+ const T tan_Ce = sin_Ce*cos_Cn * inv_denom_tan_Ce;
+ #if 0
+ // Variant of the above: found not to be measurably faster
+ const T sin_Ce_cos_Cn = sin_Ce*cos_Cn;
+ const T denom = sqrt(1 - sin_Ce_cos_Cn * sin_Ce_cos_Cn);
+ const T tan_Ce = sin_Ce_cos_Cn / denom;
+ #endif
+
+ /* compl. sph. N, E -> ell. norm. N, E */
+ T Ce = asinh ( tan_Ce ); /* Replaces: Ce = log(tan(FORTPI + Ce*0.5)); */
+
+ /*
+ * Non-optimized version:
+ * const T sin_arg_r = sin(2*Cn);
+ * const T cos_arg_r = cos(2*Cn);
+ *
+ * Given:
+ * sin(2 * Cn) = 2 sin(Cn) cos(Cn)
+ * sin(atan(y)) = y / sqrt(1 + y^2)
+ * cos(atan(y)) = 1 / sqrt(1 + y^2)
+ * ==> sin(2 * Cn) = 2 tan_Cn / (1 + tan_Cn^2)
+ *
+ * cos(2 * Cn) = 2cos^2(Cn) - 1
+ * = 2 / (1 + tan_Cn^2) - 1
+ */
+ const T two_inv_denom_tan_Ce = 2 * inv_denom_tan_Ce;
+ const T two_inv_denom_tan_Ce_square = two_inv_denom_tan_Ce * inv_denom_tan_Ce;
+ const T tmp_r = cos_Cn_cos_Ce * two_inv_denom_tan_Ce_square;
+ const T sin_arg_r = sin_Cn * tmp_r;
+ const T cos_arg_r = cos_Cn_cos_Ce * tmp_r - 1;
+
+ /*
+ * Non-optimized version:
+ * const T sinh_arg_i = sinh(2*Ce);
+ * const T cosh_arg_i = cosh(2*Ce);
+ *
+ * Given
+ * sinh(2 * Ce) = 2 sinh(Ce) cosh(Ce)
+ * sinh(asinh(y)) = y
+ * cosh(asinh(y)) = sqrt(1 + y^2)
+ * ==> sinh(2 * Ce) = 2 tan_Ce sqrt(1 + tan_Ce^2)
+ *
+ * cosh(2 * Ce) = 2cosh^2(Ce) - 1
+ * = 2 * (1 + tan_Ce^2) - 1
+ *
+ * and 1+tan_Ce^2 = 1 + sin_Ce^2 * cos_Cn^2 / (sin_Cn^2 + cos_Cn^2 * cos_Ce^2)
+ * = (sin_Cn^2 + cos_Cn^2 * cos_Ce^2 + sin_Ce^2 * cos_Cn^2) / (sin_Cn^2 + cos_Cn^2 * cos_Ce^2)
+ * = 1. / (sin_Cn^2 + cos_Cn^2 * cos_Ce^2)
+ * = inv_denom_tan_Ce^2
+ *
+ */
+ const T sinh_arg_i = tan_Ce * two_inv_denom_tan_Ce;
+ const T cosh_arg_i = two_inv_denom_tan_Ce_square - 1;
+
+ T dCn, dCe;
+ Cn += clenS (this->m_proj_parm.gtu, proj_etmerc_order,
+ sin_arg_r, cos_arg_r, sinh_arg_i, cosh_arg_i,
+ &dCn, &dCe);
+ Ce += dCe;
+ if (fabs (Ce) <= 2.623395162778) {
+ xy_y = this->m_proj_parm.Qn * Cn + this->m_proj_parm.Zb; /* Northing */
+ xy_x = this->m_proj_parm.Qn * Ce; /* Easting */
+ } else {
+ BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
+ xy_x = xy_y = HUGE_VAL;
}
+ }
- // INVERSE(s_inverse) sphere
- // Project coordinates from cartesian (x, y) to geographic (lon, lat)
- inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
- {
- T h, g;
- h = exp(xy_x / this->m_proj_parm.esp);
- g = .5 * (h - 1. / h);
- h = cos(par.phi0 + xy_y / this->m_proj_parm.esp);
- lp_lat = asin(sqrt((1. - h * h) / (1. + g * g)));
+ /* Ellipsoidal, inverse */
+ inline void inv(Parameters const& /*par*/,
+ T const& xy_x,
+ T const& xy_y,
+ T& lp_lon,
+ T& lp_lat) const
+ {
+ //PJ_LP lp = {0.0,0.0};
+ //const auto *Q = &(static_cast<struct tmerc_data*>(par.opaque)->exact);
+
+ /* normalize N, E */
+ T Cn = (xy_y - this->m_proj_parm.Zb)/this->m_proj_parm.Qn;
+ T Ce = xy_x/this->m_proj_parm.Qn;
+
+ if (fabs(Ce) <= 2.623395162778) { /* 150 degrees */
+ /* norm. N, E -> compl. sph. LAT, LNG */
+ const T sin_arg_r = sin(2*Cn);
+ const T cos_arg_r = cos(2*Cn);
+
+ //const T sinh_arg_i = sinh(2*Ce);
+ //const T cosh_arg_i = cosh(2*Ce);
+ const T exp_2_Ce = exp(2*Ce);
+ const T half_inv_exp_2_Ce = 0.5 / exp_2_Ce;
+ const T sinh_arg_i = 0.5 * exp_2_Ce - half_inv_exp_2_Ce;
+ const T cosh_arg_i = 0.5 * exp_2_Ce + half_inv_exp_2_Ce;
+
+ T dCn_ignored, dCe;
+ Cn += clenS(this->m_proj_parm.utg, proj_etmerc_order,
+ sin_arg_r, cos_arg_r, sinh_arg_i, cosh_arg_i,
+ &dCn_ignored, &dCe);
+ Ce += dCe;
+
+ /* compl. sph. LAT -> Gaussian LAT, LNG */
+ const T sin_Cn = sin (Cn);
+ const T cos_Cn = cos (Cn);
+
+ #if 0
+ // Non-optimized version:
+ T sin_Ce, cos_Ce;
+ Ce = atan (sinh (Ce)); // Replaces: Ce = 2*(atan(exp(Ce)) - FORTPI);
+ sin_Ce = sin (Ce);
+ cos_Ce = cos (Ce);
+ Ce = atan2 (sin_Ce, cos_Ce*cos_Cn);
+ Cn = atan2 (sin_Cn*cos_Ce, hypot (sin_Ce, cos_Ce*cos_Cn));
+ #else
+ /*
+ * One can divide both member of Ce = atan2(...) by cos_Ce, which gives:
+ * Ce = atan2 (tan_Ce, cos_Cn) = atan2(sinh(Ce), cos_Cn)
+ *
+ * and the same for Cn = atan2(...)
+ * Cn = atan2 (sin_Cn, hypot (sin_Ce, cos_Ce*cos_Cn)/cos_Ce)
+ * = atan2 (sin_Cn, hypot (sin_Ce/cos_Ce, cos_Cn))
+ * = atan2 (sin_Cn, hypot (tan_Ce, cos_Cn))
+ * = atan2 (sin_Cn, hypot (sinhCe, cos_Cn))
+ */
+ const T sinhCe = sinh (Ce);
+ Ce = atan2 (sinhCe, cos_Cn);
+ const T modulus_Ce = hypot (sinhCe, cos_Cn);
+ Cn = atan2 (sin_Cn, modulus_Ce);
+ #endif
+
+ /* Gaussian LAT, LNG -> ell. LAT, LNG */
+
+ // Optimization of the computation of cos(2*Cn) and sin(2*Cn)
+ const T tmp = 2 * modulus_Ce / (sinhCe * sinhCe + 1);
+ const T sin_2_Cn = sin_Cn * tmp;
+ const T cos_2_Cn = tmp * modulus_Ce - 1.;
+ //const T cos_2_Cn = cos(2 * Cn);
+ //const T sin_2_Cn = sin(2 * Cn);
+
+ lp_lat = gatg (this->m_proj_parm.cgb, proj_etmerc_order, Cn, cos_2_Cn, sin_2_Cn);
+ lp_lon = Ce;
+ }
+ else {
+ BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
+ lp_lat = lp_lon = HUGE_VAL;
+ }
+ }
- /* Make sure that phi is on the correct hemisphere when false northing is used */
- if (xy_y < 0. && -lp_lat+par.phi0 < 0.0) lp_lat = -lp_lat;
+ };
- lp_lon = (g != 0.0 || h != 0.0) ? atan2(g, h) : 0.;
- }
+ template <typename T, typename Parameters>
+ struct base_tmerc_spheroid
+ {
+ par_tmerc<T> m_proj_parm;
- static inline std::string get_name()
+ // FORWARD(s_forward) sphere
+ // Project coordinates from geographic (lon, lat) to cartesian (x, y)
+ inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const
+ {
+ static const T half_pi = detail::half_pi<T>();
+
+ T b, cosphi;
+
+ /*
+ * Fail if our longitude is more than 90 degrees from the
+ * central meridian since the results are essentially garbage.
+ * Is error -20 really an appropriate return value?
+ *
+ * http://trac.osgeo.org/proj/ticket/5
+ */
+ if( lp_lon < -half_pi || lp_lon > half_pi )
{
- return "tmerc_spheroid";
+ xy_x = HUGE_VAL;
+ xy_y = HUGE_VAL;
+ BOOST_THROW_EXCEPTION( projection_exception(error_lat_or_lon_exceed_limit) );
+ return;
}
- };
+ cosphi = cos(lp_lat);
+ b = cosphi * sin(lp_lon);
+ if (fabs(fabs(b) - 1.) <= epsilon10)
+ BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
+
+ xy_x = this->m_proj_parm.ml0 * log((1. + b) / (1. - b));
+ xy_y = cosphi * cos(lp_lon) / sqrt(1. - b * b);
+
+ b = fabs( xy_y );
+ if (b >= 1.) {
+ if ((b - 1.) > epsilon10)
+ BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) );
+ else xy_y = 0.;
+ } else
+ xy_y = acos(xy_y);
+
+ if (lp_lat < 0.)
+ xy_y = -xy_y;
+ xy_y = this->m_proj_parm.esp * (xy_y - par.phi0);
+ }
- template <typename Parameters, typename T>
- inline void setup(Parameters const& par, par_tmerc<T>& proj_parm)
+ // INVERSE(s_inverse) sphere
+ // Project coordinates from cartesian (x, y) to geographic (lon, lat)
+ inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const
{
- if (par.es != 0.0) {
- proj_parm.en = pj_enfn<T>(par.es);
- proj_parm.ml0 = pj_mlfn(par.phi0, sin(par.phi0), cos(par.phi0), proj_parm.en);
- proj_parm.esp = par.es / (1. - par.es);
- } else {
- proj_parm.esp = par.k0;
- proj_parm.ml0 = .5 * proj_parm.esp;
- }
+ T h, g;
+
+ h = exp(xy_x / this->m_proj_parm.esp);
+ g = .5 * (h - 1. / h);
+ h = cos(par.phi0 + xy_y / this->m_proj_parm.esp);
+ lp_lat = asin(sqrt((1. - h * h) / (1. + g * g)));
+
+ /* Make sure that phi is on the correct hemisphere when false northing is used */
+ if (xy_y < 0. && -lp_lat+par.phi0 < 0.0) lp_lat = -lp_lat;
+
+ lp_lon = (g != 0.0 || h != 0.0) ? atan2(g, h) : 0.;
}
+ static inline std::string get_name()
+ {
+ return "tmerc_spheroid";
+ }
+
+ };
+
+ template <typename Parameters, typename T>
+ inline void setup(Parameters const& par, par_tmerc<T>& proj_parm)
+ {
+ if (par.es != 0.0) {
+ proj_parm.en = pj_enfn<T>(par.es);
+ proj_parm.ml0 = pj_mlfn(par.phi0, sin(par.phi0), cos(par.phi0), proj_parm.en);
+ proj_parm.esp = par.es / (1. - par.es);
+ } else {
+ proj_parm.esp = par.k0;
+ proj_parm.ml0 = .5 * proj_parm.esp;
+ }
+ }
+
+ template <typename Parameters, typename T>
+ inline void setup_exact(Parameters const& par, par_tmerc_exact<T>& proj_parm)
+ {
+ assert( par.es > 0 );
+
+ /* third flattening n */
+ //since we do not keep n in parameters we compute it here;
+ const T n = pow(tan(asin(par.e)/2),2);
+ T np = n;
+
+ /* COEF. OF TRIG SERIES GEO <-> GAUSS */
+ /* cgb := Gaussian -> Geodetic, KW p190 - 191 (61) - (62) */
+ /* cbg := Geodetic -> Gaussian, KW p186 - 187 (51) - (52) */
+ /* PROJ_ETMERC_ORDER = 6th degree : Engsager and Poder: ICC2007 */
+
+ proj_parm.cgb[0] = n*( 2 + n*(-2/3.0 + n*(-2 + n*(116/45.0 + n*(26/45.0 +
+ n*(-2854/675.0 ))))));
+ proj_parm.cbg[0] = n*(-2 + n*( 2/3.0 + n*( 4/3.0 + n*(-82/45.0 + n*(32/45.0 +
+ n*( 4642/4725.0))))));
+ np *= n;
+ proj_parm.cgb[1] = np*(7/3.0 + n*( -8/5.0 + n*(-227/45.0 + n*(2704/315.0 +
+ n*( 2323/945.0)))));
+ proj_parm.cbg[1] = np*(5/3.0 + n*(-16/15.0 + n*( -13/9.0 + n*( 904/315.0 +
+ n*(-1522/945.0)))));
+ np *= n;
+ /* n^5 coeff corrected from 1262/105 -> -1262/105 */
+ proj_parm.cgb[2] = np*( 56/15.0 + n*(-136/35.0 + n*(-1262/105.0 +
+ n*( 73814/2835.0))));
+ proj_parm.cbg[2] = np*(-26/15.0 + n*( 34/21.0 + n*( 8/5.0 +
+ n*(-12686/2835.0))));
+ np *= n;
+ /* n^5 coeff corrected from 322/35 -> 332/35 */
+ proj_parm.cgb[3] = np*(4279/630.0 + n*(-332/35.0 + n*(-399572/14175.0)));
+ proj_parm.cbg[3] = np*(1237/630.0 + n*( -12/5.0 + n*( -24832/14175.0)));
+ np *= n;
+ proj_parm.cgb[4] = np*(4174/315.0 + n*(-144838/6237.0 ));
+ proj_parm.cbg[4] = np*(-734/315.0 + n*( 109598/31185.0));
+ np *= n;
+ proj_parm.cgb[5] = np*(601676/22275.0 );
+ proj_parm.cbg[5] = np*(444337/155925.0);
+
+ /* Constants of the projections */
+ /* Transverse Mercator (UTM, ITM, etc) */
+ np = n*n;
+ /* Norm. mer. quad, K&W p.50 (96), p.19 (38b), p.5 (2) */
+ proj_parm.Qn = par.k0/(1 + n) * (1 + np*(1/4.0 + np*(1/64.0 + np/256.0)));
+ /* coef of trig series */
+ /* utg := ell. N, E -> sph. N, E, KW p194 (65) */
+ /* gtu := sph. N, E -> ell. N, E, KW p196 (69) */
+ proj_parm.utg[0] = n*(-0.5 + n*( 2/3.0 + n*(-37/96.0 + n*( 1/360.0 +
+ n*( 81/512.0 + n*(-96199/604800.0))))));
+ proj_parm.gtu[0] = n*( 0.5 + n*(-2/3.0 + n*( 5/16.0 + n*(41/180.0 +
+ n*(-127/288.0 + n*( 7891/37800.0 ))))));
+ proj_parm.utg[1] = np*(-1/48.0 + n*(-1/15.0 + n*(437/1440.0 + n*(-46/105.0 +
+ n*( 1118711/3870720.0)))));
+ proj_parm.gtu[1] = np*(13/48.0 + n*(-3/5.0 + n*(557/1440.0 + n*(281/630.0 +
+ n*(-1983433/1935360.0)))));
+ np *= n;
+ proj_parm.utg[2] = np*(-17/480.0 + n*( 37/840.0 + n*( 209/4480.0 +
+ n*( -5569/90720.0 ))));
+ proj_parm.gtu[2] = np*( 61/240.0 + n*(-103/140.0 + n*(15061/26880.0 +
+ n*(167603/181440.0))));
+ np *= n;
+ proj_parm.utg[3] = np*(-4397/161280.0 + n*( 11/504.0 + n*( 830251/7257600.0)));
+ proj_parm.gtu[3] = np*(49561/161280.0 + n*(-179/168.0 + n*(6601661/7257600.0)));
+ np *= n;
+ proj_parm.utg[4] = np*(-4583/161280.0 + n*( 108847/3991680.0));
+ proj_parm.gtu[4] = np*(34729/80640.0 + n*(-3418889/1995840.0));
+ np *= n;
+ proj_parm.utg[5] = np*(-20648693/638668800.0);
+ proj_parm.gtu[5] = np*(212378941/319334400.0);
+
+ /* Gaussian latitude value of the origin latitude */
+ const T Z = base_tmerc_ellipsoid_exact<T, Parameters>::gatg (proj_parm.cbg, proj_etmerc_order, par.phi0, cos(2*par.phi0), sin(2*par.phi0));
+
+ /* Origin northing minus true northing at the origin latitude */
+ /* i.e. true northing = N - par.Zb */
+ proj_parm.Zb = - proj_parm.Qn*(Z + base_tmerc_ellipsoid_exact<T, Parameters>::clens(proj_parm.gtu, proj_etmerc_order, 2*Z));
+ }
+
}} // namespace detail::tmerc
#endif // doxygen
@@ -295,6 +646,8 @@ namespace projections
\par Example
\image html ex_tmerc.gif
*/
+ //approximate tmerc algorithm
+ /*
template <typename T, typename Parameters>
struct tmerc_ellipsoid : public detail::tmerc::base_tmerc_ellipsoid<T, Parameters>
{
@@ -304,6 +657,16 @@ namespace projections
detail::tmerc::setup(par, this->m_proj_parm);
}
};
+ */
+ template <typename T, typename Parameters>
+ struct tmerc_ellipsoid : public detail::tmerc::base_tmerc_ellipsoid_exact<T, Parameters>
+ {
+ template <typename Params>
+ inline tmerc_ellipsoid(Params const&, Parameters const& par)
+ {
+ detail::tmerc::setup_exact(par, this->m_proj_parm);
+ }
+ };
/*!
\brief Transverse Mercator projection
@@ -334,10 +697,10 @@ namespace projections
// Static projection
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(srs::spar::proj_tmerc, tmerc_spheroid, tmerc_ellipsoid)
-
+
// Factory entry(s) - dynamic projection
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(tmerc_entry, tmerc_spheroid, tmerc_ellipsoid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(tmerc_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(tmerc, tmerc_entry)
diff --git a/boost/geometry/srs/projections/proj/tpeqd.hpp b/boost/geometry/srs/projections/proj/tpeqd.hpp
index 4c059313e6..8ef38e5be8 100644
--- a/boost/geometry/srs/projections/proj/tpeqd.hpp
+++ b/boost/geometry/srs/projections/proj/tpeqd.hpp
@@ -199,7 +199,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(tpeqd_entry, tpeqd_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(tpeqd_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(tpeqd, tpeqd_entry)
diff --git a/boost/geometry/srs/projections/proj/urm5.hpp b/boost/geometry/srs/projections/proj/urm5.hpp
index b9914382eb..2277633c58 100644
--- a/boost/geometry/srs/projections/proj/urm5.hpp
+++ b/boost/geometry/srs/projections/proj/urm5.hpp
@@ -145,7 +145,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(urm5_entry, urm5_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(urm5_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(urm5, urm5_entry)
diff --git a/boost/geometry/srs/projections/proj/urmfps.hpp b/boost/geometry/srs/projections/proj/urmfps.hpp
index a065b651f3..002acc2463 100644
--- a/boost/geometry/srs/projections/proj/urmfps.hpp
+++ b/boost/geometry/srs/projections/proj/urmfps.hpp
@@ -96,7 +96,7 @@ namespace projections
};
template <typename Parameters, typename T>
- inline void setup(Parameters& par, par_urmfps<T>& proj_parm)
+ inline void setup(Parameters& par, par_urmfps<T>& proj_parm)
{
proj_parm.C_y = Cy / proj_parm.n;
par.es = 0.;
@@ -184,7 +184,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(urmfps_entry, urmfps_spheroid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(wag1_entry, wag1_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(urmfps_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(urmfps, urmfps_entry)
diff --git a/boost/geometry/srs/projections/proj/vandg.hpp b/boost/geometry/srs/projections/proj/vandg.hpp
index c34c500abe..95552d460b 100644
--- a/boost/geometry/srs/projections/proj/vandg.hpp
+++ b/boost/geometry/srs/projections/proj/vandg.hpp
@@ -126,10 +126,10 @@ namespace projections
static const T two_pi = detail::two_pi<T>();
static const T C2_27 = vandg::C2_27<T>();
- static const T PI4_3 = vandg::PI4_3<T>();
+ static const T PI4_3 = vandg::PI4_3<T>();
static const T TPISQ = vandg::TPISQ<T>();
static const T HPISQ = vandg::HPISQ<T>();
-
+
T t, c0, c1, c2, c3, al, r2, r, m, d, ay, x2, y2;
x2 = xy_x * xy_x;
@@ -210,7 +210,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(vandg_entry, vandg_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(vandg_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(vandg, vandg_entry)
diff --git a/boost/geometry/srs/projections/proj/vandg2.hpp b/boost/geometry/srs/projections/proj/vandg2.hpp
index 3d5a7d5ce2..c6ae88b97c 100644
--- a/boost/geometry/srs/projections/proj/vandg2.hpp
+++ b/boost/geometry/srs/projections/proj/vandg2.hpp
@@ -183,7 +183,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(vandg2_entry, vandg2_spheroid)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(vandg3_entry, vandg3_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(vandg2_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(vandg2, vandg2_entry)
diff --git a/boost/geometry/srs/projections/proj/vandg4.hpp b/boost/geometry/srs/projections/proj/vandg4.hpp
index 92cd6302b3..22f46b663f 100644
--- a/boost/geometry/srs/projections/proj/vandg4.hpp
+++ b/boost/geometry/srs/projections/proj/vandg4.hpp
@@ -150,7 +150,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(vandg4_entry, vandg4_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(vandg4_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(vandg4, vandg4_entry)
diff --git a/boost/geometry/srs/projections/proj/wag2.hpp b/boost/geometry/srs/projections/proj/wag2.hpp
index 78e7b0318d..fb23c222b7 100644
--- a/boost/geometry/srs/projections/proj/wag2.hpp
+++ b/boost/geometry/srs/projections/proj/wag2.hpp
@@ -129,7 +129,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(wag2_entry, wag2_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(wag2_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(wag2, wag2_entry)
diff --git a/boost/geometry/srs/projections/proj/wag3.hpp b/boost/geometry/srs/projections/proj/wag3.hpp
index 2c65eb5918..2bdb51a6ae 100644
--- a/boost/geometry/srs/projections/proj/wag3.hpp
+++ b/boost/geometry/srs/projections/proj/wag3.hpp
@@ -137,7 +137,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(wag3_entry, wag3_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(wag3_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(wag3, wag3_entry)
diff --git a/boost/geometry/srs/projections/proj/wag7.hpp b/boost/geometry/srs/projections/proj/wag7.hpp
index f2fafb58af..2e6ae918aa 100644
--- a/boost/geometry/srs/projections/proj/wag7.hpp
+++ b/boost/geometry/srs/projections/proj/wag7.hpp
@@ -118,7 +118,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(wag7_entry, wag7_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(wag7_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(wag7, wag7_entry)
diff --git a/boost/geometry/srs/projections/proj/wink1.hpp b/boost/geometry/srs/projections/proj/wink1.hpp
index c3c3998487..9d2bedb0b5 100644
--- a/boost/geometry/srs/projections/proj/wink1.hpp
+++ b/boost/geometry/srs/projections/proj/wink1.hpp
@@ -133,7 +133,7 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(wink1_entry, wink1_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(wink1_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(wink1, wink1_entry)
diff --git a/boost/geometry/srs/projections/proj/wink2.hpp b/boost/geometry/srs/projections/proj/wink2.hpp
index a8d2bdb571..484ab4ebc8 100644
--- a/boost/geometry/srs/projections/proj/wink2.hpp
+++ b/boost/geometry/srs/projections/proj/wink2.hpp
@@ -152,12 +152,12 @@ namespace projections
// Factory entry(s)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(wink2_entry, wink2_spheroid)
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_BEGIN(wink2_init)
{
BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(wink2, wink2_entry)
}
-
+
} // namespace detail
#endif // doxygen
diff --git a/boost/geometry/srs/projections/proj4.hpp b/boost/geometry/srs/projections/proj4.hpp
index 2e1d06c15d..b896acbec1 100644
--- a/boost/geometry/srs/projections/proj4.hpp
+++ b/boost/geometry/srs/projections/proj4.hpp
@@ -21,7 +21,7 @@
namespace boost { namespace geometry
{
-
+
namespace srs
{
diff --git a/boost/geometry/srs/projections/spar.hpp b/boost/geometry/srs/projections/spar.hpp
index 1a181e95a7..a727aa79c0 100644
--- a/boost/geometry/srs/projections/spar.hpp
+++ b/boost/geometry/srs/projections/spar.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry
-// Copyright (c) 2017-2020, Oracle and/or its affiliates.
+// Copyright (c) 2017-2022, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -232,6 +233,7 @@ struct proj_cass {};
struct proj_cc {};
struct proj_cea {};
struct proj_chamb {};
+struct proj_col_urban {};
struct proj_collg {};
struct proj_crast {};
struct proj_denoy {};
@@ -316,6 +318,7 @@ struct proj_vandg4 {};
struct proj_wag2 {};
struct proj_wag3 {};
struct proj_wag7 {};
+struct proj_webmerc {};
struct proj_wink1 {};
struct proj_wink2 {};
@@ -362,6 +365,7 @@ BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_F(es)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_F(f)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_F(gamma)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_F(h)
+BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_F(h_0)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_F(k)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_F(k_0)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_F(m)
@@ -407,7 +411,7 @@ BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_R(tilt)
#define BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_I(NAME) \
template <int I> struct NAME { static const int value = I; };
-
+
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_I(aperture)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_I(lsat)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_I(north_square)
@@ -432,8 +436,11 @@ BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_BE(r_au)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_BE(r_g)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_BE(r_h)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_BE(r_v)
-BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_BE(rescale)
+BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_BE(rescale)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_BE(south)
+BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_BE(variant_c)
+BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_BE(no_off)
+BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PARAM_BE(hyperbolic)
template
<
@@ -442,7 +449,7 @@ template
struct ellps
{
typedef SpheroidOrSphere model_type;
-
+
ellps() : model() {}
explicit ellps(SpheroidOrSphere const& sph) : model(sph) {}
@@ -458,9 +465,7 @@ struct nadgrids
nadgrids(std::string const& g0, std::string const& g1, std::string const& g2) : base_t(g0, g1, g2) {}
nadgrids(std::string const& g0, std::string const& g1, std::string const& g2, std::string const& g3) : base_t(g0, g1, g2, g3) {}
nadgrids(std::string const& g0, std::string const& g1, std::string const& g2, std::string const& g3, std::string const& g4) : base_t(g0, g1, g2, g3, g4) {}
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
nadgrids(std::initializer_list<std::string> l) : base_t(l) {}
-#endif
};
template <typename Proj>
@@ -481,9 +486,18 @@ struct towgs84
towgs84(T const& v0, T const& v1, T const& v2, T const& v3, T const& v4, T const& v5, T const& v6)
: base_t(v0, v1, v2, v3, v4, v5, v6)
{}
-#ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST
towgs84(std::initializer_list<T> l) : base_t(l) {}
-#endif
+};
+
+struct axis
+ : srs::detail::axis
+{
+ typedef srs::detail::axis base_t;
+
+ axis(int const& v0, int const& v1, int const& v2)
+ : base_t(v0, v1, v2)
+ {}
+ axis(std::initializer_list<int> l) : base_t(l) {}
};
template <typename Units>
@@ -742,6 +756,7 @@ BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_PROJ(proj_cass)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_PROJ(proj_cc)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_PROJ(proj_cea)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_PROJ(proj_chamb)
+BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_PROJ(proj_col_urban)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_PROJ(proj_collg)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_PROJ(proj_crast)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_PROJ(proj_denoy)
@@ -859,6 +874,7 @@ BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_PROJ(proj_vandg4)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_PROJ(proj_wag2)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_PROJ(proj_wag3)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_PROJ(proj_wag7)
+BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_PROJ(proj_webmerc)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_PROJ(proj_wink1)
BOOST_GEOMETRY_PROJECTIONS_DETAIL_REGISTER_PROJ(proj_wink2)
diff --git a/boost/geometry/srs/projections/str_cast.hpp b/boost/geometry/srs/projections/str_cast.hpp
index ee339cba59..e3729e2be5 100644
--- a/boost/geometry/srs/projections/str_cast.hpp
+++ b/boost/geometry/srs/projections/str_cast.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry
-// Copyright (c) 2018-2020, Oracle and/or its affiliates.
+// Copyright (c) 2018-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -10,13 +11,10 @@
#ifndef BOOST_GEOMETRY_SRS_PROJECTIONS_STR_CAST_HPP
#define BOOST_GEOMETRY_SRS_PROJECTIONS_STR_CAST_HPP
-#include <cstdlib>
-#include <string>
-#include <type_traits>
-
#include <boost/config.hpp>
#include <boost/geometry/core/exception.hpp>
#include <boost/throw_exception.hpp>
+#include <boost/type_traits/remove_cv.hpp>
namespace boost { namespace geometry
{
@@ -74,11 +72,6 @@ struct str_cast_traits_strtox<T, false, false>
}
};
-// Assuming a compiler supporting r-value references
-// supports long long and strtoll, strtoull, strtof, strtold
-// If it's MSVC enable in MSVC++ 12.0 aka Visual Studio 2013
-// TODO: in MSVC-11.0 _strtoi64() intrinsic could be used
-#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && (!defined(_MSC_VER) || (_MSC_VER >= 1800))
template <>
struct str_cast_traits_strtox<long long, true, true>
{
@@ -114,7 +107,6 @@ struct str_cast_traits_strtox<long double, false, false>
return strtold(str, str_end);
}
};
-#endif // C++11 strtox supported
template <typename T>
struct str_cast_traits_generic
diff --git a/boost/geometry/srs/shared_grids.hpp b/boost/geometry/srs/shared_grids.hpp
index 52b4e9944d..54bbb442a3 100644
--- a/boost/geometry/srs/shared_grids.hpp
+++ b/boost/geometry/srs/shared_grids.hpp
@@ -16,7 +16,7 @@
namespace boost { namespace geometry
{
-
+
namespace srs
{
diff --git a/boost/geometry/srs/shared_grids_boost.hpp b/boost/geometry/srs/shared_grids_boost.hpp
index e55298d73b..06414ee572 100644
--- a/boost/geometry/srs/shared_grids_boost.hpp
+++ b/boost/geometry/srs/shared_grids_boost.hpp
@@ -14,12 +14,13 @@
#include <boost/geometry/srs/projections/grids.hpp>
-#include <boost/thread.hpp>
+#include <boost/thread/lock_types.hpp>
+#include <boost/thread/shared_mutex.hpp>
namespace boost { namespace geometry
{
-
+
namespace srs
{
diff --git a/boost/geometry/srs/shared_grids_std.hpp b/boost/geometry/srs/shared_grids_std.hpp
index f940d90379..d6f4061305 100644
--- a/boost/geometry/srs/shared_grids_std.hpp
+++ b/boost/geometry/srs/shared_grids_std.hpp
@@ -25,7 +25,7 @@
namespace boost { namespace geometry
{
-
+
namespace srs
{
diff --git a/boost/geometry/srs/spheroid.hpp b/boost/geometry/srs/spheroid.hpp
index 63ef10095a..f8e5b51816 100644
--- a/boost/geometry/srs/spheroid.hpp
+++ b/boost/geometry/srs/spheroid.hpp
@@ -35,7 +35,7 @@
namespace boost { namespace geometry
{
-
+
namespace srs
{
diff --git a/boost/geometry/srs/transformation.hpp b/boost/geometry/srs/transformation.hpp
index f661e47a6b..d3c9b09c53 100644
--- a/boost/geometry/srs/transformation.hpp
+++ b/boost/geometry/srs/transformation.hpp
@@ -95,7 +95,7 @@ struct transform_geometry_point
typedef typename geometry::point_type<Geometry>::type point_type;
typedef geometry::model::point
- <
+ <
typename select_most_precise
<
typename geometry::coordinate_type<point_type>::type,
@@ -552,7 +552,7 @@ struct transform<MultiPolygon, CT, multi_polygon_tag>
}} // namespace projections::detail
-
+
namespace srs
{
diff --git a/boost/geometry/strategies/agnostic/buffer_distance_asymmetric.hpp b/boost/geometry/strategies/agnostic/buffer_distance_asymmetric.hpp
index 446d2f02cd..85404ee174 100644
--- a/boost/geometry/strategies/agnostic/buffer_distance_asymmetric.hpp
+++ b/boost/geometry/strategies/agnostic/buffer_distance_asymmetric.hpp
@@ -76,6 +76,11 @@ public :
return m_left < 0 && m_right < 0;
}
+ inline bool empty(buffer_side_selector side) const
+ {
+ return side == buffer_side_left ? m_left == 0 : m_right == 0;
+ }
+
//! Returns the max distance distance up to the buffer will reach
template <typename JoinStrategy, typename EndStrategy>
inline NumericType max_distance(JoinStrategy const& join_strategy,
diff --git a/boost/geometry/strategies/agnostic/buffer_distance_symmetric.hpp b/boost/geometry/strategies/agnostic/buffer_distance_symmetric.hpp
index fe973e3f38..aaf765accb 100644
--- a/boost/geometry/strategies/agnostic/buffer_distance_symmetric.hpp
+++ b/boost/geometry/strategies/agnostic/buffer_distance_symmetric.hpp
@@ -74,6 +74,11 @@ public :
return m_distance < 0;
}
+ inline bool empty(buffer_side_selector ) const
+ {
+ return m_distance == 0;
+ }
+
//! Returns the max distance distance up to the buffer will reach
template <typename JoinStrategy, typename EndStrategy>
inline NumericType max_distance(JoinStrategy const& join_strategy,
diff --git a/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp b/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp
index 5ea58736ee..6199634823 100644
--- a/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp
+++ b/boost/geometry/strategies/agnostic/point_in_box_by_side.hpp
@@ -3,6 +3,7 @@
// 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.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2018-2020.
// Modifications copyright (c) 2018-2020 Oracle and/or its affiliates.
@@ -18,16 +19,18 @@
#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 <array>
+
#include <boost/core/ignore_unused.hpp>
+
+#include <boost/geometry/algorithms/assign.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>
-#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/geographic/side.hpp>
+#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
+#include <boost/geometry/strategies/within.hpp>
namespace boost { namespace geometry { namespace strategy
@@ -82,7 +85,7 @@ inline bool point_in_box_by_side(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;
+ std::array<typename point_type<Box>::type, 5> bp;
geometry::detail::assign_box_corners_oriented<true>(box, bp);
bp[4] = bp[0];
@@ -114,11 +117,14 @@ struct cartesian_point_box_by_side
template <typename Point, typename Box>
static inline bool apply(Point const& point, Box const& box)
{
+ using side_strategy_type
+ = typename strategy::side::services::default_strategy
+ <cartesian_tag, CalculationType>::type;
+
return within::detail::point_in_box_by_side
<
within::detail::decide_within
- >(point, box,
- strategy::side::side_by_triangle<CalculationType>());
+ >(point, box, side_strategy_type());
}
};
@@ -185,11 +191,13 @@ struct cartesian_point_box_by_side
template <typename Point, typename Box>
static bool apply(Point const& point, Box const& box)
{
+ using side_strategy_type
+ = typename strategy::side::services::default_strategy
+ <cartesian_tag, CalculationType>::type;
return within::detail::point_in_box_by_side
<
within::detail::decide_covered_by
- >(point, box,
- strategy::side::side_by_triangle<CalculationType>());
+ >(point, box, side_strategy_type());
}
};
diff --git a/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp b/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
index e7b439b2e5..07342ae10b 100644
--- a/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
+++ b/boost/geometry/strategies/agnostic/point_in_poly_winding.hpp
@@ -61,20 +61,27 @@ struct winding_base_type
template <typename Point, typename PointOfSegment, typename CalculationType>
struct winding_base_type<Point, PointOfSegment, CalculationType, cartesian_tag>
{
- typedef within::cartesian_winding<void, void, CalculationType> type;
+ using type = within::detail::cartesian_winding_base
+ <
+ typename strategy::side::services::default_strategy
+ <
+ typename cs_tag<Point>::type
+ >::type,
+ CalculationType
+ >;
};
template <typename Point, typename PointOfSegment, typename CalculationType>
struct winding_base_type<Point, PointOfSegment, CalculationType, spherical_tag>
{
- typedef within::detail::spherical_winding_base
+ using type = within::detail::spherical_winding_base
<
typename strategy::side::services::default_strategy
<
typename cs_tag<Point>::type
>::type,
CalculationType
- > type;
+ >;
};
diff --git a/boost/geometry/strategies/area/geographic.hpp b/boost/geometry/strategies/area/geographic.hpp
index 342ba45f33..a8d806c394 100644
--- a/boost/geometry/strategies/area/geographic.hpp
+++ b/boost/geometry/strategies/area/geographic.hpp
@@ -86,8 +86,11 @@ struct strategy_converter<strategy::area::geographic<FP, SO, S, CT> >
: strategies::area::geographic<FP, S, CT>(spheroid)
{}
+ using strategies::area::geographic<FP, S, CT>::area;
+
template <typename Geometry>
- auto area(Geometry const&) const
+ auto area(Geometry const&,
+ std::enable_if_t<! util::is_box<Geometry>::value> * = nullptr) const
{
return strategy::area::geographic<FP, SO, S, CT>(this->m_spheroid);
}
diff --git a/boost/geometry/strategies/azimuth/spherical.hpp b/boost/geometry/strategies/azimuth/spherical.hpp
index a87cf927b9..c27781996b 100644
--- a/boost/geometry/strategies/azimuth/spherical.hpp
+++ b/boost/geometry/strategies/azimuth/spherical.hpp
@@ -30,7 +30,7 @@ class spherical : strategies::detail::spherical_base<void>
using base_t = strategies::detail::spherical_base<void>;
public:
-
+
static auto azimuth()
{
return strategy::azimuth::spherical<CalculationType>();
diff --git a/boost/geometry/strategies/buffer.hpp b/boost/geometry/strategies/buffer.hpp
index 86bdcc37bf..b03c9bc626 100644
--- a/boost/geometry/strategies/buffer.hpp
+++ b/boost/geometry/strategies/buffer.hpp
@@ -6,8 +6,10 @@
// 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_BUFFER_HPP
-#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_HPP
+#ifndef BOOST_GEOMETRY_STRATEGIES_BUFFER_HPP
+#define BOOST_GEOMETRY_STRATEGIES_BUFFER_HPP
+
+#include <cstdint>
namespace boost { namespace geometry
{
@@ -55,6 +57,27 @@ namespace strategy { namespace buffer
*/
enum buffer_side_selector { buffer_side_left, buffer_side_right };
+// Default number of points in a circle
+constexpr std::size_t default_points_per_circle = 90u;
+
+inline std::size_t get_point_count_for_join(std::size_t count)
+{
+ std::size_t const min_count = 4u;
+ return count > min_count ? count : min_count;
+}
+
+inline std::size_t get_point_count_for_end(std::size_t count)
+{
+ std::size_t const min_count = 4u;
+ return count > min_count ? count : min_count;
+}
+
+inline std::size_t get_point_count_for_circle(std::size_t count)
+{
+ std::size_t const min_count = 3u;
+ return count > min_count ? count : min_count;
+}
+
/*!
\brief Enumerates types of pieces (parts of buffer) around geometries
\ingroup enum
@@ -67,6 +90,7 @@ enum piece_type
buffered_flat_end,
buffered_point,
buffered_concave, // always on the inside
+ buffered_empty_side, // for one-sided buffers
piece_type_unknown
};
@@ -100,4 +124,4 @@ enum result_code
}} // namespace boost::geometry
-#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_BUFFER_HPP
+#endif // BOOST_GEOMETRY_STRATEGIES_BUFFER_HPP
diff --git a/boost/geometry/strategies/buffer/cartesian.hpp b/boost/geometry/strategies/buffer/cartesian.hpp
index 6550882806..51b68c018c 100644
--- a/boost/geometry/strategies/buffer/cartesian.hpp
+++ b/boost/geometry/strategies/buffer/cartesian.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2021, Oracle and/or its affiliates.
+// Copyright (c) 2021-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -12,11 +12,7 @@
#include <boost/geometry/strategies/buffer/services.hpp>
-#include <boost/geometry/strategies/distance/detail.hpp>
-#include <boost/geometry/strategies/relate/cartesian.hpp>
-
-#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp>
-#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
+#include <boost/geometry/strategies/distance/cartesian.hpp>
namespace boost { namespace geometry
@@ -27,21 +23,8 @@ namespace strategies { namespace buffer
template <typename CalculationType = void>
struct cartesian
- : public strategies::relate::cartesian<CalculationType>
-{
- // Additional strategies for simplify()
-
- template <typename Geometry1, typename Geometry2>
- static auto distance(Geometry1 const&, Geometry2 const&,
- distance::detail::enable_if_ps_t<Geometry1, Geometry2> * = nullptr)
- {
- return strategy::distance::projected_point
- <
- CalculationType,
- strategy::distance::pythagoras<CalculationType>
- >();
- }
-};
+ : public strategies::distance::cartesian<CalculationType>
+{};
namespace services
diff --git a/boost/geometry/strategies/buffer/geographic.hpp b/boost/geometry/strategies/buffer/geographic.hpp
index 723a4483a3..50d1b04594 100644
--- a/boost/geometry/strategies/buffer/geographic.hpp
+++ b/boost/geometry/strategies/buffer/geographic.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2021, Oracle and/or its affiliates.
+// Copyright (c) 2021-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -12,10 +12,7 @@
#include <boost/geometry/strategies/buffer/services.hpp>
-#include <boost/geometry/strategies/distance/detail.hpp>
-#include <boost/geometry/strategies/relate/geographic.hpp>
-
-#include <boost/geometry/strategies/geographic/distance_cross_track.hpp>
+#include <boost/geometry/strategies/distance/geographic.hpp>
namespace boost { namespace geometry
@@ -32,9 +29,9 @@ template
typename CalculationType = void
>
class geographic
- : public strategies::relate::geographic<FormulaPolicy, Spheroid, CalculationType>
+ : public strategies::distance::geographic<FormulaPolicy, Spheroid, CalculationType>
{
- using base_t = strategies::relate::geographic<FormulaPolicy, Spheroid, CalculationType>;
+ using base_t = strategies::distance::geographic<FormulaPolicy, Spheroid, CalculationType>;
public:
geographic() = default;
@@ -42,18 +39,6 @@ public:
explicit geographic(Spheroid const& spheroid)
: base_t(spheroid)
{}
-
- // Additional strategies for simplify()
-
- template <typename Geometry1, typename Geometry2>
- auto distance(Geometry1 const&, Geometry2 const&,
- distance::detail::enable_if_ps_t<Geometry1, Geometry2> * = nullptr) const
- {
- return strategy::distance::geographic_cross_track
- <
- FormulaPolicy, Spheroid, CalculationType
- >(base_t::m_spheroid);
- }
};
diff --git a/boost/geometry/strategies/buffer/spherical.hpp b/boost/geometry/strategies/buffer/spherical.hpp
index 524e6a2aaf..c959ec8747 100644
--- a/boost/geometry/strategies/buffer/spherical.hpp
+++ b/boost/geometry/strategies/buffer/spherical.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2021, Oracle and/or its affiliates.
+// Copyright (c) 2021-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -12,11 +12,7 @@
#include <boost/geometry/strategies/buffer/services.hpp>
-#include <boost/geometry/strategies/distance/detail.hpp>
-#include <boost/geometry/strategies/relate/spherical.hpp>
-
-#include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
-#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
+#include <boost/geometry/strategies/distance/spherical.hpp>
namespace boost { namespace geometry
@@ -31,9 +27,9 @@ template
typename CalculationType = void
>
class spherical
- : public strategies::relate::detail::spherical<RadiusTypeOrSphere, CalculationType>
+ : public strategies::distance::detail::spherical<RadiusTypeOrSphere, CalculationType>
{
- using base_t = strategies::relate::detail::spherical<RadiusTypeOrSphere, CalculationType>;
+ using base_t = strategies::distance::detail::spherical<RadiusTypeOrSphere, CalculationType>;
public:
spherical() = default;
@@ -42,19 +38,6 @@ public:
explicit spherical(RadiusOrSphere const& radius_or_sphere)
: base_t(radius_or_sphere)
{}
-
- // Additional strategies for simplify()
-
- template <typename Geometry1, typename Geometry2>
- auto distance(Geometry1 const&, Geometry2 const&,
- distance::detail::enable_if_ps_t<Geometry1, Geometry2> * = nullptr) const
- {
- return strategy::distance::cross_track
- <
- CalculationType,
- strategy::distance::haversine<typename base_t::radius_type, CalculationType>
- >(base_t::radius());
- }
};
diff --git a/boost/geometry/strategies/cartesian.hpp b/boost/geometry/strategies/cartesian.hpp
index 14ec8b7cdd..83c89f00cf 100644
--- a/boost/geometry/strategies/cartesian.hpp
+++ b/boost/geometry/strategies/cartesian.hpp
@@ -28,7 +28,7 @@
namespace boost { namespace geometry
{
-
+
namespace strategies
{
diff --git a/boost/geometry/strategies/cartesian/azimuth.hpp b/boost/geometry/strategies/cartesian/azimuth.hpp
index 74a9ea12b1..9035fdddcb 100644
--- a/boost/geometry/strategies/cartesian/azimuth.hpp
+++ b/boost/geometry/strategies/cartesian/azimuth.hpp
@@ -14,10 +14,10 @@
#include <cmath>
#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
#include <boost/geometry/strategies/azimuth.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
diff --git a/boost/geometry/strategies/cartesian/box_in_box.hpp b/boost/geometry/strategies/cartesian/box_in_box.hpp
index a0cb6d9d1b..91127b13e1 100644
--- a/boost/geometry/strategies/cartesian/box_in_box.hpp
+++ b/boost/geometry/strategies/cartesian/box_in_box.hpp
@@ -113,7 +113,7 @@ struct box_longitude_range
// min <= max <=> diff >= 0
calc_t const diff_ed = bed_max - bed_min;
calc_t const diff_ing = bing_max - bing_min;
-
+
// if containing covers the whole globe it contains all
if (diff_ing >= constants::period())
{
@@ -150,7 +150,7 @@ struct relate_box_box_loop
static inline bool apply(Box1 const& b_contained, Box2 const& b_containing)
{
assert_dimension_equal<Box1, Box2>();
-
+
if (! SubStrategy<Box1, Dimension, CSTag>::apply(
get<min_corner, Dimension>(b_contained),
get<max_corner, Dimension>(b_contained),
diff --git a/boost/geometry/strategies/cartesian/buffer_end_flat.hpp b/boost/geometry/strategies/cartesian/buffer_end_flat.hpp
index dfbc19e98d..961f201edd 100644
--- a/boost/geometry/strategies/cartesian/buffer_end_flat.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_end_flat.hpp
@@ -54,7 +54,7 @@ public :
#ifndef DOXYGEN_SHOULD_SKIP_THIS
//! Fills output_range with a flat end
- template <typename Point, typename RangeOut, typename DistanceStrategy>
+ template <typename Point, typename DistanceStrategy, typename RangeOut>
inline void apply(Point const& penultimate_point,
Point const& perp_left_point,
Point const& ultimate_point,
@@ -63,20 +63,13 @@ public :
DistanceStrategy const& distance,
RangeOut& range_out) const
{
- typedef typename coordinate_type<Point>::type coordinate_type;
+ auto const dist_left = distance.apply(penultimate_point, ultimate_point, buffer_side_left);
+ auto const dist_right = distance.apply(penultimate_point, ultimate_point, buffer_side_right);
- typedef typename geometry::select_most_precise
- <
- coordinate_type,
- double
- >::type promoted_type;
+ bool const reversed =
+ (side == buffer_side_left && dist_right < 0 && -dist_right > dist_left)
+ || (side == buffer_side_right && dist_left < 0 && -dist_left > dist_right);
- promoted_type const dist_left = distance.apply(penultimate_point, ultimate_point, buffer_side_left);
- promoted_type const dist_right = distance.apply(penultimate_point, ultimate_point, buffer_side_right);
-
- bool reversed = (side == buffer_side_left && dist_right < 0 && -dist_right > dist_left)
- || (side == buffer_side_right && dist_left < 0 && -dist_left > dist_right)
- ;
if (reversed)
{
range_out.push_back(perp_right_point);
@@ -89,7 +82,7 @@ public :
}
// Don't add the ultimate_point (endpoint of the linestring).
// The buffer might be generated completely at one side.
- // In other cases it does no harm but is further useless
+ // In other cases it does no harm but it is useless
}
template <typename NumericType>
diff --git a/boost/geometry/strategies/cartesian/buffer_end_round.hpp b/boost/geometry/strategies/cartesian/buffer_end_round.hpp
index b3bd6f2abe..47ecb22e72 100644
--- a/boost/geometry/strategies/cartesian/buffer_end_round.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_end_round.hpp
@@ -2,9 +2,9 @@
// Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2015.
-// Modifications copyright (c) 2015, Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2015-2023.
+// Modifications copyright (c) 2015-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -16,7 +16,9 @@
#include <boost/core/ignore_unused.hpp>
+#include <boost/geometry/arithmetic/arithmetic.hpp>
#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/access.hpp>
#include <boost/geometry/strategies/tags.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
@@ -24,8 +26,6 @@
#include <boost/geometry/strategies/buffer.hpp>
-#include <boost/geometry/io/wkt/wkt.hpp>
-
namespace boost { namespace geometry
{
@@ -82,8 +82,8 @@ private :
for (std::size_t i = 0; i < point_buffer_count; i++, alpha -= diff)
{
typename boost::range_value<RangeOut>::type p;
- set<0>(p, get<0>(point) + buffer_distance * cos(alpha));
- set<1>(p, get<1>(point) + buffer_distance * sin(alpha));
+ geometry::set<0>(p, geometry::get<0>(point) + buffer_distance * cos(alpha));
+ geometry::set<1>(p, geometry::get<1>(point) + buffer_distance * sin(alpha));
range_out.push_back(p);
}
}
@@ -100,16 +100,15 @@ private :
public :
//! \brief Constructs the strategy
- //! \param points_per_circle points which would be used for a full circle
- //! (if points_per_circle is smaller than 4, it is internally set to 4)
- explicit inline end_round(std::size_t points_per_circle = 90)
- : m_points_per_circle((points_per_circle < 4u) ? 4u : points_per_circle)
+ //! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
+ explicit inline end_round(std::size_t points_per_circle = default_points_per_circle)
+ : m_points_per_circle(get_point_count_for_end(points_per_circle))
{}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
- //! Fills output_range with a flat end
- template <typename Point, typename RangeOut, typename DistanceStrategy>
+ //! Fills output_range with a round end
+ template <typename Point, typename DistanceStrategy, typename RangeOut>
inline void apply(Point const& penultimate_point,
Point const& perp_left_point,
Point const& ultimate_point,
@@ -147,8 +146,8 @@ public :
: (dist_left - dist_right)) / two;
Point shifted_point;
- set<0>(shifted_point, get<0>(ultimate_point) + dist_half * cos(alpha));
- set<1>(shifted_point, get<1>(ultimate_point) + dist_half * sin(alpha));
+ geometry::set<0>(shifted_point, geometry::get<0>(ultimate_point) + dist_half * cos(alpha));
+ geometry::set<1>(shifted_point, geometry::get<1>(ultimate_point) + dist_half * sin(alpha));
generate_points(shifted_point, alpha, dist_average, range_out);
}
diff --git a/boost/geometry/strategies/cartesian/buffer_join_miter.hpp b/boost/geometry/strategies/cartesian/buffer_join_miter.hpp
index 5358156f6d..a47b3fa018 100644
--- a/boost/geometry/strategies/cartesian/buffer_join_miter.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_join_miter.hpp
@@ -89,8 +89,8 @@ public:
// Check the distance ip-vertex (= miter distance)
// (We calculate it manually (not using Pythagoras strategy) to reuse
// dx and dy)
- coordinate_type const dx = get<0>(p) - get<0>(vertex);
- coordinate_type const dy = get<1>(p) - get<1>(vertex);
+ promoted_type const dx = get<0>(p) - get<0>(vertex);
+ promoted_type const dy = get<1>(p) - get<1>(vertex);
promoted_type const distance = geometry::math::sqrt(dx * dx + dy * dy);
diff --git a/boost/geometry/strategies/cartesian/buffer_join_round.hpp b/boost/geometry/strategies/cartesian/buffer_join_round.hpp
index e1a433e1ee..95553685cb 100644
--- a/boost/geometry/strategies/cartesian/buffer_join_round.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_join_round.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2012-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015, Oracle and/or its affiliates.
@@ -58,9 +59,9 @@ class join_round
public :
//! \brief Constructs the strategy
- //! \param points_per_circle points which would be used for a full circle
- explicit inline join_round(std::size_t points_per_circle = 90)
- : m_points_per_circle(points_per_circle)
+ //! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
+ explicit inline join_round(std::size_t points_per_circle = default_points_per_circle)
+ : m_points_per_circle(get_point_count_for_join(points_per_circle))
{}
private :
@@ -143,26 +144,15 @@ public :
geometry::equal_to<Point> equals;
if (equals(perp1, perp2))
{
+ boost::ignore_unused(ip);
#ifdef BOOST_GEOMETRY_DEBUG_BUFFER_WARN
std::cout << "Corner for equal points " << geometry::wkt(ip) << " " << geometry::wkt(perp1) << std::endl;
#endif
return false;
}
- // Generate 'vectors'
- coordinate_type vix = (get<0>(ip) - get<0>(vertex));
- coordinate_type viy = (get<1>(ip) - get<1>(vertex));
-
- promoted_type length_i = geometry::math::sqrt(vix * vix + viy * viy);
- DistanceType const bd = geometry::math::abs(buffer_distance);
- promoted_type prop = bd / length_i;
-
- Point bp;
- set<0>(bp, get<0>(vertex) + vix * prop);
- set<1>(bp, get<1>(vertex) + viy * prop);
-
range_out.push_back(perp1);
- generate_points<promoted_type>(vertex, perp1, perp2, bd, range_out);
+ generate_points<promoted_type>(vertex, perp1, perp2, geometry::math::abs(buffer_distance), range_out);
range_out.push_back(perp2);
return true;
}
diff --git a/boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp b/boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp
index ed3a010cd5..0a2c7ebf63 100644
--- a/boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_join_round_by_divide.hpp
@@ -48,23 +48,21 @@ public :
RangeOut& range_out,
std::size_t level = 1) const
{
- typedef typename coordinate_type<Point>::type coordinate_type;
-
// Generate 'vectors'
- coordinate_type const vp1_x = get<0>(p1) - get<0>(vertex);
- coordinate_type const vp1_y = get<1>(p1) - get<1>(vertex);
+ PromotedType const vp1_x = get<0>(p1) - get<0>(vertex);
+ PromotedType const vp1_y = get<1>(p1) - get<1>(vertex);
- coordinate_type const vp2_x = (get<0>(p2) - get<0>(vertex));
- coordinate_type const vp2_y = (get<1>(p2) - get<1>(vertex));
+ PromotedType const vp2_x = (get<0>(p2) - get<0>(vertex));
+ PromotedType const vp2_y = (get<1>(p2) - get<1>(vertex));
// Average them to generate vector in between
- coordinate_type const two = 2;
- coordinate_type const v_x = (vp1_x + vp2_x) / two;
- coordinate_type const v_y = (vp1_y + vp2_y) / two;
+ PromotedType const two = 2;
+ PromotedType const v_x = (vp1_x + vp2_x) / two;
+ PromotedType const v_y = (vp1_y + vp2_y) / two;
PromotedType const length2 = geometry::math::sqrt(v_x * v_x + v_y * v_y);
- PromotedType prop = buffer_distance / length2;
+ PromotedType const prop = buffer_distance / length2;
Point mid_point;
set<0>(mid_point, get<0>(vertex) + v_x * prop);
@@ -106,13 +104,13 @@ public :
}
// Generate 'vectors'
- coordinate_type const vix = (get<0>(ip) - get<0>(vertex));
- coordinate_type const viy = (get<1>(ip) - get<1>(vertex));
+ promoted_type const vix = (get<0>(ip) - get<0>(vertex));
+ promoted_type const viy = (get<1>(ip) - get<1>(vertex));
promoted_type const length_i = geometry::math::sqrt(vix * vix + viy * viy);
promoted_type const bd = geometry::math::abs(buffer_distance);
- promoted_type prop = bd / length_i;
+ promoted_type const prop = bd / length_i;
Point bp;
set<0>(bp, get<0>(vertex) + vix * prop);
diff --git a/boost/geometry/strategies/cartesian/buffer_point_circle.hpp b/boost/geometry/strategies/cartesian/buffer_point_circle.hpp
index c341e3ca3b..b6fc0707bc 100644
--- a/boost/geometry/strategies/cartesian/buffer_point_circle.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_point_circle.hpp
@@ -57,10 +57,9 @@ class point_circle
{
public :
//! \brief Constructs the strategy
- //! \param count number of points for the created circle (if count
- //! is smaller than 3, count is internally set to 3)
- explicit point_circle(std::size_t count = 90)
- : m_count((count < 3u) ? 3u : count)
+ //! \param count Number of points (minimum 3) for the created circle
+ explicit point_circle(std::size_t count = default_points_per_circle)
+ : m_count(get_point_count_for_circle(count))
{}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
diff --git a/boost/geometry/strategies/cartesian/buffer_side_straight.hpp b/boost/geometry/strategies/cartesian/buffer_side_straight.hpp
index c9ecdb0199..10dac42983 100644
--- a/boost/geometry/strategies/cartesian/buffer_side_straight.hpp
+++ b/boost/geometry/strategies/cartesian/buffer_side_straight.hpp
@@ -76,8 +76,8 @@ public :
// Generate a block along (left or right of) the segment
// Simulate a vector d (dx,dy)
- coordinate_type const dx = get<0>(input_p2) - get<0>(input_p1);
- coordinate_type const dy = get<1>(input_p2) - get<1>(input_p1);
+ promoted_type const dx = get<0>(input_p2) - get<0>(input_p1);
+ promoted_type const dy = get<1>(input_p2) - get<1>(input_p1);
// For normalization [0,1] (=dot product d.d, sqrt)
promoted_type const length = geometry::math::sqrt(dx * dx + dy * dy);
diff --git a/boost/geometry/strategies/cartesian/centroid_average.hpp b/boost/geometry/strategies/cartesian/centroid_average.hpp
index 573b7f6e7e..103a1d8ab3 100644
--- a/boost/geometry/strategies/cartesian/centroid_average.hpp
+++ b/boost/geometry/strategies/cartesian/centroid_average.hpp
@@ -72,7 +72,7 @@ public :
struct state_type
{
typedef sum<GeometryPoint, ResultPoint> type;
- };
+ };
template <typename GeometryPoint, typename ResultPoint>
static inline void apply(GeometryPoint const& p,
diff --git a/boost/geometry/strategies/cartesian/centroid_weighted_length.hpp b/boost/geometry/strategies/cartesian/centroid_weighted_length.hpp
index c536d5bc24..477d68b892 100644
--- a/boost/geometry/strategies/cartesian/centroid_weighted_length.hpp
+++ b/boost/geometry/strategies/cartesian/centroid_weighted_length.hpp
@@ -3,9 +3,9 @@
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// Copyright (c) 2009-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2015-2021.
-// Modifications copyright (c) 2015-2021, Oracle and/or its affiliates.
-
+// This file was modified by Oracle on 2015-2023.
+// Modifications copyright (c) 2015-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -21,6 +21,8 @@
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/numeric/conversion/cast.hpp>
+#include <boost/geometry/algorithms/assign.hpp>
+
#include <boost/geometry/arithmetic/arithmetic.hpp>
// Helper geometry
diff --git a/boost/geometry/strategies/cartesian/closest_points_pt_seg.hpp b/boost/geometry/strategies/cartesian/closest_points_pt_seg.hpp
new file mode 100644
index 0000000000..557cd48dd6
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/closest_points_pt_seg.hpp
@@ -0,0 +1,146 @@
+// Boost.Geometry
+
+// Copyright (c) 2021-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CLOSEST_POINTS_PT_SEG_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CLOSEST_POINTS_PT_SEG_HPP
+
+#include <boost/geometry/algorithms/convert.hpp>
+
+#include <boost/geometry/core/coordinate_promotion.hpp>
+
+#include <boost/geometry/geometries/point.hpp>
+
+#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
+#include <boost/geometry/strategies/closest_points/services.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace closest_points
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename CalculationType>
+struct compute_closest_point_to_segment
+{
+ template <typename Point, typename PointOfSegment>
+ static inline auto
+ apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2)
+ {
+ // A projected point of points in Integer coordinates must be able to be
+ // represented in FP.
+ using fp_point_type = model::point
+ <
+ CalculationType,
+ dimension<PointOfSegment>::value,
+ typename coordinate_system<PointOfSegment>::type
+ >;
+
+ // For convenience
+ using fp_vector_type = fp_point_type;
+
+ /*
+ Algorithm [p: (px,py), p1: (x1,y1), p2: (x2,y2)]
+ 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, projected;
+
+ geometry::convert(p2, v);
+ geometry::convert(p, w);
+ geometry::convert(p1, projected);
+ subtract_point(v, projected);
+ subtract_point(w, projected);
+
+ CalculationType const zero = CalculationType();
+ CalculationType const c1 = dot_product(w, v);
+ if (c1 <= zero)
+ {
+ fp_vector_type fp_p1;
+ geometry::convert(p1, fp_p1);
+ return fp_p1;
+ }
+ CalculationType const c2 = dot_product(v, v);
+ if (c2 <= c1)
+ {
+ fp_vector_type fp_p2;
+ geometry::convert(p2, fp_p2);
+ return fp_p2;
+ }
+
+ // See above, c1 > 0 AND c2 > c1 so: c2 != 0
+ CalculationType const b = c1 / c2;
+
+ multiply_value(v, b);
+ add_point(projected, v);
+
+ return projected;
+ }
+};
+
+}
+#endif // DOXYGEN_NO_DETAIL
+
+template
+<
+ typename CalculationType = void
+>
+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.
+
+ template <typename Point, typename PointOfSegment>
+ struct calculation_type
+ : promote_floating_point
+ <
+ typename select_most_precise
+ <
+ typename coordinate_type<Point>::type,
+ typename coordinate_type<PointOfSegment>::type,
+ CalculationType
+ >::type
+ >
+ {};
+
+ template <typename Point, typename PointOfSegment>
+ inline auto
+ apply(Point const& p, PointOfSegment const& p1, PointOfSegment const& p2) const
+ {
+ assert_dimension_equal<Point, PointOfSegment>();
+
+ using calculation_type = typename calculation_type<Point, PointOfSegment>::type;
+
+ return detail::compute_closest_point_to_segment<calculation_type>::apply(p, p1, p2);
+ }
+
+};
+
+}} // namespace strategy::closest_points
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CLOSEST_POINTS_PT_SEG_HPP
diff --git a/boost/geometry/strategies/cartesian/densify.hpp b/boost/geometry/strategies/cartesian/densify.hpp
index 0a897bad98..a6bc0a793f 100644
--- a/boost/geometry/strategies/cartesian/densify.hpp
+++ b/boost/geometry/strategies/cartesian/densify.hpp
@@ -61,7 +61,7 @@ public:
>::type calc_t;
typedef model::point<calc_t, geometry::dimension<Point>::value, cs::cartesian> calc_point_t;
-
+
assert_dimension_equal<calc_point_t, out_point_t>();
calc_point_t cp0, dir01;
@@ -89,7 +89,7 @@ public:
for (signed_size_type i = 0 ; i < n ; ++i)
{
out_point_t out;
-
+
calc_t const num = calc_t(i + 1);
geometry::detail::for_each_dimension<out_point_t>([&](auto index)
{
diff --git a/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp b/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp
index 37ae77f2b8..d903f21008 100644
--- a/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp
+++ b/boost/geometry/strategies/cartesian/disjoint_segment_box.hpp
@@ -162,7 +162,7 @@ struct disjoint_segment_box_impl
<
RelativeDistance,
SegmentPoint,
- Box,
+ Box,
I + 1,
Dimension
>::apply(p0, p1, box, t_min, t_max);
diff --git a/boost/geometry/strategies/cartesian/distance_projected_point.hpp b/boost/geometry/strategies/cartesian/distance_projected_point.hpp
index 4cb263dd37..e3396494aa 100644
--- a/boost/geometry/strategies/cartesian/distance_projected_point.hpp
+++ b/boost/geometry/strategies/cartesian/distance_projected_point.hpp
@@ -6,6 +6,7 @@
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -35,6 +36,7 @@
#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/closest_points_pt_seg.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
#include <boost/geometry/strategies/cartesian/intersection.hpp>
@@ -103,60 +105,10 @@ public:
typedef typename calculation_type<Point, PointOfSegment>::type calculation_type;
- // 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;
-
- /*
- Algorithm [p: (px,py), p1: (x1,y1), p2: (x2,y2)]
- 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, projected;
-
- geometry::convert(p2, v);
- geometry::convert(p, w);
- geometry::convert(p1, projected);
- subtract_point(v, projected);
- subtract_point(w, projected);
-
- Strategy strategy;
- boost::ignore_unused(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;
-
- multiply_value(v, b);
- add_point(projected, v);
-
- return strategy.apply(p, projected);
+ auto closest_point = closest_points::detail::compute_closest_point_to_segment
+ <calculation_type>::apply(p, p1, p2);
+
+ return Strategy().apply(p, closest_point);
}
template <typename CT>
diff --git a/boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp b/boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp
index 85ee4b78f3..96a4ef027d 100644
--- a/boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp
+++ b/boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp
@@ -128,7 +128,7 @@ public :
assert_dimension_equal<Box1, Box2>();
typename calculation_type<Box1, Box2>::type result(0);
-
+
detail::compute_pythagoras_box_box
<
dimension<Box1>::value
diff --git a/boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp b/boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp
index d5f62c9ef8..719569d558 100644
--- a/boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp
+++ b/boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp
@@ -123,7 +123,7 @@ public :
assert_dimension_equal<Point, Box>();
typename calculation_type<Point, Box>::type result(0);
-
+
detail::compute_pythagoras_point_box
<
dimension<Point>::value
diff --git a/boost/geometry/strategies/cartesian/distance_segment_box.hpp b/boost/geometry/strategies/cartesian/distance_segment_box.hpp
index c00e426a49..ab3aab7262 100644
--- a/boost/geometry/strategies/cartesian/distance_segment_box.hpp
+++ b/boost/geometry/strategies/cartesian/distance_segment_box.hpp
@@ -17,7 +17,6 @@
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
-#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
namespace boost { namespace geometry
{
diff --git a/boost/geometry/strategies/cartesian/intersection.hpp b/boost/geometry/strategies/cartesian/intersection.hpp
index be7b92e59e..94d33401c5 100644
--- a/boost/geometry/strategies/cartesian/intersection.hpp
+++ b/boost/geometry/strategies/cartesian/intersection.hpp
@@ -1,7 +1,7 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2013-2023 Adam Wulkiewicz, Lodz, Poland.
// This file was modified by Oracle on 2014-2021.
// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
@@ -44,7 +44,6 @@
#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
#include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp>
-#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/intersection_result.hpp>
@@ -68,6 +67,61 @@ namespace boost { namespace geometry
namespace strategy { namespace intersection
{
+namespace detail_usage
+{
+
+// When calculating the intersection, the information of "a" or "b" can be used.
+// Theoretically this gives equal results, but due to floating point precision
+// there might be tiny differences. These are edge cases.
+// This structure is to determine if "a" or "b" should be used.
+// Prefer the segment closer to the endpoint.
+// If both are about equally close, then prefer the longer segment
+// To avoid hard thresholds, behavior is made fluent.
+// Calculate comparable length indications,
+// the longer the segment (relatively), the lower the value
+// such that the shorter lengths are evaluated higher and will
+// be preferred.
+template <bool IsArithmetic>
+struct use_a
+{
+ template <typename Ct, typename Ev>
+ static bool apply(Ct const& cla, Ct const& clb, Ev const& eva, Ev const& evb)
+ {
+ auto const clm = (std::max)(cla, clb);
+ if (clm <= 0)
+ {
+ return true;
+ }
+
+ // Relative comparible length
+ auto const rcla = Ct(1.0) - cla / clm;
+ auto const rclb = Ct(1.0) - clb / clm;
+
+ // Multipliers for edgevalue (ev) and relative comparible length (rcl)
+ // They determine the balance between edge value (should be larger)
+ // and segment length. In 99.9xx% of the cases there is no difference
+ // at all (if either a or b is used). Therefore the values of the
+ // constants are not sensitive for the majority of the situations.
+ // One known case is #mysql_23023665_6 (difference) which needs mev >= 2
+ Ev const mev = 5;
+ Ev const mrcl = 1;
+
+ return mev * eva + mrcl * rcla > mev * evb + mrcl * rclb;
+ }
+};
+
+// Specialization for non arithmetic types. They will always use "a"
+template <>
+struct use_a<false>
+{
+ template <typename Ct, typename Ev>
+ static bool apply(Ct const& , Ct const& , Ev const& , Ev const& )
+ {
+ return true;
+ }
+};
+
+}
/*!
\see http://mathworld.wolfram.com/Line-LineIntersection.html
@@ -116,10 +170,9 @@ struct cartesian_segments
SegmentRatio const& ratio) const
{
// Calculate the intersection point based on segment_ratio
- // Up to now, division was postponed. Here we divide using numerator/
- // denominator. In case of integer this results in an integer
- // division.
- BOOST_GEOMETRY_ASSERT(ratio.denominator() != 0);
+ // The division, postponed until here, is done now. In case of integer this
+ // results in an integer which rounds to the nearest integer.
+ BOOST_GEOMETRY_ASSERT(ratio.denominator() != typename SegmentRatio::int_type(0));
typedef typename promote_integral<CoordinateType>::type calc_type;
@@ -131,11 +184,11 @@ struct cartesian_segments
calc_type const dy_calc = boost::numeric_cast<calc_type>(dy);
set<0>(point, get<0, 0>(segment)
- + boost::numeric_cast<CoordinateType>(numerator * dx_calc
- / denominator));
+ + boost::numeric_cast<CoordinateType>(
+ math::divide<calc_type>(numerator * dx_calc, denominator)));
set<1>(point, get<0, 1>(segment)
- + boost::numeric_cast<CoordinateType>(numerator * dy_calc
- / denominator));
+ + boost::numeric_cast<CoordinateType>(
+ math::divide<calc_type>(numerator * dy_calc, denominator)));
}
template <int Index, int Dim, typename Point, typename Segment>
@@ -180,30 +233,12 @@ struct cartesian_segments
template <typename Point, typename Segment1, typename Segment2>
void calculate(Point& point, Segment1 const& a, Segment2 const& b) const
{
- bool use_a = true;
-
- // Prefer one segment if one is on or near an endpoint
- bool const a_near_end = robust_ra.near_end();
- bool const b_near_end = robust_rb.near_end();
- if (a_near_end && ! b_near_end)
- {
- use_a = true;
- }
- else if (b_near_end && ! a_near_end)
- {
- use_a = false;
- }
- else
- {
- // Prefer shorter segment
- promoted_type const len_a = comparable_length_a();
- promoted_type const len_b = comparable_length_b();
- if (len_b < len_a)
- {
- use_a = false;
- }
- // else use_a is true but was already assigned like that
- }
+ bool const use_a
+ = detail_usage::use_a
+ <
+ std::is_arithmetic<CoordinateType>::value
+ >::apply(comparable_length_a(), comparable_length_b(),
+ robust_ra.edge_value(), robust_rb.edge_value());
if (use_a)
{
@@ -214,10 +249,7 @@ struct cartesian_segments
assign_b(point, a, b);
}
-#if defined(BOOST_GEOMETRY_USE_RESCALING)
- return;
-#endif
-
+#ifndef BOOST_GEOMETRY_USE_RESCALING
// Verify nearly collinear cases (the threshold is arbitrary
// but influences performance). If the intersection is located
// outside the segments, then it should be moved.
@@ -232,6 +264,7 @@ struct cartesian_segments
assign_if_exceeds(point, a);
assign_if_exceeds(point, b);
}
+#endif
}
CoordinateType dx_a, dy_a;
@@ -402,7 +435,9 @@ struct cartesian_segments
return Policy::disjoint();
}
- typedef side::side_by_triangle<CalculationType> side_strategy_type;
+ using side_strategy_type
+ = typename side::services::default_strategy
+ <cartesian_tag, CalculationType>::type;
side_info sides;
sides.set<0>(side_strategy_type::apply(q1, q2, p1),
side_strategy_type::apply(q1, q2, p2));
@@ -415,7 +450,7 @@ struct cartesian_segments
sides.set<1>(side_strategy_type::apply(p1, p2, q1),
side_strategy_type::apply(p1, p2, q2));
-
+
if (sides.same<1>())
{
// Both points are at same side of other segment, we can leave
@@ -633,7 +668,7 @@ private:
int const a2_wrt_b = position_value(oa_2, ob_1, ob_2);
int const b1_wrt_a = position_value(ob_1, oa_1, oa_2);
int const b2_wrt_a = position_value(ob_2, oa_1, oa_2);
-
+
// fix the ratios if necessary
// CONSIDER: fixing ratios also in other cases, if they're inconsistent
// e.g. if ratio == 1 or 0 (so IP at the endpoint)
@@ -650,7 +685,7 @@ private:
{
ra_from.assign(1, 1);
rb_to.assign(0, 1);
- }
+ }
if (a2_wrt_b == 1)
{
diff --git a/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp b/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp
index b3556741c2..325af9e3e9 100644
--- a/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp
+++ b/boost/geometry/strategies/cartesian/point_in_poly_winding.hpp
@@ -24,10 +24,10 @@
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/strategy/cartesian/expand_point.hpp>
+#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/strategies/cartesian/point_in_box.hpp>
#include <boost/geometry/strategies/cartesian/disjoint_box_box.hpp>
-#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/within.hpp>
@@ -38,27 +38,18 @@ namespace boost { namespace geometry
namespace strategy { namespace within
{
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
/*!
\brief Within detection using winding rule in cartesian coordinate system.
\ingroup strategies
-\tparam Point_ \tparam_point
-\tparam PointOfSegment_ \tparam_segment_point
+\tparam SideStrategy A strategy defining creation along sides
\tparam CalculationType \tparam_calculation
-\author Barend Gehrels
-
-\qbk{
-[heading See also]
-[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]
-}
*/
-template
-<
- typename Point_ = void, // for backward compatibility
- typename PointOfSegment_ = Point_, // for backward compatibility
- typename CalculationType = void
->
-class cartesian_winding
+template <typename SideStrategy, typename CalculationType>
+class cartesian_winding_base
{
template <typename Point, typename PointOfSegment>
struct calculation_type
@@ -69,7 +60,7 @@ class cartesian_winding
CalculationType
>
{};
-
+
/*! subclass to keep state */
class counter
{
@@ -82,7 +73,7 @@ class cartesian_winding
}
public :
- friend class cartesian_winding;
+ friend class cartesian_winding_base;
inline counter()
: m_count(0)
@@ -116,10 +107,9 @@ public:
else // count == 2 || count == -2
{
// 1 left, -1 right
- typedef side::side_by_triangle<CalculationType> side_strategy_type;
- side = side_strategy_type::apply(s1, s2, point);
+ side = SideStrategy::apply(s1, s2, point);
}
-
+
if (side == 0)
{
// Point is lying on segment
@@ -227,6 +217,34 @@ private:
}
};
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+/*!
+\brief Within detection using winding rule in cartesian coordinate system.
+\ingroup strategies
+\tparam Point_ \tparam_point
+\tparam PointOfSegment_ \tparam_segment_point
+\tparam CalculationType \tparam_calculation
+
+\qbk{
+[heading See also]
+[link geometry.reference.algorithms.within.within_3_with_strategy within (with strategy)]
+}
+ */
+template
+<
+ typename Point_ = void, // for backward compatibility
+ typename PointOfSegment_ = Point_, // for backward compatibility
+ typename CalculationType = void
+>
+class cartesian_winding
+ : public detail::cartesian_winding_base
+ <
+ typename side::services::default_strategy<cartesian_tag, CalculationType>::type,
+ CalculationType
+ >
+{};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
@@ -236,13 +254,13 @@ namespace services
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
- typedef cartesian_winding<> type;
+ using type = cartesian_winding<>;
};
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
{
- typedef cartesian_winding<> type;
+ using type = cartesian_winding<>;
};
} // namespace services
@@ -260,13 +278,13 @@ namespace strategy { namespace covered_by { namespace services
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, polygonal_tag, cartesian_tag, cartesian_tag>
{
- typedef within::cartesian_winding<> type;
+ using type = within::cartesian_winding<>;
};
template <typename PointLike, typename Geometry, typename AnyTag1, typename AnyTag2>
struct default_strategy<PointLike, Geometry, AnyTag1, AnyTag2, pointlike_tag, linear_tag, cartesian_tag, cartesian_tag>
{
- typedef within::cartesian_winding<> type;
+ using type = within::cartesian_winding<>;
};
}}} // namespace strategy::covered_by::services
diff --git a/boost/geometry/strategies/cartesian/side_by_triangle.hpp b/boost/geometry/strategies/cartesian/side_by_triangle.hpp
index 989f3fbb1c..848570fd9b 100644
--- a/boost/geometry/strategies/cartesian/side_by_triangle.hpp
+++ b/boost/geometry/strategies/cartesian/side_by_triangle.hpp
@@ -1,275 +1,21 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
+// Boost.Geometry
-// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
-// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
+// Copyright (c) 2021, Oracle and/or its affiliates.
-// This file was modified by Oracle on 2015-2021.
-// Modifications copyright (c) 2015-2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
-// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
-// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
-
-// 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)
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
-#include <type_traits>
-
-#include <boost/geometry/arithmetic/determinant.hpp>
-
-#include <boost/geometry/core/access.hpp>
-
-#include <boost/geometry/strategies/cartesian/disjoint_segment_box.hpp>
-#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
-#include <boost/geometry/strategies/compare.hpp>
-#include <boost/geometry/strategies/side.hpp>
-
-#include <boost/geometry/strategy/cartesian/envelope.hpp>
-
-#include <boost/geometry/util/select_most_precise.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
-{
- template <typename Policy>
- struct eps_policy
- {
- eps_policy() {}
- template <typename Type>
- eps_policy(Type const& a, Type const& b, Type const& c, Type const& d)
- : policy(a, b, c, d)
- {}
- Policy policy;
- };
-
- struct eps_empty
- {
- eps_empty() {}
- template <typename Type>
- eps_empty(Type const&, Type const&, Type const&, Type const&) {}
- };
-
-public :
- typedef cartesian_tag cs_tag;
-
- // 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 CoordinateType,
- typename PromotedType,
- typename P1,
- typename P2,
- typename P,
- typename EpsPolicy
- >
- static inline
- PromotedType side_value(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & eps_policy)
- {
- CoordinateType const x = get<0>(p);
- CoordinateType const y = get<1>(p);
-
- CoordinateType const sx1 = get<0>(p1);
- CoordinateType const sy1 = get<1>(p1);
- CoordinateType const sx2 = get<0>(p2);
- CoordinateType const sy2 = get<1>(p2);
-
- PromotedType const dx = sx2 - sx1;
- PromotedType const dy = sy2 - sy1;
- PromotedType const dpx = x - sx1;
- PromotedType const dpy = y - sy1;
-
- eps_policy = EpsPolicy(dx, dy, dpx, dpy);
-
- return geometry::detail::determinant<PromotedType>
- (
- dx, dy,
- dpx, dpy
- );
-
- }
-
- template
- <
- typename CoordinateType,
- typename PromotedType,
- typename P1,
- typename P2,
- typename P
- >
- static inline
- PromotedType side_value(P1 const& p1, P2 const& p2, P const& p)
- {
- eps_empty dummy;
- return side_value<CoordinateType, PromotedType>(p1, p2, p, dummy);
- }
-
-
- template
- <
- typename CoordinateType,
- typename PromotedType,
- bool AreAllIntegralCoordinates
- >
- struct compute_side_value
- {
- template <typename P1, typename P2, typename P, typename EpsPolicy>
- static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
- {
- return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
- }
- };
-
- template <typename CoordinateType, typename PromotedType>
- struct compute_side_value<CoordinateType, PromotedType, false>
- {
- template <typename P1, typename P2, typename P, typename EpsPolicy>
- static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
- {
- // For robustness purposes, first check if any two points are
- // the same; in this case simply return that the points are
- // collinear
- if (equals_point_point(p1, p2)
- || equals_point_point(p1, p)
- || equals_point_point(p2, p))
- {
- return PromotedType(0);
- }
-
- // The side_by_triangle strategy computes the signed area of
- // the point triplet (p1, p2, p); as such it is (in theory)
- // invariant under cyclic permutations of its three arguments.
- //
- // In the context of numerical errors that arise in
- // floating-point computations, and in order to make the strategy
- // consistent with respect to cyclic permutations of its three
- // arguments, we cyclically permute them so that the first
- // argument is always the lexicographically smallest point.
-
- typedef compare::cartesian<compare::less> less;
-
- if (less::apply(p, p1))
- {
- if (less::apply(p, p2))
- {
- // p is the lexicographically smallest
- return side_value<CoordinateType, PromotedType>(p, p1, p2, epsp);
- }
- else
- {
- // p2 is the lexicographically smallest
- return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
- }
- }
-
- if (less::apply(p1, p2))
- {
- // p1 is the lexicographically smallest
- return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
- }
- else
- {
- // p2 is the lexicographically smallest
- return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
- }
- }
- };
-
-
- template <typename P1, typename P2, typename P>
- static inline int apply(P1 const& p1, P2 const& p2, P const& p)
- {
- typedef typename coordinate_type<P1>::type coordinate_type1;
- typedef typename coordinate_type<P2>::type coordinate_type2;
- typedef typename coordinate_type<P>::type coordinate_type3;
-
- typedef std::conditional_t
- <
- std::is_void<CalculationType>::value,
- typename select_most_precise
- <
- coordinate_type1,
- coordinate_type2,
- coordinate_type3
- >::type,
- CalculationType
- > coordinate_type;
-
- // Promote float->double, small int->int
- typedef typename select_most_precise
- <
- coordinate_type,
- double
- >::type promoted_type;
-
- bool const are_all_integral_coordinates =
- std::is_integral<coordinate_type1>::value
- && std::is_integral<coordinate_type2>::value
- && std::is_integral<coordinate_type3>::value;
-
- eps_policy< math::detail::equals_factor_policy<promoted_type> > epsp;
- promoted_type s = compute_side_value
- <
- coordinate_type, promoted_type, are_all_integral_coordinates
- >::apply(p1, p2, p, epsp);
-
- promoted_type const zero = promoted_type();
- return math::detail::equals_by_policy(s, zero, epsp.policy) ? 0
- : s > zero ? 1
- : -1;
- }
-
-private:
- template <typename P1, typename P2>
- static inline bool equals_point_point(P1 const& p1, P2 const& p2)
- {
- return strategy::within::cartesian_point_point::apply(p1, p2);
- }
-};
-
-
-#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
-namespace services
-{
-
-template <typename CalculationType>
-struct default_strategy<cartesian_tag, CalculationType>
-{
- typedef side_by_triangle<CalculationType> type;
-};
-
-}
-#endif
+#include <boost/config/pragma_message.hpp>
+BOOST_PRAGMA_MESSAGE("This include file is deprecated and will be removed in the future.")
-}} // namespace strategy::side
-}} // namespace boost::geometry
+#include <boost/geometry/strategy/cartesian/side_by_triangle.hpp>
#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_SIDE_BY_TRIANGLE_HPP
diff --git a/boost/geometry/strategies/cartesian/side_rounded_input.hpp b/boost/geometry/strategies/cartesian/side_rounded_input.hpp
new file mode 100644
index 0000000000..fc1543008f
--- /dev/null
+++ b/boost/geometry/strategies/cartesian/side_rounded_input.hpp
@@ -0,0 +1,65 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2021 Tinko Bartels, Berlin, Germany.
+
+// This file was modified by Oracle on 2023.
+// Modifications copyright (c) 2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Use, modification and distribution is subject to the Boost Software License,
+// 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_CARTESIAN_SIDE_ROUNDED_INPUT_HPP
+#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROUNDED_INPUT_HPP
+
+#include <limits>
+
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/config.hpp>
+
+#include <boost/geometry/util/math.hpp>
+
+#include <boost/geometry/strategies/side.hpp>
+
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace side
+{
+
+template <typename CalculationType = void, int Coeff1 = 5, int Coeff2 = 32>
+struct side_rounded_input
+{
+ using cs_tag = cartesian_tag;
+
+ template <typename P1, typename P2, typename P>
+ static inline int apply(P1 const& p1, P2 const& p2, P const& p)
+ {
+ using coor_t = typename select_calculation_type_alt<CalculationType, P1, P2, P>::type;
+
+ coor_t const p1_x = geometry::get<0>(p1);
+ coor_t const p1_y = geometry::get<1>(p1);
+ coor_t const p2_x = geometry::get<0>(p2);
+ coor_t const p2_y = geometry::get<1>(p2);
+ coor_t const p_x = geometry::get<0>(p);
+ coor_t const p_y = geometry::get<1>(p);
+
+ constexpr coor_t eps = std::numeric_limits<coor_t>::epsilon() / 2;
+ coor_t const det = (p1_x - p_x) * (p2_y - p_y) - (p1_y - p_y) * (p2_x - p_x);
+ coor_t const err_bound = (Coeff1 * eps + Coeff2 * eps * eps) *
+ ( (geometry::math::abs(p1_x) + geometry::math::abs(p_x))
+ * (geometry::math::abs(p2_y) + geometry::math::abs(p_y))
+ + (geometry::math::abs(p2_x) + geometry::math::abs(p_x))
+ * (geometry::math::abs(p1_y) + geometry::math::abs(p_y)));
+ return (det > err_bound) - (det < -err_bound);
+ }
+};
+
+}} // namespace strategy::side
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROUNDED_INPUT_HPP
diff --git a/boost/geometry/strategies/cartesian/turn_in_ring_winding.hpp b/boost/geometry/strategies/cartesian/turn_in_ring_winding.hpp
index 2ec4ab417e..fcbc03bca9 100644
--- a/boost/geometry/strategies/cartesian/turn_in_ring_winding.hpp
+++ b/boost/geometry/strategies/cartesian/turn_in_ring_winding.hpp
@@ -1,6 +1,11 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2020 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+
+// This file was modified by Oracle on 2023.
+// Modifications copyright (c) 2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -9,11 +14,14 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_TURN_IN_RING_WINDING_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_TURN_IN_RING_WINDING_HPP
+#include <boost/geometry/arithmetic/infinite_line_functions.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/config.hpp>
#include <boost/geometry/algorithms/detail/make/make.hpp>
#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/strategies/cartesian/side_rounded_input.hpp>
+
namespace boost { namespace geometry
{
@@ -60,34 +68,41 @@ public:
struct counter
{
- inline counter()
- : m_count(0)
- , m_min_distance(0)
- , m_close_to_offset(false)
- {}
-
- //! Returns -1 for outside, 1 for inside
- inline int code() const
+ //! Counter, is increased if point is left of a segment (outside),
+ //! and decreased if point is right of a segment (inside)
+ int count{0};
+
+ int count_on_offsetted{0};
+ int count_on_origin{0};
+ int count_on_edge{0};
+
+ CalculationType edge_min_fraction{(std::numeric_limits<CalculationType>::max)()};
+#if defined(BOOST_GEOMETRY_USE_RESCALING)
+ CalculationType inside_min_measure{(std::numeric_limits<CalculationType>::max)()};
+#endif
+
+ inline bool is_inside() const
{
- return m_count == 0 ? -1 : 1;
+ return count < 0 || count_on_origin > 0;
+ }
+
+ inline bool is_on_boundary() const
+ {
+ return count_on_origin == 0
+ && (count_on_offsetted > 0
+ || (count_on_edge > 0 && edge_min_fraction < 1.0e-3)
+#if defined(BOOST_GEOMETRY_USE_RESCALING)
+ || (count < 0 && inside_min_measure < 1.0e-5)
+#endif
+ );
}
- //! Counter, is increased if point is left of a segment (outside),
- //! and decreased if point is right of a segment (inside)
- int m_count;
-
- //! Indicate an indication of distance. It is always set, unless
- //! the point is located on the border-part of the original.
- //! It is not guaranteed to be the minimum distance, because it is only
- //! calculated for a selection of the offsetted ring.
- CalculationType m_min_distance;
- bool m_close_to_offset;
};
- typedef counter state_type;
+ using state_type = counter;
template <typename Point, typename PointOfSegment>
- static inline bool in_vertical_range(Point const& point,
+ static inline bool is_in_vertical_range(Point const& point,
PointOfSegment const& s1,
PointOfSegment const& s2)
{
@@ -95,11 +110,10 @@ public:
CalculationType const s1y = get<1>(s1);
CalculationType const s2y = get<1>(s2);
- return (s1y >= py && s2y <= py)
- || (s2y >= py && s1y <= py);
+ return s1y < s2y ? (py >= s1y && py <= s2y) : (py >= s2y && py <= s1y);
}
- template <typename Dm, typename Point, typename PointOfSegment>
+ template <typename Point, typename PointOfSegment>
static inline void apply_on_boundary(Point const& point,
PointOfSegment const& s1,
PointOfSegment const& s2,
@@ -108,95 +122,98 @@ public:
{
if (place_on_ring == place_on_ring_offsetted)
{
- // Consider the point as "outside"
- the_state.m_count = 0;
- the_state.m_close_to_offset = true;
- the_state.m_min_distance = 0;
+ the_state.count_on_offsetted++;
}
else if (place_on_ring == place_on_ring_to_offsetted
|| place_on_ring == place_on_ring_from_offsetted)
{
- // Check distance from "point" to either s1 or s2
- // on a line perpendicular to s1-s2
- typedef model::infinite_line<CalculationType> line_type;
-
- line_type const line
- = detail::make::make_perpendicular_line<CalculationType>(s1, s2,
- place_on_ring == place_on_ring_to_offsetted ? s2 : s1);
-
- Dm perp;
- perp.measure = arithmetic::side_value(line, point);
-
- // If it is to the utmost point s1 or s2, it is "outside"
- the_state.m_count = perp.is_zero() ? 0 : 1;
- the_state.m_close_to_offset = true;
- the_state.m_min_distance = geometry::math::abs(perp.measure);
+ the_state.count_on_edge++;
+
+ auto const line1 = detail::make::make_perpendicular_line<CalculationType>(s1, s2, s1);
+ auto const line2 = detail::make::make_perpendicular_line<CalculationType>(s2, s1, s2);
+
+ auto const value1 = arithmetic::side_value(line1, point);
+ auto const value2 = arithmetic::side_value(line2, point);
+ if (value1 >= 0 && value2 >= 0)
+ {
+ auto const length_value = value1 + value2;
+ if (length_value > 0)
+ {
+ // If it is to the utmost point s1 or s2, it is "outside"
+ auto const fraction = (place_on_ring == place_on_ring_to_offsetted ? value2 : value1) / length_value;
+ if (fraction < the_state.edge_min_fraction)
+ {
+ the_state.edge_min_fraction = fraction;
+ }
+ }
+ }
}
else
{
- // It is on the border, the part of the original
- // Consider it as "inside".
- the_state.m_count = 1;
+ the_state.count_on_origin++;
}
}
- template <typename Dm, typename Point, typename PointOfSegment>
+ template <typename Point, typename PointOfSegment>
static inline bool apply(Point const& point,
PointOfSegment const& s1,
PointOfSegment const& s2,
- Dm const& dm,
place_on_ring_type place_on_ring,
+ bool is_convex,
counter& the_state)
{
+ int const side = strategy::side::side_rounded_input<CalculationType>::apply(s1, s2, point);
+
+ if (is_convex && side > 0)
+ {
+ // If the point is left of this segment of a convex piece, it can never be inside.
+ // Stop further processing
+ the_state.count = 1;
+ return false;
+ }
+
CalculationType const px = get<0>(point);
CalculationType const s1x = get<0>(s1);
CalculationType const s2x = get<0>(s2);
- bool const in_horizontal_range
- = (s1x >= px && s2x <= px)
- || (s2x >= px && s1x <= px);
+ bool const in_horizontal_range = s1x < s2x ? (px >= s1x && px <= s2x) : (px >= s2x && px <= s1x);
bool const vertical = s1x == s2x;
- bool const measured_on_boundary = dm.is_zero();
-
- if (measured_on_boundary
- && (in_horizontal_range
- || (vertical && in_vertical_range(point, s1, s2))))
- {
- apply_on_boundary<Dm>(point, s1, s2, place_on_ring, the_state);
- // Indicate that no further processing is necessary.
- return false;
- }
-
- bool const is_on_right_side = dm.is_negative();
- if (place_on_ring == place_on_ring_offsetted
- && is_on_right_side
- && (! the_state.m_close_to_offset
- || -dm.measure < the_state.m_min_distance))
+ if (in_horizontal_range || (vertical && is_in_vertical_range(point, s1, s2)))
{
- // This part of the ring was the offsetted part,
- // keep track of the distance WITHIN the ring
- // with respect to the offsetted part
- // NOTE: this is also done if it is NOT in the horizontal range.
- the_state.m_min_distance = -dm.measure;
- the_state.m_close_to_offset = true;
+ if (side == 0)
+ {
+ apply_on_boundary(point, s1, s2, place_on_ring, the_state);
+ }
+#if defined(BOOST_GEOMETRY_USE_RESCALING)
+ else if (side == -1)
+ {
+ auto const line = detail::make::make_infinite_line<CalculationType>(s1, s2);
+ auto const value = -arithmetic::side_value(line, point);
+ if (value > 0 && value < the_state.inside_min_measure) { the_state.inside_min_measure = value; }
+
+ }
+#endif
}
if (in_horizontal_range)
{
- // Use only absolute comparisons, because the ring is continuous -
- // what was missed is there earlier or later, and turns should
- // not be counted twice (which can happen if an epsilon is used).
- bool const eq1 = s1x == px;
- bool const eq2 = s2x == px;
-
- // Account for 1 or 2 for left side (outside)
- // and for -1 or -2 for right side (inside)
- int const side = is_on_right_side ? -1 : 1;
- int const multiplier = eq1 || eq2 ? 1 : 2;
-
- the_state.m_count += side * multiplier;
+ auto const on_boundary = the_state.count_on_offsetted + the_state.count_on_edge + the_state.count_on_origin;
+ if (on_boundary == 0)
+ {
+ // Use only absolute comparisons, because the ring is continuous -
+ // what was missed is there earlier or later, and turns should
+ // not be counted twice (which can happen if an epsilon is used).
+ bool const eq1 = s1x == px;
+ bool const eq2 = s2x == px;
+
+ // Account for 1 or 2 for left side (outside)
+ // and for -1 or -2 for right side (inside)
+ int const multiplier = eq1 || eq2 ? 1 : 2;
+
+ the_state.count += side * multiplier;
+ }
}
return true;
diff --git a/boost/geometry/strategies/closest_points/cartesian.hpp b/boost/geometry/strategies/closest_points/cartesian.hpp
new file mode 100644
index 0000000000..00e4a58fa4
--- /dev/null
+++ b/boost/geometry/strategies/closest_points/cartesian.hpp
@@ -0,0 +1,68 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CLOSEST_POINTS_CARTESIAN_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CLOSEST_POINTS_CARTESIAN_HPP
+
+
+//#include <boost/geometry/strategies/cartesian/azimuth.hpp>
+
+//#include <boost/geometry/strategies/cartesian/distance_projected_point.hpp>
+//#include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
+#include <boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp>
+#include <boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp>
+#include <boost/geometry/strategies/cartesian/distance_segment_box.hpp>
+
+#include <boost/geometry/strategies/cartesian/closest_points_pt_seg.hpp>
+
+#include <boost/geometry/strategies/detail.hpp>
+#include <boost/geometry/strategies/distance/detail.hpp>
+#include <boost/geometry/strategies/closest_points/services.hpp>
+
+//#include <boost/geometry/strategies/normalize.hpp>
+#include <boost/geometry/strategies/distance/cartesian.hpp>
+
+#include <boost/geometry/util/type_traits.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategies { namespace closest_points
+{
+
+template <typename CalculationType = void>
+struct cartesian
+ : public strategies::distance::cartesian<CalculationType>
+{
+ template <typename Geometry1, typename Geometry2>
+ static auto closest_points(Geometry1 const&, Geometry2 const&,
+ distance::detail::enable_if_ps_t<Geometry1, Geometry2> * = nullptr)
+ {
+ return strategy::closest_points::projected_point<CalculationType>();
+ }
+};
+
+
+namespace services
+{
+
+template <typename Geometry1, typename Geometry2>
+struct default_strategy<Geometry1, Geometry2, cartesian_tag, cartesian_tag>
+{
+ using type = strategies::closest_points::cartesian<>;
+};
+
+} // namespace services
+
+}} // namespace strategies::closest_points
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CLOSEST_POINTS_CARTESIAN_HPP
diff --git a/boost/geometry/strategies/closest_points/geographic.hpp b/boost/geometry/strategies/closest_points/geographic.hpp
new file mode 100644
index 0000000000..7a20a7a50f
--- /dev/null
+++ b/boost/geometry/strategies/closest_points/geographic.hpp
@@ -0,0 +1,78 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CLOSEST_POINTS_GEOGRAPHIC_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CLOSEST_POINTS_GEOGRAPHIC_HPP
+
+#include <boost/geometry/strategies/detail.hpp>
+#include <boost/geometry/strategies/distance/detail.hpp>
+#include <boost/geometry/strategies/closest_points/services.hpp>
+#include <boost/geometry/strategies/geographic/closest_points_pt_seg.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+
+#include <boost/geometry/strategies/distance/geographic.hpp>
+
+#include <boost/geometry/util/type_traits.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategies { namespace closest_points
+{
+
+template
+<
+ typename FormulaPolicy = geometry::strategy::andoyer,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic
+ : public strategies::distance::geographic<FormulaPolicy, Spheroid, CalculationType>
+{
+ using base_t = strategies::distance::geographic<FormulaPolicy, Spheroid, CalculationType>;
+
+public:
+
+ geographic() = default;
+
+ explicit geographic(Spheroid const& spheroid)
+ : base_t(spheroid)
+ {}
+
+ template <typename Geometry1, typename Geometry2>
+ auto closest_points(Geometry1 const&, Geometry2 const&,
+ distance::detail::enable_if_ps_t<Geometry1, Geometry2> * = nullptr) const
+ {
+ return strategy::closest_points::geographic_cross_track
+ <
+ FormulaPolicy,
+ Spheroid,
+ CalculationType
+ >(base_t::m_spheroid);
+ }
+};
+
+
+namespace services
+{
+
+template <typename Geometry1, typename Geometry2>
+struct default_strategy<Geometry1, Geometry2, geographic_tag, geographic_tag>
+{
+ using type = strategies::closest_points::geographic<>;
+};
+
+} // namespace services
+
+}} // namespace strategies::closest_points
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CLOSEST_POINTS_GEOGRAPHIC_HPP
diff --git a/boost/geometry/strategies/closest_points/services.hpp b/boost/geometry/strategies/closest_points/services.hpp
new file mode 100644
index 0000000000..d99bbfda8a
--- /dev/null
+++ b/boost/geometry/strategies/closest_points/services.hpp
@@ -0,0 +1,48 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CLOSEST_POINTS_SERVICES_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CLOSEST_POINTS_SERVICES_HPP
+
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/static_assert.hpp>
+
+#include <boost/geometry/strategies/detail.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategies { namespace closest_points
+{
+
+namespace services
+{
+
+template
+<
+ typename Geometry1,
+ typename Geometry2,
+ typename CSTag1 = typename geometry::cs_tag<Geometry1>::type,
+ typename CSTag2 = typename geometry::cs_tag<Geometry2>::type
+>
+struct default_strategy
+{
+ BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
+ "Not implemented for these Geometries' coordinate systems.",
+ Geometry1, Geometry2, CSTag1, CSTag2);
+};
+
+} // namespace services
+
+}} // namespace strategies::closest_points
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CLOSEST_POINTS_SERVICES_HPP
diff --git a/boost/geometry/strategies/closest_points/spherical.hpp b/boost/geometry/strategies/closest_points/spherical.hpp
new file mode 100644
index 0000000000..d2846c722d
--- /dev/null
+++ b/boost/geometry/strategies/closest_points/spherical.hpp
@@ -0,0 +1,78 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_CLOSEST_POINTS_SPHERICAL_HPP
+#define BOOST_GEOMETRY_STRATEGIES_CLOSEST_POINTS_SPHERICAL_HPP
+
+#include <boost/geometry/strategies/spherical/closest_points_pt_seg.hpp>
+
+#include <boost/geometry/strategies/detail.hpp>
+#include <boost/geometry/strategies/distance/detail.hpp>
+#include <boost/geometry/strategies/closest_points/services.hpp>
+
+#include <boost/geometry/strategies/distance/spherical.hpp>
+
+#include <boost/geometry/util/type_traits.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategies { namespace closest_points
+{
+
+template
+<
+ typename RadiusTypeOrSphere = double,
+ typename CalculationType = void
+>
+class spherical
+ : public strategies::distance::spherical<RadiusTypeOrSphere, CalculationType>
+{
+ using base_t = strategies::distance::spherical<RadiusTypeOrSphere, CalculationType>;
+
+public:
+ spherical() = default;
+
+ template <typename RadiusOrSphere>
+ explicit spherical(RadiusOrSphere const& radius_or_sphere)
+ : base_t(radius_or_sphere)
+ {}
+
+ template <typename Geometry1, typename Geometry2>
+ auto closest_points(Geometry1 const&, Geometry2 const&,
+ distance::detail::enable_if_ps_t<Geometry1, Geometry2> * = nullptr) const
+ {
+ return strategy::closest_points::cross_track<CalculationType>(base_t::radius());
+ }
+};
+
+
+namespace services
+{
+
+template <typename Geometry1, typename Geometry2>
+struct default_strategy
+<
+ Geometry1,
+ Geometry2,
+ spherical_equatorial_tag,
+ spherical_equatorial_tag
+>
+{
+ using type = strategies::closest_points::spherical<>;
+};
+
+} // namespace services
+
+}} // namespace strategies::closest_points
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_CLOSEST_POINTS_SPHERICAL_HPP
diff --git a/boost/geometry/strategies/comparable_distance_result.hpp b/boost/geometry/strategies/comparable_distance_result.hpp
index f84e5c728e..42a6b211a5 100644
--- a/boost/geometry/strategies/comparable_distance_result.hpp
+++ b/boost/geometry/strategies/comparable_distance_result.hpp
@@ -72,7 +72,7 @@ struct comparable_distance_strategy_type<Geometry1, Geometry2, Strategy, true>
: comparable_distance_strategy_type<Geometry2, Geometry1, Strategy, false>
{};
-
+
template <typename Geometry1, typename Geometry2, typename Strategy>
struct comparable_distance_result
: strategy::distance::services::return_type
diff --git a/boost/geometry/strategies/compare.hpp b/boost/geometry/strategies/compare.hpp
index 5e35ecdff7..83de81773c 100644
--- a/boost/geometry/strategies/compare.hpp
+++ b/boost/geometry/strategies/compare.hpp
@@ -4,8 +4,10 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2017-2020.
-// Modifications copyright (c) 2017-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2023.
+// Modifications copyright (c) 2017-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -68,6 +70,24 @@ struct equal_to
}
};
+struct equals_epsilon
+{
+ template <typename T1, typename T2>
+ static inline bool apply(T1 const& l, T2 const& r)
+ {
+ return math::equals(l, r);
+ }
+};
+
+struct equals_exact
+{
+ template <typename T1, typename T2>
+ static inline bool apply(T1 const& l, T2 const& r)
+ {
+ return l == r;
+ }
+};
+
#ifndef DOXYGEN_NO_DETAIL
namespace detail
@@ -77,6 +97,7 @@ namespace detail
template
<
typename ComparePolicy,
+ typename EqualsPolicy,
std::size_t Dimension,
std::size_t DimensionCount
>
@@ -90,11 +111,12 @@ struct compare_loop
typename geometry::coordinate_type<Point2>::type const&
cright = geometry::get<Dimension>(right);
- if (math::equals(cleft, cright))
+ if (EqualsPolicy::apply(cleft, cright))
{
return compare_loop
<
ComparePolicy,
+ EqualsPolicy,
Dimension + 1, DimensionCount
>::apply(left, right);
}
@@ -108,9 +130,10 @@ struct compare_loop
template
<
typename ComparePolicy,
+ typename EqualsPolicy,
std::size_t DimensionCount
>
-struct compare_loop<ComparePolicy, DimensionCount, DimensionCount>
+struct compare_loop<ComparePolicy, EqualsPolicy, DimensionCount, DimensionCount>
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& , Point2 const& )
@@ -123,9 +146,10 @@ struct compare_loop<ComparePolicy, DimensionCount, DimensionCount>
template
<
+ typename EqualsPolicy,
std::size_t DimensionCount
>
-struct compare_loop<strategy::compare::equal_to, DimensionCount, DimensionCount>
+struct compare_loop<strategy::compare::equal_to, EqualsPolicy, DimensionCount, DimensionCount>
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& , Point2 const& )
@@ -143,6 +167,7 @@ struct compare_loop<strategy::compare::equal_to, DimensionCount, DimensionCount>
template
<
typename ComparePolicy,
+ typename EqualsPolicy,
int Dimension = -1
>
struct cartesian
@@ -152,7 +177,7 @@ struct cartesian
{
return compare::detail::compare_loop
<
- ComparePolicy, Dimension, Dimension + 1
+ ComparePolicy, EqualsPolicy, Dimension, Dimension + 1
>::apply(left, right);
}
};
@@ -160,9 +185,10 @@ struct cartesian
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
template
<
- typename ComparePolicy
+ typename ComparePolicy,
+ typename EqualsPolicy
>
-struct cartesian<ComparePolicy, -1>
+struct cartesian<ComparePolicy, EqualsPolicy, -1>
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& left, Point2 const& right)
@@ -170,6 +196,7 @@ struct cartesian<ComparePolicy, -1>
return compare::detail::compare_loop
<
ComparePolicy,
+ EqualsPolicy,
0,
((std::min)(geometry::dimension<Point1>::value,
geometry::dimension<Point2>::value))
@@ -185,6 +212,7 @@ namespace services
template
<
typename ComparePolicy,
+ typename EqualsPolicy,
typename Point1,
typename Point2 = Point1,
int Dimension = -1,
@@ -199,10 +227,17 @@ struct default_strategy
};
-template <typename ComparePolicy, typename Point1, typename Point2, int Dimension>
-struct default_strategy<ComparePolicy, Point1, Point2, Dimension, cartesian_tag, cartesian_tag>
+template
+<
+ typename ComparePolicy,
+ typename EqualsPolicy,
+ typename Point1,
+ typename Point2,
+ int Dimension
+>
+struct default_strategy<ComparePolicy, EqualsPolicy, Point1, Point2, Dimension, cartesian_tag, cartesian_tag>
{
- typedef compare::cartesian<ComparePolicy, Dimension> type;
+ typedef compare::cartesian<ComparePolicy, EqualsPolicy, Dimension> type;
};
diff --git a/boost/geometry/strategies/convex_hull/cartesian.hpp b/boost/geometry/strategies/convex_hull/cartesian.hpp
index 1bef4e3896..5bf46f2110 100644
--- a/boost/geometry/strategies/convex_hull/cartesian.hpp
+++ b/boost/geometry/strategies/convex_hull/cartesian.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry
-// Copyright (c) 2020, Oracle and/or its affiliates.
+// Copyright (c) 2020-2023, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -10,11 +11,17 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_CARTESIAN_HPP
#define BOOST_GEOMETRY_STRATEGIES_CONVEX_HULL_CARTESIAN_HPP
-
+#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
#include <boost/geometry/strategies/convex_hull/services.hpp>
+#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/strategies/detail.hpp>
+#include <boost/geometry/strategies/side.hpp>
+
#include <boost/geometry/strategy/cartesian/side_robust.hpp>
+#include <boost/geometry/util/type_traits.hpp>
+
+
namespace boost { namespace geometry
{
@@ -25,10 +32,31 @@ template <typename CalculationType = void>
class cartesian : public strategies::detail::cartesian_base
{
public:
+ template <typename Geometry1, typename Geometry2>
+ static auto relate(Geometry1 const&, Geometry2 const&,
+ std::enable_if_t
+ <
+ util::is_pointlike<Geometry1>::value
+ && util::is_pointlike<Geometry2>::value
+ > * = nullptr)
+ {
+ return strategy::within::cartesian_point_point();
+ }
+
static auto side()
{
- return strategy::side::side_robust<CalculationType>();
+ using side_strategy_type
+ = strategy::side::side_robust<CalculationType>;
+ return side_strategy_type();
}
+
+ template <typename ComparePolicy, typename EqualsPolicy>
+ using compare_type = typename strategy::compare::cartesian
+ <
+ ComparePolicy,
+ EqualsPolicy,
+ -1
+ >;
};
namespace services
diff --git a/boost/geometry/strategies/convex_hull/geographic.hpp b/boost/geometry/strategies/convex_hull/geographic.hpp
index 9f4a367eb9..879d75284f 100644
--- a/boost/geometry/strategies/convex_hull/geographic.hpp
+++ b/boost/geometry/strategies/convex_hull/geographic.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry
-// Copyright (c) 2020, Oracle and/or its affiliates.
+// Copyright (c) 2020-2023, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -12,8 +13,12 @@
#include <boost/geometry/strategies/convex_hull/services.hpp>
+#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/geographic/side.hpp>
+#include <boost/geometry/strategies/spherical/point_in_point.hpp>
+
+#include <boost/geometry/util/type_traits.hpp>
namespace boost { namespace geometry
@@ -39,6 +44,17 @@ public:
: base_t(spheroid)
{}
+ template <typename Geometry1, typename Geometry2>
+ static auto relate(Geometry1 const&, Geometry2 const&,
+ std::enable_if_t
+ <
+ util::is_pointlike<Geometry1>::value
+ && util::is_pointlike<Geometry2>::value
+ > * = nullptr)
+ {
+ return strategy::within::spherical_point_point();
+ }
+
auto side() const
{
return strategy::side::geographic
@@ -48,6 +64,14 @@ public:
CalculationType
>(base_t::m_spheroid);
}
+
+ template <typename ComparePolicy, typename EqualsPolicy>
+ using compare_type = typename strategy::compare::spherical
+ <
+ ComparePolicy,
+ EqualsPolicy,
+ -1
+ >;
};
namespace services
diff --git a/boost/geometry/strategies/convex_hull/spherical.hpp b/boost/geometry/strategies/convex_hull/spherical.hpp
index 0eec8ee82d..6365b1c0fa 100644
--- a/boost/geometry/strategies/convex_hull/spherical.hpp
+++ b/boost/geometry/strategies/convex_hull/spherical.hpp
@@ -1,8 +1,9 @@
// Boost.Geometry
-// Copyright (c) 2020, Oracle and/or its affiliates.
+// Copyright (c) 2020-2023, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
@@ -12,9 +13,13 @@
#include <boost/geometry/strategies/convex_hull/services.hpp>
+#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/strategies/detail.hpp>
+#include <boost/geometry/strategies/spherical/point_in_point.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
+#include <boost/geometry/util/type_traits.hpp>
+
namespace boost { namespace geometry
{
@@ -26,10 +31,29 @@ template <typename CalculationType = void>
class spherical : public strategies::detail::spherical_base<void>
{
public:
+ template <typename Geometry1, typename Geometry2>
+ static auto relate(Geometry1 const&, Geometry2 const&,
+ std::enable_if_t
+ <
+ util::is_pointlike<Geometry1>::value
+ && util::is_pointlike<Geometry2>::value
+ > * = nullptr)
+ {
+ return strategy::within::spherical_point_point();
+ }
+
static auto side()
{
return strategy::side::spherical_side_formula<CalculationType>();
}
+
+ template <typename ComparePolicy, typename EqualsPolicy>
+ using compare_type = typename strategy::compare::spherical
+ <
+ ComparePolicy,
+ EqualsPolicy,
+ -1
+ >;
};
namespace services
diff --git a/boost/geometry/strategies/distance/backward_compatibility.hpp b/boost/geometry/strategies/distance/backward_compatibility.hpp
index b5b627fc9e..0af5f3ec2a 100644
--- a/boost/geometry/strategies/distance/backward_compatibility.hpp
+++ b/boost/geometry/strategies/distance/backward_compatibility.hpp
@@ -22,7 +22,7 @@ namespace boost { namespace geometry
{
namespace strategies { namespace distance
-{
+{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
diff --git a/boost/geometry/strategies/distance/comparable.hpp b/boost/geometry/strategies/distance/comparable.hpp
index 34a828cfe2..07d219b8ab 100644
--- a/boost/geometry/strategies/distance/comparable.hpp
+++ b/boost/geometry/strategies/distance/comparable.hpp
@@ -14,12 +14,14 @@
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/static_assert.hpp>
+#include <boost/geometry/strategies/distance.hpp>
+
namespace boost { namespace geometry
{
namespace strategies { namespace distance
-{
+{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
diff --git a/boost/geometry/strategies/distance/services.hpp b/boost/geometry/strategies/distance/services.hpp
index 4ac35c6dd2..5ce3cd98ba 100644
--- a/boost/geometry/strategies/distance/services.hpp
+++ b/boost/geometry/strategies/distance/services.hpp
@@ -14,6 +14,8 @@
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/static_assert.hpp>
+#include <boost/geometry/strategies/detail.hpp>
+
namespace boost { namespace geometry
{
diff --git a/boost/geometry/strategies/envelope/cartesian.hpp b/boost/geometry/strategies/envelope/cartesian.hpp
index 3bce5dbc3e..1e032e3f12 100644
--- a/boost/geometry/strategies/envelope/cartesian.hpp
+++ b/boost/geometry/strategies/envelope/cartesian.hpp
@@ -13,13 +13,14 @@
#include <type_traits>
-#include <boost/geometry/strategy/cartesian/envelope.hpp>
+#include <boost/geometry/strategy/cartesian/envelope.hpp> // Not used, for backward compatibility
#include <boost/geometry/strategy/cartesian/envelope_box.hpp>
-#include <boost/geometry/strategy/cartesian/envelope_point.hpp>
+#include <boost/geometry/strategy/cartesian/envelope_boxes.hpp>
#include <boost/geometry/strategy/cartesian/envelope_multipoint.hpp>
+#include <boost/geometry/strategy/cartesian/envelope_point.hpp>
+#include <boost/geometry/strategy/cartesian/envelope_range.hpp>
#include <boost/geometry/strategy/cartesian/envelope_segment.hpp>
-#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/envelope/services.hpp>
#include <boost/geometry/strategies/expand/cartesian.hpp>
@@ -36,37 +37,54 @@ struct cartesian
{
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
- typename util::enable_if_point_t<Geometry> * = nullptr)
+ util::enable_if_point_t<Geometry> * = nullptr)
{
return strategy::envelope::cartesian_point();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
- typename util::enable_if_multi_point_t<Geometry> * = nullptr)
+ util::enable_if_multi_point_t<Geometry> * = nullptr)
{
return strategy::envelope::cartesian_multipoint();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
- typename util::enable_if_box_t<Geometry> * = nullptr)
+ util::enable_if_box_t<Geometry> * = nullptr)
{
return strategy::envelope::cartesian_box();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
- typename util::enable_if_segment_t<Geometry> * = nullptr)
+ util::enable_if_segment_t<Geometry> * = nullptr)
{
return strategy::envelope::cartesian_segment<CalculationType>();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
- typename util::enable_if_polysegmental_t<Geometry> * = nullptr)
+ std::enable_if_t
+ <
+ util::is_linestring<Geometry>::value
+ || util::is_ring<Geometry>::value
+ || util::is_polygon<Geometry>::value
+ > * = nullptr)
+ {
+ return strategy::envelope::cartesian_range();
+ }
+
+ template <typename Geometry, typename Box>
+ static auto envelope(Geometry const&, Box const&,
+ std::enable_if_t
+ <
+ util::is_multi_linestring<Geometry>::value
+ || util::is_multi_polygon<Geometry>::value
+ || util::is_geometry_collection<Geometry>::value
+ > * = nullptr)
{
- return strategy::envelope::cartesian<CalculationType>();
+ return strategy::envelope::cartesian_boxes();
}
};
diff --git a/boost/geometry/strategies/envelope/geographic.hpp b/boost/geometry/strategies/envelope/geographic.hpp
index 96940c4706..ea1eb0e82d 100644
--- a/boost/geometry/strategies/envelope/geographic.hpp
+++ b/boost/geometry/strategies/envelope/geographic.hpp
@@ -13,11 +13,10 @@
#include <type_traits>
-#include <boost/geometry/strategy/geographic/envelope.hpp>
+#include <boost/geometry/strategy/geographic/envelope.hpp> // Not used, for backward compatibility
+#include <boost/geometry/strategy/geographic/envelope_range.hpp>
#include <boost/geometry/strategy/geographic/envelope_segment.hpp>
-#include <boost/geometry/strategy/geographic/expand_segment.hpp> // TEMP
-
#include <boost/geometry/strategies/envelope/spherical.hpp>
#include <boost/geometry/strategies/expand/geographic.hpp>
@@ -48,28 +47,28 @@ public:
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
- typename util::enable_if_point_t<Geometry> * = nullptr)
+ util::enable_if_point_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_point();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
- typename util::enable_if_multi_point_t<Geometry> * = nullptr)
+ util::enable_if_multi_point_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_multipoint();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
- typename util::enable_if_box_t<Geometry> * = nullptr)
+ util::enable_if_box_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_box();
}
template <typename Geometry, typename Box>
auto envelope(Geometry const&, Box const&,
- typename util::enable_if_segment_t<Geometry> * = nullptr) const
+ util::enable_if_segment_t<Geometry> * = nullptr) const
{
return strategy::envelope::geographic_segment
<
@@ -79,13 +78,39 @@ public:
template <typename Geometry, typename Box>
auto envelope(Geometry const&, Box const&,
- typename util::enable_if_polysegmental_t<Geometry> * = nullptr) const
+ util::enable_if_linestring_t<Geometry> * = nullptr) const
+ {
+ return strategy::envelope::geographic_linestring
+ <
+ FormulaPolicy, Spheroid, CalculationType
+ >(base_t::m_spheroid);
+ }
+
+ template <typename Geometry, typename Box>
+ auto envelope(Geometry const&, Box const&,
+ std::enable_if_t
+ <
+ util::is_ring<Geometry>::value
+ || util::is_polygon<Geometry>::value
+ > * = nullptr) const
{
- return strategy::envelope::geographic
+ return strategy::envelope::geographic_ring
<
FormulaPolicy, Spheroid, CalculationType
>(base_t::m_spheroid);
}
+
+ template <typename Geometry, typename Box>
+ auto envelope(Geometry const&, Box const&,
+ std::enable_if_t
+ <
+ util::is_multi_linestring<Geometry>::value
+ || util::is_multi_polygon<Geometry>::value
+ || util::is_geometry_collection<Geometry>::value
+ > * = nullptr) const
+ {
+ return strategy::envelope::spherical_boxes();
+ }
};
diff --git a/boost/geometry/strategies/envelope/spherical.hpp b/boost/geometry/strategies/envelope/spherical.hpp
index 0c5aad62bf..c09a548264 100644
--- a/boost/geometry/strategies/envelope/spherical.hpp
+++ b/boost/geometry/strategies/envelope/spherical.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2020-2021, Oracle and/or its affiliates.
+// Copyright (c) 2020-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -13,13 +13,13 @@
#include <type_traits>
-#include <boost/geometry/strategy/spherical/envelope.hpp>
#include <boost/geometry/strategy/spherical/envelope_box.hpp>
-#include <boost/geometry/strategy/spherical/envelope_point.hpp>
+#include <boost/geometry/strategy/spherical/envelope_boxes.hpp>
#include <boost/geometry/strategy/spherical/envelope_multipoint.hpp>
+#include <boost/geometry/strategy/spherical/envelope_point.hpp>
+#include <boost/geometry/strategy/spherical/envelope_range.hpp>
#include <boost/geometry/strategy/spherical/envelope_segment.hpp>
-#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/envelope/services.hpp>
#include <boost/geometry/strategies/expand/spherical.hpp>
@@ -47,37 +47,60 @@ struct spherical
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
- typename util::enable_if_point_t<Geometry> * = nullptr)
+ util::enable_if_point_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_point();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
- typename util::enable_if_multi_point_t<Geometry> * = nullptr)
+ util::enable_if_multi_point_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_multipoint();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
- typename util::enable_if_box_t<Geometry> * = nullptr)
+ util::enable_if_box_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_box();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
- typename util::enable_if_segment_t<Geometry> * = nullptr)
+ util::enable_if_segment_t<Geometry> * = nullptr)
{
return strategy::envelope::spherical_segment<CalculationType>();
}
template <typename Geometry, typename Box>
static auto envelope(Geometry const&, Box const&,
- typename util::enable_if_polysegmental_t<Geometry> * = nullptr)
+ util::enable_if_linestring_t<Geometry> * = nullptr)
+ {
+ return strategy::envelope::spherical_linestring<CalculationType>();
+ }
+
+ template <typename Geometry, typename Box>
+ static auto envelope(Geometry const&, Box const&,
+ std::enable_if_t
+ <
+ util::is_ring<Geometry>::value
+ || util::is_polygon<Geometry>::value
+ > * = nullptr)
+ {
+ return strategy::envelope::spherical_ring<CalculationType>();
+ }
+
+ template <typename Geometry, typename Box>
+ static auto envelope(Geometry const&, Box const&,
+ std::enable_if_t
+ <
+ util::is_multi_linestring<Geometry>::value
+ || util::is_multi_polygon<Geometry>::value
+ || util::is_geometry_collection<Geometry>::value
+ > * = nullptr)
{
- return strategy::envelope::spherical<CalculationType>();
+ return strategy::envelope::spherical_boxes();
}
};
diff --git a/boost/geometry/strategies/geographic.hpp b/boost/geometry/strategies/geographic.hpp
index 11cebf46b7..435ba29b2e 100644
--- a/boost/geometry/strategies/geographic.hpp
+++ b/boost/geometry/strategies/geographic.hpp
@@ -28,7 +28,7 @@
namespace boost { namespace geometry
{
-
+
namespace strategies
{
diff --git a/boost/geometry/strategies/geographic/buffer_end_round.hpp b/boost/geometry/strategies/geographic/buffer_end_round.hpp
new file mode 100644
index 0000000000..1d6c8d197a
--- /dev/null
+++ b/boost/geometry/strategies/geographic/buffer_end_round.hpp
@@ -0,0 +1,153 @@
+// Boost.Geometry
+
+// Copyright (c) 2022 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_GEOGRAPHIC_BUFFER_END_ROUND_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_END_ROUND_HPP
+
+#include <boost/range/value_type.hpp>
+
+#include <boost/geometry/core/radian_access.hpp>
+
+#include <boost/geometry/srs/spheroid.hpp>
+#include <boost/geometry/strategies/buffer.hpp>
+#include <boost/geometry/strategies/geographic/buffer_helper.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace buffer
+{
+
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic_end_round
+{
+public :
+
+ //! \brief Constructs the strategy with a spheroid
+ //! \param spheroid The spheroid to be used
+ //! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
+ explicit inline geographic_end_round(Spheroid const& spheroid,
+ std::size_t points_per_circle = default_points_per_circle)
+ : m_spheroid(spheroid)
+ , m_points_per_circle(get_point_count_for_end(points_per_circle))
+ {}
+
+ //! \brief Constructs the strategy
+ //! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
+ explicit inline geographic_end_round(std::size_t points_per_circle = default_points_per_circle)
+ : m_points_per_circle(get_point_count_for_end(points_per_circle))
+ {}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ template <typename T, typename RangeOut>
+ inline void generate(T lon_rad, T lat_rad, T distance, T azimuth, RangeOut& range_out) const
+ {
+ using helper = geographic_buffer_helper<FormulaPolicy, T>;
+ std::size_t const n = m_points_per_circle / 2;
+ T const angle_diff = geometry::math::pi<T>() / n;
+ T azi = math::wrap_azimuth_in_radian(azimuth + angle_diff);
+
+ // Generate points between 0 and n, not including them
+ // because left and right are inserted before and after this range.
+ for (std::size_t i = 1; i < n; i++)
+ {
+ helper::append_point(lon_rad, lat_rad, distance, azi, m_spheroid, range_out);
+ azi = math::wrap_azimuth_in_radian(azi + angle_diff);
+ }
+ }
+
+ //! Fills output_range with a round end
+ template <typename Point, typename DistanceStrategy, typename RangeOut>
+ inline void apply(Point const& penultimate_point, Point const& perp_left_point,
+ Point const& ultimate_point, Point const& perp_right_point,
+ buffer_side_selector side, DistanceStrategy const& distance,
+ RangeOut& range_out) const
+ {
+ using calc_t = typename select_calculation_type
+ <
+ Point,
+ typename boost::range_value<RangeOut>::type,
+ CalculationType
+ >::type;
+
+ using helper = geographic_buffer_helper<FormulaPolicy, calc_t>;
+
+ calc_t const lon_rad = get_as_radian<0>(ultimate_point);
+ calc_t const lat_rad = get_as_radian<1>(ultimate_point);
+
+ auto const azimuth = helper::azimuth(lon_rad, lat_rad, perp_left_point, m_spheroid);
+
+ calc_t const dist_left = distance.apply(penultimate_point, ultimate_point, buffer_side_left);
+ calc_t const dist_right = distance.apply(penultimate_point, ultimate_point, buffer_side_right);
+
+ bool const reversed = (side == buffer_side_left && dist_right < 0 && -dist_right > dist_left)
+ || (side == buffer_side_right && dist_left < 0 && -dist_left > dist_right)
+ ;
+
+ if (reversed)
+ {
+ range_out.push_back(perp_right_point);
+ // generate
+ range_out.push_back(perp_left_point);
+ }
+ else
+ {
+ range_out.push_back(perp_left_point);
+
+ if (geometry::math::equals(dist_left, dist_right))
+ {
+ generate(lon_rad, lat_rad, dist_left, azimuth, range_out);
+ }
+ else
+ {
+ static calc_t const two = 2.0;
+ calc_t const dist_average = (dist_left + dist_right) / two;
+ calc_t const dist_half
+ = (side == buffer_side_right
+ ? (dist_right - dist_left)
+ : (dist_left - dist_right)) / two;
+ auto const shifted = helper::direct::apply(lon_rad, lat_rad, dist_half, azimuth, m_spheroid);
+ generate(shifted.lon2, shifted.lat2, dist_average, azimuth, range_out);
+ }
+
+ range_out.push_back(perp_right_point);
+ }
+ }
+
+ template <typename NumericType>
+ static inline NumericType max_distance(NumericType const& distance)
+ {
+ return distance;
+ }
+
+ //! Returns the piece_type (flat end)
+ static inline piece_type get_piece_type()
+ {
+ return buffered_round_end;
+ }
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+private :
+ Spheroid m_spheroid;
+ std::size_t m_points_per_circle;
+};
+
+}} // namespace strategy::buffer
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_END_ROUND_HPP
diff --git a/boost/geometry/strategies/geographic/buffer_helper.hpp b/boost/geometry/strategies/geographic/buffer_helper.hpp
new file mode 100644
index 0000000000..16caa3d027
--- /dev/null
+++ b/boost/geometry/strategies/geographic/buffer_helper.hpp
@@ -0,0 +1,101 @@
+// Boost.Geometry
+
+// Copyright (c) 2022 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_GEOGRAPHIC_BUFFER_HELPER_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_HELPER_HPP
+
+#include <boost/geometry/core/assert.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+#include <boost/geometry/util/math.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace buffer
+{
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+template <typename FormulaPolicy, typename CalculationType>
+struct geographic_buffer_helper
+{
+ static bool const enable_azimuth = true;
+ static bool const enable_coordinates = true;
+
+ using inverse = typename FormulaPolicy::template inverse
+ <
+ CalculationType, false, enable_azimuth, false, false, false
+ >;
+
+ using direct = typename FormulaPolicy::template direct
+ <
+ CalculationType, enable_coordinates, false, false, false
+ >;
+
+ // Calculates the azimuth using the inverse formula, where the first point
+ // is specified by lon/lat (for pragmatic reasons) and the second point as a point.
+ template <typename T, typename Point, typename Spheroid>
+ static inline CalculationType azimuth(T const& lon_rad, T const& lat_rad,
+ Point const& p, Spheroid const& spheroid)
+ {
+ return inverse::apply(lon_rad, lat_rad, get_as_radian<0>(p), get_as_radian<1>(p), spheroid).azimuth;
+ }
+
+ // Using specified points, distance and azimuth it calculates a new point
+ // and appends it to the range
+ template <typename T, typename Spheroid, typename RangeOut>
+ static inline void append_point(T const& lon_rad, T const& lat_rad,
+ T const& distance, T const& angle,
+ Spheroid const& spheroid, RangeOut& range_out)
+ {
+ using point_t = typename boost::range_value<RangeOut>::type;
+ point_t point;
+ auto const d = direct::apply(lon_rad, lat_rad, distance, angle, spheroid);
+ set_from_radian<0>(point, d.lon2);
+ set_from_radian<1>(point, d.lat2);
+ range_out.emplace_back(point);
+ }
+
+ // Calculates the angle diff and azimuth of a point (specified as lon/lat)
+ // and two points, perpendicular in the buffer context.
+ template <typename T, typename Point, typename Spheroid>
+ static inline bool calculate_angles(T const& lon_rad, T const& lat_rad, Point const& perp1,
+ Point const& perp2, Spheroid const& spheroid,
+ T& angle_diff, T& first_azimuth)
+ {
+ T const inv1 = azimuth(lon_rad, lat_rad, perp1, spheroid);
+ T const inv2 = azimuth(lon_rad, lat_rad, perp2, spheroid);
+
+ static CalculationType const two_pi = geometry::math::two_pi<CalculationType>();
+ static CalculationType const pi = geometry::math::pi<CalculationType>();
+
+ // For a sharp corner, perpendicular points are nearly opposite and the
+ // angle between the two azimuths can be nearly 180, but not more.
+ angle_diff = inv2 < inv1 ? (two_pi + inv2) - inv1 : inv2 - inv1;
+
+ if (angle_diff < 0 || angle_diff > pi)
+ {
+ // Defensive check with asserts
+ BOOST_GEOMETRY_ASSERT(angle_diff >= 0);
+ BOOST_GEOMETRY_ASSERT(angle_diff <= pi);
+ return false;
+ }
+
+ first_azimuth = inv1;
+
+ return true;
+ }
+};
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+}} // namespace strategy::buffer
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_HELPER_HPP
diff --git a/boost/geometry/strategies/geographic/buffer_join_miter.hpp b/boost/geometry/strategies/geographic/buffer_join_miter.hpp
new file mode 100644
index 0000000000..b479f5fb57
--- /dev/null
+++ b/boost/geometry/strategies/geographic/buffer_join_miter.hpp
@@ -0,0 +1,132 @@
+// Boost.Geometry
+
+// Copyright (c) 2022 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_GEOGRAPHIC_BUFFER_JOIN_MITER_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_JOIN_MITER_HPP
+
+#include <boost/range/value_type.hpp>
+
+#include <boost/geometry/core/radian_access.hpp>
+
+#include <boost/geometry/srs/spheroid.hpp>
+#include <boost/geometry/strategies/buffer.hpp>
+#include <boost/geometry/strategies/geographic/buffer_helper.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace buffer
+{
+
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic_join_miter
+{
+public :
+
+ //! \brief Constructs the strategy with a spheroid
+ //! \param spheroid The spheroid to be used
+ //! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners
+ explicit inline geographic_join_miter(Spheroid const& spheroid,
+ double miter_limit = 5.0)
+ : m_spheroid(spheroid)
+ , m_miter_limit(valid_limit(miter_limit))
+ {}
+
+ //! \brief Constructs the strategy
+ //! \param miter_limit The miter limit, to avoid excessively long miters around sharp corners
+ explicit inline geographic_join_miter(double miter_limit = 5.0)
+ : m_miter_limit(valid_limit(miter_limit))
+ {}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ //! Fills output_range with a sharp shape around a vertex
+ template <typename Point, typename DistanceType, typename RangeOut>
+ inline bool apply(Point const& , Point const& vertex,
+ Point const& perp1, Point const& perp2,
+ DistanceType const& buffer_distance,
+ RangeOut& range_out) const
+ {
+ using calc_t = typename select_calculation_type
+ <
+ Point,
+ typename boost::range_value<RangeOut>::type,
+ CalculationType
+ >::type;
+
+ using helper = geographic_buffer_helper<FormulaPolicy, calc_t>;
+
+ calc_t const lon_rad = get_as_radian<0>(vertex);
+ calc_t const lat_rad = get_as_radian<1>(vertex);
+
+ calc_t first_azimuth;
+ calc_t angle_diff;
+ if (! helper::calculate_angles(lon_rad, lat_rad, perp1, perp2, m_spheroid,
+ angle_diff, first_azimuth))
+ {
+ return false;
+ }
+
+ calc_t const half = 0.5;
+ calc_t const half_angle_diff = half * angle_diff;
+ calc_t const azi = math::wrap_azimuth_in_radian(first_azimuth + half_angle_diff);
+
+ calc_t const cos_angle = std::cos(half_angle_diff);
+
+ if (cos_angle == 0)
+ {
+ // It is opposite, perp1==perp2, do not generate a miter cap
+ return false;
+ }
+
+ // If it is sharp (angle close to 0), the distance will become too high and will be capped.
+ calc_t const max_distance = m_miter_limit * geometry::math::abs(buffer_distance);
+ calc_t const distance = (std::min)(max_distance, buffer_distance / cos_angle);
+
+ range_out.push_back(perp1);
+ helper::append_point(lon_rad, lat_rad, distance, azi, m_spheroid, range_out);
+ range_out.push_back(perp2);
+ return true;
+ }
+
+ template <typename NumericType>
+ inline NumericType max_distance(NumericType const& distance) const
+ {
+ return distance * m_miter_limit;
+ }
+
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+private :
+ double valid_limit(double miter_limit) const
+ {
+ if (miter_limit < 1.0)
+ {
+ // It should always exceed the buffer distance
+ miter_limit = 1.0;
+ }
+ return miter_limit;
+ }
+
+ Spheroid m_spheroid;
+ double m_miter_limit;
+};
+
+}} // namespace strategy::buffer
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_JOIN_MITER_HPP
diff --git a/boost/geometry/strategies/geographic/buffer_join_round.hpp b/boost/geometry/strategies/geographic/buffer_join_round.hpp
new file mode 100644
index 0000000000..4f891d0573
--- /dev/null
+++ b/boost/geometry/strategies/geographic/buffer_join_round.hpp
@@ -0,0 +1,123 @@
+// Boost.Geometry
+
+// Copyright (c) 2022 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2023 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_STRATEGIES_GEOGRAPHIC_BUFFER_JOIN_ROUND_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_JOIN_ROUND_HPP
+
+#include <boost/range/value_type.hpp>
+
+#include <boost/geometry/core/radian_access.hpp>
+
+#include <boost/geometry/srs/spheroid.hpp>
+#include <boost/geometry/strategies/buffer.hpp>
+#include <boost/geometry/strategies/geographic/buffer_helper.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace buffer
+{
+
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic_join_round
+{
+public :
+
+ //! \brief Constructs the strategy with a spheroid
+ //! \param spheroid The spheroid to be used
+ //! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
+ explicit inline geographic_join_round(Spheroid const& spheroid,
+ std::size_t points_per_circle = default_points_per_circle)
+ : m_spheroid(spheroid)
+ , m_points_per_circle(get_point_count_for_join(points_per_circle))
+ {}
+
+ //! \brief Constructs the strategy
+ //! \param points_per_circle Number of points (minimum 4) that would be used for a full circle
+ explicit inline geographic_join_round(std::size_t points_per_circle = default_points_per_circle)
+ : m_points_per_circle(get_point_count_for_join(points_per_circle))
+ {}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ //! Fills output_range with a rounded shape around a vertex
+ template <typename Point, typename DistanceType, typename RangeOut>
+ inline bool apply(Point const& /*ip*/, Point const& vertex,
+ Point const& perp1, Point const& perp2,
+ DistanceType const& buffer_distance,
+ RangeOut& range_out) const
+ {
+ using calc_t = typename select_calculation_type
+ <
+ Point,
+ typename boost::range_value<RangeOut>::type,
+ CalculationType
+ >::type;
+
+ using helper = geographic_buffer_helper<FormulaPolicy, calc_t>;
+
+ calc_t const lon_rad = get_as_radian<0>(vertex);
+ calc_t const lat_rad = get_as_radian<1>(vertex);
+
+ calc_t first_azimuth;
+ calc_t angle_diff;
+ if (! helper::calculate_angles(lon_rad, lat_rad, perp1, perp2, m_spheroid,
+ angle_diff, first_azimuth))
+ {
+ return false;
+ }
+
+ static calc_t const two_pi = geometry::math::two_pi<calc_t>();
+ calc_t const circle_fraction = angle_diff / two_pi;
+ std::size_t const n = (std::max)(static_cast<std::size_t>(
+ std::ceil(m_points_per_circle * circle_fraction)), std::size_t(1));
+
+ calc_t const diff = angle_diff / static_cast<calc_t>(n);
+ calc_t azi = math::wrap_azimuth_in_radian(first_azimuth + diff);
+
+ range_out.push_back(perp1);
+
+ // Generate points between 0 and n, not including them
+ // because perp1 and perp2 are inserted before and after this range.
+ for (std::size_t i = 1; i < n; i++)
+ {
+ helper::append_point(lon_rad, lat_rad, buffer_distance, azi, m_spheroid, range_out);
+ azi = math::wrap_azimuth_in_radian(azi + diff);
+ }
+
+ range_out.push_back(perp2);
+ return true;
+ }
+
+ template <typename NumericType>
+ static inline NumericType max_distance(NumericType const& distance)
+ {
+ return distance;
+ }
+
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+private :
+ Spheroid m_spheroid;
+ std::size_t m_points_per_circle;
+};
+
+}} // namespace strategy::buffer
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_JOIN_ROUND_HPP
diff --git a/boost/geometry/strategies/geographic/buffer_point_circle.hpp b/boost/geometry/strategies/geographic/buffer_point_circle.hpp
index 8d6643d73d..8aa7fce24e 100644
--- a/boost/geometry/strategies/geographic/buffer_point_circle.hpp
+++ b/boost/geometry/strategies/geographic/buffer_point_circle.hpp
@@ -1,9 +1,9 @@
// Boost.Geometry
-// Copyright (c) 2018-2019 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2018-2022 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2020.
-// Modifications copyright (c) 2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2021.
+// Modifications copyright (c) 2020-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -17,10 +17,14 @@
#include <boost/range/value_type.hpp>
-#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategies/buffer.hpp>
+#include <boost/geometry/strategies/geographic/buffer_helper.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
namespace boost { namespace geometry
@@ -55,81 +59,75 @@ template
class geographic_point_circle
{
public :
+
+ //! \brief Constructs the strategy with a spheroid
+ //! \param spheroid The spheroid to be used
+ //! \param count Number of points (minimum 3) for the created circle
+ explicit inline geographic_point_circle(Spheroid const& spheroid,
+ std::size_t count = default_points_per_circle)
+ : m_spheroid(spheroid)
+ , m_count(get_point_count_for_circle(count))
+ {}
+
//! \brief Constructs the strategy
- //! \param count number of points for the created circle (if count
- //! is smaller than 3, count is internally set to 3)
- explicit geographic_point_circle(std::size_t count = 90)
- : m_count((count < 3u) ? 3u : count)
+ //! \param count Number of points (minimum 3) for the created circle
+ explicit inline geographic_point_circle(std::size_t count = default_points_per_circle)
+ : m_count(get_point_count_for_circle(count))
{}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
- //! Fills output_range with a circle around point using distance_strategy
+ //! Fills range_out with a circle around point using distance_strategy
template
<
typename Point,
- typename OutputRange,
- typename DistanceStrategy
+ typename DistanceStrategy,
+ typename RangeOut
>
inline void apply(Point const& point,
- DistanceStrategy const& distance_strategy,
- OutputRange& output_range) const
+ DistanceStrategy const& distance_strategy,
+ RangeOut& range_out) const
{
- typedef typename boost::range_value<OutputRange>::type output_point_type;
-
- typedef typename select_calculation_type
+ using calc_t = typename select_calculation_type
<
- Point, output_point_type,
+ Point,
+ typename boost::range_value<RangeOut>::type,
CalculationType
- //double
- >::type calculation_type;
+ >::type;
- calculation_type const buffer_distance = distance_strategy.apply(point, point,
- strategy::buffer::buffer_side_left);
+ using helper = geographic_buffer_helper<FormulaPolicy, calc_t>;
- typedef typename FormulaPolicy::template direct
- <
- calculation_type, true, false, false, false
- > direct_t;
+ calc_t const lon_rad = get_as_radian<0>(point);
+ calc_t const lat_rad = get_as_radian<1>(point);
+
+ calc_t const buffer_distance = distance_strategy.apply(point,
+ point, strategy::buffer::buffer_side_left);
- calculation_type const two_pi = geometry::math::two_pi<calculation_type>();
- calculation_type const pi = geometry::math::pi<calculation_type>();
+ calc_t const two_pi = geometry::math::two_pi<calc_t>();
+ calc_t const pi = geometry::math::pi<calc_t>();
- calculation_type const diff = two_pi / calculation_type(m_count);
- // TODO: after calculation of some angles is corrected,
- // we can start at 0.0
- calculation_type angle = 0.001;
+ calc_t const diff = two_pi / calc_t(m_count);
+ calc_t angle = -pi;
for (std::size_t i = 0; i < m_count; i++, angle += diff)
{
- if (angle > pi)
- {
- angle -= two_pi;
- }
-
- typename direct_t::result_type
- dir_r = direct_t::apply(get_as_radian<0>(point), get_as_radian<1>(point),
- buffer_distance, angle,
- m_spheroid);
- output_point_type p;
- set_from_radian<0>(p, dir_r.lon2);
- set_from_radian<1>(p, dir_r.lat2);
- output_range.push_back(p);
+ // If angle is zero, shift angle a tiny bit to avoid spikes.
+ calc_t const eps = angle == 0 ? 1.0e-10 : 0.0;
+ helper::append_point(lon_rad, lat_rad, buffer_distance, angle + eps, m_spheroid, range_out);
}
{
// Close the range
- const output_point_type p = output_range.front();
- output_range.push_back(p);
+ auto const p = range_out.front();
+ range_out.push_back(p);
}
}
#endif // DOXYGEN_SHOULD_SKIP_THIS
private :
- std::size_t m_count;
Spheroid m_spheroid;
+ std::size_t m_count;
};
-
}} // namespace strategy::buffer
}} // namespace boost::geometry
diff --git a/boost/geometry/strategies/geographic/buffer_side_straight.hpp b/boost/geometry/strategies/geographic/buffer_side_straight.hpp
new file mode 100644
index 0000000000..65d05d0d4e
--- /dev/null
+++ b/boost/geometry/strategies/geographic/buffer_side_straight.hpp
@@ -0,0 +1,119 @@
+// Boost.Geometry
+
+// Copyright (c) 2022 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_GEOGRAPHIC_BUFFER_SIDE_STRAIGHT_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_SIDE_STRAIGHT_HPP
+
+#include <cstddef>
+
+#include <boost/range/value_type.hpp>
+
+#include <boost/geometry/core/radian_access.hpp>
+
+#include <boost/geometry/srs/spheroid.hpp>
+#include <boost/geometry/strategies/buffer.hpp>
+#include <boost/geometry/strategies/geographic/buffer_helper.hpp>
+#include <boost/geometry/strategies/geographic/parameters.hpp>
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace buffer
+{
+
+/*!
+\brief Create a straight buffer along a side, on the Earth
+\ingroup strategies
+\details This strategy can be used as SideStrategy for the buffer algorithm.
+ */
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic_side_straight
+{
+public :
+ //! \brief Constructs the strategy with a spheroid
+ //! \param spheroid The spheroid to be used
+ explicit inline geographic_side_straight(Spheroid const& spheroid)
+ : m_spheroid(spheroid)
+ {}
+
+ //! \brief Constructs the strategy
+ inline geographic_side_straight()
+ {}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+ // Returns true if the buffer distance is always the same
+ static inline bool equidistant()
+ {
+ return true;
+ }
+
+
+ template
+ <
+ typename Point,
+ typename DistanceStrategy,
+ typename RangeOut
+ >
+ inline result_code apply(Point const& input_p1, Point const& input_p2,
+ buffer_side_selector side,
+ DistanceStrategy const& distance_strategy,
+ RangeOut& range_out) const
+ {
+ using calc_t = typename select_calculation_type
+ <
+ Point,
+ typename boost::range_value<RangeOut>::type,
+ CalculationType
+ >::type;
+
+ using helper = geographic_buffer_helper<FormulaPolicy, calc_t>;
+
+ calc_t const lon1_rad = get_as_radian<0>(input_p1);
+ calc_t const lat1_rad = get_as_radian<1>(input_p1);
+ calc_t const lon2_rad = get_as_radian<0>(input_p2);
+ calc_t const lat2_rad = get_as_radian<1>(input_p2);
+ if (lon1_rad == lon2_rad && lat1_rad == lat2_rad)
+ {
+ // Coordinates are simplified and therefore most often not equal.
+ // But if simplify is skipped, or for lines with two
+ // equal points, length is 0 and we cannot generate output.
+ return result_no_output;
+ }
+
+
+ // Measure the angle from p1 to p2 with the Inverse transformation,
+ // and subtract pi/2 to make it perpendicular.
+ auto const inv = helper::azimuth(lon1_rad, lat1_rad, input_p2, m_spheroid);
+ auto const angle = math::wrap_azimuth_in_radian(inv - geometry::math::half_pi<calc_t>());
+
+ // Calculate the distance and generate two points at that distance
+ auto const distance = distance_strategy.apply(input_p1, input_p2, side);
+ helper::append_point(lon1_rad, lat1_rad, distance, angle, m_spheroid, range_out);
+ helper::append_point(lon2_rad, lat2_rad, distance, angle, m_spheroid, range_out);
+
+ return result_normal;
+ }
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+private :
+ Spheroid m_spheroid;
+};
+
+}} // namespace strategy::buffer
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_BUFFER_SIDE_STRAIGHT_HPP
diff --git a/boost/geometry/strategies/geographic/closest_points_pt_seg.hpp b/boost/geometry/strategies/geographic/closest_points_pt_seg.hpp
new file mode 100644
index 0000000000..94b32a50d2
--- /dev/null
+++ b/boost/geometry/strategies/geographic/closest_points_pt_seg.hpp
@@ -0,0 +1,100 @@
+// Boost.Geometry
+
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_CLOSEST_POINTS_CROSS_TRACK_HPP
+#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_CLOSEST_POINTS_CROSS_TRACK_HPP
+
+#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
+#include <boost/geometry/core/coordinate_system.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/geometries/point.hpp>
+#include <boost/geometry/srs/spheroid.hpp>
+#include <boost/geometry/strategies/geographic/distance_cross_track.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace closest_points
+{
+
+template
+<
+ typename FormulaPolicy = geometry::strategy::andoyer,
+ typename Spheroid = srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic_cross_track
+ : public distance::detail::geographic_cross_track
+ <
+ FormulaPolicy,
+ Spheroid,
+ CalculationType,
+ false,
+ true
+ >
+{
+ using base_t = distance::detail::geographic_cross_track
+ <
+ FormulaPolicy,
+ Spheroid,
+ CalculationType,
+ false,
+ true
+ >;
+
+ template <typename Point, typename PointOfSegment>
+ struct calculation_type
+ : promote_floating_point
+ <
+ typename select_calculation_type
+ <
+ Point,
+ PointOfSegment,
+ CalculationType
+ >::type
+ >
+ {};
+
+public :
+ explicit geographic_cross_track(Spheroid const& spheroid = Spheroid())
+ : base_t(spheroid)
+ {}
+
+ template <typename Point, typename PointOfSegment>
+ auto apply(Point const& p,
+ PointOfSegment const& sp1,
+ PointOfSegment const& sp2) const
+ {
+ auto result = base_t::apply(get_as_radian<0>(sp1), get_as_radian<1>(sp1),
+ get_as_radian<0>(sp2), get_as_radian<1>(sp2),
+ get_as_radian<0>(p), get_as_radian<1>(p),
+ base_t::m_spheroid);
+
+ model::point
+ <
+ typename calculation_type<Point, PointOfSegment>::type,
+ dimension<PointOfSegment>::value,
+ typename coordinate_system<PointOfSegment>::type
+ > cp;
+
+ geometry::set_from_radian<0>(cp, result.lon);
+ geometry::set_from_radian<1>(cp, result.lat);
+
+ return cp;
+ }
+};
+
+}} // namespace strategy::closest_points
+
+}} // namespace boost::geometry
+#endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_CLOSEST_POINTS_CROSS_TRACK_HPP
diff --git a/boost/geometry/strategies/geographic/disjoint_segment_box.hpp b/boost/geometry/strategies/geographic/disjoint_segment_box.hpp
index 2e06049aa6..d7ea122a34 100644
--- a/boost/geometry/strategies/geographic/disjoint_segment_box.hpp
+++ b/boost/geometry/strategies/geographic/disjoint_segment_box.hpp
@@ -67,7 +67,7 @@ public:
{}
typedef covered_by::spherical_point_box disjoint_point_box_strategy_type;
-
+
static inline disjoint_point_box_strategy_type get_disjoint_point_box_strategy()
{
return disjoint_point_box_strategy_type();
diff --git a/boost/geometry/strategies/geographic/distance.hpp b/boost/geometry/strategies/geographic/distance.hpp
index 41e3cd7aaa..3602a631a3 100644
--- a/boost/geometry/strategies/geographic/distance.hpp
+++ b/boost/geometry/strategies/geographic/distance.hpp
@@ -17,6 +17,7 @@
#define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_DISTANCE_HPP
+#include <boost/geometry/core/coordinate_promotion.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/radius.hpp>
@@ -32,7 +33,6 @@
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
diff --git a/boost/geometry/strategies/geographic/distance_cross_track.hpp b/boost/geometry/strategies/geographic/distance_cross_track.hpp
index e269703ef9..db5e46b9c1 100644
--- a/boost/geometry/strategies/geographic/distance_cross_track.hpp
+++ b/boost/geometry/strategies/geographic/distance_cross_track.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2016-2021, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2016-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -14,13 +15,12 @@
#include <algorithm>
-#include <boost/tuple/tuple.hpp>
-#include <boost/algorithm/minmax.hpp>
#include <boost/config.hpp>
#include <boost/concept_check.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -37,7 +37,6 @@
#include <boost/geometry/formulas/vincenty_direct.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
@@ -62,9 +61,37 @@ namespace boost { namespace geometry
namespace strategy { namespace distance
{
-
namespace detail
{
+
+template <bool EnableClosestPoint>
+struct set_result
+{
+ template <typename CT, typename ResultType>
+ static void apply(CT const& distance,
+ CT const&,
+ CT const&,
+ ResultType& result)
+ {
+ result.distance = distance;
+ }
+};
+
+template<>
+struct set_result<true>
+{
+ template <typename CT, typename ResultType>
+ static void apply(CT const&,
+ CT const& lon,
+ CT const& lat,
+ ResultType& result)
+ {
+ result.lon = lon;
+ result.lat = lat;
+ }
+};
+
+
/*!
\brief Strategy functor for distance point to segment calculation on ellipsoid
Algorithm uses direct and inverse geodesic problems as subroutines.
@@ -89,7 +116,20 @@ template
>
class geographic_cross_track
{
+
public:
+
+ geographic_cross_track() = default;
+
+ explicit geographic_cross_track(Spheroid const& spheroid)
+ : m_spheroid(spheroid)
+ {}
+
+ Spheroid const& model() const
+ {
+ return m_spheroid;
+ }
+
template <typename Point, typename PointOfSegment>
struct return_type
: promote_floating_point
@@ -103,96 +143,58 @@ public:
>
{};
- geographic_cross_track() = default;
-
- explicit geographic_cross_track(Spheroid const& spheroid)
- : m_spheroid(spheroid)
- {}
-
template <typename Point, typename PointOfSegment>
- inline typename return_type<Point, PointOfSegment>::type
- apply(Point const& p, PointOfSegment const& sp1, PointOfSegment const& sp2) const
+ auto apply(Point const& p,
+ PointOfSegment const& sp1,
+ PointOfSegment const& sp2) const
{
- typedef typename geometry::detail::cs_angular_units<Point>::type units_type;
-
- return (apply<units_type>(get_as_radian<0>(sp1), get_as_radian<1>(sp1),
- get_as_radian<0>(sp2), get_as_radian<1>(sp2),
- get_as_radian<0>(p), get_as_radian<1>(p),
- m_spheroid)).distance;
+ return apply(get_as_radian<0>(sp1), get_as_radian<1>(sp1),
+ get_as_radian<0>(sp2), get_as_radian<1>(sp2),
+ get_as_radian<0>(p), get_as_radian<1>(p),
+ m_spheroid).distance;
}
// points on a meridian not crossing poles
template <typename CT>
inline CT vertical_or_meridian(CT const& lat1, CT const& lat2) const
{
- typedef typename formula::meridian_inverse
+ using meridian_inverse = typename formula::meridian_inverse
<
CT,
strategy::default_order<FormulaPolicy>::value
- > meridian_inverse;
-
- return meridian_inverse::meridian_not_crossing_pole_dist(lat1, lat2,
- m_spheroid);
- }
+ >;
- Spheroid const& model() const
- {
- return m_spheroid;
+ return meridian_inverse::meridian_not_crossing_pole_dist(lat1, lat2, m_spheroid);
}
-private :
+private:
template <typename CT>
- struct result_distance_point_segment
+ struct result_type
{
- result_distance_point_segment()
+ result_type()
: distance(0)
- , closest_point_lon(0)
- , closest_point_lat(0)
+ , lon(0)
+ , lat(0)
{}
CT distance;
- CT closest_point_lon;
- CT closest_point_lat;
+ CT lon;
+ CT lat;
};
template <typename CT>
- result_distance_point_segment<CT>
- static inline non_iterative_case(CT const& lon, CT const& lat, CT const& distance)
- {
- result_distance_point_segment<CT> result;
- result.distance = distance;
-
- if (EnableClosestPoint)
- {
- result.closest_point_lon = lon;
- result.closest_point_lat = lat;
- }
- return result;
- }
-
- template <typename CT>
- result_distance_point_segment<CT>
- static inline non_iterative_case(CT const& lon1, CT const& lat1, //p1
- CT const& lon2, CT const& lat2, //p2
- Spheroid const& spheroid)
- {
- CT distance = geometry::strategy::distance::geographic<FormulaPolicy, Spheroid, CT>
- ::apply(lon1, lat1, lon2, lat2, spheroid);
-
- return non_iterative_case(lon1, lat1, distance);
- }
-
- template <typename CT>
- CT static inline normalize(CT const& g4, CT& der)
+ static inline CT normalize(CT const& g4, CT& der)
{
CT const pi = math::pi<CT>();
+ CT const c_1_5 = 1.5;
+
if (g4 < -1.25*pi)//close to -270
{
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
std::cout << "g4=" << g4 * math::r2d<CT>() << ", close to -270" << std::endl;
#endif
- return g4 + 1.5 * pi;
+ return g4 + c_1_5 * pi;
}
else if (g4 > 1.25*pi)//close to 270
{
@@ -200,7 +202,7 @@ private :
std::cout << "g4=" << g4 * math::r2d<CT>() << ", close to 270" << std::endl;
#endif
der = -der;
- return - g4 + 1.5 * pi;
+ return - g4 + c_1_5 * pi;
}
else if (g4 < 0 && g4 > -0.75*pi)//close to -90
{
@@ -213,18 +215,19 @@ private :
return g4 - pi/2;
}
+
template <typename CT>
static void bisection(CT const& lon1, CT const& lat1, //p1
CT const& lon2, CT const& lat2, //p2
CT const& lon3, CT const& lat3, //query point p3
Spheroid const& spheroid,
CT const& s14_start, CT const& a12,
- result_distance_point_segment<CT>& result)
+ result_type<CT>& result)
{
- typedef typename FormulaPolicy::template direct<CT, true, false, false, false>
- direct_distance_type;
- typedef typename FormulaPolicy::template inverse<CT, true, false, false, false, false>
- inverse_distance_type;
+ using direct_distance_type =
+ typename FormulaPolicy::template direct<CT, true, false, false, false>;
+ using inverse_distance_type =
+ typename FormulaPolicy::template inverse<CT, true, false, false, false, false>;
geometry::formula::result_direct<CT> res14;
@@ -238,53 +241,57 @@ private :
CT s14 = s14_start;
- do{
+ do {
// Solve the direct problem to find p4 (GEO)
res14 = direct_distance_type::apply(lon1, lat1, s14, a12, spheroid);
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
std::cout << "dist(pl,p3)="
- << inverse_distance_type::apply(lon3, lat3,
- pr_lon, pr_lat,
- spheroid).distance
+ << inverse_distance_type::apply(lon3, lat3, pr_lon, pr_lat, spheroid).distance
<< std::endl;
std::cout << "dist(pr,p3)="
- << inverse_distance_type::apply(lon3, lat3,
- pr_lon, pr_lat,
- spheroid).distance
+ << inverse_distance_type::apply(lon3, lat3, pr_lon, pr_lat, spheroid).distance
<< std::endl;
#endif
- if (inverse_distance_type::apply(lon3, lat3, pl_lon, pl_lat, spheroid).distance
- < inverse_distance_type::apply(lon3, lat3, pr_lon, pr_lat, spheroid).distance)
+ CT const dist_l =
+ inverse_distance_type::apply(lon3, lat3, pl_lon, pl_lat, spheroid).distance;
+ CT const dist_r =
+ inverse_distance_type::apply(lon3, lat3, pr_lon, pr_lat, spheroid).distance;
+
+ if (dist_l < dist_r)
{
- s14 -= inverse_distance_type::apply(res14.lon2, res14.lat2, pl_lon, pl_lat,
- spheroid).distance/2;
+ s14 -= inverse_distance_type::apply(res14.lon2, res14.lat2, pl_lon,
+ pl_lat, spheroid).distance/2;
pr_lon = res14.lon2;
pr_lat = res14.lat2;
}
else
{
- s14 += inverse_distance_type::apply(res14.lon2, res14.lat2, pr_lon, pr_lat,
- spheroid).distance/2;
+ s14 += inverse_distance_type::apply(res14.lon2, res14.lat2, pr_lon,
+ pr_lat, spheroid).distance/2;
pl_lon = res14.lon2;
pl_lat = res14.lat2;
}
- CT new_distance = inverse_distance_type::apply(lon3, lat3,
- res14.lon2, res14.lat2,
- spheroid).distance;
+ CT new_distance = inverse_distance_type::apply(lon3, lat3, res14.lon2, res14.lat2,
+ spheroid).distance;
dist_improve = new_distance != result.distance;
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
std::cout << "p4=" << res14.lon2 * math::r2d<CT>() <<
"," << res14.lat2 * math::r2d<CT>() << std::endl;
- std::cout << "pl=" << pl_lon * math::r2d<CT>() << "," << pl_lat * math::r2d<CT>()<< std::endl;
- std::cout << "pr=" << pr_lon * math::r2d<CT>() << "," << pr_lat * math::r2d<CT>() << std::endl;
+ std::cout << "pl=" << pl_lon * math::r2d<CT>() << ","
+ << pl_lat * math::r2d<CT>()<< std::endl;
+ std::cout << "pr=" << pr_lon * math::r2d<CT>() << ","
+ << pr_lat * math::r2d<CT>() << std::endl;
std::cout << "new_s14=" << s14 << std::endl;
- std::cout << std::setprecision(16) << "result.distance =" << result.distance << std::endl;
- std::cout << std::setprecision(16) << "new_distance =" << new_distance << std::endl;
- std::cout << "---------end of step " << counter << std::endl<< std::endl;
+ std::cout << std::setprecision(16) << "result.distance ="
+ << result.distance << std::endl;
+ std::cout << std::setprecision(16) << "new_distance ="
+ << new_distance << std::endl;
+ std::cout << "---------end of step " << counter
+ << std::endl<< std::endl;
if (!dist_improve)
{
std::cout << "Stop msg: res34.distance >= prev_distance" << std::endl;
@@ -294,11 +301,10 @@ private :
std::cout << "Stop msg: counter" << std::endl;
}
#endif
+ set_result<EnableClosestPoint>::apply(new_distance, res14.lon2, res14.lat2, result);
- result.distance = new_distance;
-
- } while (dist_improve
- && counter++ < BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS);
+ } while (dist_improve && counter++
+ < BOOST_GEOMETRY_DETAIL_POINT_SEGMENT_DISTANCE_MAX_STEPS);
}
template <typename CT>
@@ -307,17 +313,18 @@ private :
CT const& lon3, CT const& lat3, //query point p3
Spheroid const& spheroid,
CT const& s14_start, CT const& a12,
- result_distance_point_segment<CT>& result)
+ result_type<CT>& result)
{
- typedef typename FormulaPolicy::template inverse<CT, true, true, false, true, true>
- inverse_distance_azimuth_quantities_type;
- typedef typename FormulaPolicy::template inverse<CT, false, true, false, false, false>
- inverse_dist_azimuth_type;
- typedef typename FormulaPolicy::template direct<CT, true, false, false, false>
- direct_distance_type;
+ using inverse_distance_azimuth_quantities_type =
+ typename FormulaPolicy::template inverse<CT, true, true, false, true, true>;
+
+ using inverse_dist_azimuth_type =
+ typename FormulaPolicy::template inverse<CT, false, true, false, false, false>;
+
+ using direct_distance_type =
+ typename FormulaPolicy::template direct<CT, true, false, false, false>;
CT const half_pi = math::pi<CT>() / CT(2);
- CT prev_distance;
geometry::formula::result_direct<CT> res14;
geometry::formula::result_inverse<CT> res34;
res34.distance = -1;
@@ -328,22 +335,25 @@ private :
bool dist_improve = true;
CT s14 = s14_start;
- do{
- prev_distance = res34.distance;
+ do {
+ auto prev_distance = res34.distance;
+ auto prev_res = res14;
// Solve the direct problem to find p4 (GEO)
res14 = direct_distance_type::apply(lon1, lat1, s14, a12, spheroid);
// Solve an inverse problem to find g4
- // g4 is the angle between segment (p1,p2) and segment (p3,p4) that meet on p4 (GEO)
+ // g4 is the angle between segment (p1,p2) and segment (p3,p4)
+ // that meet on p4 (GEO)
CT a4 = inverse_dist_azimuth_type::apply(res14.lon2, res14.lat2,
- lon2, lat2, spheroid).azimuth;
+ lon2, lat2, spheroid).azimuth;
res34 = inverse_distance_azimuth_quantities_type::apply(res14.lon2, res14.lat2,
lon3, lat3, spheroid);
g4 = res34.azimuth - a4;
- CT M43 = res34.geodesic_scale; // cos(s14/earth_radius) is the spherical limit
+ // cos(s14/earth_radius) is the spherical limit
+ CT M43 = res34.geodesic_scale;
CT m34 = res34.reduced_length;
if (m34 != 0)
@@ -353,12 +363,17 @@ private :
s14 -= der != 0 ? delta_g4 / der : 0;
}
- result.distance = res34.distance;
-
dist_improve = prev_distance > res34.distance || prev_distance == -1;
- if (!dist_improve)
+
+ if (dist_improve)
{
- result.distance = prev_distance;
+ set_result<EnableClosestPoint>::apply(res34.distance, res14.lon2, res14.lat2,
+ result);
+ }
+ else
+ {
+ set_result<EnableClosestPoint>::apply(prev_distance, prev_res.lon2, prev_res.lat2,
+ result);
}
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
@@ -368,12 +383,13 @@ private :
std::cout << "a4=" << a4 * math::r2d<CT>() << std::endl;
std::cout << "g4(normalized)=" << g4 * math::r2d<CT>() << std::endl;
std::cout << "delta_g4=" << delta_g4 * math::r2d<CT>() << std::endl;
- std::cout << "der=" << der << std::endl;
std::cout << "M43=" << M43 << std::endl;
std::cout << "m34=" << m34 << std::endl;
std::cout << "new_s14=" << s14 << std::endl;
- std::cout << std::setprecision(16) << "dist =" << res34.distance << std::endl;
- std::cout << "---------end of step " << counter << std::endl<< std::endl;
+ std::cout << std::setprecision(16) << "dist ="
+ << res34.distance << std::endl;
+ std::cout << "---------end of step " << counter
+ << std::endl<< std::endl;
if (g4 == half_pi)
{
std::cout << "Stop msg: g4 == half_pi" << std::endl;
@@ -400,24 +416,40 @@ private :
std::cout << "distance=" << res34.distance << std::endl;
std::cout << "s34(geo) ="
- << inverse_distance_azimuth_quantities_type::apply(res14.lon2, res14.lat2, lon3, lat3, spheroid).distance
- << ", p4=(" << res14.lon2 * math::r2d<double>() << ","
- << res14.lat2 * math::r2d<double>() << ")"
+ << inverse_distance_azimuth_quantities_type
+ ::apply(res14.lon2, res14.lat2,
+ lon3, lat3, spheroid).distance
+ << ", p4=(" << res14.lon2 * math::r2d<CT>() << ","
+ << res14.lat2 * math::r2d<CT>() << ")"
<< std::endl;
- CT s31 = inverse_distance_azimuth_quantities_type::apply(lon3, lat3, lon1, lat1, spheroid).distance;
- CT s32 = inverse_distance_azimuth_quantities_type::apply(lon3, lat3, lon2, lat2, spheroid).distance;
+ CT s31 = inverse_distance_azimuth_quantities_type::apply(lon3, lat3, lon1, lat1, spheroid)
+ .distance;
+ CT s32 = inverse_distance_azimuth_quantities_type::apply(lon3, lat3, lon2, lat2, spheroid)
+ .distance;
+
+ CT a4 = inverse_dist_azimuth_type::apply(res14.lon2, res14.lat2, lon2, lat2, spheroid)
+ .azimuth;
+
+ geometry::formula::result_direct<CT> res4 =
+ direct_distance_type::apply(res14.lon2, res14.lat2, .04, a4, spheroid);
- CT a4 = inverse_dist_azimuth_type::apply(res14.lon2, res14.lat2, lon2, lat2, spheroid).azimuth;
- geometry::formula::result_direct<CT> res4 = direct_distance_type::apply(res14.lon2, res14.lat2, .04, a4, spheroid);
- CT p4_plus = inverse_distance_azimuth_quantities_type::apply(res4.lon2, res4.lat2, lon3, lat3, spheroid).distance;
+ CT p4_plus = inverse_distance_azimuth_quantities_type::apply(res4.lon2, res4.lat2, lon3,
+ lat3, spheroid).distance;
- geometry::formula::result_direct<CT> res1 = direct_distance_type::apply(lon1, lat1, s14-.04, a12, spheroid);
- CT p4_minus = inverse_distance_azimuth_quantities_type::apply(res1.lon2, res1.lat2, lon3, lat3, spheroid).distance;
+ geometry::formula::result_direct<CT> res1 =
+ direct_distance_type::apply(lon1, lat1, s14-.04, a12, spheroid);
+
+ CT p4_minus = inverse_distance_azimuth_quantities_type::apply(res1.lon2, res1.lat2, lon3,
+ lat3, spheroid).distance;
std::cout << "s31=" << s31 << "\ns32=" << s32
- << "\np4_plus=" << p4_plus << ", p4=(" << res4.lon2 * math::r2d<double>() << "," << res4.lat2 * math::r2d<double>() << ")"
- << "\np4_minus=" << p4_minus << ", p4=(" << res1.lon2 * math::r2d<double>() << "," << res1.lat2 * math::r2d<double>() << ")"
+ << "\np4_plus=" << p4_plus << ", p4=("
+ << res4.lon2 * math::r2d<CT>() << ","
+ << res4.lat2 * math::r2d<CT>() << ")"
+ << "\np4_minus=" << p4_minus << ", p4=("
+ << res1.lon2 * math::r2d<CT>() << ","
+ << res1.lat2 * math::r2d<CT>() << ")"
<< std::endl;
if (res34.distance <= p4_plus && res34.distance <= p4_minus)
@@ -431,21 +463,59 @@ private :
#endif
}
- template <typename Units, typename CT>
- result_distance_point_segment<CT>
- static inline apply(CT const& lo1, CT const& la1, //p1
- CT const& lo2, CT const& la2, //p2
- CT const& lo3, CT const& la3, //query point p3
- Spheroid const& spheroid)
+
+ template <typename CT>
+ static inline auto non_iterative_case(CT const& , CT const& , //p1
+ CT const& lon2, CT const& lat2, //p2
+ CT const& distance)
{
- typedef typename FormulaPolicy::template inverse<CT, true, true, false, false, false>
- inverse_dist_azimuth_type;
- typedef typename FormulaPolicy::template inverse<CT, true, true, true, false, false>
- inverse_dist_azimuth_reverse_type;
+ result_type<CT> result;
+
+ set_result<EnableClosestPoint>::apply(distance, lon2, lat2, result);
+
+ return result;
+ }
+
+ template <typename CT>
+ static inline auto non_iterative_case(CT const& lon1, CT const& lat1, //p1
+ CT const& lon2, CT const& lat2, //p2
+ Spheroid const& spheroid)
+ {
+ CT distance = geometry::strategy::distance::geographic
+ <
+ FormulaPolicy,
+ Spheroid,
+ CT
+ >::apply(lon1, lat1, lon2, lat2, spheroid);
+
+ return non_iterative_case(lon1, lat1, lon2, lat2, distance);
+ }
+
+protected:
+
+ template <typename CT>
+ static inline auto apply(CT const& lo1, CT const& la1, //p1
+ CT const& lo2, CT const& la2, //p2
+ CT const& lo3, CT const& la3, //query point p3
+ Spheroid const& spheroid)
+ {
+ using inverse_dist_azimuth_type =
+ typename FormulaPolicy::template inverse<CT, true, true, false, false, false>;
+
+ using inverse_dist_azimuth_reverse_type =
+ typename FormulaPolicy::template inverse<CT, true, true, true, false, false>;
CT const earth_radius = geometry::formula::mean_radius<CT>(spheroid);
- result_distance_point_segment<CT> result;
+ result_type<CT> result;
+
+ // if the query points coincide with one of segments' endpoints
+ if ((lo1 == lo3 && la1 == la3) || (lo2 == lo3 && la2 == la3))
+ {
+ result.lon = lo3;
+ result.lat = la3;
+ return result;
+ }
// Constants
//CT const f = geometry::formula::flattening<CT>(spheroid);
@@ -481,17 +551,16 @@ private :
//but pass by the pole
CT diff = geometry::math::longitude_distance_signed<geometry::radian>(lon1, lon2);
- typedef typename formula::meridian_inverse<CT>
- meridian_inverse;
+ using meridian_inverse = typename formula::meridian_inverse<CT>;
bool meridian_not_crossing_pole =
- meridian_inverse::meridian_not_crossing_pole
- (lat1, lat2, diff);
+ meridian_inverse::meridian_not_crossing_pole(lat1, lat2, diff);
bool meridian_crossing_pole =
- meridian_inverse::meridian_crossing_pole(diff);
+ meridian_inverse::meridian_crossing_pole(diff);
- if (math::equals(lat1, c0) && math::equals(lat2, c0) && !meridian_crossing_pole)
+ if (math::equals(lat1, c0) && math::equals(lat2, c0)
+ && !meridian_crossing_pole)
{
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
std::cout << "Equatorial segment" << std::endl;
@@ -504,16 +573,17 @@ private :
#endif
if (lon3 <= lon1)
{
- return non_iterative_case(lon1, lat1, lon3, lat3, spheroid);
+ return non_iterative_case(lon3, lat3, lon1, lat1, spheroid);
}
if (lon3 >= lon2)
{
- return non_iterative_case(lon2, lat2, lon3, lat3, spheroid);
+ return non_iterative_case(lon3, lat3, lon2, lat2, spheroid);
}
- return non_iterative_case(lon3, lat1, lon3, lat3, spheroid);
+ return non_iterative_case(lon3, lat3, lon3, lat1, spheroid);
}
- if ( (meridian_not_crossing_pole || meridian_crossing_pole ) && std::abs(lat1) > std::abs(lat2))
+ if ( (meridian_not_crossing_pole || meridian_crossing_pole )
+ && std::abs(lat1) > std::abs(lat2))
{
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
std::cout << "Meridian segment not crossing pole" << std::endl;
@@ -527,40 +597,29 @@ private :
std::cout << "Meridian segment crossing pole" << std::endl;
#endif
CT sign_non_zero = lat3 >= c0 ? 1 : -1;
- result_distance_point_segment<CT> res13 =
- apply<geometry::radian>(lon1, lat1,
- lon1, half_pi * sign_non_zero,
- lon3, lat3, spheroid);
- result_distance_point_segment<CT> res23 =
- apply<geometry::radian>(lon2, lat2,
- lon2, half_pi * sign_non_zero,
- lon3, lat3, spheroid);
- if (res13.distance < res23.distance)
- {
- return res13;
- }
- else
- {
- return res23;
- }
+
+ auto res13 = apply(lon1, lat1, lon1, half_pi * sign_non_zero, lon3, lat3, spheroid);
+
+ auto res23 = apply(lon2, lat2, lon2, half_pi * sign_non_zero, lon3, lat3, spheroid);
+
+ return (res13.distance) < (res23.distance) ? res13 : res23;
}
- geometry::formula::result_inverse<CT> res12 =
- inverse_dist_azimuth_reverse_type::apply(lon1, lat1, lon2, lat2, spheroid);
- geometry::formula::result_inverse<CT> res13 =
- inverse_dist_azimuth_type::apply(lon1, lat1, lon3, lat3, spheroid);
+ auto res12 = inverse_dist_azimuth_reverse_type::apply(lon1, lat1, lon2, lat2, spheroid);
+
+ auto res13 = inverse_dist_azimuth_type::apply(lon1, lat1, lon3, lat3, spheroid);
if (geometry::math::equals(res12.distance, c0))
{
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
std::cout << "Degenerate segment" << std::endl;
- std::cout << "distance between points=" << res13.distance << std::endl;
+ std::cout << "distance between points="
+ << res13.distance << std::endl;
#endif
- typename meridian_inverse::result res =
- meridian_inverse::apply(lon1, lat1, lon3, lat3, spheroid);
+ auto res = meridian_inverse::apply(lon1, lat1, lon3, lat3, spheroid);
- return non_iterative_case(lon1, lat2,
- res.meridian ? res.distance : res13.distance);
+ return non_iterative_case(lon3, lat3, lon1, lat2,
+ res.meridian ? res.distance : res13.distance);
}
// Compute a12 (GEO)
@@ -569,14 +628,15 @@ private :
// TODO: meridian case optimization
if (geometry::math::equals(a312, c0) && meridian_not_crossing_pole)
{
- boost::tuple<CT,CT> minmax_elem = boost::minmax(lat1, lat2);
- if (lat3 >= minmax_elem.template get<0>() &&
- lat3 <= minmax_elem.template get<1>())
+ auto const minmax_elem = std::minmax(lat1, lat2);
+
+ if (lat3 >= std::get<0>(minmax_elem) &&
+ lat3 <= std::get<1>(minmax_elem))
{
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
std::cout << "Point on meridian segment" << std::endl;
#endif
- return non_iterative_case(lon3, lat3, c0);
+ return non_iterative_case(lon3, lat3, lon3, lat3, c0);
}
}
@@ -598,17 +658,17 @@ private :
// projection of p3 on geodesic spanned by segment (p1,p2) fall
// outside of segment on the side of p1
- return non_iterative_case(lon1, lat1, lon3, lat3, spheroid);
+ return non_iterative_case(lon3, lat3, lon1, lat1, spheroid);
}
- geometry::formula::result_inverse<CT> res23 =
- inverse_dist_azimuth_type::apply(lon2, lat2, lon3, lat3, spheroid);
+ auto res23 = inverse_dist_azimuth_type::apply(lon2, lat2, lon3, lat3, spheroid);
CT a321 = res23.azimuth - res12.reverse_azimuth + pi;
CT projection2 = cos( a321 ) * res23.distance / res12.distance;
#ifdef BOOST_GEOMETRY_DEBUG_GEOGRAPHIC_CROSS_TRACK
- std::cout << "a21=" << res12.reverse_azimuth * math::r2d<CT>() << std::endl;
+ std::cout << "a21=" << res12.reverse_azimuth * math::r2d<CT>()
+ << std::endl;
std::cout << "a23=" << res23.azimuth * math::r2d<CT>() << std::endl;
std::cout << "a321=" << a321 * math::r2d<CT>() << std::endl;
std::cout << "cos(a321)=" << cos(a321) << std::endl;
@@ -622,15 +682,16 @@ private :
#endif
// projection of p3 on geodesic spanned by segment (p1,p2) fall
// outside of segment on the side of p2
- return non_iterative_case(lon2, lat2, lon3, lat3, spheroid);
+ return non_iterative_case(lon3, lat3, lon2, lat2, spheroid);
}
// Guess s14 (SPHERICAL) aka along-track distance
- typedef geometry::model::point
- <
- CT, 2,
- geometry::cs::spherical_equatorial<geometry::radian>
- > point;
+ using point = geometry::model::point
+ <
+ CT,
+ 2,
+ geometry::cs::spherical_equatorial<geometry::radian>
+ >;
point p1 = point(lon1, lat1);
point p2 = point(lon2, lat2);
@@ -645,14 +706,13 @@ private :
//CT s14 = acos( cos(s13/earth_radius) / cos(s34/earth_radius) ) * earth_radius;
CT cos_frac = cos(s13_sph / earth_radius) / cos(s34_sph / earth_radius);
CT s14_sph = cos_frac >= 1 ? CT(0)
- : cos_frac <= -1 ? pi * earth_radius
- : acos(cos_frac) * earth_radius;
+ : cos_frac <= -1 ? pi * earth_radius
+ : acos(cos_frac) * earth_radius;
- CT a12_sph = geometry::formula::spherical_azimuth<>(lon1, lat1, lon2, lat2);
+ CT const a12_sph = geometry::formula::spherical_azimuth<>(lon1, lat1, lon2, lat2);
- geometry::formula::result_direct<CT> res
- = geometry::formula::spherical_direct<true, false>
- (lon1, lat1, s14_sph, a12_sph, srs::sphere<CT>(earth_radius));
+ auto res = geometry::formula::spherical_direct<true, false>(lon1, lat1,
+ s14_sph, a12_sph, srs::sphere<CT>(earth_radius));
// this is what postgis (version 2.5) returns
// geometry::strategy::distance::geographic<FormulaPolicy, Spheroid, CT>
@@ -669,16 +729,19 @@ private :
if (Bisection)
{
- bisection<CT>(lon1, lat1, lon2, lat2, lon3, lat3,
- spheroid, res12.distance/2, res12.azimuth, result);
+ bisection(lon1, lat1, lon2, lat2, lon3, lat3, spheroid,
+ res12.distance/2, res12.azimuth, result);
}
else
{
- CT s14_start = geometry::strategy::distance::geographic<FormulaPolicy, Spheroid, CT>
- ::apply(lon1, lat1, res.lon2, res.lat2, spheroid);
+ CT s14_start = geometry::strategy::distance::geographic
+ <
+ FormulaPolicy,
+ Spheroid,
+ CT
+ >::apply(lon1, lat1, res.lon2, res.lat2, spheroid);
- newton<CT>(lon1, lat1, lon2, lat2, lon3, lat3,
- spheroid, s14_start, res12.azimuth, result);
+ newton(lon1, lat1, lon2, lat2, lon3, lat3, spheroid, s14_start, res12.azimuth, result);
}
return result;
@@ -705,18 +768,19 @@ class geographic_cross_track
false
>
{
+ using base_t = detail::geographic_cross_track
+ <
+ FormulaPolicy,
+ Spheroid,
+ CalculationType,
+ false,
+ false
+ >;
+
public :
explicit geographic_cross_track(Spheroid const& spheroid = Spheroid())
- :
- detail::geographic_cross_track<
- FormulaPolicy,
- Spheroid,
- CalculationType,
- false,
- false
- >(spheroid)
+ : base_t(spheroid)
{}
-
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
diff --git a/boost/geometry/strategies/geographic/distance_segment_box.hpp b/boost/geometry/strategies/geographic/distance_segment_box.hpp
index 3b076b72dc..552bfcdbe3 100644
--- a/boost/geometry/strategies/geographic/distance_segment_box.hpp
+++ b/boost/geometry/strategies/geographic/distance_segment_box.hpp
@@ -13,6 +13,8 @@
#include <boost/geometry/srs/spheroid.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
+
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
#include <boost/geometry/strategies/distance.hpp>
@@ -26,7 +28,6 @@
#include <boost/geometry/strategies/spherical/distance_segment_box.hpp>
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
namespace boost { namespace geometry
diff --git a/boost/geometry/strategies/geographic/intersection.hpp b/boost/geometry/strategies/geographic/intersection.hpp
index 179ac66366..e6a94a15e3 100644
--- a/boost/geometry/strategies/geographic/intersection.hpp
+++ b/boost/geometry/strategies/geographic/intersection.hpp
@@ -215,7 +215,7 @@ private:
: Policy::disjoint()
;
}
-
+
calc_t const a1_lon = get_as_radian<0>(a1);
calc_t const a1_lat = get_as_radian<1>(a1);
calc_t const a2_lon = get_as_radian<0>(a2);
@@ -315,7 +315,7 @@ private:
// NOTE: at this point the segments may still be disjoint
// NOTE: at this point one of the segments may be degenerated
- bool collinear = sides.collinear();
+ bool collinear = sides.collinear();
if (! collinear)
{
@@ -525,7 +525,7 @@ private:
// distance for ratio
dist_1_o = dist_1_2 - dist_1_o;
}
-
+
return Policy::one_degenerate(segment, segment_ratio<CalcT>(dist_1_o, dist_1_2), degenerated_a);
}
@@ -764,7 +764,7 @@ private:
{
return false;
}
-
+
typedef typename FormulaPolicy::template inverse<CalcT, true, false, false, false, false> inverse_dist;
ip_flag = ipi_inters;
@@ -801,7 +801,7 @@ private:
dist_a1_ip = res_a1_a2.distance;
dist_b1_ip = inverse_dist::apply(b1_lon, b1_lat, lon, lat, spheroid).distance; // for consistency
ip_flag = ipi_at_a2;
- }
+ }
return true;
}
diff --git a/boost/geometry/strategies/geographic/intersection_elliptic.hpp b/boost/geometry/strategies/geographic/intersection_elliptic.hpp
index fce9735255..c7aaf8aa8f 100644
--- a/boost/geometry/strategies/geographic/intersection_elliptic.hpp
+++ b/boost/geometry/strategies/geographic/intersection_elliptic.hpp
@@ -167,7 +167,7 @@ struct experimental_elliptic_segments_calc_policy
Point3d const v1 = normalized_vec(p1);
Point3d const v2 = normalized_vec(p2);
-
+
is_forward = dot_product(normal, cross_product(v1, v2)) >= c0;
return dot_product(v1, v2);
}
diff --git a/boost/geometry/strategies/geographic/mapping_ssf.hpp b/boost/geometry/strategies/geographic/mapping_ssf.hpp
index 20a0523616..57fd985a9c 100644
--- a/boost/geometry/strategies/geographic/mapping_ssf.hpp
+++ b/boost/geometry/strategies/geographic/mapping_ssf.hpp
@@ -17,10 +17,10 @@
#include <boost/core/ignore_unused.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
#include <boost/geometry/core/radius.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/strategies/side.hpp>
diff --git a/boost/geometry/strategies/geographic/side.hpp b/boost/geometry/strategies/geographic/side.hpp
index f9a6b23ab9..a0b4abc815 100644
--- a/boost/geometry/strategies/geographic/side.hpp
+++ b/boost/geometry/strategies/geographic/side.hpp
@@ -16,6 +16,7 @@
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/radius.hpp>
@@ -32,7 +33,6 @@
#include <boost/geometry/strategy/geographic/envelope.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
namespace boost { namespace geometry
diff --git a/boost/geometry/strategies/index/services.hpp b/boost/geometry/strategies/index/services.hpp
index f256a3ac31..635a8523d7 100644
--- a/boost/geometry/strategies/index/services.hpp
+++ b/boost/geometry/strategies/index/services.hpp
@@ -17,7 +17,7 @@
namespace boost { namespace geometry
{
-
+
namespace strategies { namespace index { namespace services
{
diff --git a/boost/geometry/strategies/intersection_result.hpp b/boost/geometry/strategies/intersection_result.hpp
index 4b5aa1c46b..94aae51d8e 100644
--- a/boost/geometry/strategies/intersection_result.hpp
+++ b/boost/geometry/strategies/intersection_result.hpp
@@ -2,8 +2,8 @@
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2015, 2016.
-// Modifications copyright (c) 2015-2016 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2015-2021.
+// Modifications copyright (c) 2015-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -15,9 +15,9 @@
#include <cstddef>
+#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/policies/robustness/segment_ratio.hpp>
-
namespace boost { namespace geometry
{
diff --git a/boost/geometry/strategies/intersection_strategies.hpp b/boost/geometry/strategies/intersection_strategies.hpp
index bba6545c99..e9a17305af 100644
--- a/boost/geometry/strategies/intersection_strategies.hpp
+++ b/boost/geometry/strategies/intersection_strategies.hpp
@@ -22,9 +22,7 @@
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/intersection_result.hpp>
#include <boost/geometry/strategies/side.hpp>
-
#include <boost/geometry/strategies/cartesian/intersection.hpp>
-#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/spherical/intersection.hpp>
#include <boost/geometry/strategies/spherical/ssf.hpp>
diff --git a/boost/geometry/strategies/is_convex/cartesian.hpp b/boost/geometry/strategies/is_convex/cartesian.hpp
index 4297c223b5..c6c340fbdc 100644
--- a/boost/geometry/strategies/is_convex/cartesian.hpp
+++ b/boost/geometry/strategies/is_convex/cartesian.hpp
@@ -11,12 +11,11 @@
#define BOOST_GEOMETRY_STRATEGIES_IS_CONVEX_CARTESIAN_HPP
-#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
-#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/convex_hull/cartesian.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/is_convex/services.hpp>
-#include <boost/geometry/util/type_traits.hpp>
+#include <boost/geometry/strategy/cartesian/side_by_triangle.hpp>
+#include <boost/geometry/strategy/cartesian/side_robust.hpp>
namespace boost { namespace geometry
@@ -25,21 +24,10 @@ namespace boost { namespace geometry
namespace strategies { namespace is_convex
{
+
template <typename CalculationType = void>
-class cartesian : public strategies::convex_hull::cartesian<CalculationType>
-{
-public:
- template <typename Geometry1, typename Geometry2>
- static auto relate(Geometry1 const&, Geometry2 const&,
- std::enable_if_t
- <
- util::is_pointlike<Geometry1>::value
- && util::is_pointlike<Geometry2>::value
- > * = nullptr)
- {
- return strategy::within::cartesian_point_point();
- }
-};
+using cartesian = strategies::convex_hull::cartesian<CalculationType>;
+
namespace services
{
diff --git a/boost/geometry/strategies/is_convex/geographic.hpp b/boost/geometry/strategies/is_convex/geographic.hpp
index 66660138fa..dd27c981a7 100644
--- a/boost/geometry/strategies/is_convex/geographic.hpp
+++ b/boost/geometry/strategies/is_convex/geographic.hpp
@@ -14,8 +14,6 @@
#include <boost/geometry/strategies/convex_hull/geographic.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/is_convex/services.hpp>
-#include <boost/geometry/strategies/spherical/point_in_point.hpp>
-#include <boost/geometry/util/type_traits.hpp>
namespace boost { namespace geometry
@@ -24,34 +22,15 @@ namespace boost { namespace geometry
namespace strategies { namespace is_convex
{
+
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
-class geographic : public strategies::convex_hull::geographic<FormulaPolicy, Spheroid, CalculationType>
-{
- using base_t = strategies::convex_hull::geographic<FormulaPolicy, Spheroid, CalculationType>;
-
-public:
- geographic() = default;
-
- explicit geographic(Spheroid const& spheroid)
- : base_t(spheroid)
- {}
-
- template <typename Geometry1, typename Geometry2>
- static auto relate(Geometry1 const&, Geometry2 const&,
- std::enable_if_t
- <
- util::is_pointlike<Geometry1>::value
- && util::is_pointlike<Geometry2>::value
- > * = nullptr)
- {
- return strategy::within::spherical_point_point();
- }
-};
+using geographic = strategies::convex_hull::geographic<FormulaPolicy, Spheroid, CalculationType>;
+
namespace services
{
diff --git a/boost/geometry/strategies/is_convex/spherical.hpp b/boost/geometry/strategies/is_convex/spherical.hpp
index 06ff3fae8c..c6e97d16d8 100644
--- a/boost/geometry/strategies/is_convex/spherical.hpp
+++ b/boost/geometry/strategies/is_convex/spherical.hpp
@@ -14,8 +14,6 @@
#include <boost/geometry/strategies/convex_hull/spherical.hpp>
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategies/is_convex/services.hpp>
-#include <boost/geometry/strategies/spherical/point_in_point.hpp>
-#include <boost/geometry/util/type_traits.hpp>
namespace boost { namespace geometry
@@ -24,21 +22,10 @@ namespace boost { namespace geometry
namespace strategies { namespace is_convex
{
+
template <typename CalculationType = void>
-class spherical : public strategies::convex_hull::spherical<CalculationType>
-{
-public:
- template <typename Geometry1, typename Geometry2>
- static auto relate(Geometry1 const&, Geometry2 const&,
- std::enable_if_t
- <
- util::is_pointlike<Geometry1>::value
- && util::is_pointlike<Geometry2>::value
- > * = nullptr)
- {
- return strategy::within::spherical_point_point();
- }
-};
+using spherical = strategies::convex_hull::spherical<CalculationType>;
+
namespace services
{
diff --git a/boost/geometry/strategies/relate/cartesian.hpp b/boost/geometry/strategies/relate/cartesian.hpp
index 532e75368c..2b8a9e13a3 100644
--- a/boost/geometry/strategies/relate/cartesian.hpp
+++ b/boost/geometry/strategies/relate/cartesian.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry
-// Copyright (c) 2020, Oracle and/or its affiliates.
+// Copyright (c) 2020-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
@@ -26,6 +27,8 @@
#include <boost/geometry/strategies/detail.hpp>
#include <boost/geometry/strategy/cartesian/area.hpp>
+#include <boost/geometry/strategy/cartesian/side_robust.hpp>
+#include <boost/geometry/strategy/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategy/cartesian/area_box.hpp>
#include <boost/geometry/util/type_traits.hpp>
@@ -156,7 +159,10 @@ public:
static auto side()
{
- return strategy::side::side_by_triangle<CalculationType>();
+ using side_strategy_type
+ = typename strategy::side::services::default_strategy
+ <cartesian_tag, CalculationType>::type;
+ return side_strategy_type();
}
// within
@@ -182,6 +188,14 @@ public:
{
return strategy::within::cartesian_box_box();
}
+
+ template <typename ComparePolicy, typename EqualsPolicy>
+ using compare_type = typename strategy::compare::cartesian
+ <
+ ComparePolicy,
+ EqualsPolicy,
+ -1
+ >;
};
@@ -381,6 +395,15 @@ struct strategy_converter<strategy::side::side_by_triangle<CalculationType>>
}
};
+template <typename CalculationType>
+struct strategy_converter<strategy::side::side_robust<CalculationType>>
+{
+ static auto get(strategy::side::side_robust<CalculationType> const&)
+ {
+ return strategies::relate::cartesian<CalculationType>();
+ }
+};
+
} // namespace services
diff --git a/boost/geometry/strategies/relate/geographic.hpp b/boost/geometry/strategies/relate/geographic.hpp
index 60c6b9e585..b756f1a16c 100644
--- a/boost/geometry/strategies/relate/geographic.hpp
+++ b/boost/geometry/strategies/relate/geographic.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry
-// Copyright (c) 2020-2021, Oracle and/or its affiliates.
+// Copyright (c) 2020-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
@@ -13,6 +14,7 @@
// TEMP - move to strategy
#include <boost/geometry/strategies/agnostic/point_in_box_by_side.hpp>
+#include <boost/geometry/strategies/cartesian/box_in_box.hpp>
#include <boost/geometry/strategies/geographic/intersection.hpp>
#include <boost/geometry/strategies/geographic/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
@@ -208,6 +210,14 @@ public:
{
return strategy::within::spherical_box_box();
}
+
+ template <typename ComparePolicy, typename EqualsPolicy>
+ using compare_type = typename strategy::compare::spherical
+ <
+ ComparePolicy,
+ EqualsPolicy,
+ -1
+ >;
};
@@ -279,6 +289,14 @@ struct strategy_converter<strategy::intersection::geographic_segments<FormulaPol
FormulaPolicy, SeriesOrder, Spheroid, CalculationType
>(base_t::m_spheroid);
}
+
+ template <typename ComparePolicy, typename EqualsPolicy>
+ using compare_type = typename strategy::compare::spherical
+ <
+ ComparePolicy,
+ EqualsPolicy,
+ -1
+ >;
};
static auto get(strategy::intersection::geographic_segments<FormulaPolicy, SeriesOrder, Spheroid, CalculationType> const& s)
diff --git a/boost/geometry/strategies/relate/spherical.hpp b/boost/geometry/strategies/relate/spherical.hpp
index cfdec10242..7914831fef 100644
--- a/boost/geometry/strategies/relate/spherical.hpp
+++ b/boost/geometry/strategies/relate/spherical.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry
-// Copyright (c) 2020-2021, Oracle and/or its affiliates.
+// Copyright (c) 2020-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
@@ -193,6 +194,14 @@ public:
{
return strategy::within::spherical_box_box();
}
+
+ template <typename ComparePolicy, typename EqualsPolicy>
+ using compare_type = typename strategy::compare::spherical
+ <
+ ComparePolicy,
+ EqualsPolicy,
+ -1
+ >;
};
diff --git a/boost/geometry/strategies/simplify/spherical.hpp b/boost/geometry/strategies/simplify/spherical.hpp
index 0858087f38..4ff51b38cb 100644
--- a/boost/geometry/strategies/simplify/spherical.hpp
+++ b/boost/geometry/strategies/simplify/spherical.hpp
@@ -12,6 +12,7 @@
#include <boost/geometry/strategies/detail.hpp>
+#include <boost/geometry/strategies/distance/comparable.hpp>
#include <boost/geometry/strategies/distance/detail.hpp>
#include <boost/geometry/strategies/simplify/services.hpp>
diff --git a/boost/geometry/strategies/spherical.hpp b/boost/geometry/strategies/spherical.hpp
index f7d6484b2f..0fed07e5ba 100644
--- a/boost/geometry/strategies/spherical.hpp
+++ b/boost/geometry/strategies/spherical.hpp
@@ -28,7 +28,7 @@
namespace boost { namespace geometry
{
-
+
namespace strategies
{
diff --git a/boost/geometry/strategies/spherical/closest_points_pt_seg.hpp b/boost/geometry/strategies/spherical/closest_points_pt_seg.hpp
new file mode 100644
index 0000000000..aff36314da
--- /dev/null
+++ b/boost/geometry/strategies/spherical/closest_points_pt_seg.hpp
@@ -0,0 +1,200 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_CLOSEST_POINTS_CROSS_TRACK_HPP
+#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_CLOSEST_POINTS_CROSS_TRACK_HPP
+
+#include <algorithm>
+#include <type_traits>
+
+#include <boost/config.hpp>
+#include <boost/concept_check.hpp>
+
+#include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
+#include <boost/geometry/core/radian_access.hpp>
+#include <boost/geometry/core/tags.hpp>
+
+#include <boost/geometry/formulas/spherical.hpp>
+
+#include <boost/geometry/strategies/distance.hpp>
+#include <boost/geometry/strategies/concepts/distance_concept.hpp>
+#include <boost/geometry/strategies/spherical/distance_haversine.hpp>
+#include <boost/geometry/strategies/spherical/distance_cross_track.hpp>
+#include <boost/geometry/strategies/spherical/point_in_point.hpp>
+#include <boost/geometry/strategies/spherical/intersection.hpp>
+
+#include <boost/geometry/util/math.hpp>
+#include <boost/geometry/util/select_calculation_type.hpp>
+
+#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
+# include <boost/geometry/io/dsv/write.hpp>
+#endif
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace closest_points
+{
+
+template
+<
+ typename CalculationType = void,
+ typename Strategy = distance::comparable::haversine<double, CalculationType>
+>
+class cross_track
+{
+public:
+ template <typename Point, typename PointOfSegment>
+ struct calculation_type
+ : promote_floating_point
+ <
+ typename select_calculation_type
+ <
+ Point,
+ PointOfSegment,
+ CalculationType
+ >::type
+ >
+ {};
+
+ using radius_type = typename Strategy::radius_type;
+
+ cross_track() = default;
+
+ explicit inline cross_track(typename Strategy::radius_type const& r)
+ : m_strategy(r)
+ {}
+
+ inline cross_track(Strategy const& s)
+ : m_strategy(s)
+ {}
+
+ template <typename Point, typename PointOfSegment>
+ inline auto apply(Point const& p,
+ PointOfSegment const& sp1,
+ PointOfSegment const& sp2) const
+ {
+ using CT = typename calculation_type<Point, PointOfSegment>::type;
+
+ // http://williams.best.vwh.net/avform.htm#XTE
+ CT d3 = m_strategy.apply(sp1, sp2);
+
+ if (geometry::math::equals(d3, 0.0))
+ {
+ // "Degenerate" segment, return either d1 or d2
+ return sp1;
+ }
+
+ CT d1 = m_strategy.apply(sp1, p);
+ CT d2 = m_strategy.apply(sp2, p);
+
+ auto d_crs_pair = distance::detail::compute_cross_track_pair<CT>::apply(
+ p, sp1, sp2);
+
+ // d1, d2, d3 are in principle not needed, only the sign matters
+ CT projection1 = cos(d_crs_pair.first) * d1 / d3;
+ CT projection2 = cos(d_crs_pair.second) * d2 / d3;
+
+#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
+ std::cout << "Course " << dsv(sp1) << " to " << dsv(p) << " "
+ << crs_AD * geometry::math::r2d<CT>() << std::endl;
+ std::cout << "Course " << dsv(sp1) << " to " << dsv(sp2) << " "
+ << crs_AB * geometry::math::r2d<CT>() << std::endl;
+ std::cout << "Course " << dsv(sp2) << " to " << dsv(sp1) << " "
+ << crs_BA * geometry::math::r2d<CT>() << std::endl;
+ std::cout << "Course " << dsv(sp2) << " to " << dsv(p) << " "
+ << crs_BD * geometry::math::r2d<CT>() << std::endl;
+ std::cout << "Projection AD-AB " << projection1 << " : "
+ << d_crs1 * geometry::math::r2d<CT>() << std::endl;
+ std::cout << "Projection BD-BA " << projection2 << " : "
+ << d_crs2 * geometry::math::r2d<CT>() << std::endl;
+ std::cout << " d1: " << (d1 )
+ << " d2: " << (d2 )
+ << std::endl;
+#endif
+
+ if (projection1 > 0.0 && projection2 > 0.0)
+ {
+#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
+ CT XTD = radius() * geometry::math::abs( asin( sin( d1 ) * sin( d_crs1 ) ));
+
+ std::cout << "Projection ON the segment" << std::endl;
+ std::cout << "XTD: " << XTD
+ << " d1: " << (d1 * radius())
+ << " d2: " << (d2 * radius())
+ << std::endl;
+#endif
+ auto distance = distance::detail::compute_cross_track_distance::apply(
+ d_crs_pair.first, d1);
+
+ CT lon1 = geometry::get_as_radian<0>(sp1);
+ CT lat1 = geometry::get_as_radian<1>(sp1);
+ CT lon2 = geometry::get_as_radian<0>(sp2);
+ CT lat2 = geometry::get_as_radian<1>(sp2);
+
+ CT dist = CT(2) * asin(math::sqrt(distance)) * m_strategy.radius();
+ CT dist_d1 = CT(2) * asin(math::sqrt(d1)) * m_strategy.radius();
+
+ // Note: this is similar to spherical computation in geographic
+ // point_segment_distance formula
+ CT earth_radius = m_strategy.radius();
+ CT cos_frac = cos(dist_d1 / earth_radius) / cos(dist / earth_radius);
+ CT s14_sph = cos_frac >= 1
+ ? CT(0) : cos_frac <= -1 ? math::pi<CT>() * earth_radius
+ : acos(cos_frac) * earth_radius;
+
+ CT a12 = geometry::formula::spherical_azimuth<>(lon1, lat1, lon2, lat2);
+ auto res_direct = geometry::formula::spherical_direct
+ <
+ true,
+ false
+ >(lon1, lat1, s14_sph, a12, srs::sphere<CT>(earth_radius));
+
+ model::point
+ <
+ CT,
+ dimension<PointOfSegment>::value,
+ typename coordinate_system<PointOfSegment>::type
+ > cp;
+
+ geometry::set_from_radian<0>(cp, res_direct.lon2);
+ geometry::set_from_radian<1>(cp, res_direct.lat2);
+
+ return cp;
+ }
+ else
+ {
+#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
+ std::cout << "Projection OUTSIDE the segment" << std::endl;
+#endif
+ return d1 < d2 ? sp1 : sp2;
+ }
+ }
+
+ template <typename T1, typename T2>
+ inline radius_type vertical_or_meridian(T1 lat1, T2 lat2) const
+ {
+ return m_strategy.radius() * (lat1 - lat2);
+ }
+
+ inline typename Strategy::radius_type radius() const
+ { return m_strategy.radius(); }
+
+private :
+ Strategy m_strategy;
+};
+
+}} // namespace strategy::closest_points
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_CLOSEST_POINTS_CROSS_TRACK_HPP
diff --git a/boost/geometry/strategies/spherical/compare.hpp b/boost/geometry/strategies/spherical/compare.hpp
index dc804acc0f..dc3d14bef8 100644
--- a/boost/geometry/strategies/spherical/compare.hpp
+++ b/boost/geometry/strategies/spherical/compare.hpp
@@ -2,9 +2,10 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2017-2020.
-// Modifications copyright (c) 2017-2020, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2017-2023.
+// Modifications copyright (c) 2017-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
@@ -60,6 +61,7 @@ get(P const& p, std::false_type /*different units*/)
template
<
typename ComparePolicy,
+ typename EqualsPolicy,
typename Point1,
typename Point2,
std::size_t DimensionCount
@@ -77,11 +79,11 @@ struct spherical_latitude
T1 const& l1, T2 const& r1)
{
// latitudes equal
- if (math::equals(l1, r1))
+ if (EqualsPolicy::apply(l1, r1))
{
return compare::detail::compare_loop
<
- ComparePolicy, 2, DimensionCount
+ ComparePolicy, EqualsPolicy, 2, DimensionCount
>::apply(left, right);
}
else
@@ -102,10 +104,11 @@ struct spherical_latitude
template
<
typename ComparePolicy,
+ typename EqualsPolicy,
typename Point1,
typename Point2
>
-struct spherical_latitude<ComparePolicy, Point1, Point2, 1>
+struct spherical_latitude<ComparePolicy, EqualsPolicy, Point1, Point2, 1>
{
template <typename T1, typename T2>
static inline bool apply(Point1 const& left, Point2 const& right,
@@ -118,7 +121,7 @@ struct spherical_latitude<ComparePolicy, Point1, Point2, 1>
{
return compare::detail::compare_loop
<
- ComparePolicy, 1, 1
+ ComparePolicy, EqualsPolicy, 1, 1
>::apply(left, right);
}
};
@@ -126,6 +129,7 @@ struct spherical_latitude<ComparePolicy, Point1, Point2, 1>
template
<
typename ComparePolicy,
+ typename EqualsPolicy,
typename Point1,
typename Point2,
std::size_t DimensionCount
@@ -165,18 +169,18 @@ struct spherical_longitude
bool is_left_at_antimeridian = false;
bool is_right_at_antimeridian = false;
-
+
// longitudes equal
- if (math::equals(l0, r0)
+ if (EqualsPolicy::apply(l0, r0)
// both at antimeridian
|| are_both_at_antimeridian(l0, r0, is_left_at_antimeridian, is_right_at_antimeridian)
// both at pole
- || (math::equals(l1, r1)
+ || (EqualsPolicy::apply(l1, r1)
&& math::is_latitude_pole<units_type, is_equatorial>(l1)))
{
return spherical_latitude
<
- ComparePolicy, Point1, Point2, DimensionCount
+ ComparePolicy, EqualsPolicy, Point1, Point2, DimensionCount
>::apply(left, right, l1, r1);
}
// if left is at antimeridian and right is not at antimeridian
@@ -214,16 +218,17 @@ struct spherical_longitude
template
<
typename ComparePolicy,
+ typename EqualsPolicy,
int Dimension = -1
>
struct spherical
- : cartesian<ComparePolicy, Dimension>
+ : cartesian<ComparePolicy, EqualsPolicy, Dimension>
{};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
// all dimensions starting from longitude
-template <typename ComparePolicy>
-struct spherical<ComparePolicy, -1>
+template <typename ComparePolicy, typename EqualsPolicy>
+struct spherical<ComparePolicy, EqualsPolicy, -1>
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& left, Point2 const& right)
@@ -231,6 +236,7 @@ struct spherical<ComparePolicy, -1>
return compare::detail::spherical_longitude
<
ComparePolicy,
+ EqualsPolicy,
Point1,
Point2,
std::conditional_t
@@ -244,29 +250,29 @@ struct spherical<ComparePolicy, -1>
};
// only longitudes (and latitudes to check poles)
-template <typename ComparePolicy>
-struct spherical<ComparePolicy, 0>
+template <typename ComparePolicy, typename EqualsPolicy>
+struct spherical<ComparePolicy, EqualsPolicy, 0>
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& left, Point2 const& right)
{
return compare::detail::spherical_longitude
<
- ComparePolicy, Point1, Point2, 1
+ ComparePolicy, EqualsPolicy, Point1, Point2, 1
>::apply(left, right);
}
};
// only latitudes
-template <typename ComparePolicy>
-struct spherical<ComparePolicy, 1>
+template <typename ComparePolicy, typename EqualsPolicy>
+struct spherical<ComparePolicy, EqualsPolicy, 1>
{
template <typename Point1, typename Point2>
static inline bool apply(Point1 const& left, Point2 const& right)
{
return compare::detail::spherical_latitude
<
- ComparePolicy, Point1, Point2, 2
+ ComparePolicy, EqualsPolicy, Point1, Point2, 2
>::apply(left, right);
}
};
@@ -278,44 +284,48 @@ namespace services
{
-template <typename ComparePolicy, typename Point1, typename Point2, int Dimension>
+template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
struct default_strategy
<
- ComparePolicy, Point1, Point2, Dimension,
+ ComparePolicy, EqualsPolicy,
+ Point1, Point2, Dimension,
spherical_tag, spherical_tag
>
{
- typedef compare::spherical<ComparePolicy, Dimension> type;
+ typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
};
-template <typename ComparePolicy, typename Point1, typename Point2, int Dimension>
+template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
struct default_strategy
<
- ComparePolicy, Point1, Point2, Dimension,
+ ComparePolicy, EqualsPolicy,
+ Point1, Point2, Dimension,
spherical_polar_tag, spherical_polar_tag
>
{
- typedef compare::spherical<ComparePolicy, Dimension> type;
+ typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
};
-template <typename ComparePolicy, typename Point1, typename Point2, int Dimension>
+template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
struct default_strategy
<
- ComparePolicy, Point1, Point2, Dimension,
+ ComparePolicy, EqualsPolicy,
+ Point1, Point2, Dimension,
spherical_equatorial_tag, spherical_equatorial_tag
>
{
- typedef compare::spherical<ComparePolicy, Dimension> type;
+ typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
};
-template <typename ComparePolicy, typename Point1, typename Point2, int Dimension>
+template <typename ComparePolicy, typename EqualsPolicy, typename Point1, typename Point2, int Dimension>
struct default_strategy
<
- ComparePolicy, Point1, Point2, Dimension,
+ ComparePolicy, EqualsPolicy,
+ Point1, Point2, Dimension,
geographic_tag, geographic_tag
>
{
- typedef compare::spherical<ComparePolicy, Dimension> type;
+ typedef compare::spherical<ComparePolicy, EqualsPolicy, Dimension> type;
};
diff --git a/boost/geometry/strategies/spherical/distance_cross_track.hpp b/boost/geometry/strategies/spherical/distance_cross_track.hpp
index f543a01c58..d9af409885 100644
--- a/boost/geometry/strategies/spherical/distance_cross_track.hpp
+++ b/boost/geometry/strategies/spherical/distance_cross_track.hpp
@@ -24,6 +24,7 @@
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -36,7 +37,6 @@
#include <boost/geometry/strategies/spherical/intersection.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
@@ -50,6 +50,82 @@ namespace boost { namespace geometry
namespace strategy { namespace distance
{
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+ template <typename CalculationType>
+ struct compute_cross_track_pair
+ {
+ template <typename Point, typename PointOfSegment>
+ static inline auto apply(Point const& p,
+ PointOfSegment const& sp1,
+ PointOfSegment const& sp2)
+ {
+ CalculationType lon1 = geometry::get_as_radian<0>(sp1);
+ CalculationType lat1 = geometry::get_as_radian<1>(sp1);
+ CalculationType lon2 = geometry::get_as_radian<0>(sp2);
+ CalculationType lat2 = geometry::get_as_radian<1>(sp2);
+ CalculationType lon = geometry::get_as_radian<0>(p);
+ CalculationType lat = geometry::get_as_radian<1>(p);
+
+ CalculationType const crs_AD = geometry::formula::spherical_azimuth
+ <
+ CalculationType,
+ false
+ >(lon1, lat1, lon, lat).azimuth;
+
+ auto result = geometry::formula::spherical_azimuth
+ <
+ CalculationType,
+ true
+ >(lon1, lat1, lon2, lat2);
+
+ CalculationType crs_AB = result.azimuth;
+ CalculationType crs_BA = result.reverse_azimuth -
+ geometry::math::pi<CalculationType>();
+
+ CalculationType crs_BD = geometry::formula::spherical_azimuth
+ <
+ CalculationType,
+ false
+ >(lon2, lat2, lon, lat).azimuth;
+
+ CalculationType d_crs1 = crs_AD - crs_AB;
+ CalculationType d_crs2 = crs_BD - crs_BA;
+
+ return std::pair<CalculationType, CalculationType>(d_crs1, d_crs2);
+ }
+ };
+
+ struct compute_cross_track_distance
+ {
+ template <typename CalculationType>
+ static inline auto apply(CalculationType const& d_crs1,
+ CalculationType const& d1)
+ {
+ CalculationType const half(0.5);
+ CalculationType const quarter(0.25);
+
+ CalculationType sin_d_crs1 = sin(d_crs1);
+ /*
+ This is the straightforward obvious way to continue:
+
+ return_type discriminant
+ = 1.0 - 4.0 * (d1 - d1 * d1) * sin_d_crs1 * sin_d_crs1;
+ return 0.5 - 0.5 * math::sqrt(discriminant);
+
+ Below we optimize the number of arithmetic operations
+ and account for numerical robustness:
+ */
+ CalculationType d1_x_sin = d1 * sin_d_crs1;
+ CalculationType d = d1_x_sin * (sin_d_crs1 - d1_x_sin);
+ return d / (half + math::sqrt(quarter - d));
+ }
+ };
+
+}
+#endif // DOXYGEN_NO_DETAIL
+
namespace comparable
{
@@ -159,7 +235,7 @@ namespace comparable
The distance d1 needed when the projection of the point D is within the
segment must be the true distance. However, comparable::haversine<>
returns a comparable distance instead of the one needed.
- To remedy this, we implicitly compute what is needed.
+ To remedy this, we implicitly compute what is needed.
More precisely, we need to compute sin(true_d1):
sin(true_d1) = sin(2 * asin(sqrt(d1)))
@@ -343,7 +419,7 @@ public:
>
{};
- typedef typename Strategy::radius_type radius_type;
+ using radius_type = typename Strategy::radius_type;
cross_track() = default;
@@ -372,7 +448,7 @@ public:
);
#endif
- typedef typename return_type<Point, PointOfSegment>::type return_type;
+ using return_type = typename return_type<Point, PointOfSegment>::type;
// http://williams.best.vwh.net/avform.htm#XTE
return_type d1 = m_strategy.apply(sp1, p);
@@ -386,31 +462,12 @@ public:
return_type d2 = m_strategy.apply(sp2, p);
- return_type lon1 = geometry::get_as_radian<0>(sp1);
- return_type lat1 = geometry::get_as_radian<1>(sp1);
- return_type lon2 = geometry::get_as_radian<0>(sp2);
- return_type lat2 = geometry::get_as_radian<1>(sp2);
- return_type lon = geometry::get_as_radian<0>(p);
- return_type lat = geometry::get_as_radian<1>(p);
-
- return_type crs_AD = geometry::formula::spherical_azimuth<return_type, false>
- (lon1, lat1, lon, lat).azimuth;
-
- geometry::formula::result_spherical<return_type> result =
- geometry::formula::spherical_azimuth<return_type, true>
- (lon1, lat1, lon2, lat2);
- return_type crs_AB = result.azimuth;
- return_type crs_BA = result.reverse_azimuth - geometry::math::pi<return_type>();
-
- return_type crs_BD = geometry::formula::spherical_azimuth<return_type, false>
- (lon2, lat2, lon, lat).azimuth;
-
- return_type d_crs1 = crs_AD - crs_AB;
- return_type d_crs2 = crs_BD - crs_BA;
+ auto d_crs_pair = detail::compute_cross_track_pair<return_type>::apply(
+ p, sp1, sp2);
// 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;
+ return_type projection1 = cos(d_crs_pair.first) * d1 / d3;
+ return_type projection2 = cos(d_crs_pair.second) * d2 / d3;
#ifdef BOOST_GEOMETRY_DEBUG_CROSS_TRACK
std::cout << "Course " << dsv(sp1) << " to " << dsv(p) << " "
@@ -441,30 +498,14 @@ public:
<< " d2: " << (d2 * radius())
<< std::endl;
#endif
- return_type const half(0.5);
- return_type const quarter(0.25);
-
- return_type sin_d_crs1 = sin(d_crs1);
- /*
- This is the straightforward obvious way to continue:
-
- return_type discriminant
- = 1.0 - 4.0 * (d1 - d1 * d1) * sin_d_crs1 * sin_d_crs1;
- return 0.5 - 0.5 * math::sqrt(discriminant);
-
- Below we optimize the number of arithmetic operations
- and account for numerical robustness:
- */
- return_type d1_x_sin = d1 * sin_d_crs1;
- return_type d = d1_x_sin * (sin_d_crs1 - d1_x_sin);
- return d / (half + math::sqrt(quarter - d));
+ return detail::compute_cross_track_distance::apply(
+ d_crs_pair.first, d1);
}
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 ) );
}
@@ -508,27 +549,6 @@ template
class cross_track
{
public :
- typedef within::spherical_point_point equals_point_point_strategy_type;
-
- typedef intersection::spherical_segments
- <
- CalculationType
- > relate_segment_segment_strategy_type;
-
- static inline relate_segment_segment_strategy_type get_relate_segment_segment_strategy()
- {
- return relate_segment_segment_strategy_type();
- }
-
- typedef within::spherical_winding
- <
- void, void, CalculationType
- > point_in_geometry_strategy_type;
-
- static inline point_in_geometry_strategy_type get_point_in_geometry_strategy()
- {
- return point_in_geometry_strategy_type();
- }
template <typename Point, typename PointOfSegment>
struct return_type
@@ -543,7 +563,7 @@ public :
>
{};
- typedef typename Strategy::radius_type radius_type;
+ using radius_type = typename Strategy::radius_type;
inline cross_track()
{}
@@ -562,8 +582,9 @@ public :
template <typename Point, typename PointOfSegment>
- inline typename return_type<Point, PointOfSegment>::type
- apply(Point const& p, PointOfSegment const& sp1, PointOfSegment const& sp2) const
+ inline auto apply(Point const& p,
+ PointOfSegment const& sp1,
+ PointOfSegment const& sp2) const
{
#if !defined(BOOST_MSVC)
@@ -572,13 +593,13 @@ public :
(concepts::PointDistanceStrategy<Strategy, Point, PointOfSegment>)
);
#endif
- typedef typename return_type<Point, PointOfSegment>::type return_type;
- typedef cross_track<CalculationType, Strategy> this_type;
+ using return_type = typename return_type<Point, PointOfSegment>::type;
+ using this_type = cross_track<CalculationType, Strategy>;
- typedef typename services::comparable_type
+ using comparable_type = typename services::comparable_type
<
this_type
- >::type comparable_type;
+ >::type;
comparable_type cstrategy
= services::get_comparable<this_type>::apply(m_strategy);
@@ -611,7 +632,7 @@ namespace services
template <typename CalculationType, typename Strategy>
struct tag<cross_track<CalculationType, Strategy> >
{
- typedef strategy_tag_distance_point_segment type;
+ using type = strategy_tag_distance_point_segment;
};
@@ -624,10 +645,10 @@ struct return_type<cross_track<CalculationType, Strategy>, P, PS>
template <typename CalculationType, typename Strategy>
struct comparable_type<cross_track<CalculationType, Strategy> >
{
- typedef comparable::cross_track
+ using type = comparable::cross_track
<
CalculationType, typename comparable_type<Strategy>::type
- > type;
+ > ;
};
@@ -638,10 +659,10 @@ template
>
struct get_comparable<cross_track<CalculationType, Strategy> >
{
- typedef typename comparable_type
+ using comparable_type = typename comparable_type
<
cross_track<CalculationType, Strategy>
- >::type comparable_type;
+ >::type;
public :
static inline comparable_type
apply(cross_track<CalculationType, Strategy> const& strategy)
@@ -661,10 +682,10 @@ template
struct result_from_distance<cross_track<CalculationType, Strategy>, P, PS>
{
private :
- typedef typename cross_track
+ using return_type = typename cross_track
<
CalculationType, Strategy
- >::template return_type<P, PS>::type return_type;
+ >::template return_type<P, PS>::type;
public :
template <typename T>
static inline return_type
@@ -679,7 +700,7 @@ public :
template <typename RadiusType, typename CalculationType>
struct tag<comparable::cross_track<RadiusType, CalculationType> >
{
- typedef strategy_tag_distance_point_segment type;
+ using type = strategy_tag_distance_point_segment;
};
@@ -701,7 +722,7 @@ struct return_type<comparable::cross_track<RadiusType, CalculationType>, P, PS>
template <typename RadiusType, typename CalculationType>
struct comparable_type<comparable::cross_track<RadiusType, CalculationType> >
{
- typedef comparable::cross_track<RadiusType, CalculationType> type;
+ using type = comparable::cross_track<RadiusType, CalculationType>;
};
@@ -709,7 +730,7 @@ template <typename RadiusType, typename CalculationType>
struct get_comparable<comparable::cross_track<RadiusType, CalculationType> >
{
private :
- typedef comparable::cross_track<RadiusType, CalculationType> this_type;
+ using this_type = comparable::cross_track<RadiusType, CalculationType>;
public :
static inline this_type apply(this_type const& input)
{
@@ -731,8 +752,8 @@ struct result_from_distance
>
{
private :
- typedef comparable::cross_track<RadiusType, CalculationType> strategy_type;
- typedef typename return_type<strategy_type, P, PS>::type return_type;
+ using strategy_type = comparable::cross_track<RadiusType, CalculationType>;
+ using return_type = typename return_type<strategy_type, P, PS>::type;
public :
template <typename T>
static inline return_type apply(strategy_type const& strategy,
@@ -783,7 +804,7 @@ struct default_strategy
Strategy
>
{
- typedef cross_track
+ using type = cross_track
<
void,
std::conditional_t
@@ -796,7 +817,7 @@ struct default_strategy
>::type,
Strategy
>
- > type;
+ >;
};
@@ -808,12 +829,12 @@ struct default_strategy
Strategy
>
{
- typedef typename default_strategy
+ using type = typename default_strategy
<
point_tag, segment_tag, Point, PointOfSegment,
spherical_equatorial_tag, spherical_equatorial_tag,
Strategy
- >::type type;
+ >::type;
};
diff --git a/boost/geometry/strategies/spherical/distance_haversine.hpp b/boost/geometry/strategies/spherical/distance_haversine.hpp
index bd46a93c6a..389277259c 100644
--- a/boost/geometry/strategies/spherical/distance_haversine.hpp
+++ b/boost/geometry/strategies/spherical/distance_haversine.hpp
@@ -17,6 +17,7 @@
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/radian_access.hpp>
@@ -26,7 +27,6 @@
#include <boost/geometry/strategies/spherical/get_radius.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
diff --git a/boost/geometry/strategies/spherical/distance_segment_box.hpp b/boost/geometry/strategies/spherical/distance_segment_box.hpp
index 48e4fec211..c48377d77a 100644
--- a/boost/geometry/strategies/spherical/distance_segment_box.hpp
+++ b/boost/geometry/strategies/spherical/distance_segment_box.hpp
@@ -14,6 +14,7 @@
#include <type_traits>
#include <boost/geometry/algorithms/detail/distance/segment_to_box.hpp>
+#include <boost/geometry/algorithms/envelope.hpp>
#include <boost/geometry/strategies/distance.hpp>
#include <boost/geometry/strategies/normalize.hpp>
diff --git a/boost/geometry/strategies/spherical/intersection.hpp b/boost/geometry/strategies/spherical/intersection.hpp
index 12995b8287..fdd44c5d14 100644
--- a/boost/geometry/strategies/spherical/intersection.hpp
+++ b/boost/geometry/strategies/spherical/intersection.hpp
@@ -197,7 +197,7 @@ struct ecef_segments
vec3d_t const a2v = calc_policy.template to_cart3d<vec3d_t>(a2);
vec3d_t const b1v = calc_policy.template to_cart3d<vec3d_t>(b1);
vec3d_t const b2v = calc_policy.template to_cart3d<vec3d_t>(b2);
-
+
bool degen_neq_coords = false;
side_info sides;
@@ -286,7 +286,7 @@ struct ecef_segments
// NOTE: at this point the segments may still be disjoint
// NOTE: at this point one of the segments may be degenerated
- bool collinear = sides.collinear();
+ bool collinear = sides.collinear();
if (! collinear)
{
@@ -324,7 +324,7 @@ struct ecef_segments
sides.set<0>(0, 0);
sides.set<1>(0, 0);
}
-
+
if (collinear)
{
if (a_is_point)
@@ -360,7 +360,7 @@ struct ecef_segments
segment_ratio<calc_t> ra_to(dist_b1_a2, dist_b1_b2);
segment_ratio<calc_t> rb_from(dist_a1_b1, dist_a1_a2);
segment_ratio<calc_t> rb_to(dist_a1_b2, dist_a1_a2);
-
+
// NOTE: this is probably not needed
int const a1_wrt_b = position_value(c0, dist_a1_b1, dist_a1_b2);
int const a2_wrt_b = position_value(dist_a1_a2, dist_a1_b1, dist_a1_b2);
@@ -526,7 +526,7 @@ private:
{
Vec3d ip1, ip2;
calc_policy.intersection_points(plane1, plane2, ip1, ip2);
-
+
calculate_dist(a1v, a2v, plane1, ip1, dist_a1_ip);
ip = ip1;
@@ -572,7 +572,7 @@ private:
ip_flag = ipi_at_a1;
return true;
}
-
+
if (is_near_b2 && equals_point_point(a1, b2))
{
dist_a1_ip = 0;
@@ -848,7 +848,7 @@ struct spherical_segments_calc_policy
});
return true;
- }
+ }
};
diff --git a/boost/geometry/strategies/spherical/point_in_point.hpp b/boost/geometry/strategies/spherical/point_in_point.hpp
index f0857c9f61..242c22010b 100644
--- a/boost/geometry/strategies/spherical/point_in_point.hpp
+++ b/boost/geometry/strategies/spherical/point_in_point.hpp
@@ -28,6 +28,7 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
#include <boost/geometry/core/coordinate_system.hpp>
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/cs.hpp>
@@ -71,7 +72,7 @@ private:
helper_point_type1 point1_normalized;
strategy::normalize::spherical_point::apply(point1, point1_normalized);
- helper_point_type2 point2_normalized;
+ helper_point_type2 point2_normalized;
strategy::normalize::spherical_point::apply(point2, point2_normalized);
return point_point_generic
diff --git a/boost/geometry/strategies/spherical/point_in_poly_winding.hpp b/boost/geometry/strategies/spherical/point_in_poly_winding.hpp
index c475105d79..ca61e4fcb5 100644
--- a/boost/geometry/strategies/spherical/point_in_poly_winding.hpp
+++ b/boost/geometry/strategies/spherical/point_in_poly_winding.hpp
@@ -3,8 +3,9 @@
// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland.
-// This file was modified by Oracle on 2013-2021.
-// Modifications copyright (c) 2013-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2013-2023.
+// Modifications copyright (c) 2013-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -77,7 +78,7 @@ class spherical_winding_base
{
return 0;
}
-
+
if (m_raw_count != 0 && m_raw_count_anti != 0)
{
if (m_raw_count > 0) // right, wrap around south pole
@@ -175,7 +176,7 @@ public:
: 1); // going right all points will be on left side
}
}
-
+
if (side == 0)
{
// Point is lying on segment
@@ -264,7 +265,7 @@ protected:
// it doesn't matter what lon it is if it's a pole
// so e.g. if one of the segment endpoints is a pole
// then only the other lon matters
-
+
bool eq1_strict = longitudes_equal<units_t>(s1_lon, p_lon);
bool eq2_strict = longitudes_equal<units_t>(s2_lon, p_lon);
bool eq1_anti = false;
@@ -273,11 +274,9 @@ protected:
calc_t const anti_p_lon = p_lon + (p_lon <= c0 ? pi : -pi);
eq1 = eq1_strict // lon strictly equal to s1
- || (eq1_anti = longitudes_equal<units_t>(s1_lon, anti_p_lon)) // anti-lon strictly equal to s1
- || math::equals(math::abs(s1_lat), half_pi); // s1 is pole
+ || (eq1_anti = longitudes_equal<units_t>(s1_lon, anti_p_lon)); // anti-lon strictly equal to s1
eq2 = eq2_strict // lon strictly equal to s2
- || (eq2_anti = longitudes_equal<units_t>(s2_lon, anti_p_lon)) // anti-lon strictly equal to s2
- || math::equals(math::abs(s2_lat), half_pi); // s2 is pole
+ || (eq2_anti = longitudes_equal<units_t>(s2_lon, anti_p_lon)); // anti-lon strictly equal to s2
// segment overlapping pole
calc_t const s_lon_diff = math::longitude_distance_signed<units_t>(s1_lon, s2_lon);
@@ -292,7 +291,29 @@ protected:
eq1 = eq2 = true;
}
}
-
+
+ // check whether point is on a segment with a pole endpoint
+ if (math::longitude_distance_signed<units_t>(s2_lon, p_lon) == c0)
+ {
+ bool const s1_north = math::equals(get<1>(seg1), half_pi);
+ bool const s1_south = math::equals(get<1>(seg1), -half_pi);
+ if (s1_north || s1_south)
+ {
+ state.m_touches = s1_south ? s2_lat > p_lat : s2_lat < p_lat;
+ return state.m_touches;
+ }
+ }
+ if (math::longitude_distance_signed<units_t>(s1_lon, p_lon) == c0)
+ {
+ bool const s2_north = math::equals(get<1>(seg2), half_pi);
+ bool const s2_south = math::equals(get<1>(seg2), -half_pi);
+ if (s2_north || s2_south)
+ {
+ state.m_touches = s2_south ? s1_lat > p_lat : s1_lat < p_lat;
+ return state.m_touches;
+ }
+ }
+
// Both equal p -> segment vertical
// The only thing which has to be done is check if point is ON segment
if (eq1 && eq2)
@@ -361,14 +382,24 @@ protected:
// If needed (eq1 && eq2 ? 0) could be returned
calc_t const c0 = 0;
+ calc_t const c2 = 2;
calc_t const pi = constants::half_period();
+ calc_t const half_pi = pi / c2;
+
+ bool const s1_is_pole = math::equals(std::abs(get<1>(seg1)), half_pi);
+ bool const s2_is_pole = math::equals(std::abs(get<1>(seg2)), half_pi);
+
+ if (s1_is_pole && s2_is_pole)
+ {
+ return count_info(0, false);
+ }
calc_t const p = get<0>(point);
calc_t const s1 = get<0>(seg1);
calc_t const s2 = get<0>(seg2);
calc_t const s1_p = math::longitude_distance_signed<units_t>(s1, p);
-
+
if (s_antipodal)
{
return count_info(s1_p < c0 ? -2 : 2, false); // choose W/E
@@ -388,7 +419,7 @@ protected:
{
return count_info(s1_s2 < c0 ? -2 : 2, false); // choose W/E
}
-
+
calc_t const s1_p_anti = math::longitude_distance_signed<units_t>(s1, p + pi);
// Anti-Point between s1 and s2
diff --git a/boost/geometry/strategies/spherical/side_by_cross_track.hpp b/boost/geometry/strategies/spherical/side_by_cross_track.hpp
index b5cdb032bb..d17de30773 100644
--- a/boost/geometry/strategies/spherical/side_by_cross_track.hpp
+++ b/boost/geometry/strategies/spherical/side_by_cross_track.hpp
@@ -16,6 +16,7 @@
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_SIDE_BY_CROSS_TRACK_HPP
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/radian_access.hpp>
@@ -26,7 +27,6 @@
#include <boost/geometry/strategies/spherical/point_in_point.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
namespace boost { namespace geometry
diff --git a/boost/geometry/strategies/spherical/ssf.hpp b/boost/geometry/strategies/spherical/ssf.hpp
index d1e0e13523..2d29c400cc 100644
--- a/boost/geometry/strategies/spherical/ssf.hpp
+++ b/boost/geometry/strategies/spherical/ssf.hpp
@@ -16,10 +16,10 @@
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/strategy/spherical/envelope.hpp>
diff --git a/boost/geometry/strategies/strategies.hpp b/boost/geometry/strategies/strategies.hpp
index 66cbc93833..d219d0053d 100644
--- a/boost/geometry/strategies/strategies.hpp
+++ b/boost/geometry/strategies/strategies.hpp
@@ -67,7 +67,6 @@
#include <boost/geometry/strategies/cartesian/point_in_poly_crossings_multiply.hpp>
#include <boost/geometry/strategies/cartesian/point_in_poly_winding.hpp>
#include <boost/geometry/strategies/cartesian/line_interpolate.hpp>
-#include <boost/geometry/strategies/cartesian/side_by_triangle.hpp>
#include <boost/geometry/strategies/spherical/azimuth.hpp>
#include <boost/geometry/strategies/spherical/densify.hpp>
@@ -85,7 +84,11 @@
#include <boost/geometry/strategies/spherical/ssf.hpp>
#include <boost/geometry/strategies/geographic/azimuth.hpp>
+#include <boost/geometry/strategies/geographic/buffer_end_round.hpp>
+#include <boost/geometry/strategies/geographic/buffer_join_miter.hpp>
+#include <boost/geometry/strategies/geographic/buffer_join_round.hpp>
#include <boost/geometry/strategies/geographic/buffer_point_circle.hpp>
+#include <boost/geometry/strategies/geographic/buffer_side_straight.hpp>
#include <boost/geometry/strategies/geographic/densify.hpp>
#include <boost/geometry/strategies/geographic/disjoint_segment_box.hpp>
#include <boost/geometry/strategies/geographic/distance.hpp>
@@ -135,6 +138,8 @@
#include <boost/geometry/strategy/cartesian/expand_box.hpp>
#include <boost/geometry/strategy/cartesian/expand_point.hpp>
#include <boost/geometry/strategy/cartesian/expand_segment.hpp>
+#include <boost/geometry/strategy/cartesian/side_by_triangle.hpp>
+#include <boost/geometry/strategy/cartesian/side_robust.hpp>
#include <boost/geometry/strategy/geographic/area.hpp>
#include <boost/geometry/strategy/geographic/envelope.hpp>
diff --git a/boost/geometry/strategies/strategy_transform.hpp b/boost/geometry/strategies/strategy_transform.hpp
index fe94c14f8e..ee2216ac71 100644
--- a/boost/geometry/strategies/strategy_transform.hpp
+++ b/boost/geometry/strategies/strategy_transform.hpp
@@ -30,10 +30,10 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
#include <boost/geometry/strategies/transform.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
namespace boost { namespace geometry
diff --git a/boost/geometry/strategies/transform/matrix_transformers.hpp b/boost/geometry/strategies/transform/matrix_transformers.hpp
index 36e60f3b67..70f11b889b 100644
--- a/boost/geometry/strategies/transform/matrix_transformers.hpp
+++ b/boost/geometry/strategies/transform/matrix_transformers.hpp
@@ -33,9 +33,9 @@
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
+#include <boost/geometry/core/coordinate_promotion.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/promote_floating_point.hpp>
#include <boost/geometry/util/select_coordinate_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
diff --git a/boost/geometry/strategies/transform/srs_transformer.hpp b/boost/geometry/strategies/transform/srs_transformer.hpp
index e1815e2362..8baeed8869 100644
--- a/boost/geometry/strategies/transform/srs_transformer.hpp
+++ b/boost/geometry/strategies/transform/srs_transformer.hpp
@@ -16,7 +16,7 @@
namespace boost { namespace geometry
{
-
+
namespace strategy { namespace transform
{
diff --git a/boost/geometry/strategy/cartesian/area.hpp b/boost/geometry/strategy/cartesian/area.hpp
index f17453fac5..a18a4f85ea 100644
--- a/boost/geometry/strategy/cartesian/area.hpp
+++ b/boost/geometry/strategy/cartesian/area.hpp
@@ -62,7 +62,7 @@ public :
CalculationType
>
{};
-
+
template <typename Geometry>
class state
{
@@ -70,7 +70,7 @@ public :
typedef typename result_type<Geometry>::type return_type;
- public:
+ public:
inline state()
: sum(0)
{
diff --git a/boost/geometry/strategy/cartesian/area_box.hpp b/boost/geometry/strategy/cartesian/area_box.hpp
index d41b412c67..1263b564df 100644
--- a/boost/geometry/strategy/cartesian/area_box.hpp
+++ b/boost/geometry/strategy/cartesian/area_box.hpp
@@ -36,7 +36,7 @@ public:
CalculationType
>
{};
-
+
template <typename Box>
static inline auto apply(Box const& box)
{
diff --git a/boost/geometry/strategy/cartesian/envelope_boxes.hpp b/boost/geometry/strategy/cartesian/envelope_boxes.hpp
new file mode 100644
index 0000000000..e45a4ca9dc
--- /dev/null
+++ b/boost/geometry/strategy/cartesian/envelope_boxes.hpp
@@ -0,0 +1,66 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_BOXES_HPP
+#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_BOXES_HPP
+
+#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
+#include <boost/geometry/strategy/cartesian/expand_box.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace envelope
+{
+
+class cartesian_boxes
+{
+public:
+ template <typename Box>
+ class state
+ {
+ friend cartesian_boxes;
+
+ Box m_box;
+ bool m_initialized = false;
+ };
+
+ template <typename Box>
+ static void apply(state<Box> & st, Box const& box)
+ {
+ if (! st.m_initialized)
+ {
+ st.m_box = box;
+ st.m_initialized = true;
+ }
+ else
+ {
+ strategy::expand::cartesian_box::apply(st.m_box, box);
+ }
+ }
+
+ template <typename Box>
+ static void result(state<Box> const& st, Box & box)
+ {
+ if (st.m_initialized)
+ {
+ box = st.m_box;
+ }
+ else
+ {
+ geometry::detail::envelope::initialize<Box, 0, dimension<Box>::value>::apply(box);
+ }
+ }
+};
+
+}} // namespace strategy::envelope
+
+}} //namepsace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_BOXES_HPP
diff --git a/boost/geometry/strategy/cartesian/envelope_range.hpp b/boost/geometry/strategy/cartesian/envelope_range.hpp
new file mode 100644
index 0000000000..e3d97bf49b
--- /dev/null
+++ b/boost/geometry/strategy/cartesian/envelope_range.hpp
@@ -0,0 +1,56 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_RANGE_HPP
+#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_RANGE_HPP
+
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+
+#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
+#include <boost/geometry/strategy/cartesian/envelope_point.hpp>
+#include <boost/geometry/strategy/cartesian/expand_point.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace envelope
+{
+
+class cartesian_range
+{
+public:
+ template <typename Range, typename Box>
+ static inline void apply(Range const& range, Box& mbr)
+ {
+ auto it = boost::begin(range);
+ auto const end = boost::end(range);
+ if (it == end)
+ {
+ // initialize box (assign inverse)
+ geometry::detail::envelope::initialize<Box>::apply(mbr);
+ return;
+ }
+
+ // initialize box with the first point
+ envelope::cartesian_point::apply(*it, mbr);
+
+ // consider now the remaining points in the range (if any)
+ for (++it; it != end; ++it)
+ {
+ expand::cartesian_point::apply(mbr, *it);
+ }
+ }
+};
+
+}} // namespace strategy::envelope
+
+}} //namepsace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_RANGE_HPP
diff --git a/boost/geometry/strategy/cartesian/envelope_segment.hpp b/boost/geometry/strategy/cartesian/envelope_segment.hpp
index 08fbc09217..75124bcbdc 100644
--- a/boost/geometry/strategy/cartesian/envelope_segment.hpp
+++ b/boost/geometry/strategy/cartesian/envelope_segment.hpp
@@ -65,7 +65,7 @@ public:
<
0,
dimension<Point>::value
- >::apply(point1, point2, box);
+ >::apply(point1, point2, box);
}
};
diff --git a/boost/geometry/strategy/cartesian/side_by_triangle.hpp b/boost/geometry/strategy/cartesian/side_by_triangle.hpp
new file mode 100644
index 0000000000..9535912e6d
--- /dev/null
+++ b/boost/geometry/strategy/cartesian/side_by_triangle.hpp
@@ -0,0 +1,258 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+
+// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
+// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
+// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
+
+// This file was modified by Oracle on 2015-2023.
+// Modifications copyright (c) 2015-2023, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// 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_CARTESIAN_SIDE_BY_TRIANGLE_HPP
+#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_BY_TRIANGLE_HPP
+
+
+#include <type_traits>
+
+#include <boost/geometry/core/config.hpp>
+#include <boost/geometry/arithmetic/determinant.hpp>
+
+#include <boost/geometry/core/access.hpp>
+
+#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
+#include <boost/geometry/strategies/compare.hpp>
+#include <boost/geometry/strategies/side.hpp>
+
+#include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/util/select_most_precise.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
+{
+ template <typename Policy>
+ struct eps_policy
+ {
+ eps_policy() {}
+ template <typename Type>
+ eps_policy(Type const& a, Type const& b, Type const& c, Type const& d)
+ : policy(a, b, c, d)
+ {}
+ Policy policy;
+ };
+
+ struct eps_empty
+ {
+ eps_empty() {}
+ template <typename Type>
+ eps_empty(Type const&, Type const&, Type const&, Type const&) {}
+ };
+
+public :
+ using cs_tag = cartesian_tag;
+
+ // 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 CoordinateType,
+ typename PromotedType,
+ typename P1,
+ typename P2,
+ typename P,
+ typename EpsPolicy
+ >
+ static inline
+ PromotedType side_value(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & eps_policy)
+ {
+ CoordinateType const x = get<0>(p);
+ CoordinateType const y = get<1>(p);
+
+ CoordinateType const sx1 = get<0>(p1);
+ CoordinateType const sy1 = get<1>(p1);
+ CoordinateType const sx2 = get<0>(p2);
+ CoordinateType const sy2 = get<1>(p2);
+
+ PromotedType const dx = sx2 - sx1;
+ PromotedType const dy = sy2 - sy1;
+ PromotedType const dpx = x - sx1;
+ PromotedType const dpy = y - sy1;
+
+ eps_policy = EpsPolicy(dx, dy, dpx, dpy);
+
+ return geometry::detail::determinant<PromotedType>
+ (
+ dx, dy,
+ dpx, dpy
+ );
+
+ }
+
+ template
+ <
+ typename CoordinateType,
+ typename PromotedType,
+ typename P1,
+ typename P2,
+ typename P
+ >
+ static inline
+ PromotedType side_value(P1 const& p1, P2 const& p2, P const& p)
+ {
+ eps_empty dummy;
+ return side_value<CoordinateType, PromotedType>(p1, p2, p, dummy);
+ }
+
+
+ template
+ <
+ typename CoordinateType,
+ typename PromotedType,
+ bool AreAllIntegralCoordinates
+ >
+ struct compute_side_value
+ {
+ template <typename P1, typename P2, typename P, typename EpsPolicy>
+ static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
+ {
+ return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
+ }
+ };
+
+ template <typename CoordinateType, typename PromotedType>
+ struct compute_side_value<CoordinateType, PromotedType, false>
+ {
+ template <typename P1, typename P2, typename P, typename EpsPolicy>
+ static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
+ {
+ // For robustness purposes, first check if any two points are
+ // the same; in this case simply return that the points are
+ // collinear
+ if (equals_point_point(p1, p2)
+ || equals_point_point(p1, p)
+ || equals_point_point(p2, p))
+ {
+ return PromotedType(0);
+ }
+
+ // The side_by_triangle strategy computes the signed area of
+ // the point triplet (p1, p2, p); as such it is (in theory)
+ // invariant under cyclic permutations of its three arguments.
+ //
+ // In the context of numerical errors that arise in
+ // floating-point computations, and in order to make the strategy
+ // consistent with respect to cyclic permutations of its three
+ // arguments, we cyclically permute them so that the first
+ // argument is always the lexicographically smallest point.
+
+ using less = compare::cartesian<compare::less, compare::equals_epsilon>;
+
+ if (less::apply(p, p1))
+ {
+ if (less::apply(p, p2))
+ {
+ // p is the lexicographically smallest
+ return side_value<CoordinateType, PromotedType>(p, p1, p2, epsp);
+ }
+ else
+ {
+ // p2 is the lexicographically smallest
+ return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
+ }
+ }
+
+ if (less::apply(p1, p2))
+ {
+ // p1 is the lexicographically smallest
+ return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
+ }
+ else
+ {
+ // p2 is the lexicographically smallest
+ return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
+ }
+ }
+ };
+
+
+ template <typename P1, typename P2, typename P>
+ static inline int apply(P1 const& p1, P2 const& p2, P const& p)
+ {
+ using coor_t = typename select_calculation_type_alt<CalculationType, P1, P2, P>::type;
+
+ // Promote float->double, small int->int
+ using promoted_t = typename select_most_precise<coor_t, double>::type;
+
+ bool const are_all_integral_coordinates =
+ std::is_integral<typename coordinate_type<P1>::type>::value
+ && std::is_integral<typename coordinate_type<P2>::type>::value
+ && std::is_integral<typename coordinate_type<P>::type>::value;
+
+ eps_policy< math::detail::equals_factor_policy<promoted_t> > epsp;
+ promoted_t s = compute_side_value
+ <
+ coor_t, promoted_t, are_all_integral_coordinates
+ >::apply(p1, p2, p, epsp);
+
+ promoted_t const zero = promoted_t();
+ return math::detail::equals_by_policy(s, zero, epsp.policy) ? 0
+ : s > zero ? 1
+ : -1;
+ }
+
+private:
+ template <typename P1, typename P2>
+ static inline bool equals_point_point(P1 const& p1, P2 const& p2)
+ {
+ return strategy::within::cartesian_point_point::apply(p1, p2);
+ }
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+namespace services
+{
+
+template <typename CalculationType>
+struct default_strategy<cartesian_tag, CalculationType>
+{
+ using type = side_by_triangle<CalculationType>;
+};
+
+}
+
+#endif
+
+}} // namespace strategy::side
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_BY_TRIANGLE_HPP
diff --git a/boost/geometry/strategy/cartesian/side_non_robust.hpp b/boost/geometry/strategy/cartesian/side_non_robust.hpp
index 2ef109cc1b..25074cc894 100644
--- a/boost/geometry/strategy/cartesian/side_non_robust.hpp
+++ b/boost/geometry/strategy/cartesian/side_non_robust.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2020, Oracle and/or its affiliates.
+// Copyright (c) 2020-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
@@ -14,6 +14,8 @@
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/util/precise_math.hpp>
+#include <boost/geometry/arithmetic/determinant.hpp>
+
namespace boost { namespace geometry
{
@@ -21,7 +23,7 @@ namespace strategy { namespace side
{
/*!
-\brief Adaptive precision predicate to check at which side of a segment a point lies:
+\brief Predicate to 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
@@ -35,8 +37,6 @@ struct side_non_robust
{
public:
//! \brief Computes double the signed area of the CCW triangle p1, p2, p
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
template
<
typename P1,
@@ -51,21 +51,44 @@ public:
P1,
P2,
P
- >::type coordinate_type;
+ >::type CoordinateType;
typedef typename select_most_precise
<
- coordinate_type,
+ CoordinateType,
double
- >::type promoted_type;
+ >::type PromotedType;
+
+ CoordinateType const x = get<0>(p);
+ CoordinateType const y = get<1>(p);
+
+ CoordinateType const sx1 = get<0>(p1);
+ CoordinateType const sy1 = get<1>(p1);
+ CoordinateType const sx2 = get<0>(p2);
+ CoordinateType const sy2 = get<1>(p2);
+
+ //non-robust 1
+ //the following is 2x slower in some generic cases when compiled with g++
+ //(tested versions 9 and 10)
+ //
+ //auto detleft = (sx1 - x) * (sy2 - y);
+ //auto detright = (sy1 - y) * (sx2 - x);
+ //return detleft > detright ? 1 : (detleft < detright ? -1 : 0 );
+
+ //non-robust 2
+ PromotedType const dx = sx2 - sx1;
+ PromotedType const dy = sy2 - sy1;
+ PromotedType const dpx = x - sx1;
+ PromotedType const dpy = y - sy1;
- auto detleft = (promoted_type(get<0>(p1)) - promoted_type(get<0>(p)))
- * (promoted_type(get<1>(p2)) - promoted_type(get<1>(p)));
- auto detright = (promoted_type(get<1>(p1)) - promoted_type(get<1>(p)))
- * (promoted_type(get<0>(p2)) - promoted_type(get<0>(p)));
- return detleft > detright ? 1 : (detleft < detright ? -1 : 0 );
+ PromotedType sv = geometry::detail::determinant<PromotedType>
+ (
+ dx, dy,
+ dpx, dpy
+ );
+ PromotedType const zero = PromotedType();
+ return sv == zero ? 0 : sv > zero ? 1 : -1;
}
-#endif
};
diff --git a/boost/geometry/strategy/cartesian/side_robust.hpp b/boost/geometry/strategy/cartesian/side_robust.hpp
index 5362ed0687..c8405e9329 100644
--- a/boost/geometry/strategy/cartesian/side_robust.hpp
+++ b/boost/geometry/strategy/cartesian/side_robust.hpp
@@ -7,6 +7,7 @@
// This file was modified by Oracle on 2021.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
+
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -17,9 +18,15 @@
#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP
+#include <boost/geometry/core/config.hpp>
+#include <boost/geometry/strategy/cartesian/side_non_robust.hpp>
+
+#include <boost/geometry/strategies/side.hpp>
+
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/util/precise_math.hpp>
+#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
@@ -27,6 +34,27 @@ namespace boost { namespace geometry
namespace strategy { namespace side
{
+struct epsilon_equals_policy
+{
+public:
+ template <typename Policy, typename T1, typename T2>
+ static bool apply(T1 const& a, T2 const& b, Policy const& policy)
+ {
+ return boost::geometry::math::detail::equals_by_policy(a, b, policy);
+ }
+};
+
+struct fp_equals_policy
+{
+public:
+ template <typename Policy, typename T1, typename T2>
+ static bool apply(T1 const& a, T2 const& b, Policy const&)
+ {
+ return a == b;
+ }
+};
+
+
/*!
\brief Adaptive precision predicate to check at which side of a segment a point lies:
left of segment (>0), right of segment (< 0), on segment (0).
@@ -38,21 +66,52 @@ namespace strategy { namespace side
template
<
typename CalculationType = void,
+ typename EqualsPolicy = epsilon_equals_policy,
std::size_t Robustness = 3
>
struct side_robust
{
+
+ template <typename CT>
+ struct epsilon_policy
+ {
+ using Policy = boost::geometry::math::detail::equals_factor_policy<CT>;
+
+ epsilon_policy() {}
+
+ template <typename Type>
+ epsilon_policy(Type const& a, Type const& b, Type const& c, Type const& d)
+ : m_policy(a, b, c, d)
+ {}
+ Policy m_policy;
+
+ public:
+
+ template <typename T1, typename T2>
+ bool apply(T1 a, T2 b) const
+ {
+ return EqualsPolicy::apply(a, b, m_policy);
+ }
+ };
+
public:
- //! \brief Computes double the signed area of the CCW triangle p1, p2, p
+
+ typedef cartesian_tag cs_tag;
+
+ //! \brief Computes the sign of the CCW triangle p1, p2, p
template
<
typename PromotedType,
typename P1,
typename P2,
- typename P
+ typename P,
+ typename EpsPolicyInternal,
+ std::enable_if_t<std::is_fundamental<PromotedType>::value, int> = 0
>
- static inline PromotedType side_value(P1 const& p1, P2 const& p2,
- P const& p)
+ static inline PromotedType side_value(P1 const& p1,
+ P2 const& p2,
+ P const& p,
+ EpsPolicyInternal& eps_policy)
{
using vec2d = ::boost::geometry::detail::precise_math::vec2d<PromotedType>;
vec2d pa;
@@ -65,7 +124,22 @@ public:
pc.x = get<0>(p);
pc.y = get<1>(p);
return ::boost::geometry::detail::precise_math::orient2d
- <PromotedType, Robustness>(pa, pb, pc);
+ <PromotedType, Robustness>(pa, pb, pc, eps_policy);
+ }
+
+ template
+ <
+ typename PromotedType,
+ typename P1,
+ typename P2,
+ typename P,
+ typename EpsPolicyInternal,
+ std::enable_if_t<!std::is_fundamental<PromotedType>::value, int> = 0
+ >
+ static inline auto side_value(P1 const& p1, P2 const& p2, P const& p,
+ EpsPolicyInternal&)
+ {
+ return side_non_robust<>::apply(p1, p2, p);
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
@@ -77,24 +151,29 @@ public:
>
static inline int apply(P1 const& p1, P2 const& p2, P const& p)
{
- typedef typename select_calculation_type_alt
+ using coordinate_type = typename select_calculation_type_alt
<
CalculationType,
P1,
P2,
P
- >::type coordinate_type;
- typedef typename select_most_precise
+ >::type;
+
+ using promoted_type = typename select_most_precise
<
coordinate_type,
double
- >::type promoted_type;
+ >::type;
- promoted_type sv = side_value<promoted_type>(p1, p2, p);
- return sv > 0 ? 1
- : sv < 0 ? -1
- : 0;
+ epsilon_policy<promoted_type> epsp;
+ promoted_type sv = side_value<promoted_type>(p1, p2, p, epsp);
+ promoted_type const zero = promoted_type();
+
+ return epsp.apply(sv, zero) ? 0
+ : sv > zero ? 1
+ : -1;
}
+
#endif
};
diff --git a/boost/geometry/strategy/geographic/area_box.hpp b/boost/geometry/strategy/geographic/area_box.hpp
index 6c0943e091..0a3fa6f80f 100644
--- a/boost/geometry/strategy/geographic/area_box.hpp
+++ b/boost/geometry/strategy/geographic/area_box.hpp
@@ -77,14 +77,14 @@ public:
explicit geographic_box(Spheroid const& spheroid)
: m_spheroid(spheroid)
{}
-
+
template <typename Box>
inline auto apply(Box const& box) const
{
typedef typename result_type<Box>::type return_type;
return_type const c0 = 0;
-
+
return_type x_min = get_as_radian<min_corner, 0>(box); // lon
return_type y_min = get_as_radian<min_corner, 1>(box); // lat
return_type x_max = get_as_radian<max_corner, 0>(box);
diff --git a/boost/geometry/strategy/geographic/envelope_range.hpp b/boost/geometry/strategy/geographic/envelope_range.hpp
new file mode 100644
index 0000000000..8a0ae5e917
--- /dev/null
+++ b/boost/geometry/strategy/geographic/envelope_range.hpp
@@ -0,0 +1,118 @@
+// Boost.Geometry
+
+// Copyright (c) 2021-2022, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_ENVELOPE_RANGE_HPP
+#define BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_ENVELOPE_RANGE_HPP
+
+#include <boost/geometry/strategy/geographic/envelope_segment.hpp>
+#include <boost/geometry/strategy/geographic/expand_segment.hpp>
+#include <boost/geometry/strategy/spherical/envelope_range.hpp>
+
+// Get rid of this dependency?
+#include <boost/geometry/strategies/spherical/point_in_poly_winding.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace envelope
+{
+
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = geometry::srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic_linestring
+{
+public:
+ using model_type = Spheroid;
+
+ geographic_linestring()
+ : m_spheroid()
+ {}
+
+ explicit geographic_linestring(Spheroid const& spheroid)
+ : m_spheroid(spheroid)
+ {}
+
+ template <typename Range, typename Box>
+ void apply(Range const& range, Box& mbr) const
+ {
+ auto const envelope_s = envelope::geographic_segment
+ <
+ FormulaPolicy, Spheroid, CalculationType
+ >(m_spheroid);
+ auto const expand_s = expand::geographic_segment
+ <
+ FormulaPolicy, Spheroid, CalculationType
+ >(m_spheroid);
+ detail::spheroidal_linestring(range, mbr, envelope_s, expand_s);
+ }
+
+ Spheroid model() const
+ {
+ return m_spheroid;
+ }
+
+private:
+ Spheroid m_spheroid;
+};
+
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = geometry::srs::spheroid<double>,
+ typename CalculationType = void
+>
+class geographic_ring
+{
+public:
+ using model_type = Spheroid;
+
+ geographic_ring()
+ : m_spheroid()
+ {}
+
+ explicit geographic_ring(Spheroid const& spheroid)
+ : m_spheroid(spheroid)
+ {}
+
+ template <typename Range, typename Box>
+ void apply(Range const& range, Box& mbr) const
+ {
+ auto const envelope_s = envelope::geographic_segment
+ <
+ FormulaPolicy, Spheroid, CalculationType
+ >(m_spheroid);
+ auto const expand_s = expand::geographic_segment
+ <
+ FormulaPolicy, Spheroid, CalculationType
+ >(m_spheroid);
+ auto const within_s = within::detail::spherical_winding_base
+ <
+ envelope::detail::side_of_pole<CalculationType>, CalculationType
+ >();
+ detail::spheroidal_ring(range, mbr, envelope_s, expand_s, within_s);
+ }
+
+ Spheroid model() const
+ {
+ return m_spheroid;
+ }
+
+private:
+ Spheroid m_spheroid;
+};
+
+}} // namespace strategy::envelope
+
+}} //namepsace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_ENVELOPE_RANGE_HPP
diff --git a/boost/geometry/strategy/relate.hpp b/boost/geometry/strategy/relate.hpp
index 6f99670827..fa523d846f 100644
--- a/boost/geometry/strategy/relate.hpp
+++ b/boost/geometry/strategy/relate.hpp
@@ -80,7 +80,7 @@ struct default_strategy<Point, Geometry, point_tag, multi_point_tag>
} // namespace point_in_geometry
-
+
namespace relate
{
diff --git a/boost/geometry/strategy/spherical/area_box.hpp b/boost/geometry/strategy/spherical/area_box.hpp
index 8ee29a7789..196dc3d8b7 100644
--- a/boost/geometry/strategy/spherical/area_box.hpp
+++ b/boost/geometry/strategy/spherical/area_box.hpp
@@ -73,7 +73,7 @@ public:
RadiusOrSphere
>::apply(radius_or_sphere))
{}
-
+
template <typename Box>
inline auto apply(Box const& box) const
{
diff --git a/boost/geometry/strategy/spherical/envelope_boxes.hpp b/boost/geometry/strategy/spherical/envelope_boxes.hpp
new file mode 100644
index 0000000000..1c04ecd4de
--- /dev/null
+++ b/boost/geometry/strategy/spherical/envelope_boxes.hpp
@@ -0,0 +1,59 @@
+// Boost.Geometry
+
+// Copyright (c) 2021, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_BOXES_HPP
+#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_BOXES_HPP
+
+#include <vector>
+
+#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
+#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace envelope
+{
+
+class spherical_boxes
+{
+public:
+ template <typename Box>
+ class state
+ {
+ friend spherical_boxes;
+
+ std::vector<Box> m_boxes;
+ };
+
+ template <typename Box>
+ static void apply(state<Box> & st, Box const& box)
+ {
+ st.m_boxes.push_back(box);
+ }
+
+ template <typename Box>
+ static void result(state<Box> const& st, Box & box)
+ {
+ if (! st.m_boxes.empty())
+ {
+ geometry::detail::envelope::envelope_range_of_boxes::apply(st.m_boxes, box);
+ }
+ else
+ {
+ geometry::detail::envelope::initialize<Box, 0, dimension<Box>::value>::apply(box);
+ }
+ }
+};
+
+}} // namespace strategy::envelope
+
+}} //namepsace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_BOXES_HPP
diff --git a/boost/geometry/strategy/spherical/envelope_multipoint.hpp b/boost/geometry/strategy/spherical/envelope_multipoint.hpp
index 2ee0c0c035..7302c41bea 100644
--- a/boost/geometry/strategy/spherical/envelope_multipoint.hpp
+++ b/boost/geometry/strategy/spherical/envelope_multipoint.hpp
@@ -1,7 +1,8 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2015-2020, Oracle and/or its affiliates.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
+// Copyright (c) 2015-2023, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -13,12 +14,11 @@
#ifndef BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_MULTIPOINT_HPP
#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_MULTIPOINT_HPP
-#include <cstddef>
#include <algorithm>
+#include <cstddef>
#include <utility>
#include <vector>
-#include <boost/algorithm/minmax_element.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/empty.hpp>
#include <boost/range/end.hpp>
@@ -42,6 +42,7 @@
#include <boost/geometry/algorithms/detail/expand/point.hpp>
#include <boost/geometry/strategy/cartesian/envelope_point.hpp>
+#include <boost/geometry/strategy/cartesian/expand_point.hpp>
#include <boost/geometry/strategies/normalize.hpp>
#include <boost/geometry/strategy/spherical/envelope_box.hpp>
#include <boost/geometry/strategy/spherical/envelope_point.hpp>
@@ -62,8 +63,7 @@ private:
template <typename Point>
inline bool operator()(Point const& point1, Point const& point2) const
{
- return math::smaller(geometry::get<Dim>(point1),
- geometry::get<Dim>(point2));
+ return math::smaller(geometry::get<Dim>(point1), geometry::get<Dim>(point2));
}
};
@@ -73,12 +73,6 @@ private:
bool& has_north_pole,
OutputIterator oit)
{
- typedef typename boost::range_value<MultiPoint>::type point_type;
- typedef typename boost::range_iterator
- <
- MultiPoint const
- >::type iterator_type;
-
// analyze point coordinates:
// (1) normalize point coordinates
// (2) check if any point is the north or the south pole
@@ -89,20 +83,16 @@ private:
has_south_pole = false;
has_north_pole = false;
- for (iterator_type it = boost::begin(multipoint);
- it != boost::end(multipoint);
- ++it)
+ for (auto it = boost::begin(multipoint); it != boost::end(multipoint); ++it)
{
- point_type point;
+ typename boost::range_value<MultiPoint>::type point;
normalize::spherical_point::apply(*it, point);
- if (math::equals(geometry::get<1>(point),
- Constants::min_latitude()))
+ if (math::equals(geometry::get<1>(point), Constants::min_latitude()))
{
has_south_pole = true;
}
- else if (math::equals(geometry::get<1>(point),
- Constants::max_latitude()))
+ else if (math::equals(geometry::get<1>(point), Constants::max_latitude()))
{
has_north_pole = true;
}
@@ -118,12 +108,8 @@ private:
Value& max_gap_left,
Value& max_gap_right)
{
- typedef typename boost::range_iterator
- <
- SortedRange const
- >::type iterator_type;
-
- iterator_type it1 = boost::begin(sorted_range), it2 = it1;
+ auto it1 = boost::begin(sorted_range);
+ auto it2 = it1;
++it2;
max_gap_left = geometry::get<0>(*it1);
max_gap_right = geometry::get<0>(*it2);
@@ -155,16 +141,9 @@ private:
CoordinateType& lon_min,
CoordinateType& lon_max)
{
- typedef typename boost::range_iterator
- <
- PointRange const
- >::type iterator_type;
-
// compute min and max longitude values
- std::pair<iterator_type, iterator_type> min_max_longitudes
- = boost::minmax_element(boost::begin(range),
- boost::end(range),
- lon_less);
+ auto const min_max_longitudes
+ = std::minmax_element(boost::begin(range), boost::end(range), lon_less);
lon_min = geometry::get<0>(*min_max_longitudes.first);
lon_max = geometry::get<0>(*min_max_longitudes.second);
@@ -212,20 +191,16 @@ private:
else if (has_south_pole)
{
lat_min = Constants::min_latitude();
- lat_max
- = geometry::get<1>(*std::max_element(first, last, lat_less));
+ lat_max = geometry::get<1>(*std::max_element(first, last, lat_less));
}
else if (has_north_pole)
{
- lat_min
- = geometry::get<1>(*std::min_element(first, last, lat_less));
+ lat_min = geometry::get<1>(*std::min_element(first, last, lat_less));
lat_max = Constants::max_latitude();
}
else
{
- std::pair<Iterator, Iterator> min_max_latitudes
- = boost::minmax_element(first, last, lat_less);
-
+ auto const min_max_latitudes = std::minmax_element(first, last, lat_less);
lat_min = geometry::get<1>(*min_max_latitudes.first);
lat_max = geometry::get<1>(*min_max_latitudes.second);
}
@@ -237,11 +212,6 @@ public:
{
typedef typename point_type<MultiPoint>::type point_type;
typedef typename coordinate_type<MultiPoint>::type coordinate_type;
- typedef typename boost::range_iterator
- <
- MultiPoint const
- >::type iterator_type;
-
typedef math::detail::constants_on_spheroid
<
coordinate_type,
@@ -332,7 +302,7 @@ public:
geometry::detail::envelope::envelope_indexed_box_on_spheroid<max_corner, 2>::apply(helper_mbr, mbr);
// compute envelope for higher coordinates
- iterator_type it = boost::begin(multipoint);
+ auto it = boost::begin(multipoint);
geometry::detail::envelope::envelope_one_point<2, dimension<Box>::value>::apply(*it, mbr);
for (++it; it != boost::end(multipoint); ++it)
diff --git a/boost/geometry/strategy/spherical/envelope_range.hpp b/boost/geometry/strategy/spherical/envelope_range.hpp
new file mode 100644
index 0000000000..8833bd8ea3
--- /dev/null
+++ b/boost/geometry/strategy/spherical/envelope_range.hpp
@@ -0,0 +1,278 @@
+// Boost.Geometry
+
+// Copyright (c) 2021-2022, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_RANGE_HPP
+#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_RANGE_HPP
+
+#include <boost/geometry/algorithms/assign.hpp>
+#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
+#include <boost/geometry/geometries/segment.hpp>
+#include <boost/geometry/strategy/spherical/envelope_point.hpp>
+#include <boost/geometry/strategy/spherical/envelope_segment.hpp>
+#include <boost/geometry/strategy/spherical/expand_segment.hpp>
+#include <boost/geometry/views/closeable_view.hpp>
+
+// Get rid of this dependency?
+#include <boost/geometry/strategies/spherical/point_in_poly_winding.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategy { namespace envelope
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+template <typename Range, typename Box, typename EnvelopeStrategy, typename ExpandStrategy>
+inline void spheroidal_linestring(Range const& range, Box& mbr,
+ EnvelopeStrategy const& envelope_strategy,
+ ExpandStrategy const& expand_strategy)
+{
+ auto it = boost::begin(range);
+ auto const end = boost::end(range);
+ if (it == end)
+ {
+ // initialize box (assign inverse)
+ geometry::detail::envelope::initialize<Box>::apply(mbr);
+ return;
+ }
+
+ auto prev = it;
+ ++it;
+ if (it == end)
+ {
+ // initialize box with the first point
+ envelope::spherical_point::apply(*prev, mbr);
+ return;
+ }
+
+ // initialize box with the first segment
+ envelope_strategy.apply(*prev, *it, mbr);
+
+ // consider now the remaining segments in the range (if any)
+ prev = it;
+ ++it;
+ while (it != end)
+ {
+ using point_t = typename boost::range_value<Range>::type;
+ geometry::model::referring_segment<point_t const> const seg(*prev, *it);
+ expand_strategy.apply(mbr, seg);
+ prev = it;
+ ++it;
+ }
+}
+
+
+// This strategy is intended to be used together with winding strategy to check
+// if ring/polygon has a pole in its interior or exterior. It is not intended
+// for checking if the pole is on the boundary.
+template <typename CalculationType = void>
+struct side_of_pole
+{
+ typedef spherical_tag cs_tag;
+
+ template <typename P>
+ static inline int apply(P const& p1, P const& p2, P const& pole)
+ {
+ using calc_t = typename promote_floating_point
+ <
+ typename select_calculation_type_alt
+ <
+ CalculationType, P
+ >::type
+ >::type;
+
+ using units_t = typename geometry::detail::cs_angular_units<P>::type;
+ using constants = math::detail::constants_on_spheroid<calc_t, units_t>;
+
+ calc_t const c0 = 0;
+ calc_t const pi = constants::half_period();
+
+ calc_t const lon1 = get<0>(p1);
+ calc_t const lat1 = get<1>(p1);
+ calc_t const lon2 = get<0>(p2);
+ calc_t const lat2 = get<1>(p2);
+ calc_t const lat_pole = get<1>(pole);
+
+ calc_t const s_lon_diff = math::longitude_distance_signed<units_t>(lon1, lon2);
+ bool const s_vertical = math::equals(s_lon_diff, c0)
+ || math::equals(s_lon_diff, pi);
+ // Side of vertical segment is 0 for both poles.
+ if (s_vertical)
+ {
+ return 0;
+ }
+
+ // This strategy shouldn't be called in this case but just in case
+ // check if segment starts at a pole
+ if (math::equals(lat_pole, lat1) || math::equals(lat_pole, lat2))
+ {
+ return 0;
+ }
+
+ // -1 is rhs
+ // 1 is lhs
+ if (lat_pole >= c0) // north pole
+ {
+ return s_lon_diff < c0 ? -1 : 1;
+ }
+ else // south pole
+ {
+ return s_lon_diff > c0 ? -1 : 1;
+ }
+ }
+};
+
+
+template <typename Point, typename Range, typename Strategy>
+inline int point_in_range(Point const& point, Range const& range, Strategy const& strategy)
+{
+ typename Strategy::state_type state;
+
+ auto it = boost::begin(range);
+ auto const end = boost::end(range);
+ for (auto previous = it++ ; it != end ; ++previous, ++it )
+ {
+ if (! strategy.apply(point, *previous, *it, state))
+ {
+ break;
+ }
+ }
+
+ return strategy.result(state);
+}
+
+
+template <typename T, typename Ring, typename PoleWithinStrategy>
+inline bool pole_within(T const& lat_pole, Ring const& ring,
+ PoleWithinStrategy const& pole_within_strategy)
+{
+ if (boost::size(ring) < core_detail::closure::minimum_ring_size
+ <
+ geometry::closure<Ring>::value
+ >::value)
+ {
+ return false;
+ }
+
+ using point_t = typename geometry::point_type<Ring>::type;
+ point_t point;
+ geometry::assign_zero(point);
+ geometry::set<1>(point, lat_pole);
+ geometry::detail::closed_clockwise_view<Ring const> view(ring);
+ return point_in_range(point, view, pole_within_strategy) > 0;
+}
+
+template
+<
+ typename Range,
+ typename Box,
+ typename EnvelopeStrategy,
+ typename ExpandStrategy,
+ typename PoleWithinStrategy
+>
+inline void spheroidal_ring(Range const& range, Box& mbr,
+ EnvelopeStrategy const& envelope_strategy,
+ ExpandStrategy const& expand_strategy,
+ PoleWithinStrategy const& pole_within_strategy)
+{
+ geometry::detail::closed_view<Range const> closed_range(range);
+
+ spheroidal_linestring(closed_range, mbr, envelope_strategy, expand_strategy);
+
+ using coord_t = typename geometry::coordinate_type<Box>::type;
+ using point_t = typename geometry::point_type<Box>::type;
+ using units_t = typename geometry::detail::cs_angular_units<point_t>::type;
+ using constants_t = math::detail::constants_on_spheroid<coord_t, units_t>;
+ coord_t const two_pi = constants_t::period();
+ coord_t const lon_min = geometry::get<0, 0>(mbr);
+ coord_t const lon_max = geometry::get<1, 0>(mbr);
+ // If box covers the whole longitude range it is possible that the ring contains
+ // one of the poles.
+ // Technically it is possible that a reversed ring may cover more than
+ // half of the globe and mbr of it's linear ring may be small and not cover the
+ // longitude range. We currently don't support such rings.
+ if (lon_max - lon_min >= two_pi)
+ {
+ coord_t const lat_n_pole = constants_t::max_latitude();
+ coord_t const lat_s_pole = constants_t::min_latitude();
+ coord_t lat_min = geometry::get<0, 1>(mbr);
+ coord_t lat_max = geometry::get<1, 1>(mbr);
+ // Normalize box latitudes, just in case
+ if (math::equals(lat_min, lat_s_pole))
+ {
+ lat_min = lat_s_pole;
+ }
+ if (math::equals(lat_max, lat_n_pole))
+ {
+ lat_max = lat_n_pole;
+ }
+
+ if (lat_max < lat_n_pole)
+ {
+ if (pole_within(lat_n_pole, range, pole_within_strategy))
+ {
+ lat_max = lat_n_pole;
+ }
+ }
+ if (lat_min > lat_s_pole)
+ {
+ if (pole_within(lat_s_pole, range, pole_within_strategy))
+ {
+ lat_min = lat_s_pole;
+ }
+ }
+
+ geometry::set<0, 1>(mbr, lat_min);
+ geometry::set<1, 1>(mbr, lat_max);
+ }
+}
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+template <typename CalculationType = void>
+class spherical_linestring
+{
+public:
+ template <typename Range, typename Box>
+ static inline void apply(Range const& range, Box& mbr)
+ {
+ detail::spheroidal_linestring(range, mbr,
+ envelope::spherical_segment<CalculationType>(),
+ expand::spherical_segment<CalculationType>());
+ }
+};
+
+template <typename CalculationType = void>
+class spherical_ring
+{
+public:
+ template <typename Range, typename Box>
+ static inline void apply(Range const& range, Box& mbr)
+ {
+ detail::spheroidal_ring(range, mbr,
+ envelope::spherical_segment<CalculationType>(),
+ expand::spherical_segment<CalculationType>(),
+ within::detail::spherical_winding_base
+ <
+ envelope::detail::side_of_pole<CalculationType>,
+ CalculationType
+ >());
+ }
+};
+
+}} // namespace strategy::envelope
+
+}} //namepsace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_RANGE_HPP
diff --git a/boost/geometry/strategy/spherical/envelope_segment.hpp b/boost/geometry/strategy/spherical/envelope_segment.hpp
index fd6e9865b3..428f0f71a7 100644
--- a/boost/geometry/strategy/spherical/envelope_segment.hpp
+++ b/boost/geometry/strategy/spherical/envelope_segment.hpp
@@ -125,7 +125,6 @@ private:
CalculationType const& a2)
{
// azimuths a1 and a2 are assumed to be in radians
- BOOST_GEOMETRY_ASSERT(! math::equals(a1, a2));
static CalculationType const pi_half = math::half_pi<CalculationType>();
@@ -164,12 +163,6 @@ private:
CalculationType lat1_rad = math::as_radian<Units>(lat1);
CalculationType lat2_rad = math::as_radian<Units>(lat2);
- if (math::equals(a1, a2))
- {
- // the segment must lie on the equator or is very short or is meridian
- return;
- }
-
if (lat1 > lat2)
{
std::swap(lat1, lat2);
diff --git a/boost/geometry/strategy/spherical/expand_box.hpp b/boost/geometry/strategy/spherical/expand_box.hpp
index 67564e15a7..9400f0cc4d 100644
--- a/boost/geometry/strategy/spherical/expand_box.hpp
+++ b/boost/geometry/strategy/spherical/expand_box.hpp
@@ -86,7 +86,7 @@ struct envelope_box_on_spheroid
// BoxIn can be non-mutable
typename helper_geometry<BoxIn>::type box_in_normalized;
geometry::convert(box_in, box_in_normalized);
-
+
if (! is_inverse_spheroidal_coordinates(box_in))
{
strategy::normalize::spherical_box::apply(box_in, box_in_normalized);
diff --git a/boost/geometry/util/combine_if.hpp b/boost/geometry/util/combine_if.hpp
index 62489dcf7f..7b00864a3b 100644
--- a/boost/geometry/util/combine_if.hpp
+++ b/boost/geometry/util/combine_if.hpp
@@ -51,9 +51,9 @@ namespace util
pair<boost::mpl::int_<1>, boost::mpl::int_<1> >,
pair<boost::mpl::int_<1>, boost::mpl::int_<0> >,
pair<boost::mpl::int_<0>, boost::mpl::int_<1> >,
- pair<boost::mpl::int_<0>, boost::mpl::int_<0> >
+ pair<boost::mpl::int_<0>, boost::mpl::int_<0> >
> result_types;
-
+
BOOST_MPL_ASSERT(( boost::mpl::equal<combinations, result_types> ));
\endcode
*/
diff --git a/boost/geometry/util/constexpr.hpp b/boost/geometry/util/constexpr.hpp
new file mode 100644
index 0000000000..72d1411456
--- /dev/null
+++ b/boost/geometry/util/constexpr.hpp
@@ -0,0 +1,27 @@
+// Boost.Geometry
+
+// Copyright (c) 2023 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_UTIL_CONSTEXPR_HPP
+#define BOOST_GEOMETRY_UTIL_CONSTEXPR_HPP
+
+
+#include <boost/geometry/util/condition.hpp>
+
+
+#ifndef BOOST_NO_CXX17_IF_CONSTEXPR
+
+#define BOOST_GEOMETRY_CONSTEXPR(CONDITION) constexpr (CONDITION)
+
+#else
+
+#define BOOST_GEOMETRY_CONSTEXPR(CONDITION) (BOOST_GEOMETRY_CONDITION(CONDITION))
+
+#endif
+
+
+#endif // BOOST_GEOMETRY_UTIL_CONSTEXPR_HPP
diff --git a/boost/geometry/util/for_each_with_index.hpp b/boost/geometry/util/for_each_with_index.hpp
new file mode 100644
index 0000000000..425f2a497c
--- /dev/null
+++ b/boost/geometry/util/for_each_with_index.hpp
@@ -0,0 +1,49 @@
+// Boost.Geometry
+
+// Copyright (c) 2023 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_UTIL_FOR_EACH_WITH_INDEX_HPP
+#define BOOST_GEOMETRY_UTIL_FOR_EACH_WITH_INDEX_HPP
+
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/size_type.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+// Utility function to implement a Kotlin like range based for loop
+template <typename Container, typename Function>
+inline void for_each_with_index(Container const& container, Function func)
+{
+ typename boost::range_size<Container>::type index = 0;
+ for (auto it = boost::begin(container); it != boost::end(container); ++it, ++index)
+ {
+ func(index, *it);
+ }
+}
+
+template <typename Container, typename Function>
+inline void for_each_with_index(Container& container, Function func)
+{
+ typename boost::range_size<Container>::type index = 0;
+ for (auto it = boost::begin(container); it != boost::end(container); ++it, ++index)
+ {
+ func(index, *it);
+ }
+}
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_UTIL_FOR_EACH_WITH_INDEX_HPP
diff --git a/boost/geometry/util/has_infinite_coordinate.hpp b/boost/geometry/util/has_infinite_coordinate.hpp
index 87a65c0245..22113e89d4 100644
--- a/boost/geometry/util/has_infinite_coordinate.hpp
+++ b/boost/geometry/util/has_infinite_coordinate.hpp
@@ -20,7 +20,7 @@
namespace boost { namespace geometry
{
-
+
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
diff --git a/boost/geometry/util/has_nan_coordinate.hpp b/boost/geometry/util/has_nan_coordinate.hpp
index 6ae111f1b8..d3fc9f1951 100644
--- a/boost/geometry/util/has_nan_coordinate.hpp
+++ b/boost/geometry/util/has_nan_coordinate.hpp
@@ -24,7 +24,7 @@
namespace boost { namespace geometry
{
-
+
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
diff --git a/boost/geometry/util/has_non_finite_coordinate.hpp b/boost/geometry/util/has_non_finite_coordinate.hpp
index 96c19dc188..df6990a159 100644
--- a/boost/geometry/util/has_non_finite_coordinate.hpp
+++ b/boost/geometry/util/has_non_finite_coordinate.hpp
@@ -20,7 +20,7 @@
namespace boost { namespace geometry
{
-
+
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
diff --git a/boost/geometry/util/math.hpp b/boost/geometry/util/math.hpp
index fc9d7a3be8..c88572ed53 100644
--- a/boost/geometry/util/math.hpp
+++ b/boost/geometry/util/math.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2022.
+// Modifications copyright (c) 2014-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adeel Ahmad, as part of Google Summer of Code 2018 program
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
@@ -139,6 +139,12 @@ struct equals_factor_policy
return factor;
}
+ template <typename E>
+ void multiply_epsilon(E const& multiplier)
+ {
+ factor *= multiplier;
+ }
+
T factor;
};
@@ -153,6 +159,8 @@ struct equals_factor_policy<T, false>
{
return T(1);
}
+
+ void multiply_epsilon(T const& ) {}
};
template <typename Type,
@@ -221,7 +229,7 @@ struct smaller<Type, true>
{
return false;
}
-
+
return ! equals<Type, true>::apply(b, a, equals_default_policy());
}
};
@@ -517,6 +525,30 @@ struct rounding_cast<Result, Source, true, false>
}
};
+template <typename T, bool IsIntegral = std::is_integral<T>::value>
+struct divide
+{
+ static inline T apply(T const& n, T const& d)
+ {
+ return n / d;
+ }
+};
+
+template <typename T>
+struct divide<T, true>
+{
+ static inline T apply(T const& n, T const& d)
+ {
+ return n == 0 ? 0
+ : n < 0
+ ? (d < 0 ? (n + (-d + 1) / 2) / d + 1
+ : (n + ( d + 1) / 2) / d - 1 )
+ : (d < 0 ? (n - (-d + 1) / 2) / d - 1
+ : (n - ( d + 1) / 2) / d + 1 )
+ ;
+ }
+};
+
} // namespace detail
#endif
@@ -632,6 +664,20 @@ inline T r2d()
return conversion_coefficient;
}
+/*!
+\brief Wraps an angle in the range [-pi, +pi] (both inclusive)
+*/
+template <typename T>
+inline T wrap_azimuth_in_radian(T const& azimuth)
+{
+ static T const pi = geometry::math::pi<T>();
+ static T const two_pi = geometry::math::two_pi<T>();
+ T result = azimuth;
+ while (result > pi) { result -= two_pi; }
+ while (result < -pi) { result += two_pi; }
+ return result;
+};
+
#ifndef DOXYGEN_NO_DETAIL
namespace detail {
@@ -788,6 +834,17 @@ inline Result rounding_cast(T const& v)
return detail::rounding_cast<Result, T>::apply(v);
}
+/*
+\brief Short utility to divide. If the division is integer, it rounds the division
+ to the nearest value, without using floating point calculations
+\ingroup utility
+*/
+template <typename T>
+inline T divide(T const& n, T const& d)
+{
+ return detail::divide<T>::apply(n, d);
+}
+
/*!
\brief Evaluate the sine and cosine function with the argument in degrees
\note The results obey exactly the elementary properties of the trigonometric
@@ -802,16 +859,16 @@ inline void sin_cos_degrees(T const& x,
{
// In order to minimize round-off errors, this function exactly reduces
// the argument to the range [-45, 45] before converting it to radians.
- T remainder; int quotient;
- remainder = math::mod(x, T(360));
- quotient = floor(remainder / 90 + T(0.5));
- remainder -= 90 * quotient;
+ T remainder = math::mod(x, T(360));
+ T const quotient = std::floor(remainder / T(90) + T(0.5));
+ remainder -= T(90) * quotient;
// Convert to radians.
remainder *= d2r<T>();
- T s = sin(remainder), c = cos(remainder);
+ T const s = sin(remainder);
+ T const c = cos(remainder);
switch (unsigned(quotient) & 3U)
{
@@ -824,7 +881,8 @@ inline void sin_cos_degrees(T const& x,
// Set sign of 0 results. -0 only produced for sin(-0).
if (x != 0)
{
- sinx += T(0); cosx += T(0);
+ sinx += T(0);
+ cosx += T(0);
}
}
diff --git a/boost/geometry/util/normalize_spheroidal_box_coordinates.hpp b/boost/geometry/util/normalize_spheroidal_box_coordinates.hpp
index 288dab20dd..9658b8bbef 100644
--- a/boost/geometry/util/normalize_spheroidal_box_coordinates.hpp
+++ b/boost/geometry/util/normalize_spheroidal_box_coordinates.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2015-2017, Oracle and/or its affiliates.
+// Copyright (c) 2015-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -19,7 +19,7 @@
namespace boost { namespace geometry
{
-namespace math
+namespace math
{
#ifndef DOXYGEN_NO_DETAIL
@@ -37,8 +37,8 @@ private:
static inline bool is_band(CoordinateType const& longitude1,
CoordinateType const& longitude2)
{
- return ! math::smaller(math::abs(longitude1 - longitude2),
- constants::period());
+ return math::larger_or_equals(math::abs(longitude1 - longitude2),
+ constants::period());
}
public:
@@ -91,8 +91,7 @@ public:
BOOST_GEOMETRY_ASSERT(! math::larger(longitude1, longitude2));
BOOST_GEOMETRY_ASSERT(! math::smaller(longitude1, constants::min_longitude()));
- BOOST_GEOMETRY_ASSERT
- (! math::larger(longitude2 - longitude1, constants::period()));
+ BOOST_GEOMETRY_ASSERT(! math::larger(longitude2 - longitude1, constants::period()));
}
static inline void apply(CoordinateType& longitude1,
diff --git a/boost/geometry/util/normalize_spheroidal_coordinates.hpp b/boost/geometry/util/normalize_spheroidal_coordinates.hpp
index e595f6c2c0..074acc8a28 100644
--- a/boost/geometry/util/normalize_spheroidal_coordinates.hpp
+++ b/boost/geometry/util/normalize_spheroidal_coordinates.hpp
@@ -2,7 +2,7 @@
// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
-// Copyright (c) 2015-2020, Oracle and/or its affiliates.
+// Copyright (c) 2015-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -22,7 +22,7 @@
namespace boost { namespace geometry
{
-namespace math
+namespace math
{
#ifndef DOXYGEN_NO_DETAIL
@@ -225,14 +225,14 @@ protected:
{
return
math::mod(value + constants::half_period(), constants::period())
- - constants::half_period();
+ - constants::half_period();
}
static inline CoordinateType normalize_down(CoordinateType const& value)
{
return
math::mod(value - constants::half_period(), constants::period())
- + constants::half_period();
+ + constants::half_period();
}
public:
@@ -308,7 +308,7 @@ public:
BOOST_GEOMETRY_ASSERT(! math::larger(latitude, constants::max_latitude()));
#endif // BOOST_GEOMETRY_NORMALIZE_LATITUDE
- BOOST_GEOMETRY_ASSERT(math::smaller(constants::min_longitude(), longitude));
+ BOOST_GEOMETRY_ASSERT(! math::larger_or_equals(constants::min_longitude(), longitude));
BOOST_GEOMETRY_ASSERT(! math::larger(longitude, constants::max_longitude()));
}
};
@@ -495,7 +495,7 @@ inline CoordinateType longitude_interval_distance_signed(CoordinateType const& l
dist_a12 = -dist_a12;
dist_a1b = -dist_a1b;
}
-
+
return dist_a1b < c0 ? dist_a1b
: dist_a1b > dist_a12 ? dist_a1b - dist_a12
: c0;
diff --git a/boost/geometry/util/parameter_type_of.hpp b/boost/geometry/util/parameter_type_of.hpp
index 1c1754eb1a..6c2209ad87 100644
--- a/boost/geometry/util/parameter_type_of.hpp
+++ b/boost/geometry/util/parameter_type_of.hpp
@@ -58,7 +58,7 @@ struct parameter_type_of
<
int,
(base_index_type::value + Index)
- >
+ >
> indexed_type;
typedef typename std::remove_reference
diff --git a/boost/geometry/util/precise_math.hpp b/boost/geometry/util/precise_math.hpp
index c707620970..fb1b078451 100644
--- a/boost/geometry/util/precise_math.hpp
+++ b/boost/geometry/util/precise_math.hpp
@@ -1,10 +1,15 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2019 Tinko Bartels, Berlin, Germany.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// Contributed and/or modified by Tinko Bartels,
// as part of Google Summer of Code 2019 program.
+// This file was modified by Oracle on 2021.
+// Modifications copyright (c) 2021, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle
+
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
@@ -18,6 +23,7 @@
#include<array>
#include <boost/geometry/core/access.hpp>
+#include <boost/geometry/util/condition.hpp>
// The following code is based on "Adaptive Precision Floating-Point Arithmetic
// and Fast Robust Geometric Predicates" by Richard Shewchuk,
@@ -157,7 +163,9 @@ inline int fast_expansion_sum_zeroelim(
int n = InSize2)
{
std::array<RealNumber, 2> Qh;
- int i_e = 0, i_f = 0, i_h = 0;
+ int i_e = 0;
+ int i_f = 0;
+ int i_h = 0;
if (std::abs(f[0]) > std::abs(e[0]))
{
Qh[0] = e[i_e++];
@@ -282,14 +290,16 @@ inline RealNumber orient2dtail(vec2d<RealNumber> const& p1,
std::array<RealNumber, 2>& t4,
std::array<RealNumber, 2>& t5_01,
std::array<RealNumber, 2>& t6_01,
- RealNumber const& magnitude
- )
+ RealNumber const& magnitude)
{
t5_01[1] = two_product_tail(t1[0], t2[0], t5_01[0]);
t6_01[1] = two_product_tail(t3[0], t4[0], t6_01[0]);
std::array<RealNumber, 4> tA_03 = two_two_expansion_diff(t5_01, t6_01);
RealNumber det = std::accumulate(tA_03.begin(), tA_03.end(), static_cast<RealNumber>(0));
- if(Robustness == 1) return det;
+ if (BOOST_GEOMETRY_CONDITION(Robustness == 1))
+ {
+ return det;
+ }
// see p.39, mind the different definition of epsilon for error bound
RealNumber B_relative_bound =
(1 + 3 * std::numeric_limits<RealNumber>::epsilon())
@@ -347,29 +357,37 @@ inline RealNumber orient2dtail(vec2d<RealNumber> const& p1,
return(D[D_nz - 1]);
}
-// see page 38, Figure 21 for the calculations, notation follows the notation in the figure.
+// see page 38, Figure 21 for the calculations, notation follows the notation
+// in the figure.
template
<
typename RealNumber,
- std::size_t Robustness = 3
+ std::size_t Robustness = 3,
+ typename EpsPolicy
>
inline RealNumber orient2d(vec2d<RealNumber> const& p1,
vec2d<RealNumber> const& p2,
- vec2d<RealNumber> const& p3)
+ vec2d<RealNumber> const& p3,
+ EpsPolicy& eps_policy)
{
- if(Robustness == 0)
- {
- return (p1.x - p3.x) * (p2.y - p3.y) - (p1.y - p3.y) * (p2.x - p3.x);
- }
std::array<RealNumber, 2> t1, t2, t3, t4;
t1[0] = p1.x - p3.x;
t2[0] = p2.y - p3.y;
t3[0] = p1.y - p3.y;
t4[0] = p2.x - p3.x;
+
+ eps_policy = EpsPolicy(t1[0], t2[0], t3[0], t4[0]);
+
std::array<RealNumber, 2> t5_01, t6_01;
t5_01[0] = t1[0] * t2[0];
t6_01[0] = t3[0] * t4[0];
RealNumber det = t5_01[0] - t6_01[0];
+
+ if (BOOST_GEOMETRY_CONDITION(Robustness == 0))
+ {
+ return det;
+ }
+
RealNumber const magnitude = std::abs(t5_01[0]) + std::abs(t6_01[0]);
// see p.39, mind the different definition of epsilon for error bound
@@ -388,7 +406,8 @@ inline RealNumber orient2d(vec2d<RealNumber> const& p1,
//obvious
return det;
}
- return orient2dtail<RealNumber, Robustness>(p1, p2, p3, t1, t2, t3, t4, t5_01, t6_01, magnitude);
+ return orient2dtail<RealNumber, Robustness>(p1, p2, p3, t1, t2, t3, t4,
+ t5_01, t6_01, magnitude);
}
// This method adaptively computes increasingly precise approximations of the following
diff --git a/boost/geometry/util/promote_floating_point.hpp b/boost/geometry/util/promote_floating_point.hpp
index a005adee60..d38109116b 100644
--- a/boost/geometry/util/promote_floating_point.hpp
+++ b/boost/geometry/util/promote_floating_point.hpp
@@ -18,35 +18,9 @@
#ifndef BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
#define BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
+#include <boost/config/header_deprecated.hpp>
+BOOST_HEADER_DEPRECATED("boost/geometry/core/coordinate_promotion.hpp")
-#include <type_traits>
-
-
-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 std::conditional_t
- <
- std::is_integral<T>::value,
- PromoteIntegerTo,
- T
- > type;
-};
-
-
-}} // namespace boost::geometry
-
+#include <boost/geometry/core/coordinate_promotion.hpp>
#endif // BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
diff --git a/boost/geometry/util/promote_integral.hpp b/boost/geometry/util/promote_integral.hpp
index 59397257ee..0566f42140 100644
--- a/boost/geometry/util/promote_integral.hpp
+++ b/boost/geometry/util/promote_integral.hpp
@@ -278,7 +278,7 @@ public:
<
T,
min_bit_size_type::value,
- integral_types
+ integral_types
>::type type;
};
diff --git a/boost/geometry/util/range.hpp b/boost/geometry/util/range.hpp
index 445636dd0f..a25ac102e4 100644
--- a/boost/geometry/util/range.hpp
+++ b/boost/geometry/util/range.hpp
@@ -327,7 +327,7 @@ erase(Range && rng,
std::size_t const count = static_cast<std::size_t>(diff);
BOOST_GEOMETRY_ASSERT(count <= boost::size(rng));
-
+
if ( count > 0 )
{
typename boost::range_difference<Range>::type const
diff --git a/boost/geometry/util/sequence.hpp b/boost/geometry/util/sequence.hpp
index 80e3b7b23a..d6c31c9a69 100644
--- a/boost/geometry/util/sequence.hpp
+++ b/boost/geometry/util/sequence.hpp
@@ -1,7 +1,7 @@
// Boost.Geometry
-// Copyright (c) 2020, Oracle and/or its affiliates.
-
+// Copyright (c) 2020-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
@@ -10,7 +10,7 @@
#ifndef BOOST_GEOMETRY_UTIL_SEQUENCE_HPP
#define BOOST_GEOMETRY_UTIL_SEQUENCE_HPP
-
+#include <utility>
#include <type_traits>
@@ -62,13 +62,13 @@ struct sequence_element {};
template <std::size_t I, typename T, typename ...Ts>
struct sequence_element<I, type_sequence<T, Ts...>>
{
- typedef typename sequence_element<I - 1, type_sequence<Ts...>>::type type;
+ using type = typename sequence_element<I - 1, type_sequence<Ts...>>::type;
};
template <typename T, typename ...Ts>
struct sequence_element<0, type_sequence<T, Ts...>>
{
- typedef T type;
+ using type = T;
};
template <std::size_t I, typename T, T J, T ...Js>
@@ -86,6 +86,19 @@ struct sequence_element<0, std::integer_sequence<T, J, Js...>>
{};
+template <typename ...Ts>
+struct pack_front
+{
+ static_assert(sizeof...(Ts) > 0, "Parameter pack can not be empty.");
+};
+
+template <typename T, typename ... Ts>
+struct pack_front<T, Ts...>
+{
+ typedef T type;
+};
+
+
template <typename Sequence>
struct sequence_front
: sequence_element<0, Sequence>
@@ -112,6 +125,7 @@ struct sequence_empty
{};
+// Defines type member for the first type in sequence that satisfies UnaryPred.
template
<
typename Sequence,
@@ -138,77 +152,71 @@ template <template <typename> class UnaryPred>
struct sequence_find_if<type_sequence<>, UnaryPred>
{
// TODO: This is technically incorrect because void can be stored in a type_sequence
- typedef void type;
+ using type = void;
};
-// merge<type_sequence<A, B>, type_sequence<C, D>>::type is
+// sequence_merge<type_sequence<A, B>, type_sequence<C, D>>::type is
// type_sequence<A, B, C, D>
-// merge<integer_sequence<A, B>, integer_sequence<C, D>>::type is
+// sequence_merge<integer_sequence<A, B>, integer_sequence<C, D>>::type is
// integer_sequence<A, B, C, D>
template <typename ...Sequences>
-struct merge;
+struct sequence_merge;
template <typename S>
-struct merge<S>
+struct sequence_merge<S>
{
- typedef S type;
+ using type = S;
};
template <typename ...T1s, typename ...T2s>
-struct merge<type_sequence<T1s...>, type_sequence<T2s...>>
+struct sequence_merge<type_sequence<T1s...>, type_sequence<T2s...>>
{
- typedef type_sequence<T1s..., T2s...> type;
+ using type = type_sequence<T1s..., T2s...>;
};
template <typename T, T ...I1s, T ...I2s>
-struct merge<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
+struct sequence_merge<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
{
- typedef std::integer_sequence<T, I1s..., I2s...> type;
+ using type = std::integer_sequence<T, I1s..., I2s...>;
};
template <typename S1, typename S2, typename ...Sequences>
-struct merge<S1, S2, Sequences...>
+struct sequence_merge<S1, S2, Sequences...>
{
- typedef typename merge
+ using type = typename sequence_merge
<
- typename merge<S1, S2>::type,
- typename merge<Sequences...>::type
- >::type type;
+ typename sequence_merge<S1, S2>::type,
+ typename sequence_merge<Sequences...>::type
+ >::type;
};
-// combine<type_sequence<A, B>, type_sequence<C, D>>::type is
+// sequence_combine<type_sequence<A, B>, type_sequence<C, D>>::type is
// type_sequence<type_sequence<A, C>, type_sequence<A, D>,
// type_sequence<B, C>, type_sequence<B, D>>
template <typename Sequence1, typename Sequence2>
-struct combine;
+struct sequence_combine;
template <typename ...T1s, typename ...T2s>
-struct combine<type_sequence<T1s...>, type_sequence<T2s...>>
+struct sequence_combine<type_sequence<T1s...>, type_sequence<T2s...>>
{
- template <typename U1, typename ...U2s>
- using type_sequence_t = type_sequence<type_sequence<U1, U2s>...>;
+ template <typename T1>
+ using type_sequence_t = type_sequence<type_sequence<T1, T2s>...>;
- typedef typename merge
- <
- type_sequence_t<T1s, T2s...>...
- >::type type;
+ using type = typename sequence_merge<type_sequence_t<T1s>...>::type;
};
-// combine<integer_sequence<T, 1, 2>, integer_sequence<T, 3, 4>>::type is
+// sequence_combine<integer_sequence<T, 1, 2>, integer_sequence<T, 3, 4>>::type is
// type_sequence<integer_sequence<T, 1, 3>, integer_sequence<T, 1, 4>,
// integer_sequence<T, 2, 3>, integer_sequence<T, 2, 4>>
template <typename T, T ...I1s, T ...I2s>
-struct combine<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
+struct sequence_combine<std::integer_sequence<T, I1s...>, std::integer_sequence<T, I2s...>>
{
- template <T J1, T ...J2s>
- using type_sequence_t = type_sequence<std::integer_sequence<T, J1, J2s>...>;
+ template <T I1>
+ using type_sequence_t = type_sequence<std::integer_sequence<T, I1, I2s>...>;
- typedef typename merge
- <
- type_sequence_t<I1s, I2s...>...
- >::type type;
+ using type = typename sequence_merge<type_sequence_t<I1s>...>::type;
};
@@ -219,16 +227,16 @@ template
template <typename, typename> class LessPred,
typename ...Ts
>
-struct select_pack_element;
+struct pack_min_element;
template
<
template <typename, typename> class LessPred,
typename T
>
-struct select_pack_element<LessPred, T>
+struct pack_min_element<LessPred, T>
{
- typedef T type;
+ using type = T;
};
template
@@ -236,9 +244,9 @@ template
template <typename, typename> class LessPred,
typename T1, typename T2
>
-struct select_pack_element<LessPred, T1, T2>
+struct pack_min_element<LessPred, T1, T2>
{
- typedef std::conditional_t<LessPred<T1, T2>::value, T1, T2> type;
+ using type = std::conditional_t<LessPred<T1, T2>::value, T1, T2>;
};
template
@@ -246,14 +254,14 @@ template
template <typename, typename> class LessPred,
typename T1, typename T2, typename ...Ts
>
-struct select_pack_element<LessPred, T1, T2, Ts...>
+struct pack_min_element<LessPred, T1, T2, Ts...>
{
- typedef typename select_pack_element
+ using type = typename pack_min_element
<
LessPred,
- typename select_pack_element<LessPred, T1, T2>::type,
- typename select_pack_element<LessPred, Ts...>::type
- >::type type;
+ typename pack_min_element<LessPred, T1, T2>::type,
+ typename pack_min_element<LessPred, Ts...>::type
+ >::type;
};
@@ -262,37 +270,24 @@ struct select_pack_element<LessPred, T1, T2, Ts...>
template
<
typename Sequence,
- template <typename, typename> class LessPred
+ template <typename, typename> class LessPred
>
-struct select_element;
+struct sequence_min_element;
template
<
typename ...Ts,
template <typename, typename> class LessPred
>
-struct select_element<type_sequence<Ts...>, LessPred>
+struct sequence_min_element<type_sequence<Ts...>, LessPred>
{
- typedef typename select_pack_element<LessPred, Ts...>::type type;
+ using type = typename pack_min_element<LessPred, Ts...>::type;
};
-// Selects least pair sequence of elements from a parameter pack based on
-// LessPred<xxx_sequence<T11, T12>, xxx_sequence<T21, T22>>::value comparison
-template
-<
- typename Sequence1,
- typename Sequence2,
- template <typename, typename> class LessPred
->
-struct select_combination_element
-{
- typedef typename select_element
- <
- typename combine<Sequence1, Sequence2>::type,
- LessPred
- >::type type;
-};
+// TODO: Since there are two kinds of parameter packs and sequences there probably should be two
+// versions of sequence_find_if as well as parameter_pack_min_element and sequence_min_element.
+// Currently these utilities support only types.
} // namespace util
diff --git a/boost/geometry/util/series_expansion.hpp b/boost/geometry/util/series_expansion.hpp
index 1a5c6472a3..bdc4d7c6eb 100644
--- a/boost/geometry/util/series_expansion.hpp
+++ b/boost/geometry/util/series_expansion.hpp
@@ -1,6 +1,7 @@
// Boost.Geometry
// Copyright (c) 2018 Adeel Ahmad, Islamabad, Pakistan.
+// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// Contributed and/or modified by Adeel Ahmad, as part of Google Summer of Code 2018 program.
@@ -60,9 +61,9 @@ namespace boost { namespace geometry { namespace series_expansion {
s/case\sCT(/case /g; s/):/:/g; s/epsCT(2)/eps2/g;'
*/
template <size_t SeriesOrder, typename CT>
- inline CT evaluate_A1(CT eps)
+ inline CT evaluate_A1(CT const& eps)
{
- CT eps2 = math::sqr(eps);
+ CT const eps2 = math::sqr(eps);
CT t;
switch (SeriesOrder/2)
{
@@ -78,7 +79,7 @@ namespace boost { namespace geometry { namespace series_expansion {
case 3:
t = eps2*(eps2*(eps2+CT(4))+CT(64))/CT(256);
break;
- case 4:
+ default:
t = eps2*(eps2*(eps2*(CT(25)*eps2+CT(64))+CT(256))+CT(4096))/CT(16384);
break;
}
@@ -224,7 +225,7 @@ namespace boost { namespace geometry { namespace series_expansion {
template <typename Coeffs, typename CT>
inline void evaluate_coeffs_C1(Coeffs &c, CT const& eps)
{
- CT eps2 = math::sqr(eps);
+ CT const eps2 = math::sqr(eps);
CT d = eps;
switch (int(Coeffs::static_size) - 1)
{
diff --git a/boost/geometry/util/type_traits.hpp b/boost/geometry/util/type_traits.hpp
index f1f89a7a1a..c58b5bad02 100644
--- a/boost/geometry/util/type_traits.hpp
+++ b/boost/geometry/util/type_traits.hpp
@@ -182,6 +182,22 @@ struct enable_if_segment
template <typename Geometry, typename T = void>
using enable_if_segment_t = typename enable_if_segment<Geometry, T>::type;
+template <typename Geometry, typename T = void>
+struct enable_if_linestring
+ : std::enable_if<is_linestring<Geometry>::value, T>
+{};
+
+template <typename Geometry, typename T = void>
+using enable_if_linestring_t = typename enable_if_linestring<Geometry, T>::type;
+
+template <typename Geometry, typename T = void>
+struct enable_if_multi_linestring
+ : std::enable_if<is_multi_linestring<Geometry>::value, T>
+{};
+
+template <typename Geometry, typename T = void>
+using enable_if_multi_linestring_t = typename enable_if_multi_linestring<Geometry, T>::type;
+
template <typename Geometry, typename T = void>
struct enable_if_polylinear
@@ -209,6 +225,30 @@ struct enable_if_box
template <typename Geometry, typename T = void>
using enable_if_box_t = typename enable_if_box<Geometry, T>::type;
+template <typename Geometry, typename T = void>
+struct enable_if_ring
+ : std::enable_if<is_ring<Geometry>::value, T>
+{};
+
+template <typename Geometry, typename T = void>
+using enable_if_ring_t = typename enable_if_ring<Geometry, T>::type;
+
+template <typename Geometry, typename T = void>
+struct enable_if_polygon
+ : std::enable_if<is_polygon<Geometry>::value, T>
+{};
+
+template <typename Geometry, typename T = void>
+using enable_if_polygon_t = typename enable_if_polygon<Geometry, T>::type;
+
+template <typename Geometry, typename T = void>
+struct enable_if_multi_polygon
+ : std::enable_if<is_multi_polygon<Geometry>::value, T>
+{};
+
+template <typename Geometry, typename T = void>
+using enable_if_multi_polygon_t = typename enable_if_multi_polygon<Geometry, T>::type;
+
template <typename Geometry, typename T = void>
struct enable_if_polygonal
@@ -237,6 +277,23 @@ template <typename Geometry, typename T = void>
using enable_if_polysegmental_t = typename enable_if_polysegmental<Geometry, T>::type;
+template <typename Geometry, typename T = void>
+struct enable_if_dynamic_geometry
+ : std::enable_if<is_dynamic_geometry<Geometry>::value, T>
+{};
+
+template <typename Geometry, typename T = void>
+using enable_if_dynamic_geometry_t = typename enable_if_dynamic_geometry<Geometry, T>::type;
+
+template <typename Geometry, typename T = void>
+struct enable_if_geometry_collection
+ : std::enable_if<is_geometry_collection<Geometry>::value, T>
+{};
+
+template <typename Geometry, typename T = void>
+using enable_if_geometry_collection_t = typename enable_if_geometry_collection<Geometry, T>::type;
+
+
} // namespace util
diff --git a/boost/geometry/views/closeable_view.hpp b/boost/geometry/views/closeable_view.hpp
index b8a4ea4ba9..c3c4b14085 100644
--- a/boost/geometry/views/closeable_view.hpp
+++ b/boost/geometry/views/closeable_view.hpp
@@ -4,8 +4,9 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2020-2021.
-// Modifications copyright (c) 2020-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2023.
+// Modifications copyright (c) 2020-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -19,6 +20,7 @@
#define BOOST_GEOMETRY_VIEWS_CLOSEABLE_VIEW_HPP
#include <boost/geometry/core/closure.hpp>
+#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tag.hpp>
#include <boost/geometry/core/tags.hpp>
@@ -55,19 +57,27 @@ private:
};
-// As template alias for now. It's possible that this should be a struct.
-// It'd also prevent instantiating the other, unneeded view.
template
<
typename Range,
closure_selector Close = geometry::closure<Range>::value
>
-using closed_view = std::conditional_t
- <
- Close == open,
- closing_view<Range>,
- identity_view<Range>
- >;
+struct closed_view
+ : identity_view<Range>
+{
+ explicit inline closed_view(Range const& r)
+ : identity_view<Range const>(r)
+ {}
+};
+
+template <typename Range>
+struct closed_view<Range, open>
+ : closing_view<Range>
+{
+ explicit inline closed_view(Range const& r)
+ : closing_view<Range const>(r)
+ {}
+};
} // namespace detail
@@ -109,6 +119,32 @@ struct closeable_view<Range, open>
#endif // DOXYGEN_NO_SPECIALIZATIONS
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+
+template <typename Range, closure_selector Close>
+struct tag<geometry::detail::closed_view<Range, Close> >
+ : geometry::tag<Range>
+{};
+
+template <typename Range, closure_selector Close>
+struct point_order<geometry::detail::closed_view<Range, Close> >
+ : geometry::point_order<Range>
+{};
+
+template <typename Range, closure_selector Close>
+struct closure<geometry::detail::closed_view<Range, Close> >
+{
+ static const closure_selector value = closed;
+};
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
}} // namespace boost::geometry
diff --git a/boost/geometry/views/detail/boundary_view/implementation.hpp b/boost/geometry/views/detail/boundary_view/implementation.hpp
index f3c3ece7a8..8a17b760ce 100644
--- a/boost/geometry/views/detail/boundary_view/implementation.hpp
+++ b/boost/geometry/views/detail/boundary_view/implementation.hpp
@@ -217,7 +217,7 @@ private:
public:
typedef typename base_type::iterator iterator;
typedef typename base_type::const_iterator const_iterator;
-
+
typedef linestring_tag tag_type;
explicit ring_boundary(Ring& ring)
diff --git a/boost/geometry/views/detail/closed_clockwise_view.hpp b/boost/geometry/views/detail/closed_clockwise_view.hpp
index 5fdd6dd5b4..2d76409d2e 100644
--- a/boost/geometry/views/detail/closed_clockwise_view.hpp
+++ b/boost/geometry/views/detail/closed_clockwise_view.hpp
@@ -5,7 +5,8 @@
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2014-2021.
-// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
+// Modifications copyright (c) 2014-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -47,7 +48,7 @@ struct closed_clockwise_view
{
using closed_view = detail::closed_view<Range const, Closure>;
using view = detail::clockwise_view<closed_view const, Order>;
-
+
explicit inline closed_clockwise_view(Range const& r)
: m_view(closed_view(r))
{}
@@ -67,6 +68,31 @@ private:
#endif // DOXYGEN_NO_DETAIL
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename Range, closure_selector Closure, order_selector Order>
+struct tag<geometry::detail::closed_clockwise_view<Range, Closure, Order> >
+ : geometry::tag<Range>
+{};
+
+template <typename Range, closure_selector Closure, order_selector Order>
+struct point_order<geometry::detail::closed_clockwise_view<Range, Closure, Order> >
+{
+ static const order_selector value = clockwise;
+};
+
+template <typename Range, closure_selector Closure, order_selector Order>
+struct closure<geometry::detail::closed_clockwise_view<Range, Closure, Order> >
+{
+ static const closure_selector value = closed;
+};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
}} // namespace boost::geometry
diff --git a/boost/geometry/views/detail/geometry_collection_view.hpp b/boost/geometry/views/detail/geometry_collection_view.hpp
new file mode 100644
index 0000000000..be3c294711
--- /dev/null
+++ b/boost/geometry/views/detail/geometry_collection_view.hpp
@@ -0,0 +1,84 @@
+// Boost.Geometry
+
+// Copyright (c) 2022, Oracle and/or its affiliates.
+
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_VIEWS_GEOMETRY_COLLECTION_VIEW_HPP
+#define BOOST_GEOMETRY_VIEWS_GEOMETRY_COLLECTION_VIEW_HPP
+
+#include <boost/core/addressof.hpp>
+
+#include <boost/geometry/core/geometry_types.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/core/visit.hpp>
+#include <boost/geometry/util/sequence.hpp>
+
+namespace boost { namespace geometry
+{
+
+namespace detail
+{
+
+
+template <typename Geometry>
+class geometry_collection_view
+{
+public:
+ using iterator = Geometry const*;
+ using const_iterator = Geometry const*;
+
+ explicit geometry_collection_view(Geometry const& geometry)
+ : m_geometry(geometry)
+ {}
+
+ const_iterator begin() const { return boost::addressof(m_geometry); }
+ const_iterator end() const { return boost::addressof(m_geometry) + 1; }
+
+private:
+ Geometry const& m_geometry;
+};
+
+} // namespace detail
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template <typename Geometry>
+struct tag<geometry::detail::geometry_collection_view<Geometry>>
+{
+ using type = geometry_collection_tag;
+};
+
+
+template <typename Geometry>
+struct geometry_types<geometry::detail::geometry_collection_view<Geometry>>
+{
+ using type = util::type_sequence<Geometry>;
+};
+
+
+template <typename Geometry>
+struct iter_visit<geometry::detail::geometry_collection_view<Geometry>>
+{
+ template <typename Function, typename Iterator>
+ static void apply(Function && function, Iterator iterator)
+ {
+ function(*iterator);
+ }
+};
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_VIEWS_GEOMETRY_COLLECTION_VIEW_HPP
diff --git a/boost/geometry/views/detail/random_access_view.hpp b/boost/geometry/views/detail/random_access_view.hpp
new file mode 100644
index 0000000000..e7c1227554
--- /dev/null
+++ b/boost/geometry/views/detail/random_access_view.hpp
@@ -0,0 +1,222 @@
+// Boost.Geometry
+
+// Copyright (c) 2022-2023, Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
+// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
+
+// Licensed under the Boost Software License version 1.0.
+// http://www.boost.org/users/license.html
+
+#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_RANDOM_ACCESS_VIEW_HPP
+#define BOOST_GEOMETRY_VIEWS_DETAIL_RANDOM_ACCESS_VIEW_HPP
+
+#include <vector>
+
+#include <boost/range/begin.hpp>
+#include <boost/range/end.hpp>
+#include <boost/range/iterator.hpp>
+#include <boost/range/size.hpp>
+
+#include <boost/geometry/algorithms/detail/visit.hpp>
+#include <boost/geometry/core/geometry_types.hpp>
+#include <boost/geometry/core/tag.hpp>
+#include <boost/geometry/core/tags.hpp>
+#include <boost/geometry/util/sequence.hpp>
+#include <boost/geometry/util/type_traits.hpp>
+
+namespace boost { namespace geometry
+{
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+
+template <typename Range>
+struct is_random_access_range
+ : std::is_convertible
+ <
+ typename boost::iterator_traversal
+ <
+ typename boost::range_iterator<Range>::type
+ >::type,
+ boost::random_access_traversal_tag
+ >
+{};
+
+template <typename Geometry>
+struct is_geometry_collection_recursive
+ : util::bool_constant
+ <
+ util::is_geometry_collection
+ <
+ typename util::sequence_find_if
+ <
+ typename traits::geometry_types<std::remove_const_t<Geometry>>::type,
+ util::is_geometry_collection
+ >::type
+ >::value
+ >
+{};
+
+template
+<
+ typename GeometryCollection,
+ bool IsRandomAccess = is_random_access_range<GeometryCollection>::value,
+ bool IsRecursive = is_geometry_collection_recursive<GeometryCollection>::value
+>
+class random_access_view
+ : public std::vector<typename boost::range_iterator<GeometryCollection>::type>
+{
+ // NOTE: An alternative would be to implement iterator holding base iterators
+ // to geometry collections of lower levels to process after the current level
+ // of bfs traversal is finished.
+
+ using base_t = std::vector<typename boost::range_iterator<GeometryCollection>::type>;
+
+public:
+ random_access_view(GeometryCollection & geometry)
+ {
+ this->reserve(boost::size(geometry));
+ detail::visit_breadth_first_impl<true>::apply([&](auto&&, auto iter)
+ {
+ this->push_back(iter);
+ return true;
+ }, geometry);
+ }
+};
+
+template <typename GeometryCollection>
+class random_access_view<GeometryCollection, true, false>
+{
+public:
+ using iterator = typename boost::range_iterator<GeometryCollection>::type;
+ using const_iterator = typename boost::range_const_iterator<GeometryCollection>::type;
+
+ random_access_view(GeometryCollection & geometry)
+ : m_begin(boost::begin(geometry))
+ , m_end(boost::end(geometry))
+ {}
+
+ iterator begin() { return m_begin; }
+ iterator end() { return m_end; }
+ const_iterator begin() const { return m_begin; }
+ const_iterator end() const { return m_end; }
+
+private:
+ iterator m_begin, m_end;
+};
+
+
+template <typename GeometryCollection>
+struct random_access_view_iter_visit
+{
+ template <typename Function, typename Iterator>
+ static void apply(Function && function, Iterator iterator)
+ {
+ geometry::traits::iter_visit
+ <
+ std::remove_const_t<GeometryCollection>
+ >::apply(std::forward<Function>(function), *iterator);
+ }
+};
+
+
+template <typename ...Ts>
+struct remove_geometry_collections_pack
+{
+ using type = util::type_sequence<>;
+};
+
+template <typename T, typename ...Ts>
+struct remove_geometry_collections_pack<T, Ts...>
+{
+ using next_sequence = typename remove_geometry_collections_pack<Ts...>::type;
+ using type = std::conditional_t
+ <
+ util::is_geometry_collection<T>::value,
+ next_sequence,
+ typename util::sequence_merge<util::type_sequence<T>, next_sequence>::type
+ >;
+};
+
+template <typename Types>
+struct remove_geometry_collections;
+
+template <typename ...Ts>
+struct remove_geometry_collections<util::type_sequence<Ts...>>
+ : remove_geometry_collections_pack<Ts...>
+{};
+
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+template<typename GeometryCollection, bool IsRandomAccess, bool IsRecursive>
+struct tag<geometry::detail::random_access_view<GeometryCollection, IsRandomAccess, IsRecursive>>
+{
+ using type = geometry_collection_tag;
+};
+
+
+template <typename GeometryCollection>
+struct iter_visit<geometry::detail::random_access_view<GeometryCollection, false, false>>
+ : geometry::detail::random_access_view_iter_visit<GeometryCollection>
+{};
+
+template <typename GeometryCollection>
+struct iter_visit<geometry::detail::random_access_view<GeometryCollection, true, true>>
+ : geometry::detail::random_access_view_iter_visit<GeometryCollection>
+{};
+
+template <typename GeometryCollection>
+struct iter_visit<geometry::detail::random_access_view<GeometryCollection, false, true>>
+ : geometry::detail::random_access_view_iter_visit<GeometryCollection>
+{};
+
+template <typename GeometryCollection>
+struct iter_visit<geometry::detail::random_access_view<GeometryCollection, true, false>>
+{
+ template <typename Function, typename Iterator>
+ static void apply(Function && function, Iterator iterator)
+ {
+ geometry::traits::iter_visit
+ <
+ std::remove_const_t<GeometryCollection>
+ >::apply(std::forward<Function>(function), iterator);
+ }
+};
+
+
+template <typename GeometryCollection, bool IsRandomAccess>
+struct geometry_types<geometry::detail::random_access_view<GeometryCollection, IsRandomAccess, false>>
+ : traits::geometry_types
+ <
+ std::remove_const_t<GeometryCollection>
+ >
+{};
+
+template <typename GeometryCollection, bool IsRandomAccess>
+struct geometry_types<geometry::detail::random_access_view<GeometryCollection, IsRandomAccess, true>>
+ : geometry::detail::remove_geometry_collections
+ <
+ typename traits::geometry_types
+ <
+ std::remove_const_t<GeometryCollection>
+ >::type
+ >
+{};
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_VIEWS_DETAIL_RANDOM_ACCESS_VIEW_HPP
diff --git a/boost/geometry/views/reversible_view.hpp b/boost/geometry/views/reversible_view.hpp
index 90446135a7..5aad54382c 100644
--- a/boost/geometry/views/reversible_view.hpp
+++ b/boost/geometry/views/reversible_view.hpp
@@ -4,8 +4,9 @@
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2020-2021.
-// Modifications copyright (c) 2020-2021 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2020-2023.
+// Modifications copyright (c) 2020-2023 Oracle and/or its affiliates.
+// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
@@ -22,6 +23,7 @@
#include <boost/version.hpp>
#include <boost/range/adaptor/reversed.hpp>
+#include <boost/geometry/core/closure.hpp>
#include <boost/geometry/core/point_order.hpp>
#include <boost/geometry/core/ring_type.hpp>
#include <boost/geometry/core/tag.hpp>
@@ -40,19 +42,27 @@ namespace detail
{
-// As template alias for now. It's possible that this should be a struct.
-// It'd also prevent instantiating the other, unneeded view.
template
<
typename Range,
order_selector Order = geometry::point_order<Range>::value
>
-using clockwise_view = std::conditional_t
- <
- Order == counterclockwise,
- boost::reversed_range<Range>,
- identity_view<Range>
- >;
+struct clockwise_view
+ : identity_view<Range>
+{
+ explicit inline clockwise_view(Range& r)
+ : identity_view<Range>(r)
+ {}
+};
+
+template <typename Range>
+struct clockwise_view<Range, counterclockwise>
+ : boost::reversed_range<Range>
+{
+ explicit inline clockwise_view(Range& r)
+ : boost::reversed_range<Range>(r)
+ {}
+};
} // namespace detail
@@ -87,6 +97,32 @@ struct reversible_view<Range, iterate_reverse>
#endif // DOXYGEN_NO_SPECIALIZATIONS
+#ifndef DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+namespace traits
+{
+
+
+template <typename Range, order_selector Order>
+struct tag<geometry::detail::clockwise_view<Range, Order> >
+ : geometry::tag<Range>
+{};
+
+template <typename Range, order_selector Order>
+struct point_order<geometry::detail::clockwise_view<Range, Order> >
+{
+ static const order_selector value = clockwise;
+};
+
+template <typename Range, order_selector Order>
+struct closure<geometry::detail::clockwise_view<Range, Order> >
+ : geometry::closure<Range>
+{};
+
+
+} // namespace traits
+#endif // DOXYGEN_NO_TRAITS_SPECIALIZATIONS
+
+
}} // namespace boost::geometry