From d1c21baf6079e01bd83d6829aa7d980bbe5bde75 Mon Sep 17 00:00:00 2001 From: Vissarion Fysikopoulos Date: Mon, 15 Aug 2016 19:38:46 +0300 Subject: [PATCH] merge and resolve conflicts --- .../doxygen_input/sourcecode/doxygen_5.cpp | 8 +- doc/quickbook/quickref.xml | 44 +- doc/release_notes.qbk | 4 + extensions/test/algorithms/dissolve.cpp | 11 +- include/boost/geometry/algorithms/append.hpp | 2 +- include/boost/geometry/algorithms/area.hpp | 7 +- include/boost/geometry/algorithms/assign.hpp | 18 +- include/boost/geometry/algorithms/buffer.hpp | 12 +- .../boost/geometry/algorithms/centroid.hpp | 2 +- include/boost/geometry/algorithms/clear.hpp | 2 +- include/boost/geometry/algorithms/convert.hpp | 2 +- .../boost/geometry/algorithms/convex_hull.hpp | 10 +- include/boost/geometry/algorithms/correct.hpp | 2 +- .../boost/geometry/algorithms/covered_by.hpp | 6 +- include/boost/geometry/algorithms/crosses.hpp | 4 +- .../algorithms/detail/assign_box_corners.hpp | 4 +- .../detail/assign_indexed_point.hpp | 8 +- .../buffer/buffered_piece_collection.hpp | 25 +- .../detail/buffer/buffered_ring.hpp | 16 + .../detail/comparable_distance/interface.hpp | 8 +- .../algorithms/detail/disjoint/interface.hpp | 2 +- .../algorithms/detail/distance/interface.hpp | 8 +- .../algorithms/detail/envelope/interface.hpp | 4 +- .../detail/equals/collect_vectors.hpp | 2 +- .../algorithms/detail/expand/interface.hpp | 8 +- .../algorithms/detail/extreme_points.hpp | 6 +- .../detail/intersection/interface.hpp | 4 +- .../algorithms/detail/is_simple/interface.hpp | 2 +- .../algorithms/detail/is_valid/interface.hpp | 2 +- .../detail/overlay/cluster_info.hpp | 49 ++ .../detail/overlay/copy_segment_point.hpp | 14 +- .../detail/overlay/copy_segments.hpp | 2 +- .../overlay/enrich_intersection_points.hpp | 11 +- .../detail/overlay/enrichment_info.hpp | 6 +- .../overlay/get_intersection_points.hpp | 2 +- .../algorithms/detail/overlay/get_turns.hpp | 2 +- .../detail/overlay/handle_colocations.hpp | 172 +++- .../detail/overlay/handle_touch.hpp | 336 ------- .../detail/overlay/intersection_insert.hpp | 8 +- .../algorithms/detail/overlay/overlay.hpp | 31 +- .../detail/overlay/overlay_type.hpp | 38 + .../detail/overlay/select_rings.hpp | 6 +- .../detail/overlay/self_turn_points.hpp | 2 +- .../detail/overlay/sort_by_side.hpp | 190 +++- .../algorithms/detail/overlay/traversal.hpp | 672 ++++++++++++++ .../detail/overlay/traversal_ring_creator.hpp | 347 ++++++++ .../overlay/traversal_switch_detector.hpp | 291 +++++++ .../algorithms/detail/overlay/traverse.hpp | 819 +----------------- .../algorithms/detail/overlay/turn_info.hpp | 16 +- .../algorithms/detail/overlay/visit_info.hpp | 5 + .../algorithms/detail/point_on_border.hpp | 4 +- .../algorithms/detail/recalculate.hpp | 4 +- .../algorithms/detail/relate/interface.hpp | 4 +- .../algorithms/detail/relation/interface.hpp | 4 +- .../algorithms/detail/ring_identifier.hpp | 5 + .../detail/sections/range_by_section.hpp | 2 +- .../detail/sections/sectionalize.hpp | 2 +- .../detail/within/point_in_geometry.hpp | 2 +- .../boost/geometry/algorithms/difference.hpp | 18 +- include/boost/geometry/algorithms/equals.hpp | 2 +- .../boost/geometry/algorithms/for_each.hpp | 4 +- .../boost/geometry/algorithms/intersects.hpp | 6 +- .../boost/geometry/algorithms/is_empty.hpp | 2 +- include/boost/geometry/algorithms/length.hpp | 4 +- include/boost/geometry/algorithms/make.hpp | 12 +- .../geometry/algorithms/num_geometries.hpp | 2 +- .../algorithms/num_interior_rings.hpp | 2 +- .../boost/geometry/algorithms/num_points.hpp | 2 +- .../geometry/algorithms/num_segments.hpp | 2 +- .../boost/geometry/algorithms/overlaps.hpp | 4 +- .../boost/geometry/algorithms/perimeter.hpp | 2 +- .../geometry/algorithms/point_on_surface.hpp | 4 +- .../geometry/algorithms/remove_spikes.hpp | 2 +- include/boost/geometry/algorithms/reverse.hpp | 2 +- .../boost/geometry/algorithms/simplify.hpp | 14 +- .../geometry/algorithms/sym_difference.hpp | 18 +- include/boost/geometry/algorithms/touches.hpp | 6 +- .../boost/geometry/algorithms/transform.hpp | 4 +- include/boost/geometry/algorithms/union.hpp | 12 +- include/boost/geometry/algorithms/unique.hpp | 2 +- include/boost/geometry/algorithms/within.hpp | 6 +- .../boost/geometry/arithmetic/arithmetic.hpp | 30 +- .../geometry/arithmetic/cross_product.hpp | 10 +- .../boost/geometry/arithmetic/determinant.hpp | 4 +- .../boost/geometry/arithmetic/dot_product.hpp | 4 +- .../extensions/algebra/algorithms/assign.hpp | 2 +- .../algebra/algorithms/rotation.hpp | 4 +- .../algorithms/transform_geometrically.hpp | 12 +- .../algebra/algorithms/translation.hpp | 4 +- .../algebra/geometries/concepts/check.hpp | 12 +- .../geometries/concepts/matrix_concept.hpp | 4 +- .../concepts/quaternion_concept.hpp | 4 +- .../concepts/rotation_matrix_concept.hpp | 4 +- .../concepts/rotation_quaternion_concept.hpp | 4 +- .../geometries/concepts/vector_concept.hpp | 4 +- .../extensions/algebra/geometries/matrix.hpp | 2 +- .../algebra/geometries/quaternion.hpp | 2 +- .../algebra/geometries/rotation_matrix.hpp | 2 +- .../geometries/rotation_quaternion.hpp | 2 +- .../extensions/algebra/geometries/vector.hpp | 2 +- .../extensions/algorithms/connect.hpp | 8 +- .../algorithms/detail/overlay/dissolver.hpp | 4 +- .../algorithms/detail/overlay/split_rings.hpp | 4 +- .../extensions/algorithms/dissolve.hpp | 114 ++- .../extensions/algorithms/distance_info.hpp | 6 +- .../extensions/algorithms/midpoints.hpp | 2 +- .../geometry/extensions/algorithms/offset.hpp | 4 +- .../geometry/extensions/algorithms/parse.hpp | 6 +- .../extensions/algorithms/remove_holes_if.hpp | 2 +- .../extensions/algorithms/remove_marked.hpp | 2 +- .../extensions/algorithms/selected.hpp | 4 +- .../gis/io/veshape/write_veshape.hpp | 6 +- .../nsphere/geometries/concepts/check.hpp | 4 +- .../geometries/concepts/nsphere_concept.hpp | 6 +- .../extensions/nsphere/geometries/nsphere.hpp | 2 +- .../geometry/formulas/andoyer_inverse.hpp | 20 +- .../formulas/differential_quantities.hpp | 254 ++++-- .../formulas/gnomonic_intersection.hpp | 148 ++++ .../geometry/formulas/gnomonic_spheroid.hpp | 14 +- .../formulas/sjoberg_intersection.hpp | 385 ++++++++ .../boost/geometry/formulas/thomas_direct.hpp | 117 ++- .../geometry/formulas/thomas_inverse.hpp | 12 +- .../geometry/formulas/vincenty_direct.hpp | 5 +- .../geometry/formulas/vincenty_inverse.hpp | 5 +- include/boost/geometry/geometries/box.hpp | 2 +- .../geometries/concepts/box_concept.hpp | 4 +- .../geometry/geometries/concepts/check.hpp | 40 +- .../concepts/linestring_concept.hpp | 8 +- .../concepts/multi_linestring_concept.hpp | 8 +- .../concepts/multi_point_concept.hpp | 8 +- .../concepts/multi_polygon_concept.hpp | 8 +- .../geometries/concepts/point_concept.hpp | 4 +- .../geometries/concepts/polygon_concept.hpp | 12 +- .../geometries/concepts/ring_concept.hpp | 8 +- .../geometries/concepts/segment_concept.hpp | 8 +- .../boost/geometry/geometries/linestring.hpp | 2 +- .../geometry/geometries/multi_linestring.hpp | 2 +- .../boost/geometry/geometries/multi_point.hpp | 2 +- .../geometry/geometries/multi_polygon.hpp | 2 +- .../geometry/geometries/pointing_segment.hpp | 4 +- include/boost/geometry/geometries/polygon.hpp | 2 +- include/boost/geometry/geometries/ring.hpp | 2 +- include/boost/geometry/geometries/segment.hpp | 6 +- .../index/detail/algorithms/bounds.hpp | 2 +- include/boost/geometry/io/dsv/write.hpp | 2 +- include/boost/geometry/io/io.hpp | 2 +- include/boost/geometry/io/svg/svg_mapper.hpp | 122 +-- include/boost/geometry/io/svg/write.hpp | 29 +- include/boost/geometry/io/wkt/read.hpp | 2 +- include/boost/geometry/io/wkt/write.hpp | 2 +- .../strategies/cartesian/cart_intersect.hpp | 4 +- .../cartesian/distance_pythagoras.hpp | 4 +- .../cartesian/distance_pythagoras_box_box.hpp | 4 +- .../distance_pythagoras_point_box.hpp | 4 +- .../strategies/concepts/area_concept.hpp | 4 +- .../strategies/concepts/centroid_concept.hpp | 4 +- .../concepts/convex_hull_concept.hpp | 4 +- .../strategies/concepts/distance_concept.hpp | 4 +- .../concepts/segment_intersect_concept.hpp | 4 +- .../strategies/concepts/simplify_concept.hpp | 6 +- .../strategies/concepts/within_concept.hpp | 18 +- .../spherical/distance_cross_track.hpp | 4 +- .../distance_cross_track_point_box.hpp | 2 +- .../strategies/spherical/intersection.hpp | 4 +- .../geometry/util/for_each_coordinate.hpp | 4 +- test/Jamfile.v2 | 1 + test/algorithms/buffer/buffer_linestring.cpp | 4 +- .../buffer/buffer_multi_polygon.cpp | 9 +- test/algorithms/buffer/buffer_polygon.cpp | 2 +- test/algorithms/distance/distance.cpp | 2 +- test/algorithms/overlay/handle_touch.cpp | 516 ----------- .../overlay/multi_overlay_cases.hpp | 202 ++++- test/algorithms/overlay/overlay.cpp | 5 +- test/algorithms/overlay/overlay_cases.hpp | 12 +- test/algorithms/overlay/traverse_multi.cpp | 7 +- .../set_operations/difference/difference.cpp | 206 +++-- .../difference/difference_multi.cpp | 115 +-- .../difference/difference_multi_spike.cpp | 9 +- .../difference/test_difference.hpp | 3 +- .../intersection/intersection.cpp | 65 +- .../intersection/intersection_multi.cpp | 58 +- .../intersection/test_intersection.hpp | 4 +- .../set_operations/union/test_union.hpp | 21 +- .../algorithms/set_operations/union/union.cpp | 49 +- .../set_operations/union/union_multi.cpp | 150 +++- test/algorithms/test_simplify.hpp | 6 +- test/concepts/function_asserting_a_point.hpp | 4 +- test/concepts/function_requiring_a_point.hpp | 4 +- test/concepts/linestring_concept.cpp | 4 +- test/concepts/point_concept_checker.cpp | 4 +- ...int_geographic_custom_with_wrong_units.cpp | 2 +- .../point_geographic_with_wrong_units.cpp | 2 +- ...oint_spherical_custom_with_wrong_units.cpp | 2 +- .../point_well_formed_non_cartesian.cpp | 20 +- test/formulas/Jamfile.v2 | 16 + test/formulas/direct.cpp | 66 ++ test/formulas/direct_cases.hpp | 452 ++++++++++ test/formulas/intersection.cpp | 87 ++ test/formulas/intersection_cases.hpp | 129 +++ test/formulas/inverse.cpp | 71 ++ test/formulas/inverse_cases.hpp | 480 ++++++++++ test/formulas/test_formula.hpp | 59 ++ test/geometries/adapted.cpp | 6 +- test/geometries/boost_polygon.cpp | 6 +- test/geometries/concepts/check.cpp | 4 +- test/geometries/custom_linestring.cpp | 4 +- test/geometries/segment.cpp | 6 +- test/strategies/andoyer.cpp | 2 +- test/strategies/cross_track.cpp | 2 +- test/strategies/haversine.cpp | 2 +- test/strategies/pythagoras.cpp | 2 +- test/strategies/pythagoras_point_box.cpp | 2 +- test/strategies/test_projected_point.hpp | 6 +- test/strategies/test_within.hpp | 2 +- test/strategies/thomas.cpp | 2 +- test/strategies/vincenty.cpp | 2 +- 216 files changed, 5230 insertions(+), 2690 deletions(-) create mode 100644 include/boost/geometry/algorithms/detail/overlay/cluster_info.hpp delete mode 100644 include/boost/geometry/algorithms/detail/overlay/handle_touch.hpp create mode 100644 include/boost/geometry/algorithms/detail/overlay/traversal.hpp create mode 100644 include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp create mode 100644 include/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp create mode 100644 include/boost/geometry/formulas/gnomonic_intersection.hpp create mode 100644 include/boost/geometry/formulas/sjoberg_intersection.hpp delete mode 100644 test/algorithms/overlay/handle_touch.cpp create mode 100644 test/formulas/Jamfile.v2 create mode 100644 test/formulas/direct.cpp create mode 100644 test/formulas/direct_cases.hpp create mode 100644 test/formulas/intersection.cpp create mode 100644 test/formulas/intersection_cases.hpp create mode 100644 test/formulas/inverse.cpp create mode 100644 test/formulas/inverse_cases.hpp create mode 100644 test/formulas/test_formula.hpp diff --git a/doc/doxy/doxygen_input/sourcecode/doxygen_5.cpp b/doc/doxy/doxygen_input/sourcecode/doxygen_5.cpp index 942df9285..02a888b33 100644 --- a/doc/doxy/doxygen_input/sourcecode/doxygen_5.cpp +++ b/doc/doxy/doxygen_input/sourcecode/doxygen_5.cpp @@ -47,7 +47,7 @@ namespace example_legacy_point1 // The first way to check a concept at compile time: checking if the input is parameter // or return type is OK. template - BOOST_CONCEPT_REQUIRES(((boost::geometry::concept::Point

)), (void)) + BOOST_CONCEPT_REQUIRES(((boost::geometry::concepts::Point

)), (void)) test1(P& p) { } @@ -57,7 +57,7 @@ namespace example_legacy_point1 template void test2(P& p) { - BOOST_CONCEPT_ASSERT((boost::geometry::concept::Point

)); + BOOST_CONCEPT_ASSERT((boost::geometry::concepts::Point

)); } @@ -90,7 +90,7 @@ namespace example_legacy_point2 // test it using boost concept requires template - BOOST_CONCEPT_REQUIRES(((boost::geometry::concept::ConstPoint

)), (double)) + BOOST_CONCEPT_REQUIRES(((boost::geometry::concepts::ConstPoint

)), (double)) test3(P& p) { return boost::geometry::get<0>(p); @@ -123,7 +123,7 @@ namespace example_custom_linestring1 void example() { typedef custom_linestring1 L; - BOOST_CONCEPT_ASSERT((boost::geometry::concept::Linestring)); + BOOST_CONCEPT_ASSERT((boost::geometry::concepts::Linestring)); } } diff --git a/doc/quickbook/quickref.xml b/doc/quickbook/quickref.xml index 8179d7a87..3188d3287 100644 --- a/doc/quickbook/quickref.xml +++ b/doc/quickbook/quickref.xml @@ -32,28 +32,28 @@ 0-dimensional - boost::geometry::concept::Point - boost::geometry::concept::ConstPoint + boost::geometry::concepts::Point + boost::geometry::concepts::ConstPoint 1-dimensional - boost::geometry::concept::Segment - boost::geometry::concept::ConstSegment - boost::geometry::concept::Linestring - boost::geometry::concept::ConstLinestring + boost::geometry::concepts::Segment + boost::geometry::concepts::ConstSegment + boost::geometry::concepts::Linestring + boost::geometry::concepts::ConstLinestring 2-dimensional - boost::geometry::concept::Box - boost::geometry::concept::ConstBox - boost::geometry::concept::Ring - boost::geometry::concept::ConstRing - boost::geometry::concept::Polygon - boost::geometry::concept::ConstPolygon + boost::geometry::concepts::Box + boost::geometry::concepts::ConstBox + boost::geometry::concepts::Ring + boost::geometry::concepts::ConstRing + boost::geometry::concepts::Polygon + boost::geometry::concepts::ConstPolygon @@ -61,8 +61,8 @@ Functions - boost::geometry::concept::check - boost::geometry::concept::check_concepts_and_equal_dimensions + boost::geometry::concepts::check + boost::geometry::concepts::check_concepts_and_equal_dimensions @@ -496,18 +496,18 @@ - boost::geometry::concept::AreaStrategy - boost::geometry::concept::CentroidStrategy - boost::geometry::concept::ConvexHullStrategy - boost::geometry::concept::PointDistanceStrategy - boost::geometry::concept::PointSegmentDistanceStrategy + boost::geometry::concepts::AreaStrategy + boost::geometry::concepts::CentroidStrategy + boost::geometry::concepts::ConvexHullStrategy + boost::geometry::concepts::PointDistanceStrategy + boost::geometry::concepts::PointSegmentDistanceStrategy - boost::geometry::concept::SegmentIntersectStrategy - boost::geometry::concept::SimplifyStrategy - boost::geometry::concept::WithinStrategy + boost::geometry::concepts::SegmentIntersectStrategy + boost::geometry::concepts::SimplifyStrategy + boost::geometry::concepts::WithinStrategy diff --git a/doc/release_notes.qbk b/doc/release_notes.qbk index 2981028d8..cd7e52951 100644 --- a/doc/release_notes.qbk +++ b/doc/release_notes.qbk @@ -24,12 +24,16 @@ [*Improvements] +* Union: take care that output is valid (with some exceptions), also with self-tangent polygons or shared edges * SVG: support boost::variant of geometries +* SVG: coordinates are now written as double (by default) to svg +* Rename namespace concept to concepts to avoid conflicts with the newest compilers [*Solved tickets] * [@https://svn.boost.org/trac/boost/ticket/12189 12189] Relational operations not compiling when point types of inputs are different * [@https://svn.boost.org/trac/boost/ticket/12287 12287] Invalid result of rtree.query() for contains() predicate +* [@https://svn.boost.org/trac/boost/ticket/12289 12289] Avoid warning/compilation error for std::cout [/=================] [heading Boost 1.61] diff --git a/extensions/test/algorithms/dissolve.cpp b/extensions/test/algorithms/dissolve.cpp index 08cf6b2a4..9a0921b72 100644 --- a/extensions/test/algorithms/dissolve.cpp +++ b/extensions/test/algorithms/dissolve.cpp @@ -209,21 +209,23 @@ void test_all() "POLYGON((1 2,1 1,2 1,2 2.25,3 2.25,3 0,0 0,0 3,3 3,2.75 2,1 2))", 1, 12, 7.9296875); +#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS // Self intersecting in last segment test_one("3", "POLYGON((0 2,2 4,2 0,4 2,0 2))", 0, 8, 4.0); - // Self tangent + // Self tangent - polygons are now included twice test_one("4", "POLYGON((0 0,0 4,4 4,4 0,2 4,0 0))", 0, 8, 8.0); - // Self tangent in corner + // Self tangent in corner - polygons are now included twice test_one("5", "POLYGON((0 0,0 4,4 4,4 0,0 4,2 0,0 0))", 0, 8, 12.0); +#endif // With spike @@ -273,6 +275,9 @@ void test_all() "POLYGON((5 0,2.5 9,9.5 3.5,0.5 3.5,7.5 9,5 0))", 0, 11, 25.6158412); +#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS + // Poygons contain too many polygons + // CCW polygons should turn CW after dissolve test_one("cw", "POLYGON((2 8,8 8,8 0,0 0,0 6,4 6,4 4,2 4,2 8))", @@ -284,6 +289,7 @@ void test_all() test_one("ticket_10713", "POLYGON((-0.7189743518829346 4.1308121681213379, 0.0831791982054710 4.1034231185913086, 0.1004156470298767 4.1107301712036133, 0.1044322624802589 4.1026973724365234, 0.0831791982054710 4.1034231185913086, -0.7711903452873230 3.7412264347076416, -0.7189743518829346 4.1308121681213379))", 0, 8, 0.157052766); +#endif // Multi-geometries @@ -347,7 +353,6 @@ void test_all() test_one("ticket17", ticket17, 1, 228, 0.00920834633689); - return; // next one does not work for gcc/linux // Real-life std::string const toolkit = "POLYGON((170718 605997,170718 605997,170776 606016,170773 606015,170786 606020,170778 606016,170787 606021,170781 606017,170795 606028,170795 606028,170829 606055,170939 606140,170933 605968,170933 605968,170932 605908,170929 605834,170920 605866,170961 605803,170739 605684,170699 605749,170691 605766,170693 605762,170686 605775,170688 605771,170673 605794,170676 605790,170668 605800,170672 605796,170651 605818,170653 605816,170639 605829,170568 605899,170662 605943,170633 605875,170603 605961,170718 605997))"; test_one("toolkit", toolkit, diff --git a/include/boost/geometry/algorithms/append.hpp b/include/boost/geometry/algorithms/append.hpp index 894f52c68..5cfad0c52 100644 --- a/include/boost/geometry/algorithms/append.hpp +++ b/include/boost/geometry/algorithms/append.hpp @@ -284,7 +284,7 @@ struct append int ring_index, int multi_index) { - concept::check(); + concepts::check(); dispatch::append::apply(geometry, range_or_point, ring_index, diff --git a/include/boost/geometry/algorithms/area.hpp b/include/boost/geometry/algorithms/area.hpp index 1d68b2c37..4751d4e74 100644 --- a/include/boost/geometry/algorithms/area.hpp +++ b/include/boost/geometry/algorithms/area.hpp @@ -82,7 +82,7 @@ struct ring_area static inline typename Strategy::return_type apply(Ring const& ring, Strategy const& strategy) { - BOOST_CONCEPT_ASSERT( (geometry::concept::AreaStrategy) ); + BOOST_CONCEPT_ASSERT( (geometry::concepts::AreaStrategy) ); assert_dimension(); // Ignore warning (because using static method sometimes) on strategy @@ -266,7 +266,7 @@ and Geographic as well. template inline typename default_area_result::type area(Geometry const& geometry) { - concept::check(); + concepts::check(); // TODO put this into a resolve_strategy stage // (and take the return type from resolve_variant) @@ -310,7 +310,7 @@ template inline typename Strategy::return_type area( Geometry const& geometry, Strategy const& strategy) { - concept::check(); + concepts::check(); // detail::throw_on_empty_input(geometry); @@ -320,4 +320,5 @@ inline typename Strategy::return_type area( }} // namespace boost::geometry + #endif // BOOST_GEOMETRY_ALGORITHMS_AREA_HPP diff --git a/include/boost/geometry/algorithms/assign.hpp b/include/boost/geometry/algorithms/assign.hpp index e3d664de3..589a5c545 100644 --- a/include/boost/geometry/algorithms/assign.hpp +++ b/include/boost/geometry/algorithms/assign.hpp @@ -69,7 +69,7 @@ namespace boost { namespace geometry template inline void assign_points(Geometry& geometry, Range const& range) { - concept::check(); + concepts::check(); clear(geometry); geometry::append(geometry, range, -1, 0); @@ -96,7 +96,7 @@ collect the minimum bounding box of a geometry. template inline void assign_inverse(Geometry& geometry) { - concept::check(); + concepts::check(); dispatch::assign_inverse < @@ -116,7 +116,7 @@ inline void assign_inverse(Geometry& geometry) template inline void assign_zero(Geometry& geometry) { - concept::check(); + concepts::check(); dispatch::assign_zero < @@ -146,7 +146,7 @@ inline void assign_zero(Geometry& geometry) template inline void assign_values(Geometry& geometry, Type const& c1, Type const& c2) { - concept::check(); + concepts::check(); dispatch::assign < @@ -179,7 +179,7 @@ template inline void assign_values(Geometry& geometry, Type const& c1, Type const& c2, Type const& c3) { - concept::check(); + concepts::check(); dispatch::assign < @@ -206,7 +206,7 @@ template inline void assign_values(Geometry& geometry, Type const& c1, Type const& c2, Type const& c3, Type const& c4) { - concept::check(); + concepts::check(); dispatch::assign < @@ -227,9 +227,9 @@ struct assign static inline void apply(Geometry1& geometry1, const Geometry2& geometry2) { - concept::check(); - concept::check(); - concept::check_concepts_and_equal_dimensions(); + concepts::check(); + concepts::check(); + concepts::check_concepts_and_equal_dimensions(); static bool const same_point_order = point_order::value == point_order::value; diff --git a/include/boost/geometry/algorithms/buffer.hpp b/include/boost/geometry/algorithms/buffer.hpp index 5dfe9d884..e1d3c20e4 100644 --- a/include/boost/geometry/algorithms/buffer.hpp +++ b/include/boost/geometry/algorithms/buffer.hpp @@ -182,8 +182,8 @@ template inline void buffer(Input const& geometry_in, Output& geometry_out, Distance const& distance, Distance const& chord_length = -1) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); resolve_variant::buffer::apply(geometry_in, distance, chord_length, geometry_out); } @@ -204,8 +204,8 @@ inline void buffer(Input const& geometry_in, Output& geometry_out, template Output return_buffer(Input const& geometry, Distance const& distance, Distance const& chord_length = -1) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); Output geometry_out; @@ -256,8 +256,8 @@ inline void buffer(GeometryIn const& geometry_in, PointStrategy const& point_strategy) { typedef typename boost::range_value::type polygon_type; - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); typedef typename point_type::type point_type; typedef typename rescale_policy_type::type rescale_policy_type; diff --git a/include/boost/geometry/algorithms/centroid.hpp b/include/boost/geometry/algorithms/centroid.hpp index 8ef017a3f..fc2908ab1 100644 --- a/include/boost/geometry/algorithms/centroid.hpp +++ b/include/boost/geometry/algorithms/centroid.hpp @@ -545,7 +545,7 @@ struct centroid template static inline void apply(Geometry const& geometry, Point& out, Strategy const& strategy) { - concept::check_concepts_and_equal_dimensions(); + concepts::check_concepts_and_equal_dimensions(); resolve_strategy::centroid::apply(geometry, out, strategy); } }; diff --git a/include/boost/geometry/algorithms/clear.hpp b/include/boost/geometry/algorithms/clear.hpp index 54b216276..97f5efa45 100644 --- a/include/boost/geometry/algorithms/clear.hpp +++ b/include/boost/geometry/algorithms/clear.hpp @@ -185,7 +185,7 @@ struct clear > template inline void clear(Geometry& geometry) { - concept::check(); + concepts::check(); resolve_variant::clear::apply(geometry); } diff --git a/include/boost/geometry/algorithms/convert.hpp b/include/boost/geometry/algorithms/convert.hpp index 78618aed2..6a8ba1acb 100644 --- a/include/boost/geometry/algorithms/convert.hpp +++ b/include/boost/geometry/algorithms/convert.hpp @@ -494,7 +494,7 @@ struct convert { static inline void apply(Geometry1 const& geometry1, Geometry2& geometry2) { - concept::check_concepts_and_equal_dimensions(); + concepts::check_concepts_and_equal_dimensions(); dispatch::convert::apply(geometry1, geometry2); } }; diff --git a/include/boost/geometry/algorithms/convex_hull.hpp b/include/boost/geometry/algorithms/convex_hull.hpp index 19d28bc7b..26bb8509e 100644 --- a/include/boost/geometry/algorithms/convex_hull.hpp +++ b/include/boost/geometry/algorithms/convex_hull.hpp @@ -154,7 +154,7 @@ struct convex_hull OutputGeometry& out, Strategy const& strategy) { - BOOST_CONCEPT_ASSERT( (geometry::concept::ConvexHullStrategy) ); + BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy) ); dispatch::convex_hull::apply(geometry, out, strategy); } @@ -179,7 +179,7 @@ struct convex_hull_insert OutputIterator& out, Strategy const& strategy) { - BOOST_CONCEPT_ASSERT( (geometry::concept::ConvexHullStrategy) ); + BOOST_CONCEPT_ASSERT( (geometry::concepts::ConvexHullStrategy) ); return dispatch::convex_hull_insert< geometry::point_order::value, @@ -212,7 +212,7 @@ struct convex_hull template static inline void apply(Geometry const& geometry, OutputGeometry& out, Strategy const& strategy) { - concept::check_concepts_and_equal_dimensions< + concepts::check_concepts_and_equal_dimensions< const Geometry, OutputGeometry >(); @@ -258,8 +258,8 @@ struct convex_hull_insert static inline OutputIterator apply(Geometry const& geometry, OutputIterator& out, Strategy const& strategy) { // Concept: output point type = point type of input geometry - concept::check(); - concept::check::type>(); + concepts::check(); + concepts::check::type>(); return resolve_strategy::convex_hull_insert::apply(geometry, out, strategy); } diff --git a/include/boost/geometry/algorithms/correct.hpp b/include/boost/geometry/algorithms/correct.hpp index 11ed6ecff..5d3b6939a 100644 --- a/include/boost/geometry/algorithms/correct.hpp +++ b/include/boost/geometry/algorithms/correct.hpp @@ -283,7 +283,7 @@ struct correct { static inline void apply(Geometry& geometry) { - concept::check(); + concepts::check(); dispatch::correct::apply(geometry); } }; diff --git a/include/boost/geometry/algorithms/covered_by.hpp b/include/boost/geometry/algorithms/covered_by.hpp index eb8e73240..2001d5810 100644 --- a/include/boost/geometry/algorithms/covered_by.hpp +++ b/include/boost/geometry/algorithms/covered_by.hpp @@ -260,15 +260,15 @@ struct covered_by Geometry2 const& geometry2, Strategy const& strategy) { - concept::within::check + concepts::within::check < typename tag::type, typename tag::type, typename tag_cast::type, areal_tag>::type, Strategy >(); - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); assert_dimension_equal(); return dispatch::covered_by::apply(geometry1, diff --git a/include/boost/geometry/algorithms/crosses.hpp b/include/boost/geometry/algorithms/crosses.hpp index 9546a5335..73d86ef52 100644 --- a/include/boost/geometry/algorithms/crosses.hpp +++ b/include/boost/geometry/algorithms/crosses.hpp @@ -72,8 +72,8 @@ namespace resolve_variant const Geometry1& geometry1, const Geometry2& geometry2) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); return dispatch::crosses::apply(geometry1, geometry2); } diff --git a/include/boost/geometry/algorithms/detail/assign_box_corners.hpp b/include/boost/geometry/algorithms/detail/assign_box_corners.hpp index 669d6d365..bd8b84afc 100644 --- a/include/boost/geometry/algorithms/detail/assign_box_corners.hpp +++ b/include/boost/geometry/algorithms/detail/assign_box_corners.hpp @@ -54,8 +54,8 @@ inline void assign_box_corners(Box const& box, Point& lower_left, Point& lower_right, Point& upper_left, Point& upper_right) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); detail::assign::assign_box_2d_corner (box, lower_left); diff --git a/include/boost/geometry/algorithms/detail/assign_indexed_point.hpp b/include/boost/geometry/algorithms/detail/assign_indexed_point.hpp index acfc37e25..e5d9358c1 100644 --- a/include/boost/geometry/algorithms/detail/assign_indexed_point.hpp +++ b/include/boost/geometry/algorithms/detail/assign_indexed_point.hpp @@ -46,8 +46,8 @@ namespace detail template inline void assign_point_to_index(Point const& point, Geometry& geometry) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); detail::assign::assign_point_to_index < @@ -74,8 +74,8 @@ inline void assign_point_to_index(Point const& point, Geometry& geometry) template inline void assign_point_from_index(Geometry const& geometry, Point& point) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); detail::assign::assign_point_from_index < diff --git a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp index 3fc3c2347..e7214428e 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -297,7 +298,7 @@ struct buffered_piece_collection typedef std::map < signed_size_type, - std::set + detail::overlay::cluster_info > cluster_type; cluster_type m_clusters; @@ -1216,9 +1217,8 @@ struct buffered_piece_collection typename cs_tag::type >::type side_strategy_type; - enrich_intersection_points(m_turns, - m_clusters, detail::overlay::operation_union, - offsetted_rings, offsetted_rings, + enrich_intersection_points(m_turns, + m_clusters, offsetted_rings, offsetted_rings, m_robust_policy, side_strategy_type()); } @@ -1330,17 +1330,12 @@ struct buffered_piece_collection for (typename boost::range_iterator::type it = boost::begin(m_turns); it != boost::end(m_turns); ++it) { - if (it->location != location_ok) + buffer_turn_info_type& turn = *it; + if (turn.location != location_ok) { - // Set it to blocked. They should not be discarded, to avoid - // generating rings over these turns - // Performance goes down a tiny bit from 161 s to 173 because there - // are sometimes much more turns. - // We might speed it up a bit by keeping only one blocked - // intersection per segment, but that is complex to program - // because each turn involves two segments - it->operations[0].operation = detail::overlay::operation_blocked; - it->operations[1].operation = detail::overlay::operation_blocked; + // Discard this turn (don't set it to blocked to avoid colocated + // clusters being discarded afterwards + turn.discarded = true; } } } @@ -1352,7 +1347,7 @@ struct buffered_piece_collection false, false, buffered_ring_collection >, buffered_ring_collection >, - detail::overlay::operation_union, + overlay_buffer, backtrack_for_buffer > traverser; diff --git a/include/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp b/include/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp index db6136e1a..4fd24b145 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_ring.hpp @@ -16,6 +16,8 @@ #include #include +#include +#include #include #include @@ -147,6 +149,20 @@ struct ring_type typedef Ring type; }; + +// There is a specific tag, so this specialization cannot be placed in traits +template +struct point_order + > > +{ + static const order_selector value + = core_dispatch::point_order::value; +}; + + } diff --git a/include/boost/geometry/algorithms/detail/comparable_distance/interface.hpp b/include/boost/geometry/algorithms/detail/comparable_distance/interface.hpp index 86eec4c03..3e48a05ba 100644 --- a/include/boost/geometry/algorithms/detail/comparable_distance/interface.hpp +++ b/include/boost/geometry/algorithms/detail/comparable_distance/interface.hpp @@ -318,8 +318,8 @@ inline typename comparable_distance_result::type comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); return resolve_variant::comparable_distance < @@ -350,8 +350,8 @@ template inline typename default_comparable_distance_result::type comparable_distance(Geometry1 const& geometry1, Geometry2 const& geometry2) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); return geometry::comparable_distance(geometry1, geometry2, default_strategy()); } diff --git a/include/boost/geometry/algorithms/detail/disjoint/interface.hpp b/include/boost/geometry/algorithms/detail/disjoint/interface.hpp index 18c010731..ce7fe6d45 100644 --- a/include/boost/geometry/algorithms/detail/disjoint/interface.hpp +++ b/include/boost/geometry/algorithms/detail/disjoint/interface.hpp @@ -73,7 +73,7 @@ struct disjoint { static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) { - concept::check_concepts_and_equal_dimensions + concepts::check_concepts_and_equal_dimensions < Geometry1 const, Geometry2 const diff --git a/include/boost/geometry/algorithms/detail/distance/interface.hpp b/include/boost/geometry/algorithms/detail/distance/interface.hpp index 1e7cc433e..53d24d992 100644 --- a/include/boost/geometry/algorithms/detail/distance/interface.hpp +++ b/include/boost/geometry/algorithms/detail/distance/interface.hpp @@ -361,8 +361,8 @@ distance(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); detail::throw_on_empty_input(geometry1); detail::throw_on_empty_input(geometry2); @@ -392,8 +392,8 @@ inline typename default_distance_result::type distance(Geometry1 const& geometry1, Geometry2 const& geometry2) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); return geometry::distance(geometry1, geometry2, default_strategy()); } diff --git a/include/boost/geometry/algorithms/detail/envelope/interface.hpp b/include/boost/geometry/algorithms/detail/envelope/interface.hpp index 997ac1b23..befe4e42d 100644 --- a/include/boost/geometry/algorithms/detail/envelope/interface.hpp +++ b/include/boost/geometry/algorithms/detail/envelope/interface.hpp @@ -40,8 +40,8 @@ struct envelope template static inline void apply(Geometry const& geometry, Box& box) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); dispatch::envelope::apply(geometry, box); } diff --git a/include/boost/geometry/algorithms/detail/equals/collect_vectors.hpp b/include/boost/geometry/algorithms/detail/equals/collect_vectors.hpp index 2f9132146..eab73ea68 100644 --- a/include/boost/geometry/algorithms/detail/equals/collect_vectors.hpp +++ b/include/boost/geometry/algorithms/detail/equals/collect_vectors.hpp @@ -521,7 +521,7 @@ struct collect_vectors template inline void collect_vectors(Collection& collection, Geometry const& geometry) { - concept::check(); + concepts::check(); dispatch::collect_vectors < diff --git a/include/boost/geometry/algorithms/detail/expand/interface.hpp b/include/boost/geometry/algorithms/detail/expand/interface.hpp index 01936387a..140754af4 100644 --- a/include/boost/geometry/algorithms/detail/expand/interface.hpp +++ b/include/boost/geometry/algorithms/detail/expand/interface.hpp @@ -42,9 +42,9 @@ struct expand template static inline void apply(Box& box, Geometry const& geometry) { - concept::check(); - concept::check(); - concept::check_concepts_and_equal_dimensions(); + concepts::check(); + concepts::check(); + concepts::check_concepts_and_equal_dimensions(); dispatch::expand::apply(box, geometry); } @@ -100,7 +100,7 @@ inline void expand(Box& box, Geometry const& geometry, StrategyLess const& strategy_less, StrategyGreater const& strategy_greater) { - concept::check_concepts_and_equal_dimensions(); + concepts::check_concepts_and_equal_dimensions(); dispatch::expand::apply(box, geometry); } diff --git a/include/boost/geometry/algorithms/detail/extreme_points.hpp b/include/boost/geometry/algorithms/detail/extreme_points.hpp index 61839d296..65795cd05 100644 --- a/include/boost/geometry/algorithms/detail/extreme_points.hpp +++ b/include/boost/geometry/algorithms/detail/extreme_points.hpp @@ -492,15 +492,15 @@ struct extreme_points template inline bool extreme_points(Geometry const& geometry, Extremes& extremes, Intruders& intruders) { - concept::check(); + concepts::check(); // Extremes is not required to follow a geometry concept (but it should support an output iterator), // but its elements should fulfil the point-concept - concept::check::type>(); + concepts::check::type>(); // Intruders should contain collections which value type is point-concept // Extremes might be anything (supporting an output iterator), but its elements should fulfil the point-concept - concept::check + concepts::check < typename boost::range_value < diff --git a/include/boost/geometry/algorithms/detail/intersection/interface.hpp b/include/boost/geometry/algorithms/detail/intersection/interface.hpp index 56b859b85..e0955de3d 100644 --- a/include/boost/geometry/algorithms/detail/intersection/interface.hpp +++ b/include/boost/geometry/algorithms/detail/intersection/interface.hpp @@ -110,8 +110,8 @@ struct intersection const Geometry2& geometry2, GeometryOut& geometry_out) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); typedef typename geometry::rescale_overlay_policy_type < diff --git a/include/boost/geometry/algorithms/detail/is_simple/interface.hpp b/include/boost/geometry/algorithms/detail/is_simple/interface.hpp index fd8482697..6d425232b 100644 --- a/include/boost/geometry/algorithms/detail/is_simple/interface.hpp +++ b/include/boost/geometry/algorithms/detail/is_simple/interface.hpp @@ -30,7 +30,7 @@ struct is_simple { static inline bool apply(Geometry const& geometry) { - concept::check(); + concepts::check(); return dispatch::is_simple::apply(geometry); } }; diff --git a/include/boost/geometry/algorithms/detail/is_valid/interface.hpp b/include/boost/geometry/algorithms/detail/is_valid/interface.hpp index 0ec13b1b3..5a04a9282 100644 --- a/include/boost/geometry/algorithms/detail/is_valid/interface.hpp +++ b/include/boost/geometry/algorithms/detail/is_valid/interface.hpp @@ -37,7 +37,7 @@ struct is_valid template static inline bool apply(Geometry const& geometry, VisitPolicy& visitor) { - concept::check(); + concepts::check(); return dispatch::is_valid::apply(geometry, visitor); } }; diff --git a/include/boost/geometry/algorithms/detail/overlay/cluster_info.hpp b/include/boost/geometry/algorithms/detail/overlay/cluster_info.hpp new file mode 100644 index 000000000..5b460919f --- /dev/null +++ b/include/boost/geometry/algorithms/detail/overlay/cluster_info.hpp @@ -0,0 +1,49 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2016 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_CLUSTER_INFO_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLUSTER_INFO_HPP + + +#include +#include + + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +struct cluster_info +{ + std::set turn_indices; + + bool switch_source; // For clusters with a touch, conform turn_info uu + + //! Number of open spaces (e.g. 2 for touch) + std::size_t open_count; + + inline cluster_info() + : switch_source(false) + , open_count(0) + {} +}; + + +}} // namespace detail::overlay +#endif //DOXYGEN_NO_DETAIL + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_CLUSTER_INFO_HPP + diff --git a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp index 790819917..795523d7a 100644 --- a/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp @@ -284,7 +284,7 @@ inline bool copy_segment_point(Geometry const& geometry, SegmentIdentifier const& seg_id, int offset, PointOut& point_out) { - concept::check(); + concepts::check(); return dispatch::copy_segment_point < @@ -313,8 +313,8 @@ inline bool copy_segment_point(Geometry1 const& geometry1, Geometry2 const& geom SegmentIdentifier const& seg_id, int offset, PointOut& point_out) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); BOOST_GEOMETRY_ASSERT(seg_id.source_index == 0 || seg_id.source_index == 1); @@ -361,8 +361,8 @@ inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geo SegmentIdentifier const& seg_id, PointOut& point1, PointOut& point2) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); return copy_segment_point(geometry1, geometry2, seg_id, 0, point1) && copy_segment_point(geometry1, geometry2, seg_id, 1, point2); @@ -384,8 +384,8 @@ inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geo SegmentIdentifier const& seg_id, PointOut& point1, PointOut& point2, PointOut& point3) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); return copy_segment_point(geometry1, geometry2, seg_id, 0, point1) && copy_segment_point(geometry1, geometry2, seg_id, 1, point2) diff --git a/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp b/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp index 2eefa03c6..fe1a034f8 100644 --- a/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/copy_segments.hpp @@ -349,7 +349,7 @@ inline void copy_segments(Geometry const& geometry, RobustPolicy const& robust_policy, RangeOut& range_out) { - concept::check(); + concepts::check(); dispatch::copy_segments < diff --git a/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp b/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp index bc5d3b91e..5cab2b4cb 100644 --- a/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/enrich_intersection_points.hpp @@ -159,6 +159,7 @@ inline void enrich_assign(Operations& operations, Turns& turns) << " nxt=" << op.enriched.next_ip_index << " / " << op.enriched.travels_to_ip_index << " [vx " << op.enriched.travels_to_vertex_index << "]" + << std::boolalpha << turns[it->turn_index].discarded << std::endl; ; } @@ -235,11 +236,12 @@ inline void create_map(Turns const& turns, \ingroup overlay \tparam Turns type of intersection container (e.g. vector of "intersection/turn point"'s) +\tparam Clusters type of cluster container \tparam Geometry1 \tparam_geometry \tparam Geometry2 \tparam_geometry \tparam Strategy side strategy type -\param turns container containing intersectionpoints -\param for_operation operation_type (union or intersection) +\param turns container containing intersection points +\param clusters container containing clusters \param geometry1 \param_geometry \param geometry2 \param_geometry \param robust_policy policy to handle robustness issues @@ -257,11 +259,12 @@ template > inline void enrich_intersection_points(Turns& turns, Clusters& clusters, - detail::overlay::operation_type for_operation, Geometry1 const& geometry1, Geometry2 const& geometry2, RobustPolicy const& robust_policy, Strategy const& strategy) { + static const detail::overlay::operation_type for_operation + = detail::overlay::operation_from_overlay::value; typedef typename boost::range_value::type turn_type; typedef typename turn_type::turn_operation_type op_type; typedef detail::overlay::indexed_turn_operation @@ -328,7 +331,7 @@ inline void enrich_intersection_points(Turns& turns, if (has_colocations) { - detail::overlay::assign_startable_in_clusters( + detail::overlay::gather_cluster_properties( clusters, turns, for_operation, geometry1, geometry2); } diff --git a/include/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp b/include/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp index f5c5cc6a2..cc5541487 100644 --- a/include/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp @@ -9,6 +9,8 @@ #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICHMENT_INFO_HPP #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ENRICHMENT_INFO_HPP +#include + namespace boost { namespace geometry { @@ -25,7 +27,7 @@ namespace detail { namespace overlay of the overlay process). The information is gathered during the enrichment phase */ -template +template struct enrichment_info { inline enrichment_info() @@ -35,6 +37,7 @@ struct enrichment_info , startable(true) , count_left(0) , count_right(0) + , zone(-1) {} // vertex to which is free travel after this IP, @@ -53,6 +56,7 @@ struct enrichment_info // Counts if polygons left/right of this operation std::size_t count_left; std::size_t count_right; + signed_size_type zone; // open zone, in cluster }; diff --git a/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp b/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp index 4d5211919..99281eaec 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_intersection_points.hpp @@ -109,7 +109,7 @@ inline void get_intersection_points(Geometry1 const& geometry1, RobustPolicy const& robust_policy, Turns& turns) { - concept::check_concepts_and_equal_dimensions(); + concepts::check_concepts_and_equal_dimensions(); typedef detail::get_intersection_points::get_turn_without_info < diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp index 23cf77125..1eb18b74d 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turns.hpp @@ -972,7 +972,7 @@ inline void get_turns(Geometry1 const& geometry1, Turns& turns, InterruptPolicy& interrupt_policy) { - concept::check_concepts_and_equal_dimensions(); + concepts::check_concepts_and_equal_dimensions(); typedef detail::overlay::get_turn_info TurnPolicy; //typedef detail::get_turns::get_turn_info_type TurnPolicy; diff --git a/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp b/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp index 1028f9870..b21733912 100644 --- a/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/handle_colocations.hpp @@ -15,6 +15,9 @@ #include #include +#include +#include +#include #include #include #include @@ -195,13 +198,14 @@ inline signed_size_type add_turn_to_cluster(Turn const& turn, // Both operations.seg_id/fraction were already part of any cluster, and // these clusters are not the same. Merge of two clusters is necessary +#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_COLOCATIONS) std::cout << " TODO: merge " << cid0 << " and " << cid1 << std::endl; +#endif return cid0; } template < - bool Reverse1, bool Reverse2, typename Turns, typename ClusterPerSegment, typename Operations, @@ -312,13 +316,15 @@ inline void assign_cluster_to_turns(Turns& turns, typename ClusterPerSegment::const_iterator it = cluster_per_segment.find(seg_frac); if (it != cluster_per_segment.end()) { +#if defined(BOOST_GEOMETRY_DEBUG_HANDLE_COLOCATIONS) if (turn.cluster_id != -1 && turn.cluster_id != it->second) { std::cout << " CONFLICT " << std::endl; } +#endif turn.cluster_id = it->second; - clusters[turn.cluster_id].insert(turn_index); + clusters[turn.cluster_id].turn_indices.insert(turn_index); } } } @@ -339,7 +345,8 @@ inline void remove_clusters(Turns& turns, Clusters& clusters) typename Clusters::iterator current_it = it; ++it; - std::set const& turn_indices = current_it->second; + std::set const& turn_indices + = current_it->second.turn_indices; if (turn_indices.size() == 1) { signed_size_type turn_index = *turn_indices.begin(); @@ -349,6 +356,134 @@ inline void remove_clusters(Turns& turns, Clusters& clusters) } } +template +inline void discard_ie_turn(Turn& turn, IdSet& ids, signed_size_type id) +{ + turn.discarded = true; + turn.cluster_id = -1; + // To remove it later from clusters + ids.insert(id); +} + +template +inline bool is_interior(segment_identifier const& seg_id) +{ + return Reverse ? seg_id.ring_index == -1 : seg_id.ring_index >= 0; +} + +template +inline bool is_ie_turn(segment_identifier const& ext_seg_0, + segment_identifier const& ext_seg_1, + segment_identifier const& int_seg_0, + segment_identifier const& other_seg_1) +{ + // Compares two segment identifiers from two turns (external / one internal) + + // From first turn [0], both are from same polygon (multi_index), + // one is exterior (-1), the other is interior (>= 0), + // and the second turn [1] handles the same ring + + // For difference, where the rings are processed in reversal, all interior + // rings become exterior and vice versa. But also the multi property changes: + // rings originally from the same multi should now be considered as from + // different multi polygons. + // But this is not always the case, and at this point hard to figure out + // (not yet implemented, TODO) + + bool const same_multi0 = ! Reverse0 + && ext_seg_0.multi_index == int_seg_0.multi_index; + + bool const same_multi1 = ! Reverse1 + && ext_seg_1.multi_index == other_seg_1.multi_index; + + return same_multi0 + && same_multi1 + && ! is_interior(ext_seg_0) + && is_interior(int_seg_0) + && ext_seg_1.ring_index == other_seg_1.ring_index; + + // The other way round is tested in another call +} + +template +< + bool Reverse0, bool Reverse1, // Reverse interpretation interior/exterior + typename Turns, + typename Clusters +> +inline void discard_interior_exterior_turns(Turns& turns, Clusters& clusters) +{ + typedef std::set::const_iterator set_iterator; + typedef typename boost::range_value::type turn_type; + + std::set ids_to_remove; + + for (typename Clusters::iterator cit = clusters.begin(); + cit != clusters.end(); ++cit) + { + cluster_info& cinfo = cit->second; + std::set& ids = cinfo.turn_indices; + + ids_to_remove.clear(); + + for (set_iterator it = ids.begin(); it != ids.end(); ++it) + { + turn_type& turn = turns[*it]; + segment_identifier const& seg_0 = turn.operations[0].seg_id; + segment_identifier const& seg_1 = turn.operations[1].seg_id; + + if (turn.both(operation_intersection) + && Reverse0 == Reverse1) + { + if ( is_interior(seg_0) + && is_interior(seg_1)) + { + // ii touch with, two interior rings + discard_ie_turn(turn, ids_to_remove, *it); + } + + continue; + } + + if (! (turn.both(operation_union) + || turn.combination(operation_union, operation_blocked))) + { + // Not a uu/ux, so cannot be colocated with a iu turn + continue; + } + + for (set_iterator int_it = ids.begin(); int_it != ids.end(); ++int_it) + { + if (*it == *int_it) + { + 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; + + if (is_ie_turn(seg_0, seg_1, int_seg_0, int_seg_1)) + { + discard_ie_turn(int_turn, ids_to_remove, *int_it); + } + if (is_ie_turn(seg_1, seg_0, int_seg_1, int_seg_0)) + { + discard_ie_turn(int_turn, ids_to_remove, *int_it); + } + } + } + + // Erase from the ids (which cannot be done above) + for (set_iterator sit = ids_to_remove.begin(); + sit != ids_to_remove.end(); ++sit) + { + ids.erase(*sit); + } + } +} + // Checks colocated turns and flags combinations of uu/other, possibly a // combination of a ring touching another geometry's interior ring which is @@ -434,13 +569,17 @@ inline bool handle_colocations(Turns& turns, Clusters& clusters, { if (it->second.size() > 1u) { - handle_colocation_cluster(turns, cluster_id, - cluster_per_segment, it->second, - geometry1, geometry2); + handle_colocation_cluster(turns, cluster_id, cluster_per_segment, + it->second, geometry1, geometry2); } } assign_cluster_to_turns(turns, clusters, cluster_per_segment); + discard_interior_exterior_turns + < + do_reverse::value>::value != Reverse1, + do_reverse::value>::value != Reverse2 + >(turns, clusters); remove_clusters(turns, clusters); #if defined(BOOST_GEOMETRY_DEBUG_HANDLE_COLOCATIONS) @@ -497,7 +636,7 @@ template typename Geometry1, typename Geometry2 > -inline void assign_startable_in_clusters(Clusters& clusters, Turns& turns, +inline void gather_cluster_properties(Clusters& clusters, Turns& turns, operation_type for_operation, Geometry1 const& geometry1, Geometry2 const& geometry2) { @@ -515,7 +654,8 @@ inline void assign_startable_in_clusters(Clusters& clusters, Turns& turns, for (typename Clusters::iterator mit = clusters.begin(); mit != clusters.end(); ++mit) { - std::set const& ids = mit->second; + cluster_info& cinfo = mit->second; + std::set const& ids = cinfo.turn_indices; if (ids.empty()) { continue; @@ -545,30 +685,32 @@ inline void assign_startable_in_clusters(Clusters& clusters, Turns& turns, sbs.find_open(); - // Unset the startable flag for all 'closed' spaces + // Unset the startable flag for all 'closed' zones for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++) { const typename sbs_type::rp& ranked = sbs.m_ranked_points[i]; turn_type& turn = turns[ranked.turn_index]; - turn_operation_type& op = turn.operations[ranked.op_index]; + turn_operation_type& op = turn.operations[ranked.operation_index]; - if (ranked.index != sort_by_side::index_to) + if (ranked.direction != sort_by_side::dir_to) { continue; } - op.enriched.count_left = ranked.left_count; - op.enriched.count_right = ranked.right_count; + op.enriched.count_left = ranked.count_left; + op.enriched.count_right = ranked.count_right; + op.enriched.zone = ranked.zone; if ((for_operation == operation_union - && ranked.left_count != 0) + && ranked.count_left != 0) || (for_operation == operation_intersection - && ranked.right_count != 2)) + && ranked.count_right != 2)) { op.enriched.startable = false; } } + cinfo.open_count = sbs.open_count(turns); } } diff --git a/include/boost/geometry/algorithms/detail/overlay/handle_touch.hpp b/include/boost/geometry/algorithms/detail/overlay/handle_touch.hpp deleted file mode 100644 index 399193d48..000000000 --- a/include/boost/geometry/algorithms/detail/overlay/handle_touch.hpp +++ /dev/null @@ -1,336 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) - -// Copyright (c) 2015 Barend Gehrels, Amsterdam, the Netherlands. - -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_TOUCH_HPP -#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_TOUCH_HPP - -#include - -#include - -#include -#include -#include -#include - - -namespace boost { namespace geometry -{ - -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace overlay -{ - - -template -class handle_touch_uu -{ -private : - typedef typename boost::range_value::type turn_type; - typedef typename boost::range_iterator::type turn_iterator; - typedef typename boost::range_iterator::type turn_const_iterator; - - typedef typename boost::range_iterator - < - typename turn_type::container_type const - >::type operation_const_iterator; - -public : - - handle_touch_uu(Visitor& visitor) - : m_visitor(visitor) - {} - - inline void apply(detail::overlay::operation_type /*operation*/, Turns& turns) - { - if (! has_uu(turns)) - { - // Performance - if there is no u/u at all, nothing to be done - return; - } - - // Iterate through all u/u points - int turn_index = 0; - for (turn_iterator it = boost::begin(turns); - it != boost::end(turns); - ++it, ++turn_index) - { - turn_type& turn = *it; - if (! turn.both(operation_union)) - { - continue; - } - - m_visitor.print("handle_touch uu:", turns, turn_index); - - bool const traverse = turn_should_be_traversed(turns, turn, turn_index); - bool const start = traverse - && turn_should_be_startable(turns, turn, turn_index); - m_visitor.print("handle_touch, ready ", turns, turn_index); -// << std::boolalpha -// << traverse << " " << start - - if (traverse) - { - // Indicate the sources should switch here to create - // separate rings (outer ring / inner ring) - turn.switch_source = true; - } - // TODO: this is often not correct, fix this - turn.operations[0].enriched.startable = start; - turn.operations[1].enriched.startable = start; - } - } - -private : - - // Generic utility to be moved somewhere else - static inline - ring_identifier ring_id_from_seg_id(const segment_identifier& seg_id) - { - return ring_identifier(seg_id.source_index, - seg_id.multi_index, - seg_id.ring_index); - } - - static inline - ring_identifier ring_id_from_op(const turn_type& turn, - int operation_index) - { - return ring_id_from_seg_id(turn.operations[operation_index].seg_id); - } - - static inline bool in_range(const Turns& turns, signed_size_type index) - { - signed_size_type const turns_size = - static_cast(boost::size(turns)); - return index >= 0 && index < turns_size; - } - - static inline bool has_uu(const Turns& turns) - { - for (turn_const_iterator it = boost::begin(turns); - it != boost::end(turns); - ++it) - { - const turn_type& turn = *it; - if (turn.both(operation_union)) - { - return true; - } - } - return false; - } - - static inline - bool turn_should_be_startable(const Turns& turns, - const turn_type& uu_turn, - signed_size_type uu_turn_index) - { - return turn_startable(turns, uu_turn, 0, uu_turn_index) - || turn_startable(turns, uu_turn, 1, uu_turn_index); - - } - - static inline - bool turn_startable(const Turns& turns, - const turn_type& uu_turn, - std::size_t op_index, - signed_size_type original_turn_index, - std::size_t iteration = 0) - { - if (iteration >= boost::size(turns)) - { - // Defensive check to avoid infinite recursion - return false; - } - - signed_size_type const index - = uu_turn.operations[op_index].enriched.travels_to_ip_index; - if (index == original_turn_index) - { - // Completely traveled, having u/u only, via this op_index - return true; - } - - if (! in_range(turns, index)) - { - return false; - } - - const turn_type& new_turn = turns[index]; - - if (new_turn.operations[0].enriched.startable) - { - // Already selectable - no need to select u/u turn too - return false; - } - - // If this u/u turn is traversed normally (without skipping), sources are switched - return turn_startable(turns, new_turn, 1 - op_index, - original_turn_index, iteration + 1); - } - - inline bool turn_should_be_traversed(const Turns& turns, - const turn_type& uu_turn, - signed_size_type uu_turn_index) - { - return turn_should_be_traversed(turns, uu_turn, uu_turn_index, 0) - || turn_should_be_traversed(turns, uu_turn, uu_turn_index, 1); - } - - inline bool turn_should_be_traversed(const Turns& turns, - const turn_type& uu_turn, - signed_size_type uu_turn_index, - int uu_operation_index) - { - // Suppose this is a u/u turn between P and Q - // Examine all other turns on P and check if Q can be reached - // Use one of the operations and check if you can reach the other - signed_size_type const to_turn_index - = uu_turn.operations[uu_operation_index].enriched.travels_to_ip_index; - if (! in_range(turns, to_turn_index)) - { - return false; - } - - m_visitor.print("Examine:", turns, to_turn_index); - ring_identifier const other_ring_id - = ring_id_from_op(uu_turn, 1 - uu_operation_index); - - bool complete = false; - return can_reach(complete, turns, turns[to_turn_index], uu_operation_index, - other_ring_id, uu_turn_index, to_turn_index); - } - - inline bool can_reach(bool& complete, const Turns& turns, - const turn_type& turn, - signed_size_type uu_operation_index, - const ring_identifier& target_ring_id, - signed_size_type uu_turn_index, - signed_size_type to_turn_index, - std::size_t iteration = 0) - { - if (complete) - { - return false; - } - - if (turn.cluster_id >= 0) - { - // Clustered turns are yet not supported - return false; - } - - if (iteration >= boost::size(turns)) - { - m_visitor.print("Too much iterations"); - // Defensive check to avoid infinite recursion - return false; - } - - if (uu_operation_index != -1 && turn.both(operation_union)) - { - // If we end up in a u/u turn, check the way how, for this operation - m_visitor.print("Via u/u"); - return can_reach_via(complete, turns, uu_operation_index, - turn.operations[uu_operation_index], - target_ring_id, - uu_turn_index, to_turn_index, iteration); - } - else - { - // Check if specified ring can be reached via one of both operations - return can_reach_via(complete, turns, 0, turn.operations[0], target_ring_id, - uu_turn_index, to_turn_index, iteration) - || can_reach_via(complete, turns, 1, turn.operations[1], target_ring_id, - uu_turn_index, to_turn_index, iteration); - } - } - - template - inline bool can_reach_via(bool& complete, const Turns& turns, - signed_size_type operation_index, - const Operation& operation, - const ring_identifier& target_ring_id, - signed_size_type uu_turn_index, - signed_size_type to_turn_index, - std::size_t iteration = 0) - { - if (operation.operation != operation_union - && operation.operation != operation_continue) - { - return false; - } - - signed_size_type const index = operation.enriched.travels_to_ip_index; - if (index == to_turn_index) - { - m_visitor.print("Dead end at", turns, index); - // Completely traveled, the target is not found - return false; - } - if (index == uu_turn_index) - { - // End up where trial was started - m_visitor.print("Travel complete at", turns, index); - complete = true; - return false; - } - - if (! in_range(turns, index)) - { - return false; - } - - m_visitor.print("Now to", turns, index, operation_index); - const turn_type& new_turn = turns[index]; - - if (new_turn.both(operation_union)) - { - ring_identifier const ring_id = ring_id_from_op(new_turn, operation_index); - if (ring_id == target_ring_id) - { - m_visitor.print("Found (at u/u)!"); - return true; - } - } - else - { - ring_identifier const ring_id1 = ring_id_from_op(new_turn, 0); - ring_identifier const ring_id2 = ring_id_from_op(new_turn, 1); - if (ring_id1 == target_ring_id || ring_id2 == target_ring_id) - { - m_visitor.print("Found!"); - return true; - } - } - - // Recursively check this turn - return can_reach(complete, turns, new_turn, operation_index, target_ring_id, - uu_turn_index, to_turn_index, iteration + 1); - } - -private : - Visitor m_visitor; -}; - -template -inline void handle_touch(detail::overlay::operation_type operation, - Turns& turns, Visitor& visitor) -{ - handle_touch_uu handler(visitor); - handler.apply(operation, turns); -} - -}} // namespace detail::overlay -#endif // DOXYGEN_NO_DETAIL - -}} // namespace boost::geometry - -#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_HANDLE_TOUCH_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp index 2817ba9d6..bb82003a2 100644 --- a/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/intersection_insert.hpp @@ -993,8 +993,8 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1, OutputIterator out, Strategy const& strategy) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); typedef typename Strategy::rescale_policy_type rescale_policy_type; rescale_policy_type robust_policy @@ -1034,8 +1034,8 @@ inline OutputIterator intersection_insert(Geometry1 const& geometry1, Geometry2 const& geometry2, OutputIterator out) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); typedef typename geometry::rescale_policy_type < diff --git a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp index c3ecaa0b0..09c80025a 100644 --- a/include/boost/geometry/algorithms/detail/overlay/overlay.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/overlay.hpp @@ -23,10 +23,10 @@ #include +#include #include #include #include -#include #include #include #include @@ -220,11 +220,9 @@ struct overlay typedef std::map < signed_size_type, - std::set + cluster_info > cluster_type; - cluster_type clusters; - turn_container_type turns; #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE @@ -239,18 +237,14 @@ std::cout << "get turns" << std::endl; visitor.visit_turns(1, turns); - static const operation_type op_type - = OverlayType == overlay_union - ? geometry::detail::overlay::operation_union - : geometry::detail::overlay::operation_intersection; - #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE std::cout << "enrich" << std::endl; #endif typename Strategy::side_strategy_type side_strategy; + cluster_type clusters; + geometry::enrich_intersection_points(turns, - clusters, op_type, - geometry1, geometry2, + clusters, geometry1, geometry2, robust_policy, side_strategy); @@ -258,19 +252,6 @@ std::cout << "enrich" << std::endl; visitor.visit_clusters(clusters, turns); - -#if 0 - // TODO: does not work always correctly, move to traverse and fix - if (op_type == geometry::detail::overlay::operation_union) - { - #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE - std::cout << "handle_touch" << std::endl; - #endif - - handle_touch(op_type, turns, visitor); - } -#endif - #ifdef BOOST_GEOMETRY_DEBUG_ASSEMBLE std::cout << "traverse" << std::endl; #endif @@ -278,7 +259,7 @@ std::cout << "traverse" << std::endl; // Note that these rings are always in clockwise order, even in CCW polygons, // and are marked as "to be reversed" below ring_container_type rings; - traverse::apply + traverse::apply ( geometry1, geometry2, robust_policy, diff --git a/include/boost/geometry/algorithms/detail/overlay/overlay_type.hpp b/include/boost/geometry/algorithms/detail/overlay/overlay_type.hpp index af62131f0..0f6084097 100644 --- a/include/boost/geometry/algorithms/detail/overlay/overlay_type.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/overlay_type.hpp @@ -14,14 +14,52 @@ namespace boost { namespace geometry { +// TODO: move to detail enum overlay_type { overlay_union, overlay_intersection, overlay_difference, + overlay_buffer, overlay_dissolve }; +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +enum operation_type +{ + operation_none, + operation_union, + operation_intersection, + operation_blocked, + operation_continue, + operation_opposite +}; + + +template +struct operation_from_overlay +{ + static const operation_type value = operation_union; +}; + +template <> +struct operation_from_overlay +{ + static const operation_type value = operation_intersection; +}; + +template <> +struct operation_from_overlay +{ + static const operation_type value = operation_intersection; +}; + +}} // namespace detail::overlay +#endif //DOXYGEN_NO_DETAIL + }} // namespace boost::geometry diff --git a/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp b/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp index 1b3cd866d..de5eac8ac 100644 --- a/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/select_rings.hpp @@ -165,11 +165,8 @@ namespace dispatch template struct decide -{}; - -template<> -struct decide { + // Default implementation (union, inflate, deflate, dissolve) static bool include(ring_identifier const& , ring_turn_info const& info) { return ! info.within_other; @@ -179,6 +176,7 @@ struct decide { return false; } + }; template<> diff --git a/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp b/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp index a74cb83f7..aedf22e1f 100644 --- a/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/self_turn_points.hpp @@ -276,7 +276,7 @@ inline void self_turns(Geometry const& geometry, RobustPolicy const& robust_policy, Turns& turns, InterruptPolicy& interrupt_policy) { - concept::check(); + concepts::check(); typedef detail::overlay::get_turn_info turn_policy; diff --git a/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp b/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp index 894cddab8..429ef4f92 100644 --- a/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/sort_by_side.hpp @@ -23,42 +23,44 @@ namespace boost { namespace geometry namespace detail { namespace overlay { namespace sort_by_side { -enum index_type { index_unknown = -1, index_from = 0, index_to = 1 }; +enum direction_type { dir_unknown = -1, dir_from = 0, dir_to = 1 }; // Point-wrapper, adding some properties template struct ranked_point { ranked_point() - : main_rank(0) + : rank(0) , turn_index(-1) - , op_index(-1) - , index(index_unknown) - , left_count(0) - , right_count(0) + , operation_index(-1) + , direction(dir_unknown) + , count_left(0) + , count_right(0) , operation(operation_none) {} - ranked_point(const Point& p, signed_size_type ti, signed_size_type oi, - index_type i, operation_type op, segment_identifier sid) + ranked_point(const Point& p, signed_size_type ti, int oi, + direction_type d, operation_type op, segment_identifier sid) : point(p) - , main_rank(0) + , rank(0) + , zone(-1) , turn_index(ti) - , op_index(oi) - , index(i) - , left_count(0) - , right_count(0) + , operation_index(oi) + , direction(d) + , count_left(0) + , count_right(0) , operation(op) , seg_id(sid) {} Point point; - std::size_t main_rank; + std::size_t rank; + signed_size_type zone; // index of closed zone, in uu turn there would be 2 zones signed_size_type turn_index; - signed_size_type op_index; - index_type index; - std::size_t left_count; - std::size_t right_count; + int operation_index; // 0,1 + direction_type direction; + std::size_t count_left; + std::size_t count_right; operation_type operation; segment_identifier seg_id; }; @@ -81,9 +83,9 @@ struct less_by_index inline bool operator()(const T& first, const T& second) const { // First order by from/to - if (first.index != second.index) + if (first.direction != second.direction) { - return first.index < second.index; + return first.direction < second.direction; } // All the same, order by turn index (we might consider length too) return first.turn_index < second.turn_index; @@ -200,8 +202,8 @@ struct side_sorter op.seg_id, point1, point2, point3); Point const& point_to = op.fraction.is_one() ? point3 : point2; - m_ranked_points.push_back(rp(point1, turn_index, op_index, index_from, op.operation, op.seg_id)); - m_ranked_points.push_back(rp(point_to, turn_index, op_index, index_to, op.operation, op.seg_id)); + m_ranked_points.push_back(rp(point1, turn_index, op_index, dir_from, op.operation, op.seg_id)); + m_ranked_points.push_back(rp(point_to, turn_index, op_index, dir_to, op.operation, op.seg_id)); if (is_origin) { @@ -233,7 +235,7 @@ struct side_sorter colinear_rank++; } - m_ranked_points[i].main_rank = colinear_rank; + m_ranked_points[i].rank = colinear_rank; } } @@ -243,7 +245,7 @@ struct side_sorter for (std::size_t i = 0; i < m_ranked_points.size(); i++) { const rp& ranked = m_ranked_points[i]; - if (ranked.index != index_from) + if (ranked.direction != dir_from) { continue; } @@ -290,6 +292,8 @@ struct side_sorter &segment_identifier::source_index >(handled); } + + assign_zones(); } void reverse() @@ -299,25 +303,25 @@ struct side_sorter return; } - int const last = 1 + m_ranked_points.back().main_rank; + std::size_t const last = 1 + m_ranked_points.back().rank; - // Move iterator after main_rank==0 + // Move iterator after rank==0 bool has_first = false; typename container_type::iterator it = m_ranked_points.begin() + 1; - for (; it != m_ranked_points.end() && it->main_rank == 0; ++it) + for (; it != m_ranked_points.end() && it->rank == 0; ++it) { has_first = true; } if (has_first) { - // Reverse first part (having main_rank == 0), if any, + // 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) { - BOOST_ASSERT(fit->main_rank == 0); + BOOST_ASSERT(fit->rank == 0); } } @@ -325,11 +329,41 @@ struct side_sorter std::reverse(it, m_ranked_points.end()); for (; it != m_ranked_points.end(); ++it) { - BOOST_ASSERT(it->main_rank > 0); - it->main_rank = last - it->main_rank; + BOOST_ASSERT(it->rank > 0); + it->rank = last - it->rank; } } + //! Check how many open spaces there are + template + std::size_t open_count(Turns const& turns) const + { + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::turn_operation_type turn_operation_type; + + std::size_t result = 0; + std::size_t last_rank = 0; + for (std::size_t i = 0; i < m_ranked_points.size(); i++) + { + rp const& ranked_point = m_ranked_points[i]; + + if (ranked_point.rank > last_rank + && ranked_point.direction == sort_by_side::dir_to) + { + // TODO: take count-left / count_right from rank itself + turn_type const& ranked_turn = turns[ranked_point.turn_index]; + turn_operation_type const& ranked_op = ranked_turn.operations[ranked_point.operation_index]; + if (ranked_op.enriched.count_left == 0 + && ranked_op.enriched.count_right > 0) + { + result++; + last_rank = ranked_point.rank; + } + } + } + return result; + } + //protected : typedef std::vector container_type; @@ -366,19 +400,19 @@ private : // if min=5,max=2: assign from 5,6,7,1,2 bool const in_range = max_rank >= min_rank - ? ranked.main_rank >= min_rank && ranked.main_rank <= max_rank - : ranked.main_rank >= min_rank || ranked.main_rank <= max_rank + ? ranked.rank >= min_rank && ranked.rank <= max_rank + : ranked.rank >= min_rank || ranked.rank <= max_rank ; if (in_range) { if (side_index == 1) { - ranked.left_count++; + ranked.count_left++; } else if (side_index == 2) { - ranked.right_count++; + ranked.count_right++; } } } @@ -389,8 +423,8 @@ private : std::size_t start_index) { int state = 1; // 'closed', because start_index is "from", arrives at the turn - std::size_t last_from_rank = m_ranked_points[start_index].main_rank; - std::size_t previous_rank = m_ranked_points[start_index].main_rank; + std::size_t last_from_rank = m_ranked_points[start_index].rank; + std::size_t previous_rank = m_ranked_points[start_index].rank; for (std::size_t index = move(the_index, start_index); ; @@ -398,7 +432,7 @@ private : { rp& ranked = m_ranked_points[index]; - if (ranked.main_rank != previous_rank && state == 0) + if (ranked.rank != previous_rank && state == 0) { assign_ranks(last_from_rank, previous_rank - 1, 1); assign_ranks(last_from_rank + 1, previous_rank, 2); @@ -409,19 +443,91 @@ private : return; } - if (ranked.index == index_from) + if (ranked.direction == dir_from) { - last_from_rank = ranked.main_rank; + last_from_rank = ranked.rank; state++; } - else if (ranked.index == index_to) + else if (ranked.direction == dir_to) { state--; } - previous_rank = ranked.main_rank; + previous_rank = ranked.rank; } } + + //! Find closed zones and assign it + void assign_zones() + { + // Find a starting point (the first rank after an outgoing rank + // with no polygons on the left side) + std::size_t start_rank = m_ranked_points.size() + 1; + std::size_t start_index = 0; + std::size_t max_rank = 0; + for (std::size_t i = 0; i < m_ranked_points.size(); i++) + { + rp const& ranked_point = m_ranked_points[i]; + if (ranked_point.rank > max_rank) + { + max_rank = ranked_point.rank; + } + if (ranked_point.direction == sort_by_side::dir_to + && ranked_point.count_left == 0 + && ranked_point.count_right > 0) + { + start_rank = ranked_point.rank + 1; + } + if (ranked_point.rank == start_rank && start_index == 0) + { + start_index = i; + } + } + + // Assign the zones + std::size_t const undefined_rank = max_rank + 1; + std::size_t zone_id = 0; + std::size_t last_rank = 0; + std::size_t rank_at_next_zone = undefined_rank; + std::size_t index = start_index; + for (std::size_t i = 0; i < m_ranked_points.size(); i++) + { + rp& ranked_point = m_ranked_points[index]; + + // Implement cyclic behavior + index++; + if (index == m_ranked_points.size()) + { + index = 0; + } + + if (ranked_point.rank != last_rank) + { + if (ranked_point.rank == rank_at_next_zone) + { + zone_id++; + rank_at_next_zone = undefined_rank; + } + + if (ranked_point.direction == sort_by_side::dir_to + && ranked_point.count_left == 0 + && ranked_point.count_right > 0) + { + rank_at_next_zone = ranked_point.rank + 1; + if (rank_at_next_zone > max_rank) + { + rank_at_next_zone = 0; + } + } + + last_rank = ranked_point.rank; + } + + ranked_point.zone = zone_id; + } + } + + }; diff --git a/include/boost/geometry/algorithms/detail/overlay/traversal.hpp b/include/boost/geometry/algorithms/detail/overlay/traversal.hpp new file mode 100644 index 000000000..1156644bc --- /dev/null +++ b/include/boost/geometry/algorithms/detail/overlay/traversal.hpp @@ -0,0 +1,672 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_HPP + +#include + +#include + +#include +#include +#include +#include + +#if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) \ + || defined(BOOST_GEOMETRY_OVERLAY_REPORT_WKT) \ + || defined(BOOST_GEOMETRY_DEBUG_TRAVERSE) +# include +# include +# include +#endif + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +template +#ifdef BOOST_GEOMETRY_DEBUG_TRAVERSE +inline void debug_traverse(Turn const& turn, Operation op, + std::string const& header) +{ + std::cout << header + << " at " << op.seg_id + << " meth: " << method_char(turn.method) + << " op: " << operation_char(op.operation) + << " vis: " << visited_char(op.visited) + << " of: " << operation_char(turn.operations[0].operation) + << operation_char(turn.operations[1].operation) + << " " << geometry::wkt(turn.point) + << std::endl; + + if (boost::contains(header, "Finished")) + { + std::cout << std::endl; + } +} +#else +inline void debug_traverse(Turn const& , Operation, const char*) +{ +} +#endif + + +//! Metafunction to define side_order (clockwise, ccw) by operation_type +template +struct side_compare {}; + +template <> +struct side_compare +{ + typedef std::greater type; +}; + +template <> +struct side_compare +{ + typedef std::less type; +}; + + +template +< + bool Reverse1, + bool Reverse2, + overlay_type OverlayType, + typename Geometry1, + typename Geometry2, + typename Turns, + typename Clusters, + typename RobustPolicy, + typename Visitor +> +struct traversal +{ + static const operation_type target_operation = operation_from_overlay::value; + + typedef typename side_compare::type side_compare_type; + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::turn_operation_type turn_operation_type; + + typedef typename geometry::point_type::type point_type; + typedef sort_by_side::side_sorter + < + Reverse1, Reverse2, + point_type, side_compare_type + > sbs_type; + + inline traversal(Geometry1 const& geometry1, Geometry2 const& geometry2, + Turns& turns, Clusters const& clusters, + RobustPolicy const& robust_policy, Visitor& visitor) + : m_geometry1(geometry1) + , m_geometry2(geometry2) + , m_turns(turns) + , m_clusters(clusters) + , m_robust_policy(robust_policy) + , m_visitor(visitor) + { + } + + inline void finalize_visit_info() + { + for (typename boost::range_iterator::type + it = boost::begin(m_turns); + it != boost::end(m_turns); + ++it) + { + turn_type& turn = *it; + for (int i = 0; i < 2; i++) + { + turn_operation_type& op = turn.operations[i]; + op.visited.finalize(); + } + } + } + + inline void set_visited(turn_type& turn, turn_operation_type& op) + { + // On "continue", set "visited" for ALL directions in this turn + if (op.operation == detail::overlay::operation_continue) + { + for (int i = 0; i < 2; i++) + { + turn_operation_type& op = turn.operations[i]; + if (op.visited.none()) + { + op.visited.set_visited(); + } + } + } + else + { + op.visited.set_visited(); + } + } + + inline bool is_visited(turn_type const& turn, turn_operation_type const& op, + signed_size_type turn_index, int op_index) const + { + return op.visited.visited(); + } + + inline bool select_source(signed_size_type turn_index, + segment_identifier const& seg_id1, + segment_identifier const& seg_id2) const + { + if (target_operation == operation_intersection) + { + // For intersections always switch sources + return seg_id1.source_index != seg_id2.source_index; + } + else if (target_operation == operation_union) + { + // For uu, only switch sources if indicated + turn_type const& turn = m_turns[turn_index]; + + if (OverlayType == overlay_buffer) + { + // Buffer does not use source_index (always 0) + return turn.switch_source + ? seg_id1.multi_index != seg_id2.multi_index + : seg_id1.multi_index == seg_id2.multi_index; + } + +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) + if (turn.switch_source == 1) + { + std::cout << "Switch source at " << turn_index << std::endl; + } + else + { + std::cout << "DON'T SWITCH SOURCES at " << turn_index << std::endl; + } +#endif + return turn.switch_source + ? seg_id1.source_index != seg_id2.source_index + : seg_id1.source_index == seg_id2.source_index; + } + return false; + } + + inline + signed_size_type get_next_turn_index(turn_operation_type const& op) const + { + return op.enriched.next_ip_index == -1 + ? op.enriched.travels_to_ip_index + : op.enriched.next_ip_index; + } + + inline bool traverse_possible(signed_size_type turn_index) const + { + if (turn_index == -1) + { + return false; + } + + turn_type const& turn = m_turns[turn_index]; + + // It is not a dead end if there is an operation to continue, or of + // there is a cluster (assuming for now we can get out of the cluster) + return turn.cluster_id >= 0 + || turn.has(target_operation) + || turn.has(operation_continue); + } + + inline + bool select_cc_operation(turn_type const& turn, + signed_size_type start_turn_index, + int& selected_op_index) const + { + // For "cc", take either one, but if there is a starting one, + // take that one. If next is dead end, skip that one. + + bool result = false; + + typename turn_operation_type::comparable_distance_type + max_remaining_distance = 0; + + for (int i = 0; i < 2; i++) + { + turn_operation_type const& op = turn.operations[i]; + + signed_size_type const next_turn_index = get_next_turn_index(op); + + if (! result && traverse_possible(next_turn_index)) + { + max_remaining_distance = op.remaining_distance; + selected_op_index = i; + debug_traverse(turn, op, " Candidate"); + result = true; + } + + if (result) + { + if (next_turn_index == start_turn_index) + { + selected_op_index = i; + debug_traverse(turn, op, " Candidate cc override (start)"); + } + else if (op.remaining_distance > max_remaining_distance) + { + max_remaining_distance = op.remaining_distance; + selected_op_index = i; + debug_traverse(turn, op, " Candidate cc override (remaining)"); + } + } + } + + return result; + } + + inline + bool select_noncc_operation(turn_type const& turn, + signed_size_type turn_index, + segment_identifier const& seg_id, + int& selected_op_index) const + { + // For "ii", take the other one (alternate) + // UNLESS the other one is already visited + // For "uu", take the same one (see above); + + bool result = false; + + for (int i = 0; i < 2; i++) + { + turn_operation_type const& op = turn.operations[i]; + + if (op.operation == target_operation + && ! op.visited.finished() + && (! result || select_source(turn_index, op.seg_id, seg_id))) + { + selected_op_index = i; + debug_traverse(turn, op, " Candidate"); + result = true; + } + } + + return result; + } + + inline + bool select_operation(const turn_type& turn, + signed_size_type turn_index, + signed_size_type start_turn_index, + segment_identifier const& previous_seg_id, + int& selected_op_index) const + { + bool result = false; + selected_op_index = -1; + if (turn.both(operation_continue)) + { + result = select_cc_operation(turn, start_turn_index, + selected_op_index); + } + else + { + result = select_noncc_operation(turn, turn_index, + previous_seg_id, selected_op_index); + } + if (result) + { + debug_traverse(turn, turn.operations[selected_op_index], " Accepted"); + } + + return result; + } + + inline int starting_operation_index(const turn_type& turn) const + { + for (int i = 0; i < 2; i++) + { + if (turn.operations[i].visited.started()) + { + return i; + } + } + return -1; + } + + inline bool both_finished(const turn_type& turn) const + { + for (int i = 0; i < 2; i++) + { + if (! turn.operations[i].visited.finished()) + { + return false; + } + } + return true; + } + + inline bool select_from_cluster(signed_size_type& turn_index, + int& op_index, signed_size_type start_turn_index, + sbs_type const& sbs, bool is_touching) const + { + bool const is_union = target_operation == operation_union; + bool const is_intersection = target_operation == operation_intersection; + + std::size_t selected_rank = 0; + std::size_t min_rank = 0; + bool result = false; + for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++) + { + typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[i]; + if (result && ranked_point.rank > selected_rank) + { + return result; + } + + turn_type const& ranked_turn = m_turns[ranked_point.turn_index]; + turn_operation_type const& ranked_op = ranked_turn.operations[ranked_point.operation_index]; + + if (result && ranked_op.visited.finalized()) + { + // One of the arcs in the same direction as the selected result + // is already traversed. + return false; + } + + if (! is_touching && ranked_op.visited.finalized()) + { + // Skip this one, go to next + min_rank = ranked_point.rank; + continue; + } + + if (ranked_point.direction == sort_by_side::dir_to + && (ranked_point.rank > min_rank + || ranked_turn.both(operation_continue))) + { + if ((is_union + && ranked_op.enriched.count_left == 0 + && ranked_op.enriched.count_right > 0) + || (is_intersection + && ranked_op.enriched.count_right == 2)) + { + if (result && ranked_point.turn_index != start_turn_index) + { + // Don't override - only override if arrive at start + continue; + } + + turn_index = ranked_point.turn_index; + op_index = ranked_point.operation_index; + + if (is_intersection + && ranked_turn.both(operation_intersection) + && ranked_op.visited.finalized()) + { + // Override: + // For a ii turn, even though one operation might be selected, + // it should take the other one if the first one is used in a completed ring + op_index = 1 - ranked_point.operation_index; + } + + result = true; + selected_rank = ranked_point.rank; + } + else if (! is_touching) + { + return result; + } + } + } + return result; + } + + inline bool select_turn_from_cluster(signed_size_type& turn_index, + int& op_index, bool& is_touching, + signed_size_type start_turn_index, + segment_identifier const& previous_seg_id) const + { + bool const is_union = target_operation == operation_union; + + turn_type const& turn = m_turns[turn_index]; + BOOST_ASSERT(turn.cluster_id >= 0); + + typename Clusters::const_iterator mit = m_clusters.find(turn.cluster_id); + BOOST_ASSERT(mit != m_clusters.end()); + + cluster_info const& cinfo = mit->second; + std::set const& ids = cinfo.turn_indices; + + sbs_type sbs; + + bool has_origin = false; + + for (typename std::set::const_iterator sit = ids.begin(); + sit != ids.end(); ++sit) + { + signed_size_type cluster_turn_index = *sit; + turn_type const& cluster_turn = m_turns[cluster_turn_index]; + if (cluster_turn.discarded) + { + // Defensive check, discarded turns should not be in cluster + continue; + } + + for (int i = 0; i < 2; i++) + { + turn_operation_type const& op = cluster_turn.operations[i]; + bool is_origin = false; + if (cluster_turn_index == turn_index) + { + // Check if this is the origin + if (OverlayType == overlay_buffer) + { + is_origin = op.seg_id.multi_index == previous_seg_id.multi_index; + } + else + { + is_origin = op.seg_id.source_index + == previous_seg_id.source_index; + } + if (is_origin) + { + has_origin = true; + } + } + + sbs.add(op, cluster_turn_index, i, m_geometry1, m_geometry2, + is_origin); + } + } + + if (! has_origin) + { + return false; + } + + sbs.apply(turn.point); + +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) + is_touching = is_union && cinfo.open_count > 1; + if (is_touching) + { + if (cinfo.switch_source) + { + is_touching = false; + std::cout << "CLUSTER: SWITCH SOURCES at " << turn_index << std::endl; + } + else + { + std::cout << "CLUSTER: CONTINUE at " << turn_index << std::endl; + } + } +#else + is_touching = is_union && cinfo.open_count > 1 && ! cinfo.switch_source; +#endif + if (is_touching) + { + sbs.reverse(); + } + + return select_from_cluster(turn_index, op_index, start_turn_index, sbs, + is_touching); + } + + inline void change_index_for_self_turn(signed_size_type& to_vertex_index, + turn_type const& start_turn, + turn_operation_type const& start_op, + int start_op_index) const + { + if (OverlayType != overlay_buffer) + { + return; + } + + // It travels to itself, can happen. If this is a buffer, it can + // sometimes travel to itself in the following configuration: + // + // +---->--+ + // | | + // | +---*----+ *: one turn, with segment index 2/7 + // | | | | + // | +---C | C: closing point (start/end) + // | | + // +------------+ + // + // If it starts on segment 2 and travels to itself on segment 2, that + // should be corrected to 7 because that is the shortest path + // + // Also a uu turn (touching with another buffered ring) might have this + // apparent configuration, but there it should + // always travel the whole ring + + turn_operation_type const& other_op + = start_turn.operations[1 - start_op_index]; + + bool const correct + = ! start_turn.both(operation_union) + && start_op.seg_id.segment_index == to_vertex_index; + +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSE) + std::cout << " WARNING: self-buffer " + << " correct=" << correct + << " turn=" << operation_char(start_turn.operations[0].operation) + << operation_char(start_turn.operations[1].operation) + << " start=" << start_op.seg_id.segment_index + << " from=" << to_vertex_index + << " to=" << other_op.enriched.travels_to_vertex_index + << std::endl; +#endif + + if (correct) + { + to_vertex_index = other_op.enriched.travels_to_vertex_index; + } + } + + bool select_turn_from_enriched(signed_size_type& turn_index, + segment_identifier& previous_seg_id, + signed_size_type& to_vertex_index, + signed_size_type start_turn_index, + int start_op_index, + turn_type const& previous_turn, + turn_operation_type const& previous_op, + bool is_start) const + { + to_vertex_index = -1; + + if (previous_op.enriched.next_ip_index < 0) + { + // There is no next IP on this segment + if (previous_op.enriched.travels_to_vertex_index < 0 + || previous_op.enriched.travels_to_ip_index < 0) + { + return false; + } + + to_vertex_index = previous_op.enriched.travels_to_vertex_index; + + if (is_start && + previous_op.enriched.travels_to_ip_index == start_turn_index) + { + change_index_for_self_turn(to_vertex_index, previous_turn, + previous_op, start_op_index); + } + + turn_index = previous_op.enriched.travels_to_ip_index; + previous_seg_id = previous_op.seg_id; + } + else + { + // Take the next IP on this segment + turn_index = previous_op.enriched.next_ip_index; + previous_seg_id = previous_op.seg_id; + } + return true; + } + + bool select_turn(signed_size_type start_turn_index, + signed_size_type& turn_index, + int& op_index, + bool& is_touching, + int previous_op_index, + signed_size_type previous_turn_index, + segment_identifier const& previous_seg_id, + bool is_start) + { + if (m_turns[turn_index].cluster_id >= 0) + { + if (! select_turn_from_cluster(turn_index, op_index, is_touching, + start_turn_index, previous_seg_id)) + { + return false; + } + + if (is_start && turn_index == previous_turn_index) + { + op_index = previous_op_index; + } + } + else + { + turn_type const& current_turn = m_turns[turn_index]; + + op_index = starting_operation_index(current_turn); + if (op_index == -1) + { + if (both_finished(current_turn)) + { + return false; + } + + if (! select_operation(current_turn, turn_index, + start_turn_index, + previous_seg_id, + op_index)) + { + return false; + } + } + } + return true; + } + +private : + Geometry1 const& m_geometry1; + Geometry2 const& m_geometry2; + Turns& m_turns; + Clusters const& m_clusters; + RobustPolicy const& m_robust_policy; + Visitor& m_visitor; +}; + + + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp b/include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp new file mode 100644 index 000000000..104bd6b8e --- /dev/null +++ b/include/boost/geometry/algorithms/detail/overlay/traversal_ring_creator.hpp @@ -0,0 +1,347 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_RING_CREATOR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_RING_CREATOR_HPP + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + + +template +< + bool Reverse1, + bool Reverse2, + overlay_type OverlayType, + typename Geometry1, + typename Geometry2, + typename Turns, + typename Clusters, + typename RobustPolicy, + typename Visitor, + typename Backtrack +> +struct traversal_ring_creator +{ + typedef traversal + traversal_type; + + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::turn_operation_type turn_operation_type; + + static const operation_type target_operation + = operation_from_overlay::value; + + inline traversal_ring_creator(Geometry1 const& geometry1, Geometry2 const& geometry2, + Turns& turns, Clusters const& clusters, + RobustPolicy const& robust_policy, Visitor& visitor) + : m_trav(geometry1, geometry2, turns, clusters, robust_policy,visitor) + , m_geometry1(geometry1) + , m_geometry2(geometry2) + , m_turns(turns) + , m_clusters(clusters) + , m_robust_policy(robust_policy) + , m_visitor(visitor) + , m_has_uu(false) + { + + } + + template + inline traverse_error_type travel_to_next_turn(signed_size_type start_turn_index, + int start_op_index, + signed_size_type& turn_index, + int& op_index, + Ring& current_ring, + bool is_start) + { + int const previous_op_index = op_index; + signed_size_type const previous_turn_index = turn_index; + turn_type& previous_turn = m_turns[turn_index]; + turn_operation_type& previous_op = previous_turn.operations[op_index]; + segment_identifier previous_seg_id; + + signed_size_type to_vertex_index = -1; + if (! m_trav.select_turn_from_enriched(turn_index, previous_seg_id, + to_vertex_index, start_turn_index, start_op_index, + previous_turn, previous_op, is_start)) + { + return is_start + ? traverse_error_no_next_ip_at_start + : traverse_error_no_next_ip; + } + if (to_vertex_index >= 0) + { + if (previous_op.seg_id.source_index == 0) + { + geometry::copy_segments(m_geometry1, + previous_op.seg_id, to_vertex_index, + m_robust_policy, current_ring); + } + else + { + geometry::copy_segments(m_geometry2, + previous_op.seg_id, to_vertex_index, + m_robust_policy, current_ring); + } + } + + if (m_turns[turn_index].discarded) + { + return is_start + ? traverse_error_dead_end_at_start + : traverse_error_dead_end; + } + + if (is_start) + { + // Register the start + previous_op.visited.set_started(); + m_visitor.visit_traverse(m_turns, previous_turn, previous_op, "Start"); + } + + bool is_touching = false; + if (! m_trav.select_turn(start_turn_index, turn_index, op_index, + is_touching, + previous_op_index, previous_turn_index, previous_seg_id, + is_start)) + { + return is_start + ? traverse_error_no_next_ip_at_start + : traverse_error_no_next_ip; + } + + { + // Check operation (TODO: this might be redundant or should be catched before) + const turn_type& current_turn = m_turns[turn_index]; + const turn_operation_type& op = current_turn.operations[op_index]; + if (op.visited.finalized() + || m_trav.is_visited(current_turn, op, turn_index, op_index)) + { + return traverse_error_visit_again; + } + } + + // Update registration and append point + turn_type& current_turn = m_turns[turn_index]; + turn_operation_type& op = current_turn.operations[op_index]; + detail::overlay::append_no_dups_or_spikes(current_ring, current_turn.point, + m_robust_policy); + + // Register the visit + m_trav.set_visited(current_turn, op); + m_visitor.visit_traverse(m_turns, current_turn, op, "Visit"); + + return traverse_error_none; + } + + template + inline traverse_error_type traverse(Ring& ring, + signed_size_type start_turn_index, int start_op_index) + { + turn_type const& start_turn = m_turns[start_turn_index]; + turn_operation_type& start_op = m_turns[start_turn_index].operations[start_op_index]; + + detail::overlay::append_no_dups_or_spikes(ring, start_turn.point, + m_robust_policy); + + signed_size_type current_turn_index = start_turn_index; + int current_op_index = start_op_index; + + traverse_error_type error = travel_to_next_turn(start_turn_index, + start_op_index, + current_turn_index, current_op_index, + ring, true); + + if (error != traverse_error_none) + { + // This is not necessarily a problem, it happens for clustered turns + // which are "build in" or otherwise point inwards + return error; + } + + if (current_turn_index == start_turn_index) + { + start_op.visited.set_finished(); + m_visitor.visit_traverse(m_turns, m_turns[current_turn_index], start_op, "Early finish"); + return traverse_error_none; + } + + std::size_t const max_iterations = 2 + 2 * m_turns.size(); + for (std::size_t i = 0; i <= max_iterations; i++) + { + // We assume clockwise polygons only, non self-intersecting, closed. + // However, the input might be different, and checking validity + // is up to the library user. + + // Therefore we make here some sanity checks. If the input + // violates the assumptions, the output polygon will not be correct + // but the routine will stop and output the current polygon, and + // will continue with the next one. + + // Below three reasons to stop. + error = travel_to_next_turn(start_turn_index, start_op_index, + current_turn_index, current_op_index, + ring, false); + + if (error != traverse_error_none) + { + return error; + } + + if (current_turn_index == start_turn_index + && current_op_index == start_op_index) + { + start_op.visited.set_finished(); + m_visitor.visit_traverse(m_turns, start_turn, start_op, "Finish"); + return traverse_error_none; + } + } + + return traverse_error_endless_loop; + } + + template + void traverse_with_operation(turn_type const& start_turn, + std::size_t turn_index, int op_index, + Rings& rings, std::size_t& finalized_ring_size, + typename Backtrack::state_type& state) + { + typedef typename boost::range_value::type ring_type; + + turn_operation_type const& start_op = start_turn.operations[op_index]; + + if (! start_op.visited.none() + || ! start_op.enriched.startable + || start_op.visited.rejected() + || ! (start_op.operation == target_operation + || start_op.operation == detail::overlay::operation_continue)) + { + return; + } + + ring_type ring; + traverse_error_type traverse_error = traverse(ring, turn_index, op_index); + + if (traverse_error == traverse_error_none) + { + std::size_t const min_num_points + = core_detail::closure::minimum_ring_size + < + geometry::closure::value + >::value; + + if (geometry::num_points(ring) >= min_num_points) + { + clean_closing_dups_and_spikes(ring, m_robust_policy); + rings.push_back(ring); + + m_trav.finalize_visit_info(); + finalized_ring_size++; + } + } + else + { + Backtrack::apply( + finalized_ring_size, + rings, ring, m_turns, start_turn, + m_turns[turn_index].operations[op_index], + traverse_error, + m_geometry1, m_geometry2, m_robust_policy, + state, m_visitor); + } + } + + template + void iterate(Rings& rings, std::size_t& finalized_ring_size, + typename Backtrack::state_type& state, + int pass) + { + if (pass == 1) + { + if (target_operation == operation_intersection) + { + // Second pass currently only used for uu + return; + } + if (! m_has_uu) + { + // There is no uu found in first pass + return; + } + } + + // Iterate through all unvisited points + for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index) + { + turn_type const& start_turn = m_turns[turn_index]; + + if (start_turn.discarded || start_turn.blocked()) + { + // Skip discarded and blocked turns + continue; + } + if (target_operation == operation_union) + { + if (start_turn.both(operation_union)) + { + // Start with a uu-turn only in the second pass + m_has_uu = true; + if (pass == 0) + { + continue; + } + } + } + + for (int op_index = 0; op_index < 2; op_index++) + { + traverse_with_operation(start_turn, turn_index, op_index, + rings, finalized_ring_size, state); + } + } + } + +private: + traversal_type m_trav; + + Geometry1 const& m_geometry1; + Geometry2 const& m_geometry2; + Turns& m_turns; + Clusters const& m_clusters; + RobustPolicy const& m_robust_policy; + Visitor& m_visitor; + + // Next member is only used for operation union + bool m_has_uu; + +}; + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_RING_CREATOR_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp b/include/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp new file mode 100644 index 000000000..e37c8657c --- /dev/null +++ b/include/boost/geometry/algorithms/detail/overlay/traversal_switch_detector.hpp @@ -0,0 +1,291 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2015-2016 Barend Gehrels, Amsterdam, the Netherlands. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_SWITCH_DETECTOR_HPP +#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_SWITCH_DETECTOR_HPP + +#include + +#include + +#include +#include +#include +#include +#include +#include + +namespace boost { namespace geometry +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail { namespace overlay +{ + +// Generic function (is this used somewhere else too?) +inline ring_identifier ring_id_by_seg_id(segment_identifier const& seg_id) +{ + return ring_identifier(seg_id.source_index, seg_id.multi_index, seg_id.ring_index); +} + +template +< + bool Reverse1, + bool Reverse2, + overlay_type OverlayType, + typename Geometry1, + typename Geometry2, + typename Turns, + typename Clusters, + typename RobustPolicy, + typename Visitor +> +struct traversal_switch_detector +{ + typedef typename boost::range_value::type turn_type; + typedef typename turn_type::turn_operation_type turn_operation_type; + + // For convenience + typedef std::set::const_iterator set_iterator; + + inline traversal_switch_detector(Geometry1 const& geometry1, Geometry2 const& geometry2, + Turns& turns, Clusters& clusters, + RobustPolicy const& robust_policy, Visitor& visitor) + : m_geometry1(geometry1) + , m_geometry2(geometry2) + , m_turns(turns) + , m_clusters(clusters) + , m_robust_policy(robust_policy) + , m_visitor(visitor) + , m_region_id(0) + { + + } + + static inline bool connects_same_zone(turn_type const& turn) + { + if (turn.cluster_id == -1) + { + // If it is a uu-turn (non clustered), it is never same zone + return ! turn.both(operation_union); + } + + // It is a cluster, check zones of both operations + return turn.operations[0].enriched.zone + == turn.operations[1].enriched.zone; + } + + inline int get_region_id(turn_operation_type const& op) const + { + std::map::const_iterator it + = m_regions.find(ring_id_by_seg_id(op.seg_id)); + return it == m_regions.end() ? -1 : it->second; + } + + void create_region(ring_identifier const& ring_id, std::set const& ring_turn_indices, int region_id = -1) + { + std::map::const_iterator it = m_regions.find(ring_id); + if (it != m_regions.end()) + { + // The ring is already gathered in a region, quit + return; + } + if (region_id == -1) + { + region_id = m_region_id++; + } + + // Assign this ring to specified region + m_regions[ring_id] = region_id; +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) + std::cout << " ADD " << ring_id << " TO REGION " << region_id << std::endl; +#endif + + // Find connecting rings, recursively + for (set_iterator sit = ring_turn_indices.begin(); + sit != ring_turn_indices.end(); ++sit) + { + signed_size_type const turn_index = *sit; + turn_type const& turn = m_turns[turn_index]; + if (! connects_same_zone(turn)) + { + // This is a non clustered uu-turn, or a cluster connecting different 'zones' + continue; + } + + // This turn connects two rings (interior connected), create the + // same region + for (int op_index = 0; op_index < 2; op_index++) + { + turn_operation_type const& op = turn.operations[op_index]; + ring_identifier connected_ring_id = ring_id_by_seg_id(op.seg_id); + if (connected_ring_id != ring_id) + { + propagate_region(connected_ring_id, region_id); + } + } + } + } + + void propagate_region(ring_identifier const& ring_id, int region_id) + { + std::map >::const_iterator it = m_turns_per_ring.find(ring_id); + if (it != m_turns_per_ring.end()) + { + create_region(ring_id, it->second, region_id); + } + } + + void iterate() + { +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) + std::cout << "SWITCH BEGIN ITERATION" << std::endl; +#endif + + // Collect turns per ring + m_turns_per_ring.clear(); + m_regions.clear(); + m_region_id = 1; + + for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index) + { + turn_type const& turn = m_turns[turn_index]; + + for (int op_index = 0; op_index < 2; op_index++) + { + turn_operation_type const& op = turn.operations[op_index]; + m_turns_per_ring[ring_id_by_seg_id(op.seg_id)].insert(turn_index); + } + } + + // All rings having turns are in the map. Now iterate them + for (std::map >::const_iterator it + = m_turns_per_ring.begin(); it != m_turns_per_ring.end(); ++it) + { + create_region(it->first, it->second); + } + + // Now that all regions are filled, assign switch_source property + // Iterate through all clusters + for (typename Clusters::iterator it = m_clusters.begin(); it != m_clusters.end(); ++it) + { + cluster_info& cinfo = it->second; + if (cinfo.open_count <= 1) + { + // Not a touching cluster + continue; + } + + // A touching cluster, gather regions + std::set regions; + + std::set const& ids = cinfo.turn_indices; + +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) + std::cout << "SWITCH EXAMINE CLUSTER " << it->first << std::endl; +#endif + + for (set_iterator sit = ids.begin(); sit != ids.end(); ++sit) + { + signed_size_type turn_index = *sit; + turn_type const& turn = m_turns[turn_index]; + for (int oi = 0; oi < 2; oi++) + { + int const region = get_region_id(turn.operations[oi]); + regions.insert(region); + } + } + // Switch source if this cluster connects the same region + cinfo.switch_source = regions.size() == 1; + } + + // Iterate through all uu turns (non-clustered) + for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index) + { + turn_type& turn = m_turns[turn_index]; + + if (turn.discarded + || turn.blocked() + || turn.cluster_id >= 0 + || ! turn.both(operation_union)) + { + // Skip discarded, blocked, non-uu and clustered turns + continue; + } + + if (OverlayType == overlay_buffer) + { + // For deflate, the region approach does not work because many + // pieces are outside the real polygons + // TODO: implement this in another way for buffer + // (because now buffer might output invalid geometries) + continue; + } + + int const region0 = get_region_id(turn.operations[0]); + int const region1 = get_region_id(turn.operations[1]); + + // Switch sources for same region + turn.switch_source = region0 == region1; + } + + +#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSAL_SWITCH_DETECTOR) + std::cout << "SWITCH END ITERATION" << 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.cluster_id < 0) + { + std::cout << "UU SWITCH RESULT " + << turn_index << " -> " + << turn.switch_source << std::endl; + } + } + + for (typename Clusters::const_iterator it = m_clusters.begin(); it != m_clusters.end(); ++it) + { + cluster_info const& cinfo = it->second; + if (cinfo.open_count > 1) + { + std::cout << "CL SWITCH RESULT " << it->first + << " -> " << cinfo.switch_source << std::endl; + } + else + { + std::cout << "CL SWITCH RESULT " << it->first + << " is not registered as open" << std::endl; + } + } +#endif + + } + +private: + + Geometry1 const& m_geometry1; + Geometry2 const& m_geometry2; + Turns& m_turns; + Clusters& m_clusters; + RobustPolicy const& m_robust_policy; + Visitor& m_visitor; + + std::map m_regions; + std::map > m_turns_per_ring; + int m_region_id; + +}; + +}} // namespace detail::overlay +#endif // DOXYGEN_NO_DETAIL + +}} // namespace boost::geometry + +#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_TRAVERSAL_SWITCH_DETECTOR_HPP diff --git a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp index a8f423212..2d2933ebd 100644 --- a/include/boost/geometry/algorithms/detail/overlay/traverse.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/traverse.hpp @@ -11,26 +11,10 @@ #include -#include - #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include -#if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) \ - || defined(BOOST_GEOMETRY_OVERLAY_REPORT_WKT) \ - || defined(BOOST_GEOMETRY_DEBUG_TRAVERSE) -# include -# include -# include -#endif namespace boost { namespace geometry { @@ -39,768 +23,6 @@ namespace boost { namespace geometry namespace detail { namespace overlay { -template -#ifdef BOOST_GEOMETRY_DEBUG_TRAVERSE -inline void debug_traverse(Turn const& turn, Operation op, - std::string const& header) -{ - std::cout << header - << " at " << op.seg_id - << " meth: " << method_char(turn.method) - << " op: " << operation_char(op.operation) - << " vis: " << visited_char(op.visited) - << " of: " << operation_char(turn.operations[0].operation) - << operation_char(turn.operations[1].operation) - << " " << geometry::wkt(turn.point) - << std::endl; - - if (boost::contains(header, "Finished")) - { - std::cout << std::endl; - } -} -#else -inline void debug_traverse(Turn const& , Operation, const char*) -{ -} -#endif - - -//! Metafunction to define side_order (clockwise, ccw) by operation_type -template -struct side_compare {}; - -template <> -struct side_compare -{ - typedef std::greater type; -}; - -template <> -struct side_compare -{ - typedef std::less type; -}; - - -template -< - bool Reverse1, - bool Reverse2, - operation_type OperationType, - typename Geometry1, - typename Geometry2, - typename Turns, - typename Clusters, - typename RobustPolicy, - typename Visitor, - typename Backtrack -> -struct traversal -{ - typedef typename side_compare::type side_compare_type; - typedef typename boost::range_value::type turn_type; - typedef typename turn_type::turn_operation_type turn_operation_type; - - typedef typename geometry::point_type::type point_type; - typedef sort_by_side::side_sorter - < - Reverse1, Reverse2, - point_type, side_compare_type - > sbs_type; - - inline traversal(Geometry1 const& geometry1, Geometry2 const& geometry2, - Turns& turns, Clusters const& clusters, - RobustPolicy const& robust_policy, Visitor& visitor) - : m_geometry1(geometry1) - , m_geometry2(geometry2) - , m_turns(turns) - , m_clusters(clusters) - , m_robust_policy(robust_policy) - , m_visitor(visitor) - , m_has_uu(false) - , m_has_only_uu(true) - , m_switch_at_uu(true) - {} - - - inline bool select_source(signed_size_type turn_index, - segment_identifier const& seg_id1, - segment_identifier const& seg_id2) - { - if (OperationType == operation_intersection) - { - // For intersections always switch sources - return seg_id1.source_index != seg_id2.source_index; - } - else if (OperationType == operation_union) - { - // For uu, only switch sources if indicated - turn_type const& turn = m_turns[turn_index]; - - // TODO: pass this information - bool const is_buffer - = turn.operations[0].seg_id.source_index - == turn.operations[1].seg_id.source_index; - - if (is_buffer) - { - // Buffer does not use source_index (always 0) - return turn.switch_source - ? seg_id1.multi_index != seg_id2.multi_index - : seg_id1.multi_index == seg_id2.multi_index; - } - - // Temporarily use m_switch_at_uu, which does not solve all cases, - // but the majority of the more simple cases, making the interior - // rings valid - return m_switch_at_uu // turn.switch_source - ? seg_id1.source_index != seg_id2.source_index - : seg_id1.source_index == seg_id2.source_index; - } - return false; - } - - inline - signed_size_type get_next_turn_index(turn_operation_type const& op) const - { - return op.enriched.next_ip_index == -1 - ? op.enriched.travels_to_ip_index - : op.enriched.next_ip_index; - } - - inline bool traverse_possible(signed_size_type turn_index) const - { - if (turn_index == -1) - { - return false; - } - - turn_type const& turn = m_turns[turn_index]; - - // It is not a dead end if there is an operation to continue, or of - // there is a cluster (assuming for now we can get out of the cluster) - return turn.cluster_id >= 0 - || turn.has(OperationType) - || turn.has(operation_continue); - } - - inline bool select_operation(turn_type& turn, - signed_size_type start_turn_index, - segment_identifier const& seg_id, - int& selected_op_index) - { - if (turn.discarded) - { - return false; - } - - bool result = false; - - typename turn_operation_type::comparable_distance_type - max_remaining_distance = 0; - - selected_op_index = -1; - for (int i = 0; i < 2; i++) - { - turn_operation_type const& op = turn.operations[i]; - if (op.visited.started()) - { - selected_op_index = i; - return true; - } - - signed_size_type const next_turn_index = get_next_turn_index(op); - - // In some cases there are two alternatives. - // For "ii", take the other one (alternate) - // UNLESS the other one is already visited - // For "uu", take the same one (see above); - // For "cc", take either one, but if there is a starting one, - // take that one. If next is dead end, skip that one. - if ( (op.operation == operation_continue - && traverse_possible(next_turn_index) - && ! result) - || (op.operation == OperationType - && ! op.visited.finished() - && (! result - || select_source(next_turn_index, op.seg_id, seg_id) - ) - ) - ) - { - if (op.operation == operation_continue) - { - max_remaining_distance = op.remaining_distance; - } - selected_op_index = i; - debug_traverse(turn, op, " Candidate"); - result = true; - } - - if (op.operation == operation_continue && result) - { - if (next_turn_index == start_turn_index) - { - selected_op_index = i; - debug_traverse(turn, op, " Candidate override (start)"); - } - else if (op.remaining_distance > max_remaining_distance) - { - max_remaining_distance = op.remaining_distance; - selected_op_index = i; - debug_traverse(turn, op, " Candidate override (remaining)"); - } - } - } - - if (result) - { - debug_traverse(turn, turn.operations[selected_op_index], " Accepted"); - } - - return result; - } - - inline bool select_from_cluster(signed_size_type& turn_index, - int& op_index, signed_size_type start_turn_index, - sbs_type const& sbs, bool allow_pass_rank) - { - bool const is_union = OperationType == operation_union; - bool const is_intersection = OperationType == operation_intersection; - - std::size_t selected_rank = 0; - std::size_t min_rank = 0; - bool result = false; - for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++) - { - typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[i]; - if (result && ranked_point.main_rank > selected_rank) - { - return result; - } - - turn_type const& ranked_turn = m_turns[ranked_point.turn_index]; - turn_operation_type const& ranked_op = ranked_turn.operations[ranked_point.op_index]; - - if (result && ranked_op.visited.finalized()) - { - // One of the arcs in the same direction as the selected result - // is already traversed. - return false; - } - - if (! allow_pass_rank && ranked_op.visited.finalized()) - { - // Skip this one, go to next - min_rank = ranked_point.main_rank; - continue; - } - - if (ranked_point.index == sort_by_side::index_to - && (ranked_point.main_rank > min_rank - || ranked_turn.both(operation_continue))) - { - if ((is_union - && ranked_op.enriched.count_left == 0 - && ranked_op.enriched.count_right > 0) - || (is_intersection - && ranked_op.enriched.count_right == 2)) - { - if (result && ranked_point.turn_index != start_turn_index) - { - // Don't override - only override if arrive at start - continue; - } - - turn_index = ranked_point.turn_index; - op_index = ranked_point.op_index; - - if (is_intersection - && ranked_turn.both(operation_intersection) - && ranked_op.visited.finalized()) - { - // Override: - // For a ii turn, even though one operation might be selected, - // it should take the other one if the first one is used in a completed ring - op_index = 1 - ranked_point.op_index; - } - - result = true; - selected_rank = ranked_point.main_rank; - } - else if (! allow_pass_rank) - { - return result; - } - } - } - return result; - } - - inline bool select_turn_from_cluster(signed_size_type& turn_index, - int& op_index, signed_size_type start_turn_index, - point_type const& point) - { - bool const is_union = OperationType == operation_union; - - turn_type const& turn = m_turns[turn_index]; - BOOST_ASSERT(turn.cluster_id >= 0); - - typename Clusters::const_iterator mit = m_clusters.find(turn.cluster_id); - BOOST_ASSERT(mit != m_clusters.end()); - - std::set const& ids = mit->second; - - sbs_type sbs; - sbs.set_origin(point); - - for (typename std::set::const_iterator sit = ids.begin(); - sit != ids.end(); ++sit) - { - signed_size_type cluster_turn_index = *sit; - turn_type const& cluster_turn = m_turns[cluster_turn_index]; - if (cluster_turn.discarded) - { - // Defensive check, discarded turns should not be in cluster - continue; - } - - for (int i = 0; i < 2; i++) - { - sbs.add(cluster_turn.operations[i], cluster_turn_index, i, - m_geometry1, m_geometry2, false); - } - } - - sbs.apply(turn.point); - - int open_count = 0; - if (is_union) - { - // Check how many open spaces there are. - // TODO: might be moved to sbs itself, though it also uses turns - - std::size_t last_rank = 0; - for (std::size_t i = 0; i < sbs.m_ranked_points.size(); i++) - { - typename sbs_type::rp const& ranked_point = sbs.m_ranked_points[i]; - - if (ranked_point.main_rank > last_rank - && ranked_point.index == sort_by_side::index_to) - { - turn_type const& ranked_turn = m_turns[ranked_point.turn_index]; - turn_operation_type const& ranked_op = ranked_turn.operations[ranked_point.op_index]; - if (ranked_op.enriched.count_left == 0 - && ranked_op.enriched.count_right > 0) - { - open_count++; - last_rank = ranked_point.main_rank; - } - } - } - } - - bool allow = false; - if (open_count > 1) - { - sbs.reverse(); - allow = true; - } - - return select_from_cluster(turn_index, op_index, start_turn_index, sbs, allow); - } - - inline void change_index_for_self_turn(signed_size_type& to_vertex_index, - turn_type const& start_turn, - turn_operation_type const& start_op, - int start_op_index) - { - turn_operation_type const& other_op - = start_turn.operations[1 - start_op_index]; - if (start_op.seg_id.source_index != other_op.seg_id.source_index) - { - // Not a buffer/self-turn - return; - } - - // It travels to itself, can happen. If this is a buffer, it can - // sometimes travel to itself in the following configuration: - // - // +---->--+ - // | | - // | +---*----+ *: one turn, with segment index 2/7 - // | | | | - // | +---C | C: closing point (start/end) - // | | - // +------------+ - // - // If it starts on segment 2 and travels to itself on segment 2, that - // should be corrected to 7 because that is the shortest path - // - // Also a uu turn (touching with another buffered ring) might have this - // apparent configuration, but there it should - // always travel the whole ring - - bool const correct - = ! start_turn.both(operation_union) - && start_op.seg_id.segment_index == to_vertex_index; - -#if defined(BOOST_GEOMETRY_DEBUG_TRAVERSE) - std::cout << " WARNING: self-buffer " - << " correct=" << correct - << " turn=" << operation_char(start_turn.operations[0].operation) - << operation_char(start_turn.operations[1].operation) - << " start=" << start_op.seg_id.segment_index - << " from=" << to_vertex_index - << " to=" << other_op.enriched.travels_to_vertex_index - << std::endl; -#endif - - if (correct) - { - to_vertex_index = other_op.enriched.travels_to_vertex_index; - } - } - - template - inline traverse_error_type travel_to_next_turn(signed_size_type start_turn_index, - int start_op_index, - signed_size_type& turn_index, - int& op_index, - segment_identifier& seg_id, - Ring& current_ring, - bool is_start) - { - int const previous_op_index = op_index; - signed_size_type const previous_turn_index = turn_index; - turn_type& previous_turn = m_turns[turn_index]; - turn_operation_type& previous_op = previous_turn.operations[op_index]; - - // If there is no next IP on this segment - if (previous_op.enriched.next_ip_index < 0) - { - if (previous_op.enriched.travels_to_vertex_index < 0 - || previous_op.enriched.travels_to_ip_index < 0) - { - return is_start - ? traverse_error_no_next_ip_at_start - : traverse_error_no_next_ip; - } - - signed_size_type to_vertex_index = previous_op.enriched.travels_to_vertex_index; - - if (is_start && - previous_op.enriched.travels_to_ip_index == start_turn_index) - { - change_index_for_self_turn(to_vertex_index, previous_turn, - previous_op, start_op_index); - } - - if (previous_op.seg_id.source_index == 0) - { - geometry::copy_segments(m_geometry1, - previous_op.seg_id, to_vertex_index, - m_robust_policy, current_ring); - } - else - { - geometry::copy_segments(m_geometry2, - previous_op.seg_id, to_vertex_index, - m_robust_policy, current_ring); - } - seg_id = previous_op.seg_id; - turn_index = previous_op.enriched.travels_to_ip_index; - } - else - { - turn_index = previous_op.enriched.next_ip_index; - seg_id = previous_op.seg_id; - } - - // turn_index is not yet finally selected, can change for clusters - bool const has_cluster = m_turns[turn_index].cluster_id >= 0; - if (has_cluster) - { - - if (! select_turn_from_cluster(turn_index, op_index, - start_turn_index, current_ring.back())) - { - return is_start - ? traverse_error_no_next_ip_at_start - : traverse_error_no_next_ip; - } - - if (is_start && turn_index == previous_turn_index) - { - op_index = previous_op_index; - } - } - - turn_type& current_turn = m_turns[turn_index]; - detail::overlay::append_no_dups_or_spikes(current_ring, current_turn.point, - m_robust_policy); - - if (is_start) - { - // Register the start - previous_op.visited.set_started(); - m_visitor.visit_traverse(m_turns, previous_turn, previous_op, "Start"); - } - - if (! has_cluster) - { - if (! select_operation(current_turn, - start_turn_index, - seg_id, - op_index)) - { - return is_start - ? traverse_error_dead_end_at_start - : traverse_error_dead_end; - } - } - - turn_operation_type& op = current_turn.operations[op_index]; - if (op.visited.finalized() || op.visited.visited()) - { - return traverse_error_visit_again; - } - - // Register the visit - set_visited(current_turn, op); - m_visitor.visit_traverse(m_turns, current_turn, op, "Visit"); - - return traverse_error_none; - } - - inline void finalize_visit_info() - { - for (typename boost::range_iterator::type - it = boost::begin(m_turns); - it != boost::end(m_turns); - ++it) - { - turn_type& turn = *it; - for (int i = 0; i < 2; i++) - { - turn_operation_type& op = turn.operations[i]; - op.visited.finalize(); - } - } - } - - inline void set_visited(turn_type& turn, turn_operation_type& op) - { - // On "continue", set "visited" for ALL directions in this turn - if (op.operation == detail::overlay::operation_continue) - { - for (int i = 0; i < 2; i++) - { - turn_operation_type& op = turn.operations[i]; - if (op.visited.none()) - { - op.visited.set_visited(); - } - } - } - else - { - op.visited.set_visited(); - } - } - - - template - inline traverse_error_type traverse(Ring& ring, - signed_size_type start_turn_index, int start_op_index) - { - turn_type const& start_turn = m_turns[start_turn_index]; - turn_operation_type& start_op = m_turns[start_turn_index].operations[start_op_index]; - - detail::overlay::append_no_dups_or_spikes(ring, start_turn.point, - m_robust_policy); - - signed_size_type current_turn_index = start_turn_index; - int current_op_index = start_op_index; - segment_identifier current_seg_id; - - traverse_error_type error = travel_to_next_turn(start_turn_index, - start_op_index, - current_turn_index, current_op_index, current_seg_id, - ring, true); - - if (error != traverse_error_none) - { - // This is not necessarily a problem, it happens for clustered turns - // which are "build in" or otherwise point inwards - return error; - } - - if (current_turn_index == start_turn_index) - { - start_op.visited.set_finished(); - m_visitor.visit_traverse(m_turns, m_turns[current_turn_index], start_op, "Early finish"); - return traverse_error_none; - } - - std::size_t const max_iterations = 2 + 2 * m_turns.size(); - for (std::size_t i = 0; i <= max_iterations; i++) - { - // We assume clockwise polygons only, non self-intersecting, closed. - // However, the input might be different, and checking validity - // is up to the library user. - - // Therefore we make here some sanity checks. If the input - // violates the assumptions, the output polygon will not be correct - // but the routine will stop and output the current polygon, and - // will continue with the next one. - - // Below three reasons to stop. - error = travel_to_next_turn(start_turn_index, start_op_index, - current_turn_index, current_op_index, current_seg_id, - ring, false); - - if (error != traverse_error_none) - { - return error; - } - - if (current_turn_index == start_turn_index - && current_op_index == start_op_index) - { - start_op.visited.set_finished(); - m_visitor.visit_traverse(m_turns, start_turn, start_op, "Finish"); - return traverse_error_none; - } - } - - return traverse_error_endless_loop; - } - - template - void traverse_with_operation(turn_type const& start_turn, - std::size_t turn_index, int op_index, - Rings& rings, std::size_t& finalized_ring_size, - typename Backtrack::state_type& state) - { - typedef typename boost::range_value::type ring_type; - - turn_operation_type const& start_op = start_turn.operations[op_index]; - - if (! start_op.visited.none() - || ! start_op.enriched.startable - || start_op.visited.rejected() - || ! (start_op.operation == OperationType - || start_op.operation == detail::overlay::operation_continue)) - { - return; - } - - ring_type ring; - traverse_error_type traverse_error = traverse(ring, turn_index, op_index); - - if (traverse_error == traverse_error_none) - { - std::size_t const min_num_points - = core_detail::closure::minimum_ring_size - < - geometry::closure::value - >::value; - - if (geometry::num_points(ring) >= min_num_points) - { - clean_closing_dups_and_spikes(ring, m_robust_policy); - rings.push_back(ring); - - finalize_visit_info(); - finalized_ring_size++; - } - } - else - { - Backtrack::apply( - finalized_ring_size, - rings, ring, m_turns, start_turn, - m_turns[turn_index].operations[op_index], - traverse_error, - m_geometry1, m_geometry2, m_robust_policy, - state, m_visitor); - } - } - - template - void iterate(Rings& rings, std::size_t& finalized_ring_size, - typename Backtrack::state_type& state, - int pass) - { - if (pass == 1) - { - if (OperationType == operation_intersection) - { - // Second pass currently only used for uu - return; - } - if (! m_has_uu) - { - // There is no uu found in first pass - return; - } - if (m_has_only_uu) - { - m_switch_at_uu = false; - } - } - - // Iterate through all unvisited points - for (std::size_t turn_index = 0; turn_index < m_turns.size(); ++turn_index) - { - turn_type const& start_turn = m_turns[turn_index]; - - if (start_turn.discarded || start_turn.blocked()) - { - // Skip discarded and blocked turns - continue; - } - if (OperationType == operation_union) - { - if (start_turn.both(operation_union)) - { - // Start with a uu-turn only in the second pass - m_has_uu = true; - if (pass == 0) - { - continue; - } - } - else - { - m_has_only_uu = false; - } - } - - for (int op_index = 0; op_index < 2; op_index++) - { - traverse_with_operation(start_turn, turn_index, op_index, - rings, finalized_ring_size, state); - } - } - } - -private : - Geometry1 const& m_geometry1; - Geometry2 const& m_geometry2; - Turns& m_turns; - Clusters const& m_clusters; - RobustPolicy const& m_robust_policy; - Visitor& m_visitor; - - // Next members are only used for operation union - bool m_has_uu; - bool m_has_only_uu; - bool m_switch_at_uu; -}; - /*! \brief Traverses through intersection points / geometries @@ -811,11 +33,28 @@ template bool Reverse1, bool Reverse2, typename Geometry1, typename Geometry2, - operation_type OperationType, + overlay_type OverlayType, typename Backtrack = backtrack_check_self_intersections > class traverse { + + template + static void reset_visits(Turns& turns) + { + for (typename boost::range_iterator::type + it = boost::begin(turns); + it != boost::end(turns); + ++it) + { + for (int i = 0; i < 2; i++) + { + it->operations[i].visited.reset(); + } + } + } + + public : template < @@ -829,12 +68,24 @@ public : Geometry2 const& geometry2, RobustPolicy const& robust_policy, Turns& turns, Rings& rings, - Clusters const& clusters, + Clusters& clusters, Visitor& visitor) { - traversal + traversal_switch_detector < - Reverse1, Reverse2, OperationType, + Reverse1, Reverse2, OverlayType, + Geometry1, Geometry2, + Turns, Clusters, + RobustPolicy, Visitor + > switch_detector(geometry1, geometry2, turns, clusters, + robust_policy, visitor); + + switch_detector.iterate(); + reset_visits(turns); + + traversal_ring_creator + < + Reverse1, Reverse2, OverlayType, Geometry1, Geometry2, Turns, Clusters, RobustPolicy, Visitor, diff --git a/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp index 699997fc3..d9f5a7d13 100644 --- a/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/turn_info.hpp @@ -13,7 +13,9 @@ #include #include +#include #include +#include namespace boost { namespace geometry { @@ -22,18 +24,6 @@ namespace boost { namespace geometry namespace detail { namespace overlay { - -enum operation_type -{ - operation_none, - operation_union, - operation_intersection, - operation_blocked, - operation_continue, - operation_opposite -}; - - enum method_type { method_none, @@ -99,7 +89,7 @@ struct turn_info Point point; method_type method; - int cluster_id; + signed_size_type cluster_id; bool discarded; bool colocated; bool switch_source; // For u/u turns which can either switch or not diff --git a/include/boost/geometry/algorithms/detail/overlay/visit_info.hpp b/include/boost/geometry/algorithms/detail/overlay/visit_info.hpp index 9e1e6b905..e401fbbb4 100644 --- a/include/boost/geometry/algorithms/detail/overlay/visit_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/visit_info.hpp @@ -61,6 +61,11 @@ public: } } + inline void reset() + { + *this = visit_info(); + } + inline void finalize() { if (visited() || started() || finished() ) diff --git a/include/boost/geometry/algorithms/detail/point_on_border.hpp b/include/boost/geometry/algorithms/detail/point_on_border.hpp index 24b88a8d1..1c751c23e 100644 --- a/include/boost/geometry/algorithms/detail/point_on_border.hpp +++ b/include/boost/geometry/algorithms/detail/point_on_border.hpp @@ -286,8 +286,8 @@ inline bool point_on_border(Point& point, Geometry const& geometry, bool midpoint = false) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); return dispatch::point_on_border < diff --git a/include/boost/geometry/algorithms/detail/recalculate.hpp b/include/boost/geometry/algorithms/detail/recalculate.hpp index fd3ed6b8d..b75dd135e 100644 --- a/include/boost/geometry/algorithms/detail/recalculate.hpp +++ b/include/boost/geometry/algorithms/detail/recalculate.hpp @@ -219,8 +219,8 @@ struct recalculate template inline void recalculate(Geometry1& geometry1, Geometry2 const& geometry2, Strategy const& strategy) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); // static assert dimensions (/types) are the same diff --git a/include/boost/geometry/algorithms/detail/relate/interface.hpp b/include/boost/geometry/algorithms/detail/relate/interface.hpp index e2c067b68..95d452931 100644 --- a/include/boost/geometry/algorithms/detail/relate/interface.hpp +++ b/include/boost/geometry/algorithms/detail/relate/interface.hpp @@ -199,8 +199,8 @@ struct relate Geometry2 const& geometry2, Mask const& mask) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); assert_dimension_equal(); typename detail::relate::result_handler_type diff --git a/include/boost/geometry/algorithms/detail/relation/interface.hpp b/include/boost/geometry/algorithms/detail/relation/interface.hpp index 73737cf2c..e9a947455 100644 --- a/include/boost/geometry/algorithms/detail/relation/interface.hpp +++ b/include/boost/geometry/algorithms/detail/relation/interface.hpp @@ -46,8 +46,8 @@ struct relation static inline Matrix apply(Geometry1 const& geometry1, Geometry2 const& geometry2) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); assert_dimension_equal(); typename detail::relate::result_handler_type diff --git a/include/boost/geometry/algorithms/detail/ring_identifier.hpp b/include/boost/geometry/algorithms/detail/ring_identifier.hpp index 9ba39e4a8..4a7e717cf 100644 --- a/include/boost/geometry/algorithms/detail/ring_identifier.hpp +++ b/include/boost/geometry/algorithms/detail/ring_identifier.hpp @@ -56,6 +56,11 @@ struct ring_identifier ; } + inline bool operator!=(ring_identifier const& other) const + { + return ! operator==(other); + } + #if defined(BOOST_GEOMETRY_DEBUG_IDENTIFIER) friend std::ostream& operator<<(std::ostream &os, ring_identifier const& ring_id) { diff --git a/include/boost/geometry/algorithms/detail/sections/range_by_section.hpp b/include/boost/geometry/algorithms/detail/sections/range_by_section.hpp index 02cec6cb4..611ad172d 100644 --- a/include/boost/geometry/algorithms/detail/sections/range_by_section.hpp +++ b/include/boost/geometry/algorithms/detail/sections/range_by_section.hpp @@ -177,7 +177,7 @@ template inline typename ring_return_type::type range_by_section(Geometry const& geometry, Section const& section) { - concept::check(); + concepts::check(); return dispatch::range_by_section < diff --git a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp index 39c7894e2..3ed5b8db0 100644 --- a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp +++ b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp @@ -822,7 +822,7 @@ inline void sectionalize(Geometry const& geometry, int source_index = 0, std::size_t max_count = 10) { - concept::check(); + concepts::check(); typedef typename boost::range_value::type section_type; diff --git a/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp b/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp index 68e74a8c5..a73364c33 100644 --- a/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp +++ b/include/boost/geometry/algorithms/detail/within/point_in_geometry.hpp @@ -400,7 +400,7 @@ namespace detail { namespace within { template inline int point_in_geometry(Point const& point, Geometry const& geometry, Strategy const& strategy) { - concept::within::check + concepts::within::check < typename tag::type, typename tag::type, diff --git a/include/boost/geometry/algorithms/difference.hpp b/include/boost/geometry/algorithms/difference.hpp index 8fec85e7c..f7ca48cbe 100644 --- a/include/boost/geometry/algorithms/difference.hpp +++ b/include/boost/geometry/algorithms/difference.hpp @@ -54,9 +54,9 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1, OutputIterator out, Strategy const& strategy) { - concept::check(); - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); + concepts::check(); return geometry::dispatch::intersection_insert < @@ -97,9 +97,9 @@ inline OutputIterator difference_insert(Geometry1 const& geometry1, RobustPolicy const& robust_policy, OutputIterator out) { - concept::check(); - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); + concepts::check(); typedef intersection_strategies < @@ -142,11 +142,11 @@ template inline void difference(Geometry1 const& geometry1, Geometry2 const& geometry2, Collection& output_collection) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); typedef typename boost::range_value::type geometry_out; - concept::check(); + concepts::check(); typedef typename geometry::rescale_overlay_policy_type < diff --git a/include/boost/geometry/algorithms/equals.hpp b/include/boost/geometry/algorithms/equals.hpp index 138f3218b..d04d5c7f3 100644 --- a/include/boost/geometry/algorithms/equals.hpp +++ b/include/boost/geometry/algorithms/equals.hpp @@ -352,7 +352,7 @@ struct equals static inline bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) { - concept::check_concepts_and_equal_dimensions + concepts::check_concepts_and_equal_dimensions < Geometry1 const, Geometry2 const diff --git a/include/boost/geometry/algorithms/for_each.hpp b/include/boost/geometry/algorithms/for_each.hpp index c5c099b1a..741dc359f 100644 --- a/include/boost/geometry/algorithms/for_each.hpp +++ b/include/boost/geometry/algorithms/for_each.hpp @@ -337,7 +337,7 @@ struct for_each_segment template inline Functor for_each_point(Geometry& geometry, Functor f) { - concept::check(); + concepts::check(); dispatch::for_each_point::apply(geometry, f); return f; @@ -360,7 +360,7 @@ inline Functor for_each_point(Geometry& geometry, Functor f) template inline Functor for_each_segment(Geometry& geometry, Functor f) { - concept::check(); + concepts::check(); dispatch::for_each_segment::apply(geometry, f); return f; diff --git a/include/boost/geometry/algorithms/intersects.hpp b/include/boost/geometry/algorithms/intersects.hpp index 1bb85aa3b..5349db76b 100644 --- a/include/boost/geometry/algorithms/intersects.hpp +++ b/include/boost/geometry/algorithms/intersects.hpp @@ -49,7 +49,7 @@ namespace boost { namespace geometry template inline bool intersects(Geometry const& geometry) { - concept::check(); + concepts::check(); typedef typename geometry::point_type::type point_type; typedef detail::no_rescale_policy rescale_policy_type; @@ -93,8 +93,8 @@ inline bool intersects(Geometry const& geometry) template inline bool intersects(Geometry1 const& geometry1, Geometry2 const& geometry2) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); return ! geometry::disjoint(geometry1, geometry2); } diff --git a/include/boost/geometry/algorithms/is_empty.hpp b/include/boost/geometry/algorithms/is_empty.hpp index 02c295eab..8dab69c87 100644 --- a/include/boost/geometry/algorithms/is_empty.hpp +++ b/include/boost/geometry/algorithms/is_empty.hpp @@ -157,7 +157,7 @@ struct is_empty { static inline bool apply(Geometry const& geometry) { - concept::check(); + concepts::check(); return dispatch::is_empty::apply(geometry); } diff --git a/include/boost/geometry/algorithms/length.hpp b/include/boost/geometry/algorithms/length.hpp index cf5234da1..39a567a26 100644 --- a/include/boost/geometry/algorithms/length.hpp +++ b/include/boost/geometry/algorithms/length.hpp @@ -251,7 +251,7 @@ template inline typename default_length_result::type length(Geometry const& geometry) { - concept::check(); + concepts::check(); // detail::throw_on_empty_input(geometry); @@ -283,7 +283,7 @@ template inline typename default_length_result::type length(Geometry const& geometry, Strategy const& strategy) { - concept::check(); + concepts::check(); // detail::throw_on_empty_input(geometry); diff --git a/include/boost/geometry/algorithms/make.hpp b/include/boost/geometry/algorithms/make.hpp index d0e309249..899d5489b 100644 --- a/include/boost/geometry/algorithms/make.hpp +++ b/include/boost/geometry/algorithms/make.hpp @@ -45,7 +45,7 @@ namespace detail { namespace make template inline Geometry make_points(Range const& range) { - concept::check(); + concepts::check(); Geometry geometry; geometry::append(geometry, range); @@ -78,7 +78,7 @@ inline Geometry make_points(Range const& range) template inline Geometry make(Type const& c1, Type const& c2) { - concept::check(); + concepts::check(); Geometry geometry; dispatch::assign @@ -112,7 +112,7 @@ inline Geometry make(Type const& c1, Type const& c2) template inline Geometry make(Type const& c1, Type const& c2, Type const& c3) { - concept::check(); + concepts::check(); Geometry geometry; dispatch::assign @@ -127,7 +127,7 @@ inline Geometry make(Type const& c1, Type const& c2, Type const& c3) template inline Geometry make(Type const& c1, Type const& c2, Type const& c3, Type const& c4) { - concept::check(); + concepts::check(); Geometry geometry; dispatch::assign @@ -163,7 +163,7 @@ inline Geometry make(Type const& c1, Type const& c2, Type const& c3, Type const& template inline Geometry make_inverse() { - concept::check(); + concepts::check(); Geometry geometry; dispatch::assign_inverse @@ -184,7 +184,7 @@ inline Geometry make_inverse() template inline Geometry make_zero() { - concept::check(); + concepts::check(); Geometry geometry; dispatch::assign_zero diff --git a/include/boost/geometry/algorithms/num_geometries.hpp b/include/boost/geometry/algorithms/num_geometries.hpp index 8144c22ab..e122241fe 100644 --- a/include/boost/geometry/algorithms/num_geometries.hpp +++ b/include/boost/geometry/algorithms/num_geometries.hpp @@ -90,7 +90,7 @@ struct num_geometries { static inline std::size_t apply(Geometry const& geometry) { - concept::check(); + concepts::check(); return dispatch::num_geometries::apply(geometry); } diff --git a/include/boost/geometry/algorithms/num_interior_rings.hpp b/include/boost/geometry/algorithms/num_interior_rings.hpp index 04b4eb2a7..b7531a3dd 100644 --- a/include/boost/geometry/algorithms/num_interior_rings.hpp +++ b/include/boost/geometry/algorithms/num_interior_rings.hpp @@ -88,7 +88,7 @@ struct num_interior_rings { static inline std::size_t apply(Geometry const& geometry) { - concept::check(); + concepts::check(); return dispatch::num_interior_rings::apply(geometry); } diff --git a/include/boost/geometry/algorithms/num_points.hpp b/include/boost/geometry/algorithms/num_points.hpp index 214fe9c8b..9ef77f271 100644 --- a/include/boost/geometry/algorithms/num_points.hpp +++ b/include/boost/geometry/algorithms/num_points.hpp @@ -149,7 +149,7 @@ struct num_points static inline std::size_t apply(Geometry const& geometry, bool add_for_open) { - concept::check(); + concepts::check(); return add_for_open ? dispatch::num_points::apply(geometry) diff --git a/include/boost/geometry/algorithms/num_segments.hpp b/include/boost/geometry/algorithms/num_segments.hpp index 08af226ca..86eb63fad 100644 --- a/include/boost/geometry/algorithms/num_segments.hpp +++ b/include/boost/geometry/algorithms/num_segments.hpp @@ -150,7 +150,7 @@ struct num_segments { static inline std::size_t apply(Geometry const& geometry) { - concept::check(); + concepts::check(); return dispatch::num_segments::apply(geometry); } diff --git a/include/boost/geometry/algorithms/overlaps.hpp b/include/boost/geometry/algorithms/overlaps.hpp index 9b5abdb2a..32738c294 100644 --- a/include/boost/geometry/algorithms/overlaps.hpp +++ b/include/boost/geometry/algorithms/overlaps.hpp @@ -184,8 +184,8 @@ struct overlaps template inline bool overlaps(Geometry1 const& geometry1, Geometry2 const& geometry2) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); return dispatch::overlaps < diff --git a/include/boost/geometry/algorithms/perimeter.hpp b/include/boost/geometry/algorithms/perimeter.hpp index 1b5ccacf9..47b064972 100644 --- a/include/boost/geometry/algorithms/perimeter.hpp +++ b/include/boost/geometry/algorithms/perimeter.hpp @@ -142,7 +142,7 @@ struct perimeter static inline typename default_length_result::type apply(Geometry const& geometry, Strategy const& strategy) { - concept::check(); + concepts::check(); return resolve_strategy::perimeter::apply(geometry, strategy); } }; diff --git a/include/boost/geometry/algorithms/point_on_surface.hpp b/include/boost/geometry/algorithms/point_on_surface.hpp index 3fa83bfe6..e9041f937 100644 --- a/include/boost/geometry/algorithms/point_on_surface.hpp +++ b/include/boost/geometry/algorithms/point_on_surface.hpp @@ -295,8 +295,8 @@ inline bool calculate_point_on_surface(Geometry const& geometry, Point& point) template inline void point_on_surface(Geometry const& geometry, Point & point) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); // First try in Y-direction (which should always succeed for valid polygons) if (! detail::point_on_surface::calculate_point_on_surface<1>(geometry, point)) diff --git a/include/boost/geometry/algorithms/remove_spikes.hpp b/include/boost/geometry/algorithms/remove_spikes.hpp index 080db92f6..caa7fed9b 100644 --- a/include/boost/geometry/algorithms/remove_spikes.hpp +++ b/include/boost/geometry/algorithms/remove_spikes.hpp @@ -241,7 +241,7 @@ struct remove_spikes { static void apply(Geometry& geometry) { - concept::check(); + concepts::check(); dispatch::remove_spikes::apply(geometry); } }; diff --git a/include/boost/geometry/algorithms/reverse.hpp b/include/boost/geometry/algorithms/reverse.hpp index 578771bfe..dc7d2de42 100644 --- a/include/boost/geometry/algorithms/reverse.hpp +++ b/include/boost/geometry/algorithms/reverse.hpp @@ -137,7 +137,7 @@ struct reverse { static void apply(Geometry& geometry) { - concept::check(); + concepts::check(); dispatch::reverse::apply(geometry); } }; diff --git a/include/boost/geometry/algorithms/simplify.hpp b/include/boost/geometry/algorithms/simplify.hpp index 0b28eb7d1..cfeb54222 100644 --- a/include/boost/geometry/algorithms/simplify.hpp +++ b/include/boost/geometry/algorithms/simplify.hpp @@ -333,7 +333,7 @@ struct simplify > strategy_type; BOOST_CONCEPT_ASSERT( - (concept::SimplifyStrategy) + (concepts::SimplifyStrategy) ); apply(geometry, out, max_distance, strategy_type()); @@ -376,7 +376,7 @@ struct simplify_insert > strategy_type; BOOST_CONCEPT_ASSERT( - (concept::SimplifyStrategy) + (concepts::SimplifyStrategy) ); apply(geometry, out, max_distance, strategy_type()); @@ -461,7 +461,7 @@ template inline void simplify(Geometry const& geometry, Geometry& out, Distance const& max_distance, Strategy const& strategy) { - concept::check(); + concepts::check(); geometry::clear(out); @@ -489,7 +489,7 @@ template inline void simplify(Geometry const& geometry, Geometry& out, Distance const& max_distance) { - concept::check(); + concepts::check(); geometry::simplify(geometry, out, max_distance, default_strategy()); } @@ -519,7 +519,7 @@ template(); + concepts::check(); resolve_strategy::simplify_insert::apply(geometry, out, max_distance, strategy); } @@ -540,8 +540,8 @@ inline void simplify_insert(Geometry const& geometry, OutputIterator out, Distance const& max_distance) { // Concept: output point type = point type of input geometry - concept::check(); - concept::check::type>(); + concepts::check(); + concepts::check::type>(); simplify_insert(geometry, out, max_distance, default_strategy()); } diff --git a/include/boost/geometry/algorithms/sym_difference.hpp b/include/boost/geometry/algorithms/sym_difference.hpp index f56029cc1..33f94c932 100644 --- a/include/boost/geometry/algorithms/sym_difference.hpp +++ b/include/boost/geometry/algorithms/sym_difference.hpp @@ -235,9 +235,9 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, OutputIterator out, Strategy const& strategy) { - concept::check(); - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); + concepts::check(); return dispatch::sym_difference_insert < @@ -272,9 +272,9 @@ inline OutputIterator sym_difference_insert(Geometry1 const& geometry1, Geometry2 const& geometry2, RobustPolicy const& robust_policy, OutputIterator out) { - concept::check(); - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); + concepts::check(); typedef intersection_strategies < @@ -315,11 +315,11 @@ template inline void sym_difference(Geometry1 const& geometry1, Geometry2 const& geometry2, Collection& output_collection) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); typedef typename boost::range_value::type geometry_out; - concept::check(); + concepts::check(); typedef typename geometry::rescale_overlay_policy_type < diff --git a/include/boost/geometry/algorithms/touches.hpp b/include/boost/geometry/algorithms/touches.hpp index 99ddbbd1c..6384cc2a8 100644 --- a/include/boost/geometry/algorithms/touches.hpp +++ b/include/boost/geometry/algorithms/touches.hpp @@ -410,8 +410,8 @@ struct touches { static bool apply(Geometry1 const& geometry1, Geometry2 const& geometry2) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); return dispatch::touches ::apply(geometry1, geometry2); @@ -494,7 +494,7 @@ struct self_touches { static bool apply(Geometry const& geometry) { - concept::check(); + concepts::check(); typedef detail::no_rescale_policy rescale_policy_type; typedef typename geometry::point_type::type point_type; diff --git a/include/boost/geometry/algorithms/transform.hpp b/include/boost/geometry/algorithms/transform.hpp index f6748b11e..b514c1dac 100644 --- a/include/boost/geometry/algorithms/transform.hpp +++ b/include/boost/geometry/algorithms/transform.hpp @@ -349,8 +349,8 @@ struct transform Geometry2& geometry2, Strategy const& strategy) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); return dispatch::transform::apply( geometry1, diff --git a/include/boost/geometry/algorithms/union.hpp b/include/boost/geometry/algorithms/union.hpp index 29135f5fd..f0e55ec98 100644 --- a/include/boost/geometry/algorithms/union.hpp +++ b/include/boost/geometry/algorithms/union.hpp @@ -204,9 +204,9 @@ inline OutputIterator union_insert(Geometry1 const& geometry1, Geometry2 const& geometry2, OutputIterator out) { - concept::check(); - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); + concepts::check(); typedef typename geometry::rescale_overlay_policy_type < @@ -264,11 +264,11 @@ inline void union_(Geometry1 const& geometry1, Geometry2 const& geometry2, Collection& output_collection) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); typedef typename boost::range_value::type geometry_out; - concept::check(); + concepts::check(); detail::union_::union_insert(geometry1, geometry2, range::back_inserter(output_collection)); diff --git a/include/boost/geometry/algorithms/unique.hpp b/include/boost/geometry/algorithms/unique.hpp index fed9f8af4..f57f4505b 100644 --- a/include/boost/geometry/algorithms/unique.hpp +++ b/include/boost/geometry/algorithms/unique.hpp @@ -166,7 +166,7 @@ struct unique template inline void unique(Geometry& geometry) { - concept::check(); + concepts::check(); // Default strategy is the default point-comparison policy typedef geometry::equal_to diff --git a/include/boost/geometry/algorithms/within.hpp b/include/boost/geometry/algorithms/within.hpp index 35f9396ba..a1e6a58f8 100644 --- a/include/boost/geometry/algorithms/within.hpp +++ b/include/boost/geometry/algorithms/within.hpp @@ -284,7 +284,7 @@ struct within Geometry2 const& geometry2, Strategy const& strategy) { - concept::within::check + concepts::within::check < typename tag::type, typename tag::type, @@ -339,8 +339,8 @@ struct within Geometry2 const& geometry2, Strategy const& strategy) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); assert_dimension_equal(); return resolve_strategy::within::apply(geometry1, diff --git a/include/boost/geometry/arithmetic/arithmetic.hpp b/include/boost/geometry/arithmetic/arithmetic.hpp index fbc3ca443..3ab66b27f 100644 --- a/include/boost/geometry/arithmetic/arithmetic.hpp +++ b/include/boost/geometry/arithmetic/arithmetic.hpp @@ -139,7 +139,7 @@ struct point_assignment template inline void add_value(Point& p, typename detail::param::type value) { - BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); for_each_coordinate(p, detail::value_operation @@ -162,8 +162,8 @@ inline void add_value(Point& p, typename detail::param::type value) template inline void add_point(Point1& p1, Point2 const& p2) { - BOOST_CONCEPT_ASSERT( (concept::Point) ); - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); for_each_coordinate(p1, detail::point_operation(p2)); } @@ -179,7 +179,7 @@ inline void add_point(Point1& p1, Point2 const& p2) template inline void subtract_value(Point& p, typename detail::param::type value) { - BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); for_each_coordinate(p, detail::value_operation @@ -202,8 +202,8 @@ inline void subtract_value(Point& p, typename detail::param::type value) template inline void subtract_point(Point1& p1, Point2 const& p2) { - BOOST_CONCEPT_ASSERT( (concept::Point) ); - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); for_each_coordinate(p1, detail::point_operation(p2)); } @@ -219,7 +219,7 @@ inline void subtract_point(Point1& p1, Point2 const& p2) template inline void multiply_value(Point& p, typename detail::param::type value) { - BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); for_each_coordinate(p, detail::value_operation @@ -243,8 +243,8 @@ inline void multiply_value(Point& p, typename detail::param::type value) template inline void multiply_point(Point1& p1, Point2 const& p2) { - BOOST_CONCEPT_ASSERT( (concept::Point) ); - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); for_each_coordinate(p1, detail::point_operation(p2)); } @@ -260,7 +260,7 @@ inline void multiply_point(Point1& p1, Point2 const& p2) template inline void divide_value(Point& p, typename detail::param::type value) { - BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); for_each_coordinate(p, detail::value_operation @@ -283,8 +283,8 @@ inline void divide_value(Point& p, typename detail::param::type value) template inline void divide_point(Point1& p1, Point2 const& p2) { - BOOST_CONCEPT_ASSERT( (concept::Point) ); - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); for_each_coordinate(p1, detail::point_operation(p2)); } @@ -300,7 +300,7 @@ inline void divide_point(Point1& p1, Point2 const& p2) template inline void assign_value(Point& p, typename detail::param::type value) { - BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); for_each_coordinate(p, detail::value_assignment @@ -322,8 +322,8 @@ inline void assign_value(Point& p, typename detail::param::type value) template inline void assign_point(Point1& p1, Point2 const& p2) { - BOOST_CONCEPT_ASSERT( (concept::Point) ); - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); for_each_coordinate(p1, detail::point_assignment(p2)); } diff --git a/include/boost/geometry/arithmetic/cross_product.hpp b/include/boost/geometry/arithmetic/cross_product.hpp index ad0a3567f..485c2123b 100644 --- a/include/boost/geometry/arithmetic/cross_product.hpp +++ b/include/boost/geometry/arithmetic/cross_product.hpp @@ -94,9 +94,9 @@ struct cross_product<3> template inline ResultP cross_product(P1 const& p1, P2 const& p2) { - BOOST_CONCEPT_ASSERT( (concept::Point) ); - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); ResultP result; detail::cross_product::value>::apply(p1, p2, result); @@ -114,8 +114,8 @@ inline ResultP cross_product(P1 const& p1, P2 const& p2) template inline P cross_product(P const& p1, P const& p2) { - BOOST_CONCEPT_ASSERT((concept::Point

)); - BOOST_CONCEPT_ASSERT((concept::ConstPoint

)); + BOOST_CONCEPT_ASSERT((concepts::Point

)); + BOOST_CONCEPT_ASSERT((concepts::ConstPoint

)); P result; detail::cross_product::value>::apply(p1, p2, result); diff --git a/include/boost/geometry/arithmetic/determinant.hpp b/include/boost/geometry/arithmetic/determinant.hpp index a8e46ca9a..59c596b12 100644 --- a/include/boost/geometry/arithmetic/determinant.hpp +++ b/include/boost/geometry/arithmetic/determinant.hpp @@ -59,8 +59,8 @@ inline ReturnType determinant(U const& ux, U const& uy template inline ReturnType determinant(U const& u, V const& v) { - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); return calculate_determinant < diff --git a/include/boost/geometry/arithmetic/dot_product.hpp b/include/boost/geometry/arithmetic/dot_product.hpp index fc2b3844e..747bd01ab 100644 --- a/include/boost/geometry/arithmetic/dot_product.hpp +++ b/include/boost/geometry/arithmetic/dot_product.hpp @@ -69,8 +69,8 @@ template inline typename select_coordinate_type::type dot_product( Point1 const& p1, Point2 const& p2) { - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); return detail::dot_product_maker < diff --git a/include/boost/geometry/extensions/algebra/algorithms/assign.hpp b/include/boost/geometry/extensions/algebra/algorithms/assign.hpp index d25785de7..ee8486da0 100644 --- a/include/boost/geometry/extensions/algebra/algorithms/assign.hpp +++ b/include/boost/geometry/extensions/algebra/algorithms/assign.hpp @@ -82,7 +82,7 @@ struct assign_identity template inline void assign_identity(Rotation & rotation) { - concept::check(); + concepts::check(); dispatch::assign_identity< typename tag::type, diff --git a/include/boost/geometry/extensions/algebra/algorithms/rotation.hpp b/include/boost/geometry/extensions/algebra/algorithms/rotation.hpp index 2de45254a..dc9e2db2f 100644 --- a/include/boost/geometry/extensions/algebra/algorithms/rotation.hpp +++ b/include/boost/geometry/extensions/algebra/algorithms/rotation.hpp @@ -248,9 +248,9 @@ struct rotation template inline void rotation(V1 const& v1, V2 const& v2, Rotation & r) { - concept::check_concepts_and_equal_dimensions(); + concepts::check_concepts_and_equal_dimensions(); // TODO - replace the following by check_equal_dimensions - concept::check_concepts_and_equal_dimensions(); + concepts::check_concepts_and_equal_dimensions(); dispatch::rotation::apply(v1, v2, r); } diff --git a/include/boost/geometry/extensions/algebra/algorithms/transform_geometrically.hpp b/include/boost/geometry/extensions/algebra/algorithms/transform_geometrically.hpp index 501cdde79..a5fdb86af 100644 --- a/include/boost/geometry/extensions/algebra/algorithms/transform_geometrically.hpp +++ b/include/boost/geometry/extensions/algebra/algorithms/transform_geometrically.hpp @@ -58,8 +58,8 @@ struct transform_geometrically template struct transform_geometrically { - BOOST_CONCEPT_ASSERT( (concept::Point) ); - BOOST_CONCEPT_ASSERT( (concept::Vector) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Vector) ); static inline void apply(Point & point, Vector const& vector) { @@ -90,8 +90,8 @@ struct transform_geometrically { typedef typename traits::point_type::type point_type; - BOOST_CONCEPT_ASSERT( (concept::Point) ); - BOOST_CONCEPT_ASSERT( (concept::Vector) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Vector) ); static inline void apply(Box & box, Vector const& vector) { @@ -124,7 +124,7 @@ struct transform_geometrically(); + concepts::check_concepts_and_equal_dimensions(); detail::algebra::quaternion_rotate(v, r); } @@ -136,7 +136,7 @@ struct transform_geometrically(); + concepts::check_concepts_and_equal_dimensions(); // TODO vector_type and convert from Vector Vector tmp(v); diff --git a/include/boost/geometry/extensions/algebra/algorithms/translation.hpp b/include/boost/geometry/extensions/algebra/algorithms/translation.hpp index feeb3a70c..282616b52 100644 --- a/include/boost/geometry/extensions/algebra/algorithms/translation.hpp +++ b/include/boost/geometry/extensions/algebra/algorithms/translation.hpp @@ -23,9 +23,9 @@ namespace boost { namespace geometry template inline void translation(Point1 const& p1, Point2 const& p2, Vector & v) { - concept::check_concepts_and_equal_dimensions(); + concepts::check_concepts_and_equal_dimensions(); // TODO - replace the following by check_equal_dimensions - concept::check_concepts_and_equal_dimensions(); + concepts::check_concepts_and_equal_dimensions(); for_each_coordinate(v, detail::point_assignment(p2)); for_each_coordinate(v, detail::point_operation(p1)); diff --git a/include/boost/geometry/extensions/algebra/geometries/concepts/check.hpp b/include/boost/geometry/extensions/algebra/geometries/concepts/check.hpp index 606095f11..df0bcb2a6 100644 --- a/include/boost/geometry/extensions/algebra/geometries/concepts/check.hpp +++ b/include/boost/geometry/extensions/algebra/geometries/concepts/check.hpp @@ -30,32 +30,32 @@ namespace dispatch template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; } // namespace dispatch diff --git a/include/boost/geometry/extensions/algebra/geometries/concepts/matrix_concept.hpp b/include/boost/geometry/extensions/algebra/geometries/concepts/matrix_concept.hpp index 0bb880a7e..2203f719c 100644 --- a/include/boost/geometry/extensions/algebra/geometries/concepts/matrix_concept.hpp +++ b/include/boost/geometry/extensions/algebra/geometries/concepts/matrix_concept.hpp @@ -20,7 +20,7 @@ #include #include -namespace boost { namespace geometry { namespace concept { +namespace boost { namespace geometry { namespace concepts { template class Matrix @@ -136,6 +136,6 @@ public: #endif }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_EXTENSIONS_ALGEBRA_GEOMETRIES_CONCEPTS_MATRIX_CONCEPT_HPP diff --git a/include/boost/geometry/extensions/algebra/geometries/concepts/quaternion_concept.hpp b/include/boost/geometry/extensions/algebra/geometries/concepts/quaternion_concept.hpp index 376d83800..91c3ad2b1 100644 --- a/include/boost/geometry/extensions/algebra/geometries/concepts/quaternion_concept.hpp +++ b/include/boost/geometry/extensions/algebra/geometries/concepts/quaternion_concept.hpp @@ -20,7 +20,7 @@ #include #include -namespace boost { namespace geometry { namespace concept { +namespace boost { namespace geometry { namespace concepts { template class Quaternion @@ -106,6 +106,6 @@ public: #endif }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_EXTENSIONS_ALGEBRA_GEOMETRIES_CONCEPTS_QUATERNION_CONCEPT_HPP diff --git a/include/boost/geometry/extensions/algebra/geometries/concepts/rotation_matrix_concept.hpp b/include/boost/geometry/extensions/algebra/geometries/concepts/rotation_matrix_concept.hpp index 8f54f3dd6..89d24e5c4 100644 --- a/include/boost/geometry/extensions/algebra/geometries/concepts/rotation_matrix_concept.hpp +++ b/include/boost/geometry/extensions/algebra/geometries/concepts/rotation_matrix_concept.hpp @@ -20,7 +20,7 @@ #include #include -namespace boost { namespace geometry { namespace concept { +namespace boost { namespace geometry { namespace concepts { template class RotationMatrix @@ -136,6 +136,6 @@ public: #endif }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_EXTENSIONS_ALGEBRA_GEOMETRIES_CONCEPTS_ROTATION_MATRIX_CONCEPT_HPP diff --git a/include/boost/geometry/extensions/algebra/geometries/concepts/rotation_quaternion_concept.hpp b/include/boost/geometry/extensions/algebra/geometries/concepts/rotation_quaternion_concept.hpp index cd0c0661b..ab6425f21 100644 --- a/include/boost/geometry/extensions/algebra/geometries/concepts/rotation_quaternion_concept.hpp +++ b/include/boost/geometry/extensions/algebra/geometries/concepts/rotation_quaternion_concept.hpp @@ -20,7 +20,7 @@ #include #include -namespace boost { namespace geometry { namespace concept { +namespace boost { namespace geometry { namespace concepts { template class RotationQuaternion @@ -106,6 +106,6 @@ public: #endif }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_EXTENSIONS_ALGEBRA_GEOMETRIES_CONCEPTS_ROTATION_QUATERNION_CONCEPT_HPP diff --git a/include/boost/geometry/extensions/algebra/geometries/concepts/vector_concept.hpp b/include/boost/geometry/extensions/algebra/geometries/concepts/vector_concept.hpp index b13753a49..c515baff4 100644 --- a/include/boost/geometry/extensions/algebra/geometries/concepts/vector_concept.hpp +++ b/include/boost/geometry/extensions/algebra/geometries/concepts/vector_concept.hpp @@ -20,7 +20,7 @@ #include #include -namespace boost { namespace geometry { namespace concept { +namespace boost { namespace geometry { namespace concepts { template class Vector @@ -107,6 +107,6 @@ public: #endif }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_EXTENSIONS_ALGEBRA_GEOMETRIES_CONCEPTS_VECTOR_CONCEPT_HPP diff --git a/include/boost/geometry/extensions/algebra/geometries/matrix.hpp b/include/boost/geometry/extensions/algebra/geometries/matrix.hpp index 61b988403..1e5356bba 100644 --- a/include/boost/geometry/extensions/algebra/geometries/matrix.hpp +++ b/include/boost/geometry/extensions/algebra/geometries/matrix.hpp @@ -27,7 +27,7 @@ namespace model { template class matrix { - BOOST_CONCEPT_ASSERT( (concept::Matrix) ); + BOOST_CONCEPT_ASSERT( (concepts::Matrix) ); public: diff --git a/include/boost/geometry/extensions/algebra/geometries/quaternion.hpp b/include/boost/geometry/extensions/algebra/geometries/quaternion.hpp index f252285bd..d41569f66 100644 --- a/include/boost/geometry/extensions/algebra/geometries/quaternion.hpp +++ b/include/boost/geometry/extensions/algebra/geometries/quaternion.hpp @@ -33,7 +33,7 @@ namespace model template class quaternion { - BOOST_CONCEPT_ASSERT( (concept::Quaternion) ); + BOOST_CONCEPT_ASSERT( (concepts::Quaternion) ); public: diff --git a/include/boost/geometry/extensions/algebra/geometries/rotation_matrix.hpp b/include/boost/geometry/extensions/algebra/geometries/rotation_matrix.hpp index 2a4d30ed8..be426a0ac 100644 --- a/include/boost/geometry/extensions/algebra/geometries/rotation_matrix.hpp +++ b/include/boost/geometry/extensions/algebra/geometries/rotation_matrix.hpp @@ -27,7 +27,7 @@ namespace model { template class rotation_matrix { - BOOST_CONCEPT_ASSERT( (concept::RotationMatrix) ); + BOOST_CONCEPT_ASSERT( (concepts::RotationMatrix) ); public: diff --git a/include/boost/geometry/extensions/algebra/geometries/rotation_quaternion.hpp b/include/boost/geometry/extensions/algebra/geometries/rotation_quaternion.hpp index ebc99ffb6..05482858a 100644 --- a/include/boost/geometry/extensions/algebra/geometries/rotation_quaternion.hpp +++ b/include/boost/geometry/extensions/algebra/geometries/rotation_quaternion.hpp @@ -33,7 +33,7 @@ namespace model template class rotation_quaternion { - BOOST_CONCEPT_ASSERT( (concept::RotationQuaternion) ); + BOOST_CONCEPT_ASSERT( (concepts::RotationQuaternion) ); public: diff --git a/include/boost/geometry/extensions/algebra/geometries/vector.hpp b/include/boost/geometry/extensions/algebra/geometries/vector.hpp index 679fe547f..733b07bbd 100644 --- a/include/boost/geometry/extensions/algebra/geometries/vector.hpp +++ b/include/boost/geometry/extensions/algebra/geometries/vector.hpp @@ -32,7 +32,7 @@ namespace model template class vector { - BOOST_CONCEPT_ASSERT( (concept::Vector) ); + BOOST_CONCEPT_ASSERT( (concepts::Vector) ); public: diff --git a/include/boost/geometry/extensions/algorithms/connect.hpp b/include/boost/geometry/extensions/algorithms/connect.hpp index 7c5439b97..a969ef4c7 100644 --- a/include/boost/geometry/extensions/algorithms/connect.hpp +++ b/include/boost/geometry/extensions/algorithms/connect.hpp @@ -521,8 +521,8 @@ inline void connect(Geometry const& geometry, Collection& output_collection) { typedef typename boost::range_value::type geometry_out; - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); typedef detail::connect::map_policy < @@ -553,8 +553,8 @@ inline void connect(Geometry const& geometry, Collection& output_collection, { typedef typename boost::range_value::type geometry_out; - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); typedef detail::connect::fuzzy_policy < diff --git a/include/boost/geometry/extensions/algorithms/detail/overlay/dissolver.hpp b/include/boost/geometry/extensions/algorithms/detail/overlay/dissolver.hpp index f54dfecd2..68738af8f 100644 --- a/include/boost/geometry/extensions/algorithms/detail/overlay/dissolver.hpp +++ b/include/boost/geometry/extensions/algorithms/detail/overlay/dissolver.hpp @@ -639,8 +639,8 @@ inline void dissolver(InputRange const& input_range, { typedef typename boost::range_value::type geometry_in; typedef typename boost::range_value::type geometry_out; - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); dispatch::dissolver < diff --git a/include/boost/geometry/extensions/algorithms/detail/overlay/split_rings.hpp b/include/boost/geometry/extensions/algorithms/detail/overlay/split_rings.hpp index bd6e96ea2..bcea70549 100644 --- a/include/boost/geometry/extensions/algorithms/detail/overlay/split_rings.hpp +++ b/include/boost/geometry/extensions/algorithms/detail/overlay/split_rings.hpp @@ -542,8 +542,8 @@ template > inline void split_rings(Geometry const& geometry, RingCollection& out) { - concept::check(); - concept::check::type>(); + concepts::check(); + concepts::check::type>(); dispatch::split_rings < diff --git a/include/boost/geometry/extensions/algorithms/dissolve.hpp b/include/boost/geometry/extensions/algorithms/dissolve.hpp index 451298c6a..da03c1fb3 100644 --- a/include/boost/geometry/extensions/algorithms/dissolve.hpp +++ b/include/boost/geometry/extensions/algorithms/dissolve.hpp @@ -65,15 +65,26 @@ class backtrack_for_dissolve public : typedef detail::overlay::backtrack_state state_type; - template + template + < + typename Operation, + typename Rings, + typename Turns, + typename RobustPolicy, + typename Visitor + > static inline void apply(std::size_t size_at_start, - Rings& rings, typename boost::range_value::type& ring, - Turns& turns, Operation& operation, - std::string const& , + Rings& rings, + typename boost::range_value::type& ring, + Turns& turns, + typename boost::range_value::type const& turn, + Operation& operation, + detail::overlay::traverse_error_type, Geometry const& , Geometry const& , - RescalePolicy const& , - state_type& state + RobustPolicy const& , + state_type& state, + Visitor const& visitor ) { state.m_good = false; @@ -90,6 +101,41 @@ public : } }; +struct dissolve_overlay_visitor +{ +public : + void print(char const* /*header*/) + { + } + + template + void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/) + { + } + + template + void print(char const* /*header*/, Turns const& /*turns*/, int /*turn_index*/, int /*op_index*/) + { + } + + template + void visit_turns(int , Turns const& ) {} + + template + void visit_clusters(Clusters const& , Turns const& ) {} + + template + void visit_traverse(Turns const& /*turns*/, Turn const& /*turn*/, Operation const& /*op*/, const char* /*header*/) + { + } + + template + void visit_traverse_reject(Turns const& , Turn const& , Operation const& , + detail::overlay::traverse_error_type ) + {} +}; + + template struct dissolve_ring_or_polygon @@ -123,43 +169,49 @@ struct dissolve_ring_or_polygon typedef std::vector out_vector; out_vector rings; - // Enrich the turns + typedef std::map + < + signed_size_type, + detail::overlay::cluster_info + > cluster_type; + + cluster_type clusters; + dissolve_overlay_visitor visitor; + + // Enrich/traverse the polygons twice: once for union... typedef typename strategy::side::services::default_strategy < typename cs_tag::type >::type side_strategy_type; enrich_intersection_points(turns, - detail::overlay::operation_union, - geometry, geometry, rescale_policy, + clusters, geometry, geometry, rescale_policy, side_strategy_type()); - typedef detail::overlay::traverse + detail::overlay::traverse < false, false, Geometry, Geometry, + overlay_dissolve, backtrack_for_dissolve - > traverser; - - - // Traverse the polygons twice for union... - traverser::apply(geometry, geometry, - detail::overlay::operation_union, - rescale_policy, - turns, rings); + >::apply(geometry, geometry, rescale_policy, + turns, rings, clusters, visitor); clear_visit_info(turns); - enrich_intersection_points(turns, - detail::overlay::operation_intersection, - geometry, geometry, rescale_policy, + // ... and for intersection + enrich_intersection_points(turns, + clusters, geometry, geometry, rescale_policy, side_strategy_type()); - // ... and for intersection - traverser::apply(geometry, geometry, - detail::overlay::operation_intersection, - rescale_policy, - turns, rings); + detail::overlay::traverse + < + false, false, + Geometry, Geometry, + overlay_intersection, + backtrack_for_dissolve + >::apply(geometry, geometry, rescale_policy, + turns, rings, clusters, visitor); std::map map; get_ring_turn_info(map, turns); @@ -168,7 +220,7 @@ struct dissolve_ring_or_polygon std::map selected; - detail::overlay::select_rings(geometry, map, selected); + detail::overlay::select_rings(geometry, map, selected); // Add intersected rings { @@ -257,8 +309,8 @@ template > inline OutputIterator dissolve_inserter(Geometry const& geometry, OutputIterator out) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); typedef typename geometry::rescale_policy_type < @@ -285,11 +337,11 @@ template > inline void dissolve(Geometry const& geometry, Collection& output_collection) { - concept::check(); + concepts::check(); typedef typename boost::range_value::type geometry_out; - concept::check(); + concepts::check(); dispatch::dissolve < diff --git a/include/boost/geometry/extensions/algorithms/distance_info.hpp b/include/boost/geometry/extensions/algorithms/distance_info.hpp index 2a0879cdf..e792798b2 100644 --- a/include/boost/geometry/extensions/algorithms/distance_info.hpp +++ b/include/boost/geometry/extensions/algorithms/distance_info.hpp @@ -206,9 +206,9 @@ struct distance_info template inline void distance_info(Geometry1 const& geometry1, Geometry2 const& geometry2, Result& result) { - concept::check(); - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); + concepts::check(); assert_dimension_equal(); assert_dimension_equal(); diff --git a/include/boost/geometry/extensions/algorithms/midpoints.hpp b/include/boost/geometry/extensions/algorithms/midpoints.hpp index 6c669d7d1..15ec0d536 100644 --- a/include/boost/geometry/extensions/algorithms/midpoints.hpp +++ b/include/boost/geometry/extensions/algorithms/midpoints.hpp @@ -116,7 +116,7 @@ template inline void midpoints(Geometry const& geometry, bool start_and_end, Iterator out) { - concept::check(); + concepts::check(); dispatch::midpoints < diff --git a/include/boost/geometry/extensions/algorithms/offset.hpp b/include/boost/geometry/extensions/algorithms/offset.hpp index 525b7c44c..18b319532 100644 --- a/include/boost/geometry/extensions/algorithms/offset.hpp +++ b/include/boost/geometry/extensions/algorithms/offset.hpp @@ -140,8 +140,8 @@ inline void offset(Geometry const& geometry, GeometryOut& out, JoinStrategy const& join_strategy, Distance const& distance) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); typedef typename geometry::point_type::type point_type; diff --git a/include/boost/geometry/extensions/algorithms/parse.hpp b/include/boost/geometry/extensions/algorithms/parse.hpp index db2d75caa..4edba604d 100644 --- a/include/boost/geometry/extensions/algorithms/parse.hpp +++ b/include/boost/geometry/extensions/algorithms/parse.hpp @@ -89,7 +89,7 @@ struct parsing template inline void parse(Geometry& geometry, std::string const& c1, std::string const& c2) { - concept::check(); + concepts::check(); dispatch::parsing::type, Geometry>::parse(geometry, c1, c2); } @@ -102,7 +102,7 @@ template inline void parse(Geometry& geometry, std::string const& c1, std::string const& c2, S const& strategy) { - concept::check(); + concepts::check(); dispatch::parsing::type, Geometry>::parse(geometry, c1, c2, strategy); } @@ -111,7 +111,7 @@ inline void parse(Geometry& geometry, std::string const& c1, template inline Geometry parse(std::string const& c1, std::string const& c2) { - concept::check(); + concepts::check(); Geometry geometry; dispatch::parsing::type, Geometry>::parse(geometry, c1, c2); diff --git a/include/boost/geometry/extensions/algorithms/remove_holes_if.hpp b/include/boost/geometry/extensions/algorithms/remove_holes_if.hpp index 5d11d3404..bdc6dcda2 100644 --- a/include/boost/geometry/extensions/algorithms/remove_holes_if.hpp +++ b/include/boost/geometry/extensions/algorithms/remove_holes_if.hpp @@ -98,7 +98,7 @@ struct remove_holes_if template inline void remove_holes_if(Geometry& geometry, Predicate const& predicate) { - concept::check(); + concepts::check(); dispatch::remove_holes_if < diff --git a/include/boost/geometry/extensions/algorithms/remove_marked.hpp b/include/boost/geometry/extensions/algorithms/remove_marked.hpp index 2ab8c3184..9a91e4d82 100644 --- a/include/boost/geometry/extensions/algorithms/remove_marked.hpp +++ b/include/boost/geometry/extensions/algorithms/remove_marked.hpp @@ -203,7 +203,7 @@ template inline void remove_marked(Geometry const& geometry_in, Geometry& geometry_out, MarkMap const& mark_map) { - concept::check(); + concepts::check(); ring_identifier id; dispatch::remove_marked diff --git a/include/boost/geometry/extensions/algorithms/selected.hpp b/include/boost/geometry/extensions/algorithms/selected.hpp index 8890d6ab0..bf699c9f2 100644 --- a/include/boost/geometry/extensions/algorithms/selected.hpp +++ b/include/boost/geometry/extensions/algorithms/selected.hpp @@ -258,8 +258,8 @@ inline bool selected(Geometry const& geometry, Point const& selection_point, RadiusType const& search_radius) { - concept::check(); - concept::check(); + concepts::check(); + concepts::check(); typedef dispatch::selected < diff --git a/include/boost/geometry/extensions/gis/io/veshape/write_veshape.hpp b/include/boost/geometry/extensions/gis/io/veshape/write_veshape.hpp index 4b4caffc0..98d4507c4 100644 --- a/include/boost/geometry/extensions/gis/io/veshape/write_veshape.hpp +++ b/include/boost/geometry/extensions/gis/io/veshape/write_veshape.hpp @@ -120,7 +120,7 @@ struct veshape_point } private: - BOOST_CONCEPT_ASSERT( (concept::ConstPoint

) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint

) ); }; /*! @@ -151,7 +151,7 @@ struct veshape_range private: typedef typename boost::range_value::type point; - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); }; @@ -179,7 +179,7 @@ struct veshape_poly } private: - BOOST_CONCEPT_ASSERT( (concept::ConstPoint::type>) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint::type>) ); }; diff --git a/include/boost/geometry/extensions/nsphere/geometries/concepts/check.hpp b/include/boost/geometry/extensions/nsphere/geometries/concepts/check.hpp index c8d2fb7c4..ecab04eff 100644 --- a/include/boost/geometry/extensions/nsphere/geometries/concepts/check.hpp +++ b/include/boost/geometry/extensions/nsphere/geometries/concepts/check.hpp @@ -30,12 +30,12 @@ namespace dispatch template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; } // namespace dispatch diff --git a/include/boost/geometry/extensions/nsphere/geometries/concepts/nsphere_concept.hpp b/include/boost/geometry/extensions/nsphere/geometries/concepts/nsphere_concept.hpp index 03decb40d..e493ad412 100644 --- a/include/boost/geometry/extensions/nsphere/geometries/concepts/nsphere_concept.hpp +++ b/include/boost/geometry/extensions/nsphere/geometries/concepts/nsphere_concept.hpp @@ -21,7 +21,7 @@ #include #include -namespace boost { namespace geometry { namespace concept { +namespace boost { namespace geometry { namespace concepts { /*! \brief Checks Nsphere concept (const version) @@ -78,7 +78,7 @@ public : template class Nsphere { - BOOST_CONCEPT_ASSERT( (concept::ConstNsphere) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstNsphere) ); typedef typename point_type::type point_type; typedef typename radius_type::type radius_type; @@ -117,6 +117,6 @@ public : -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_EXTENSIONS_NSPHERE_GEOMETRIES_CONCEPTS_NSPHERE_CONCEPT_HPP diff --git a/include/boost/geometry/extensions/nsphere/geometries/nsphere.hpp b/include/boost/geometry/extensions/nsphere/geometries/nsphere.hpp index 4f7cb72b3..5e1443cbf 100644 --- a/include/boost/geometry/extensions/nsphere/geometries/nsphere.hpp +++ b/include/boost/geometry/extensions/nsphere/geometries/nsphere.hpp @@ -47,7 +47,7 @@ namespace model template class nsphere { - BOOST_CONCEPT_ASSERT( (concept::Point

) ); + BOOST_CONCEPT_ASSERT( (concepts::Point

) ); public: diff --git a/include/boost/geometry/formulas/andoyer_inverse.hpp b/include/boost/geometry/formulas/andoyer_inverse.hpp index a419d0489..04a43995b 100644 --- a/include/boost/geometry/formulas/andoyer_inverse.hpp +++ b/include/boost/geometry/formulas/andoyer_inverse.hpp @@ -130,10 +130,7 @@ public: // T = inf // dA = inf // azimuth = -inf - if (lat1 <= lat2) - result.azimuth = c0; - else - result.azimuth = pi; + result.azimuth = lat1 <= lat2 ? c0 : pi; } else { @@ -188,19 +185,16 @@ public: } } - if (BOOST_GEOMETRY_CONDITION(CalcQuantities)) { - typedef differential_quantities quantities; + typedef differential_quantities quantities; quantities::apply(dlon, sin_lat1, cos_lat1, sin_lat2, cos_lat2, result.azimuth, result.reverse_azimuth, get_radius<2>(spheroid), f, - result.reduced_length, result.geodesic_scale, - quantities::J12_calc_f1); + result.reduced_length, result.geodesic_scale); } return result; - } private: @@ -213,13 +207,17 @@ private: if (dA >= c0) // A altered towards 0 { if (azimuth < c0) + { azimuth = c0; + } } else // dA < 0, A altered towards pi { CT const pi = math::pi(); if (azimuth > pi) + { azimuth = pi; + } } } else // A indicates Western hemisphere @@ -227,13 +225,17 @@ private: if (dA <= c0) // A altered towards 0 { if (azimuth > c0) + { azimuth = c0; + } } else // dA > 0, A altered towards -pi { CT const minus_pi = -math::pi(); if (azimuth < minus_pi) + { azimuth = minus_pi; + } } } } diff --git a/include/boost/geometry/formulas/differential_quantities.hpp b/include/boost/geometry/formulas/differential_quantities.hpp index 5fb69fd3a..9a92f14e1 100644 --- a/include/boost/geometry/formulas/differential_quantities.hpp +++ b/include/boost/geometry/formulas/differential_quantities.hpp @@ -28,18 +28,18 @@ https://arxiv.org/pdf/1109.4448.pdf template < typename CT, bool EnableReducedLength, - bool EnableGeodesicScale + bool EnableGeodesicScale, + unsigned int Order = 2, + bool ApproxF = true > class differential_quantities { public: - template static inline void apply(CT const& lon1, CT const& lat1, CT const& lon2, CT const& lat2, CT const& azimuth, CT const& reverse_azimuth, CT const& b, CT const& f, - CT & reduced_length, CT & geodesic_scale, - J12Calc J12_calc) + CT & reduced_length, CT & geodesic_scale) { CT const dlon = lon2 - lon1; CT const sin_lat1 = sin(lat1); @@ -50,48 +50,52 @@ public: apply(dlon, sin_lat1, cos_lat1, sin_lat2, cos_lat2, azimuth, reverse_azimuth, b, f, - reduced_length, geodesic_scale, - J12_calc); + reduced_length, geodesic_scale); } - template static inline void apply(CT const& dlon, CT const& sin_lat1, CT const& cos_lat1, CT const& sin_lat2, CT const& cos_lat2, CT const& azimuth, CT const& reverse_azimuth, CT const& b, CT const& f, - CT & reduced_length, CT & geodesic_scale, - J12Calc J12_calc) + CT & reduced_length, CT & geodesic_scale) { - CT one_minus_f = CT(1) - f; - CT sin_bet1 = one_minus_f * sin_lat1; - CT sin_bet2 = one_minus_f * sin_lat2; + CT const c0 = 0; + CT const c1 = 1; + CT const one_minus_f = c1 - f; + + CT const sin_bet1 = one_minus_f * sin_lat1; + CT const sin_bet2 = one_minus_f * sin_lat2; // equator - if (math::equals(sin_bet1, CT(0)) && math::equals(sin_bet2, CT(0))) + if (math::equals(sin_bet1, c0) && math::equals(sin_bet2, c0)) { - CT sig12 = math::abs(dlon) / one_minus_f; + CT const sig_12 = math::abs(dlon) / one_minus_f; if (BOOST_GEOMETRY_CONDITION(EnableReducedLength)) { - CT m12 = sin(sig12) * b; + CT m12 = sin(sig_12) * b; reduced_length = m12; } if (BOOST_GEOMETRY_CONDITION(EnableGeodesicScale)) { - CT M12 = cos(sig12); + CT M12 = cos(sig_12); geodesic_scale = M12; } } else { - CT cos_bet1 = cos_lat1; - CT cos_bet2 = cos_lat2; + CT const c2 = 2; + CT const e2 = f * (c2 - f); + CT const ep2 = e2 / math::sqr(one_minus_f); - CT sin_alp1 = sin(azimuth); - CT cos_alp1 = cos(azimuth); - CT sin_alp2 = sin(reverse_azimuth); - CT cos_alp2 = cos(reverse_azimuth); + CT const cos_bet1 = cos_lat1; + CT const cos_bet2 = cos_lat2; + + CT const sin_alp1 = sin(azimuth); + CT const cos_alp1 = cos(azimuth); + //CT const sin_alp2 = sin(reverse_azimuth); + CT const cos_alp2 = cos(reverse_azimuth); CT sin_sig1 = sin_bet1; CT cos_sig1 = cos_alp1 * cos_bet1; @@ -101,14 +105,15 @@ public: normalize(sin_sig1, cos_sig1); normalize(sin_sig2, cos_sig2); - CT sin_alp0 = sin_alp1 * cos_bet1; - CT cos_alp0_sqr = CT(1) - math::sqr(sin_alp0); + CT const sin_alp0 = sin_alp1 * cos_bet1; + CT const cos_alp0_sqr = c1 - math::sqr(sin_alp0); - CT const J12 = J12_calc(sin_sig1, cos_sig1, sin_sig2, cos_sig2, cos_alp0_sqr, f); + CT const J12 = BOOST_GEOMETRY_CONDITION(ApproxF) ? + J12_f(sin_sig1, cos_sig1, sin_sig2, cos_sig2, cos_alp0_sqr, f) : + J12_ep_sqr(sin_sig1, cos_sig1, sin_sig2, cos_sig2, cos_alp0_sqr, ep2) ; - CT const e2 = f * (CT(2) - f); - CT const dn1 = math::sqrt(CT(1) + e2 * math::sqr(sin_lat1)); - CT const dn2 = math::sqrt(CT(1) + e2 * math::sqr(sin_lat2)); + CT const dn1 = math::sqrt(c1 + e2 * math::sqr(sin_lat1)); + CT const dn2 = math::sqrt(c1 + e2 * math::sqr(sin_lat2)); if (BOOST_GEOMETRY_CONDITION(EnableReducedLength)) { @@ -122,7 +127,6 @@ public: if (BOOST_GEOMETRY_CONDITION(EnableGeodesicScale)) { - CT const ep2 = e2 / math::sqr(one_minus_f); CT const cos_sig12 = cos_sig1 * cos_sig2 + sin_sig1 * sin_sig2; CT const t = ep2 * (cos_bet1 - cos_bet2) * (cos_bet1 + cos_bet2) / (dn1 + dn2); CT const M12 = cos_sig12 + (t * sin_sig2 - cos_sig2 * J12) * sin_sig1 / dn1; @@ -132,49 +136,161 @@ public: } } - static inline CT J12_calc_f1(CT const& sin_sig1, CT const& cos_sig1, - CT const& sin_sig2, CT const& cos_sig2, - CT const& cos_alp0_sqr, CT const& f) - { - CT const sig12 = atan2(cos_sig1 * sin_sig2 - sin_sig1 * cos_sig2, - cos_sig1 * cos_sig2 + sin_sig1 * sin_sig2); - CT const sin_2sig1 = 2 * cos_sig1 * sin_sig1; // sin(2sig1) - CT const sin_2sig2 = 2 * cos_sig2 * sin_sig2; // sin(2sig2) - CT const sin_2sig12 = sin_2sig2 - sin_2sig1; - - CT const J12 = (sig12 - sin_2sig12 / 2) * cos_alp0_sqr * f; - - return J12; - } - - static inline CT J12_calc_f2(CT const& sin_sig1, CT const& cos_sig1, - CT const& sin_sig2, CT const& cos_sig2, - CT const& cos_alp0_sqr, CT const& f) - { - CT const sig12 = atan2(cos_sig1 * sin_sig2 - sin_sig1 * cos_sig2, - cos_sig1 * cos_sig2 + sin_sig1 * sin_sig2); - CT const sin_2sig1 = CT(2) * cos_sig1 * sin_sig1; // sin(2sig1) - CT const sin_2sig2 = CT(2) * cos_sig2 * sin_sig2; // sin(2sig2) - CT const sin_2sig12 = sin_2sig2 - sin_2sig1; - CT const sin_4sig1 = CT(2) * sin_2sig1 * (math::sqr(cos_sig1) - math::sqr(sin_sig1)); // sin(4sig1) - CT const sin_4sig2 = CT(2) * sin_2sig2 * (math::sqr(cos_sig2) - math::sqr(sin_sig2)); // sin(4sig2) - CT const sin_4sig12 = sin_4sig2 - sin_4sig1; - - CT const t1 = CT(2) * sig12 - sin_2sig12; - CT const t2 = cos_alp0_sqr * sin_4sig12 - + (-CT(8) * cos_alp0_sqr + CT(12)) * sin_2sig12 - + (CT(12) * cos_alp0_sqr - CT(24)) * sig12; - CT const J12 = cos_alp0_sqr * f * (t1 / 2 - f * t2 / 16); - - return J12; - } - private: + /*! Approximation of J12, expanded into taylor series in f + Maxima script: + ep2: f * (2-f) / ((1-f)^2); + k2: ca02 * ep2; + assume(f < 1); + assume(sig > 0); + I1(sig):= integrate(sqrt(1 + k2 * sin(s)^2), s, 0, sig); + I2(sig):= integrate(1/sqrt(1 + k2 * sin(s)^2), s, 0, sig); + J(sig):= I1(sig) - I2(sig); + S: taylor(J(sig), f, 0, 3); + S1: factor( 2*integrate(sin(s)^2,s,0,sig)*ca02*f ); + S2: factor( ((integrate(-6*ca02^2*sin(s)^4+6*ca02*sin(s)^2,s,0,sig)+integrate(-2*ca02^2*sin(s)^4+6*ca02*sin(s)^2,s,0,sig))*f^2)/4 ); + S3: factor( ((integrate(30*ca02^3*sin(s)^6-54*ca02^2*sin(s)^4+24*ca02*sin(s)^2,s,0,sig)+integrate(6*ca02^3*sin(s)^6-18*ca02^2*sin(s)^4+24*ca02*sin(s)^2,s,0,sig))*f^3)/12 ); + */ + static inline CT J12_f(CT const& sin_sig1, CT const& cos_sig1, + CT const& sin_sig2, CT const& cos_sig2, + CT const& cos_alp0_sqr, CT const& f) + { + if (Order == 0) + { + return 0; + } + + CT const c2 = 2; + + CT const sig_12 = atan2(cos_sig1 * sin_sig2 - sin_sig1 * cos_sig2, + cos_sig1 * cos_sig2 + sin_sig1 * sin_sig2); + CT const sin_2sig1 = c2 * cos_sig1 * sin_sig1; // sin(2sig1) + CT const sin_2sig2 = c2 * cos_sig2 * sin_sig2; // sin(2sig2) + CT const sin_2sig_12 = sin_2sig2 - sin_2sig1; + CT const L1 = sig_12 - sin_2sig_12 / c2; + + if (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; + CT const c24 = 24; + + CT const L2 = -( cos_alp0_sqr * sin_4sig_12 + + (-c8 * cos_alp0_sqr + c12) * sin_2sig_12 + + (c12 * cos_alp0_sqr - c24) * sig_12) + / c16; + + if (Order == 2) + { + return cos_alp0_sqr * f * (L1 + f * L2); + } + + CT const c4 = 4; + CT const c9 = 9; + CT const c48 = 48; + CT const c60 = 60; + CT const c64 = 64; + CT const c96 = 96; + CT const c128 = 128; + CT const c144 = 144; + + CT const cos_alp0_quad = math::sqr(cos_alp0_sqr); + CT const sin3_2sig1 = math::sqr(sin_2sig1) * sin_2sig1; + CT const sin3_2sig2 = math::sqr(sin_2sig2) * sin_2sig2; + CT const sin3_2sig_12 = sin3_2sig2 - sin3_2sig1; + + CT const A = (c9 * cos_alp0_quad - c12 * cos_alp0_sqr) * sin_4sig_12; + CT const B = c4 * cos_alp0_quad * sin3_2sig_12; + CT const C = (-c48 * cos_alp0_quad + c96 * cos_alp0_sqr - c64) * sin_2sig_12; + CT const D = (c60 * cos_alp0_quad - c144 * cos_alp0_sqr + c128) * sig_12; + + CT const L3 = (A + B + C + D) / c64; + + // Order 3 and higher + return cos_alp0_sqr * f * (L1 + f * (L2 + f * L3)); + } + + /*! Approximation of J12, expanded into taylor series in e'^2 + Maxima script: + k2: ca02 * ep2; + assume(sig > 0); + I1(sig):= integrate(sqrt(1 + k2 * sin(s)^2), s, 0, sig); + I2(sig):= integrate(1/sqrt(1 + k2 * sin(s)^2), s, 0, sig); + J(sig):= I1(sig) - I2(sig); + S: taylor(J(sig), ep2, 0, 3); + S1: factor( integrate(sin(s)^2,s,0,sig)*ca02*ep2 ); + S2: factor( (integrate(sin(s)^4,s,0,sig)*ca02^2*ep2^2)/2 ); + S3: factor( (3*integrate(sin(s)^6,s,0,sig)*ca02^3*ep2^3)/8 ); + */ + static inline CT J12_ep_sqr(CT const& sin_sig1, CT const& cos_sig1, + CT const& sin_sig2, CT const& cos_sig2, + CT const& cos_alp0_sqr, CT const& ep_sqr) + { + if (Order == 0) + { + return 0; + } + + CT const c2 = 2; + CT const c4 = 4; + + CT const c2a0ep2 = cos_alp0_sqr * ep_sqr; + + CT const sig_12 = atan2(cos_sig1 * sin_sig2 - sin_sig1 * cos_sig2, + cos_sig1 * cos_sig2 + sin_sig1 * sin_sig2); // sig2 - sig1 + CT const sin_2sig1 = c2 * cos_sig1 * sin_sig1; // sin(2sig1) + CT const sin_2sig2 = c2 * cos_sig2 * sin_sig2; // sin(2sig2) + CT const sin_2sig_12 = sin_2sig2 - sin_2sig1; + + CT const L1 = (c2 * sig_12 - sin_2sig_12) / c4; + + if (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) + { + return c2a0ep2 * (L1 + c2a0ep2 * L2); + } + + CT const sin3_2sig1 = math::sqr(sin_2sig1) * sin_2sig1; + CT const sin3_2sig2 = math::sqr(sin_2sig2) * sin_2sig2; + CT const sin3_2sig_12 = sin3_2sig2 - sin3_2sig1; + + CT const c9 = 9; + CT const c48 = 48; + CT const c60 = 60; + CT const c512 = 512; + + CT const L3 = (c9 * sin_4sig_12 + c4 * sin3_2sig_12 - c48 * sin_2sig_12 + c60 * sig_12) / c512; + + // Order 3 and higher + return c2a0ep2 * (L1 + c2a0ep2 * (L2 + c2a0ep2 * L3)); + } + static inline void normalize(CT & x, CT & y) { - CT const l = math::sqrt(math::sqr(x) + math::sqr(y)); - x /= l; - y /= l; + CT const len = math::sqrt(math::sqr(x) + math::sqr(y)); + x /= len; + y /= len; } }; diff --git a/include/boost/geometry/formulas/gnomonic_intersection.hpp b/include/boost/geometry/formulas/gnomonic_intersection.hpp new file mode 100644 index 000000000..7e1b7bcda --- /dev/null +++ b/include/boost/geometry/formulas/gnomonic_intersection.hpp @@ -0,0 +1,148 @@ +// Boost.Geometry + +// 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, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_FORMULAS_GNOMONIC_INTERSECTION_HPP +#define BOOST_GEOMETRY_FORMULAS_GNOMONIC_INTERSECTION_HPP + +#include +#include + +#include +#include +#include +#include + + +namespace boost { namespace geometry { namespace formula +{ + +/*! +\brief The intersection of two geodesics using spheroidal gnomonic projection + as proposed by Karney. +\author See + - Charles F.F Karney, Algorithms for geodesics, 2011 + https://arxiv.org/pdf/1109.4448.pdf + - GeographicLib forum thread: Intersection between two geodesic lines + https://sourceforge.net/p/geographiclib/discussion/1026621/thread/21aaff9f/ +*/ +template +< + typename CT, + template class Inverse, + template class Direct +> +class gnomonic_intersection +{ +public: + template + static inline bool apply(T1 const& lona1, T1 const& lata1, + T1 const& lona2, T1 const& lata2, + T2 const& lonb1, T2 const& latb1, + T2 const& lonb2, T2 const& latb2, + CT & lon, CT & lat, + Spheroid const& spheroid) + { + CT const lon_a1 = lona1; + CT const lat_a1 = lata1; + CT const lon_a2 = lona2; + CT const lat_a2 = lata2; + CT const lon_b1 = lonb1; + CT const lat_b1 = latb1; + CT const lon_b2 = lonb2; + CT const lat_b2 = latb2; + + return apply(lon_a1, lat_a1, lon_a2, lat_a2, lon_b1, lat_b1, lon_b2, lat_b2, lon, lat, spheroid); + } + + template + static inline bool apply(CT const& lona1, CT const& lata1, + CT const& lona2, CT const& lata2, + CT const& lonb1, CT const& latb1, + CT const& lonb2, CT const& latb2, + CT & lon, CT & lat, + Spheroid const& spheroid) + { + typedef gnomonic_spheroid gnom_t; + + lon = (lona1 + lona2 + lonb1 + lonb2) / 4; + lat = (lata1 + lata2 + latb1 + latb2) / 4; + // TODO: consider normalizing lon + + for (int i = 0; i < 10; ++i) + { + CT xa1, ya1, xa2, ya2; + CT xb1, yb1, xb2, yb2; + CT x, y; + double lat1, lon1; + + bool ok = gnom_t::forward(lon, lat, lona1, lata1, xa1, ya1, spheroid) + && gnom_t::forward(lon, lat, lona2, lata2, xa2, ya2, spheroid) + && gnom_t::forward(lon, lat, lonb1, latb1, xb1, yb1, spheroid) + && gnom_t::forward(lon, lat, lonb2, latb2, xb2, yb2, spheroid) + && intersect(xa1, ya1, xa2, ya2, xb1, yb1, xb2, yb2, x, y) + && gnom_t::inverse(lon, lat, x, y, lon1, lat1, spheroid); + + if (! ok) + { + return false; + } + + if (math::equals(lat1, lat) && math::equals(lon1, lon)) + { + break; + } + + lat = lat1; + lon = lon1; + } + + // NOTE: true is also returned if the number of iterations is too great + // which means that the accuracy of the result is low + return true; + } + +private: + static inline bool intersect(CT const& xa1, CT const& ya1, CT const& xa2, CT const& ya2, + CT const& xb1, CT const& yb1, CT const& xb2, CT const& yb2, + CT & x, CT & y) + { + typedef model::point v3d_t; + + CT const c0 = 0; + CT const c1 = 1; + + v3d_t const va1(xa1, ya1, c1); + v3d_t const va2(xa2, ya2, c1); + v3d_t const vb1(xb1, yb1, c1); + v3d_t const vb2(xb2, yb2, c1); + + v3d_t const la = cross_product(va1, va2); + v3d_t const lb = cross_product(vb1, vb2); + v3d_t const p = cross_product(la, lb); + + CT const z = get<2>(p); + + if (math::equals(z, c0)) + { + // degenerated or collinear segments + return false; + } + + x = get<0>(p) / z; + y = get<1>(p) / z; + + return true; + } +}; + +}}} // namespace boost::geometry::formula + + +#endif // BOOST_GEOMETRY_FORMULAS_GNOMONIC_INTERSECTION_HPP diff --git a/include/boost/geometry/formulas/gnomonic_spheroid.hpp b/include/boost/geometry/formulas/gnomonic_spheroid.hpp index fcb6e7165..3457397b0 100644 --- a/include/boost/geometry/formulas/gnomonic_spheroid.hpp +++ b/include/boost/geometry/formulas/gnomonic_spheroid.hpp @@ -56,13 +56,15 @@ public: Spheroid const& spheroid) { inverse_result i_res = inverse_type::apply(lon0, lat0, lon, lat, spheroid); + CT const& m = i_res.reduced_length; + CT const& M = i_res.geodesic_scale; - if (math::smaller_or_equals(i_res.geodesic_scale, CT(0))) + if (math::smaller_or_equals(M, CT(0))) { return false; } - CT rho = i_res.reduced_length / i_res.geodesic_scale; + CT rho = m / M; x = sin(i_res.azimuth) * rho; y = cos(i_res.azimuth) * rho; @@ -76,8 +78,6 @@ public: Spheroid const& spheroid) { CT const a = get_radius<0>(spheroid); - CT const b = get_radius<2>(spheroid); - CT const f = detail::flattening(spheroid); CT const ds_threshold = a * std::numeric_limits::epsilon(); // TODO: 0 for non-fundamental type CT const azimuth = atan2(x, y); @@ -90,6 +90,12 @@ public: direct_result d_res = direct_quantities_type::apply(lon0, lat0, distance, azimuth, spheroid); CT const& m = d_res.reduced_length; CT const& M = d_res.geodesic_scale; + + if (math::smaller_or_equals(M, CT(0))) + { + // 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 diff --git a/include/boost/geometry/formulas/sjoberg_intersection.hpp b/include/boost/geometry/formulas/sjoberg_intersection.hpp new file mode 100644 index 000000000..03bd4bc97 --- /dev/null +++ b/include/boost/geometry/formulas/sjoberg_intersection.hpp @@ -0,0 +1,385 @@ +// Boost.Geometry + +// 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, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_FORMULAS_SJOBERG_INTERSECTION_HPP +#define BOOST_GEOMETRY_FORMULAS_SJOBERG_INTERSECTION_HPP + + +#include + +#include +#include + +#include +#include + +#include + + +namespace boost { namespace geometry { namespace formula +{ + +/*! +\brief The intersection of two geodesics as proposed by Sjoberg. +\author See + - [Sjoberg02] Lars E. Sjoberg, Intersections on the sphere and ellipsoid, 2002 + http://link.springer.com/article/10.1007/s00190-001-0230-9 + - [Sjoberg07] Lars E. Sjoberg, Geodetic intersection on the ellipsoid, 2007 + http://link.springer.com/article/10.1007/s00190-007-0204-7 +*/ +template +< + typename CT, + template class Inverse, + unsigned int Order = 4 +> +class sjoberg_intersection +{ + typedef Inverse inverse_type; + typedef typename inverse_type::result_type inverse_result; + +public: + template + static inline bool apply(T1 const& lona1, T1 const& lata1, + T1 const& lona2, T1 const& lata2, + T2 const& lonb1, T2 const& latb1, + T2 const& lonb2, T2 const& latb2, + CT & lon, CT & lat, + Spheroid const& spheroid) + { + CT const lon_a1 = lona1; + CT const lat_a1 = lata1; + CT const lon_a2 = lona2; + CT const lat_a2 = lata2; + CT const lon_b1 = lonb1; + CT const lat_b1 = latb1; + CT const lon_b2 = lonb2; + CT const lat_b2 = latb2; + + CT const alpha1 = inverse_type::apply(lon_a1, lat_a1, lon_a2, lat_a2, spheroid).azimuth; + CT const alpha2 = inverse_type::apply(lon_b1, lat_b1, lon_b2, lat_b2, spheroid).azimuth; + + return apply(lon_a1, lat_a1, alpha1, lon_b1, lat_b1, alpha2, lon, lat, spheroid); + } + + template + static inline bool apply(CT const& lon1, CT const& lat1, CT const& alpha1, + CT const& lon2, CT const& lat2, CT const& alpha2, + CT & lon, CT & lat, + Spheroid const& spheroid) + { + // coordinates in radians + + // TODO - handle special cases like degenerated segments, equator, poles, etc. + + CT const c0 = 0; + CT const c1 = 1; + CT const c2 = 2; + + CT const pi = math::pi(); + CT const pi_half = pi / c2; + CT const f = detail::flattening(spheroid); + CT const one_minus_f = c1 - f; + CT const e_sqr = f * (c2 - f); + + CT const sin_alpha1 = sin(alpha1); + CT const sin_alpha2 = sin(alpha2); + + CT const tan_beta1 = one_minus_f * tan(lat1); + CT const tan_beta2 = one_minus_f * tan(lat2); + CT const beta1 = atan(tan_beta1); + CT const beta2 = atan(tan_beta2); + CT const cos_beta1 = cos(beta1); + CT const cos_beta2 = cos(beta2); + CT const sin_beta1 = sin(beta1); + CT const sin_beta2 = sin(beta2); + + // Clairaut constants (lower-case in the paper) + int const sign_C1 = math::abs(alpha1) <= pi_half ? 1 : -1; + int const sign_C2 = math::abs(alpha2) <= pi_half ? 1 : -1; + // Cj = 1 if on equator + CT const C1 = sign_C1 * cos_beta1 * sin_alpha1; + CT const C2 = sign_C2 * cos_beta2 * sin_alpha2; + + CT const sqrt_1_C1_sqr = math::sqrt(c1 - math::sqr(C1)); + CT const sqrt_1_C2_sqr = math::sqrt(c1 - math::sqr(C2)); + + // handle special case: segments on the equator + bool const on_equator1 = math::equals(sqrt_1_C1_sqr, c0); + bool const on_equator2 = math::equals(sqrt_1_C2_sqr, c0); + if (on_equator1 && on_equator2) + { + return false; + } + else if (on_equator1) + { + CT const dL2 = d_lambda_e_sqr(sin_beta2, c0, C2, sqrt_1_C2_sqr, e_sqr); + CT const asin_t2_t02 = asin(C2 * tan_beta2 / sqrt_1_C2_sqr); + lat = c0; + lon = lon2 - asin_t2_t02 + dL2; + return true; + } + else if (on_equator2) + { + CT const dL1 = d_lambda_e_sqr(sin_beta1, c0, C1, sqrt_1_C1_sqr, e_sqr); + CT const asin_t1_t01 = asin(C1 * tan_beta1 / sqrt_1_C1_sqr); + lat = c0; + lon = lon1 - asin_t1_t01 + dL1; + return true; + } + + CT const t01 = sqrt_1_C1_sqr / C1; + CT const t02 = sqrt_1_C2_sqr / C2; + + CT const asin_t1_t01 = asin(tan_beta1 / t01); + CT const asin_t2_t02 = asin(tan_beta2 / t02); + CT const t01_t02 = t01 * t02; + CT const t01_t02_2 = c2 * t01_t02; + CT const sqr_t01_sqr_t02 = math::sqr(t01) + math::sqr(t02); + + CT t = tan_beta1; + int t_id = 0; + + // find the initial t using simplified spherical solution + // though not entirely since the reduced latitudes and azimuths are spheroidal + // [Sjoberg07] + CT const k_base = lon1 - lon2 + asin_t2_t02 - asin_t1_t01; + + { + CT const K = sin(k_base); + CT const d1 = sqr_t01_sqr_t02; + //CT const d2 = t01_t02_2 * math::sqrt(c1 - math::sqr(K)); + CT const d2 = t01_t02_2 * cos(k_base); + CT const D1 = math::sqrt(d1 - d2); + CT const D2 = math::sqrt(d1 + d2); + CT const K_t01_t02 = K * t01_t02; + + CT const T1 = K_t01_t02 / D1; + CT const T2 = K_t01_t02 / D2; + CT asin_T1_t01 = 0; + CT asin_T1_t02 = 0; + CT asin_T2_t01 = 0; + CT asin_T2_t02 = 0; + + // test 4 possible results + CT l1 = 0, l2 = 0, dl = 0; + bool found = check_t<0>( T1, + lon1, asin_T1_t01 = asin(T1 / t01), asin_t1_t01, + lon2, asin_T1_t02 = asin(T1 / t02), asin_t2_t02, + t, l1, l2, dl, t_id) + || check_t<1>(-T1, + lon1, -asin_T1_t01 , asin_t1_t01, + lon2, -asin_T1_t02 , asin_t2_t02, + t, l1, l2, dl, t_id) + || check_t<2>( T2, + lon1, asin_T2_t01 = asin(T2 / t01), asin_t1_t01, + lon2, asin_T2_t02 = asin(T2 / t02), asin_t2_t02, + t, l1, l2, dl, t_id) + || check_t<3>(-T2, + lon1, -asin_T2_t01 , asin_t1_t01, + lon2, -asin_T2_t02 , asin_t2_t02, + t, l1, l2, dl, t_id); + + boost::ignore_unused(found); + } + + // [Sjoberg07] + //int const d2_sign = t_id < 2 ? -1 : 1; + int const t_sign = (t_id % 2) ? -1 : 1; + // [Sjoberg02] + CT const C1_sqr = math::sqr(C1); + CT const C2_sqr = math::sqr(C2); + + CT beta = atan(t); + CT dL1 = 0, dL2 = 0; + CT asin_t_t01 = 0; + CT asin_t_t02 = 0; + + for (int i = 0; i < 10; ++i) + { + CT const sin_beta = sin(beta); + + // integrals approximation + dL1 = d_lambda_e_sqr(sin_beta1, sin_beta, C1, sqrt_1_C1_sqr, e_sqr); + dL2 = d_lambda_e_sqr(sin_beta2, sin_beta, C2, sqrt_1_C2_sqr, e_sqr); + + // [Sjoberg07] + /*CT const k = k_base + dL1 - dL2; + CT const K = sin(k); + CT const d1 = sqr_t01_sqr_t02; + //CT const d2 = t01_t02_2 * math::sqrt(c1 - math::sqr(K)); + CT const d2 = t01_t02_2 * cos(k); + CT const D = math::sqrt(d1 + d2_sign * d2); + CT const t_new = t_sign * K * t01_t02 / D; + CT const dt = math::abs(t_new - t); + t = t_new; + CT const new_beta = atan(t); + CT const dbeta = math::abs(new_beta - beta); + beta = new_beta;*/ + + // [Sjoberg02] - it converges faster + // Newton–Raphson method + asin_t_t01 = asin(t / t01); + asin_t_t02 = asin(t / t02); + CT const R1 = asin_t_t01 + dL1; + CT const R2 = asin_t_t02 + dL2; + CT const cos_beta = cos(beta); + CT const cos_beta_sqr = math::sqr(cos_beta); + CT const G = c1 - e_sqr * cos_beta_sqr; + CT const f1 = C1 / cos_beta * math::sqrt(G / (cos_beta_sqr - C1_sqr)); + CT const f2 = C2 / cos_beta * math::sqrt(G / (cos_beta_sqr - C2_sqr)); + CT const abs_f1 = math::abs(f1); + CT const abs_f2 = math::abs(f2); + CT const dbeta = t_sign * (k_base - R2 + R1) / (abs_f1 + abs_f2); + + if (math::equals(dbeta, CT(0))) + { + break; + } + + beta = beta - dbeta; + t = tan(beta); + } + + // t = tan(beta) = (1-f)tan(lat) + lat = atan(t / one_minus_f); + + CT const l1 = lon1 + asin_t_t01 - asin_t1_t01 + dL1; + //CT const l2 = lon2 + asin_t_t02 - asin_t2_t02 + dL2; + lon = l1; + + return true; + } + +private: + /*! Approximation of dLambda_j [Sjoberg07], expanded into taylor series in e^2 + Maxima script: + dLI_j(c_j, sinB_j, sinB) := integrate(1 / (sqrt(1 - c_j ^ 2 - x ^ 2)*(1 + sqrt(1 - e2*(1 - x ^ 2)))), x, sinB_j, sinB); + dL_j(c_j, B_j, B) := -e2 * c_j * dLI_j(c_j, B_j, B); + S: taylor(dLI_j(c_j, sinB_j, sinB), e2, 0, 3); + assume(c_j < 1); + assume(c_j > 0); + L1: factor(integrate(sqrt(-x ^ 2 - c_j ^ 2 + 1) / (x ^ 2 + c_j ^ 2 - 1), x)); + L2: factor(integrate(((x ^ 2 - 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x)); + L3: factor(integrate(((x ^ 4 - 2 * x ^ 2 + 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x)); + L4: factor(integrate(((x ^ 6 - 3 * x ^ 4 + 3 * x ^ 2 - 1)*sqrt(-x ^ 2 - c_j ^ 2 + 1)) / (x ^ 2 + c_j ^ 2 - 1), x)); + */ + static inline CT d_lambda_e_sqr(CT const& sin_betaj, CT const& sin_beta, + CT const& Cj, CT const& sqrt_1_Cj_sqr, + CT const& e_sqr) + { + if (Order == 0) + { + return 0; + } + + CT const c2 = 2; + + CT const asin_B = asin(sin_beta / sqrt_1_Cj_sqr); + CT const asin_Bj = asin(sin_betaj / sqrt_1_Cj_sqr); + CT const L0 = (asin_B - asin_Bj) / c2; + + if (Order == 1) + { + return -Cj * e_sqr * L0; + } + + CT const c1 = 1; + CT const c16 = 16; + + CT const X = sin_beta; + CT const Xj = sin_betaj; + CT const Cj_sqr = math::sqr(Cj); + CT const Cj_sqr_plus_one = Cj_sqr + c1; + CT const one_minus_Cj_sqr = c1 - Cj_sqr; + CT const sqrt_Y = math::sqrt(-math::sqr(X) + one_minus_Cj_sqr); + CT const sqrt_Yj = math::sqrt(-math::sqr(Xj) + 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) + { + return -Cj * e_sqr * (L0 + e_sqr * L1); + } + + CT const c3 = 3; + CT const c5 = 5; + CT const c128 = 128; + + CT const E = Cj_sqr * (c3 * Cj_sqr + c2) + c3; + CT const X_sqr = math::sqr(X); + CT const Xj_sqr = math::sqr(Xj); + CT const F = X * (-c2 * X_sqr + c3 * Cj_sqr + c5); + 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) + { + return -Cj * e_sqr * (L0 + e_sqr * (L1 + e_sqr * L2)); + } + + CT const c8 = 8; + CT const c9 = 9; + CT const c10 = 10; + CT const c15 = 15; + CT const c24 = 24; + CT const c26 = 26; + CT const c33 = 33; + CT const c6144 = 6144; + + CT const G = Cj_sqr * (Cj_sqr * (Cj_sqr * c15 + c9) + c9) + c15; + CT const H = -c10 * Cj_sqr - c26; + CT const I = Cj_sqr * (Cj_sqr * c15 + c24) + c33; + CT const J = X_sqr * (X * (c8 * X_sqr + H)) + X * I; + CT const Jj = Xj_sqr * (Xj * (c8 * Xj_sqr + H)) + Xj * I; + CT const L3 = (G * (asin_B - asin_Bj) + J * sqrt_Y - Jj * sqrt_Yj) / c6144; + + // Order 4 and higher + return -Cj * e_sqr * (L0 + e_sqr * (L1 + e_sqr * (L2 + e_sqr * L3))); + } + + static inline CT fj(CT const& cos_beta, CT const& cos2_beta, CT const& Cj, CT const& e_sqr) + { + CT const c1 = 1; + CT const Cj_sqr = math::sqr(Cj); + return Cj / cos_beta * math::sqrt((c1 - e_sqr * cos2_beta) / (cos2_beta - Cj_sqr)); + } + + template + static inline bool check_t(CT const& t, + CT const& lon_a1, CT const& asin_t_t01, CT const& asin_t1_t01, + CT const& lon_b1, CT const& asin_t_t02, CT const& asin_t2_t02, + CT & current_t, CT & current_lon1, CT & current_lon2, CT & current_dlon, + int & t_id) + { + CT const lon1 = lon_a1 + asin_t_t01 - asin_t1_t01; + CT const lon2 = lon_b1 + asin_t_t02 - asin_t2_t02; + + // TODO - true angle difference + CT const dlon = math::abs(lon2 - lon1); + + bool are_equal = math::equals(dlon, CT(0)); + + if ((TId == 0) || are_equal || dlon < current_dlon) + { + current_t = t; + current_lon1 = lon1; + current_lon2 = lon2; + current_dlon = dlon; + t_id = TId; + } + + return are_equal; + } +}; + +}}} // namespace boost::geometry::formula + + +#endif // BOOST_GEOMETRY_FORMULAS_SJOBERG_INTERSECTION_HPP diff --git a/include/boost/geometry/formulas/thomas_direct.hpp b/include/boost/geometry/formulas/thomas_direct.hpp index 0ae4ab218..f8a7f8394 100644 --- a/include/boost/geometry/formulas/thomas_direct.hpp +++ b/include/boost/geometry/formulas/thomas_direct.hpp @@ -85,16 +85,23 @@ public: CT const f = detail::flattening(spheroid); CT const one_minus_f = c1 - f; - CT const pi_half = math::pi() / c2; + CT const pi = math::pi(); + CT const pi_half = pi / c2; - CT const theta1 = math::equals(lat1, pi_half) ? lat1 : - math::equals(lat1, -pi_half) ? lat1 : - atan(one_minus_f * tan(lat1)); + // keep azimuth small - experiments show low accuracy + // if the azimuth is closer to (+-)180 deg. + CT azi12_alt = azimuth12; + CT lat1_alt = lat1; + bool alter_result = vflip_if_south(lat1, azimuth12, lat1_alt, azi12_alt); + + CT const theta1 = math::equals(lat1_alt, pi_half) ? lat1_alt : + math::equals(lat1_alt, -pi_half) ? lat1_alt : + atan(one_minus_f * tan(lat1_alt)); CT const sin_theta1 = sin(theta1); CT const cos_theta1 = cos(theta1); - CT const sin_a12 = sin(azimuth12); - CT const cos_a12 = cos(azimuth12); + CT const sin_a12 = sin(azi12_alt); + CT const cos_a12 = cos(azi12_alt); CT const M = cos_theta1 * sin_a12; // cos_theta0 CT const theta0 = acos(M); @@ -106,11 +113,20 @@ public: CT const D = (c1 - C2) * (c1 - C2 - C1 * M); CT const P = C2 * (c1 + C1 * M / c2) / D; - CT const cos_sigma1 = sin_theta1 / sin_theta0; + // special case for equator: + // sin_theta0 = 0 <=> lat1 = 0 ^ |azimuth12| = pi/2 + // NOTE: in this case it doesn't matter what's the value of cos_sigma1 because + // theta1=0, theta0=0, M=1|-1, C2=0 so X=0 and Y=0 so d_sigma=d + // cos_a12=0 so N=0, therefore + // lat2=0, azi21=pi/2|-pi/2 + // d_eta = atan2(sin_d_sigma, cos_d_sigma) + // H = C1 * d_sigma + CT const cos_sigma1 = math::equals(sin_theta0, c0) + ? c1 + : normalized1_1(sin_theta1 / sin_theta0); CT const sigma1 = acos(cos_sigma1); CT const d = distance / (a * D); CT const u = 2 * (sigma1 - d); - CT const sin_sigma1 = sin(sigma1); CT const cos_d = cos(d); CT const sin_d = sin(d); CT const cos_u = cos(u); @@ -127,17 +143,15 @@ public: if (BOOST_GEOMETRY_CONDITION(CalcRevAzimuth)) { result.reverse_azimuth = atan2(M, N * cos_d_sigma - sin_theta1 * sin_d_sigma); + + if (alter_result) + { + vflip_rev_azi(result.reverse_azimuth, azimuth12); + } } if (BOOST_GEOMETRY_CONDITION(CalcCoordinates)) { - CT const sin_a21 = sin(result.reverse_azimuth); - CT const cos_a21 = cos(result.reverse_azimuth); - - CT const tan_lat2 = (sin_theta1 * cos_d_sigma + N * sin_d_sigma) * sin_a21 / (one_minus_f * M); - - result.lat2 = atan(tan_lat2); - CT const S_sigma = c2 * sigma1 - d_sigma; CT const cos_S_sigma = cos(S_sigma); CT const d_eta = atan2(sin_d_sigma * sin_a12, cos_theta1 * cos_d_sigma - sin_theta1 * sin_d_sigma * cos_a12); @@ -145,21 +159,88 @@ public: CT const d_lambda = d_eta - H; result.lon2 = lon1 + d_lambda; + + if (! math::equals(M, c0)) + { + CT const sin_a21 = sin(result.reverse_azimuth); + CT const tan_theta2 = (sin_theta1 * cos_d_sigma + N * sin_d_sigma) * sin_a21 / M; + result.lat2 = atan(tan_theta2 / one_minus_f); + } + else + { + CT const sigma2 = S_sigma - sigma1; + //theta2 = asin(cos(sigma2)) <=> sin_theta0 = 1 + CT const tan_theta2 = cos(sigma2) / sin(sigma2); + result.lat2 = atan(tan_theta2 / one_minus_f); + } + + if (alter_result) + { + result.lat2 = -result.lat2; + } } if (BOOST_GEOMETRY_CONDITION(CalcQuantities)) { - typedef differential_quantities quantities; + typedef differential_quantities quantities; quantities::apply(lon1, lat1, result.lon2, result.lat2, azimuth12, result.reverse_azimuth, b, f, - result.reduced_length, result.geodesic_scale, - quantities::J12_calc_f2); + result.reduced_length, result.geodesic_scale); } return result; } +private: + static inline bool vflip_if_south(CT const& lat1, CT const& azi12, CT & lat1_alt, CT & azi12_alt) + { + CT const c2 = 2; + CT const pi = math::pi(); + CT const pi_half = pi / c2; + + if (azi12 > pi_half) + { + azi12_alt = pi - azi12; + lat1_alt = -lat1; + return true; + } + else if (azi12 < -pi_half) + { + azi12_alt = -pi - azi12; + lat1_alt = -lat1; + return true; + } + + return false; + } + + static inline void vflip_rev_azi(CT & rev_azi, CT const& azimuth12) + { + CT const c0 = 0; + CT const pi = math::pi(); + + if (rev_azi == c0) + { + rev_azi = azimuth12 >= 0 ? pi : -pi; + } + else if (rev_azi > c0) + { + rev_azi = pi - rev_azi; + } + else + { + rev_azi = -pi - rev_azi; + } + } + + static inline CT normalized1_1(CT const& value) + { + CT const c1 = 1; + return value > c1 ? c1 : + value < -c1 ? -c1 : + value; + } }; }}} // namespace boost::geometry::formula diff --git a/include/boost/geometry/formulas/thomas_inverse.hpp b/include/boost/geometry/formulas/thomas_inverse.hpp index 9ca2f331c..d68c9de05 100644 --- a/include/boost/geometry/formulas/thomas_inverse.hpp +++ b/include/boost/geometry/formulas/thomas_inverse.hpp @@ -163,9 +163,14 @@ 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. + // In the edge case the result may be 2 orders of magnitude less + // accurate than Andoyer's. CT const tan_d_lambda = tan(d_lambda); CT const Q = -(F*G*tan_d_lambda) / c4; - CT const d_lambda_m_p = (d_lambda + Q) / c2; CT const tan_d_lambda_m_p = tan(d_lambda_m_p); @@ -199,12 +204,11 @@ public: if (BOOST_GEOMETRY_CONDITION(CalcQuantities)) { - typedef differential_quantities quantities; + typedef differential_quantities quantities; quantities::apply(lon1, lat1, lon2, lat2, result.azimuth, result.reverse_azimuth, get_radius<2>(spheroid), f, - result.reduced_length, result.geodesic_scale, - quantities::J12_calc_f2); + result.reduced_length, result.geodesic_scale); } return result; diff --git a/include/boost/geometry/formulas/vincenty_direct.hpp b/include/boost/geometry/formulas/vincenty_direct.hpp index 5e9464632..f3647ff4e 100644 --- a/include/boost/geometry/formulas/vincenty_direct.hpp +++ b/include/boost/geometry/formulas/vincenty_direct.hpp @@ -167,12 +167,11 @@ public: if (BOOST_GEOMETRY_CONDITION(CalcQuantities)) { - typedef differential_quantities quantities; + typedef differential_quantities quantities; quantities::apply(lon1, lat1, result.lon2, result.lat2, azimuth12, result.reverse_azimuth, radius_b, flattening, - result.reduced_length, result.geodesic_scale, - quantities::J12_calc_f2); // TODO use more accurate J12 + result.reduced_length, result.geodesic_scale); } return result; diff --git a/include/boost/geometry/formulas/vincenty_inverse.hpp b/include/boost/geometry/formulas/vincenty_inverse.hpp index 94097cb86..bbda00036 100644 --- a/include/boost/geometry/formulas/vincenty_inverse.hpp +++ b/include/boost/geometry/formulas/vincenty_inverse.hpp @@ -203,12 +203,11 @@ public: if (BOOST_GEOMETRY_CONDITION(CalcQuantities)) { - typedef differential_quantities quantities; + typedef differential_quantities quantities; quantities::apply(lon1, lat1, lon2, lat2, result.azimuth, result.reverse_azimuth, radius_b, flattening, - result.reduced_length, result.geodesic_scale, - quantities::J12_calc_f2); // TODO use more accurate J12 + result.reduced_length, result.geodesic_scale); } return result; diff --git a/include/boost/geometry/geometries/box.hpp b/include/boost/geometry/geometries/box.hpp index 97a4ba06d..23fd098f6 100644 --- a/include/boost/geometry/geometries/box.hpp +++ b/include/boost/geometry/geometries/box.hpp @@ -53,7 +53,7 @@ The box can also take a latlong point type as template parameter. template class box { - BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); public: diff --git a/include/boost/geometry/geometries/concepts/box_concept.hpp b/include/boost/geometry/geometries/concepts/box_concept.hpp index ea0d84cf3..816a90f63 100644 --- a/include/boost/geometry/geometries/concepts/box_concept.hpp +++ b/include/boost/geometry/geometries/concepts/box_concept.hpp @@ -26,7 +26,7 @@ #include -namespace boost { namespace geometry { namespace concept +namespace boost { namespace geometry { namespace concepts { @@ -130,7 +130,7 @@ public : #endif }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_BOX_CONCEPT_HPP diff --git a/include/boost/geometry/geometries/concepts/check.hpp b/include/boost/geometry/geometries/concepts/check.hpp index 07ef84f4a..f609d5f13 100644 --- a/include/boost/geometry/geometries/concepts/check.hpp +++ b/include/boost/geometry/geometries/concepts/check.hpp @@ -71,108 +71,108 @@ struct check : not_implemented template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; template struct check - : detail::concept_check::check > + : detail::concept_check::check > {}; @@ -182,7 +182,7 @@ struct check -namespace concept +namespace concepts { @@ -234,7 +234,7 @@ inline void check_concepts_and_equal_dimensions() } -} // namespace concept +} // namespace concepts }} // namespace boost::geometry diff --git a/include/boost/geometry/geometries/concepts/linestring_concept.hpp b/include/boost/geometry/geometries/concepts/linestring_concept.hpp index 091336fe3..6775239d0 100644 --- a/include/boost/geometry/geometries/concepts/linestring_concept.hpp +++ b/include/boost/geometry/geometries/concepts/linestring_concept.hpp @@ -28,7 +28,7 @@ -namespace boost { namespace geometry { namespace concept +namespace boost { namespace geometry { namespace concepts { @@ -76,7 +76,7 @@ class Linestring #ifndef DOXYGEN_NO_CONCEPT_MEMBERS typedef typename point_type::type point_type; - BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept) ); public : @@ -105,7 +105,7 @@ class ConstLinestring #ifndef DOXYGEN_NO_CONCEPT_MEMBERS typedef typename point_type::type point_type; - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); //BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept) ); // Relaxed the concept. BOOST_CONCEPT_ASSERT( (boost::ForwardRangeConcept) ); @@ -119,7 +119,7 @@ public : #endif }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_LINESTRING_CONCEPT_HPP diff --git a/include/boost/geometry/geometries/concepts/multi_linestring_concept.hpp b/include/boost/geometry/geometries/concepts/multi_linestring_concept.hpp index f13f7ac7e..793167090 100644 --- a/include/boost/geometry/geometries/concepts/multi_linestring_concept.hpp +++ b/include/boost/geometry/geometries/concepts/multi_linestring_concept.hpp @@ -24,7 +24,7 @@ #include -namespace boost { namespace geometry { namespace concept +namespace boost { namespace geometry { namespace concepts { @@ -45,7 +45,7 @@ class MultiLinestring #ifndef DOXYGEN_NO_CONCEPT_MEMBERS typedef typename boost::range_value::type linestring_type; - BOOST_CONCEPT_ASSERT( (concept::Linestring) ); + BOOST_CONCEPT_ASSERT( (concepts::Linestring) ); BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept) ); @@ -73,7 +73,7 @@ class ConstMultiLinestring #ifndef DOXYGEN_NO_CONCEPT_MEMBERS typedef typename boost::range_value::type linestring_type; - BOOST_CONCEPT_ASSERT( (concept::ConstLinestring) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstLinestring) ); BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept) ); @@ -85,7 +85,7 @@ public : #endif }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_MULTI_LINESTRING_CONCEPT_HPP diff --git a/include/boost/geometry/geometries/concepts/multi_point_concept.hpp b/include/boost/geometry/geometries/concepts/multi_point_concept.hpp index 81c087166..9e205f163 100644 --- a/include/boost/geometry/geometries/concepts/multi_point_concept.hpp +++ b/include/boost/geometry/geometries/concepts/multi_point_concept.hpp @@ -24,7 +24,7 @@ #include -namespace boost { namespace geometry { namespace concept +namespace boost { namespace geometry { namespace concepts { @@ -44,7 +44,7 @@ class MultiPoint #ifndef DOXYGEN_NO_CONCEPT_MEMBERS typedef typename boost::range_value::type point_type; - BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept) ); @@ -72,7 +72,7 @@ class ConstMultiPoint #ifndef DOXYGEN_NO_CONCEPT_MEMBERS typedef typename boost::range_value::type point_type; - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept) ); @@ -84,7 +84,7 @@ public : #endif }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_MULTI_POINT_CONCEPT_HPP diff --git a/include/boost/geometry/geometries/concepts/multi_polygon_concept.hpp b/include/boost/geometry/geometries/concepts/multi_polygon_concept.hpp index b13d330f3..63de6e5bf 100644 --- a/include/boost/geometry/geometries/concepts/multi_polygon_concept.hpp +++ b/include/boost/geometry/geometries/concepts/multi_polygon_concept.hpp @@ -23,7 +23,7 @@ #include -namespace boost { namespace geometry { namespace concept +namespace boost { namespace geometry { namespace concepts { @@ -44,7 +44,7 @@ class MultiPolygon #ifndef DOXYGEN_NO_CONCEPT_MEMBERS typedef typename boost::range_value::type polygon_type; - BOOST_CONCEPT_ASSERT( (concept::Polygon) ); + BOOST_CONCEPT_ASSERT( (concepts::Polygon) ); BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept) ); @@ -72,7 +72,7 @@ class ConstMultiPolygon #ifndef DOXYGEN_NO_CONCEPT_MEMBERS typedef typename boost::range_value::type polygon_type; - BOOST_CONCEPT_ASSERT( (concept::ConstPolygon) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPolygon) ); BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept) ); @@ -85,7 +85,7 @@ public : }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_MULTI_POLYGON_CONCEPT_HPP diff --git a/include/boost/geometry/geometries/concepts/point_concept.hpp b/include/boost/geometry/geometries/concepts/point_concept.hpp index 52f8d038e..4001f4e06 100644 --- a/include/boost/geometry/geometries/concepts/point_concept.hpp +++ b/include/boost/geometry/geometries/concepts/point_concept.hpp @@ -30,7 +30,7 @@ -namespace boost { namespace geometry { namespace concept +namespace boost { namespace geometry { namespace concepts { /*! @@ -187,6 +187,6 @@ public: #endif }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POINT_CONCEPT_HPP diff --git a/include/boost/geometry/geometries/concepts/polygon_concept.hpp b/include/boost/geometry/geometries/concepts/polygon_concept.hpp index b478a2274..58b780009 100644 --- a/include/boost/geometry/geometries/concepts/polygon_concept.hpp +++ b/include/boost/geometry/geometries/concepts/polygon_concept.hpp @@ -27,7 +27,7 @@ #include -namespace boost { namespace geometry { namespace concept +namespace boost { namespace geometry { namespace concepts { /*! @@ -48,8 +48,8 @@ class Polygon typedef typename point_type::type point_type; typedef typename ring_type::type ring_type; - BOOST_CONCEPT_ASSERT( (concept::Point) ); - BOOST_CONCEPT_ASSERT( (concept::Ring) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Ring) ); //BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept) ); @@ -101,8 +101,8 @@ class ConstPolygon typedef typename point_type::type point_type; typedef typename ring_type::type ring_type; - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); - BOOST_CONCEPT_ASSERT( (concept::ConstRing) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstRing) ); ////BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept) ); @@ -130,6 +130,6 @@ public: #endif }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_POLYGON_CONCEPT_HPP diff --git a/include/boost/geometry/geometries/concepts/ring_concept.hpp b/include/boost/geometry/geometries/concepts/ring_concept.hpp index 02a36c96f..d75d42843 100644 --- a/include/boost/geometry/geometries/concepts/ring_concept.hpp +++ b/include/boost/geometry/geometries/concepts/ring_concept.hpp @@ -27,7 +27,7 @@ #include -namespace boost { namespace geometry { namespace concept +namespace boost { namespace geometry { namespace concepts { @@ -52,7 +52,7 @@ class Ring #ifndef DOXYGEN_NO_CONCEPT_MEMBERS typedef typename point_type::type point_type; - BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept) ); public : @@ -81,7 +81,7 @@ class ConstRing #ifndef DOXYGEN_NO_CONCEPT_MEMBERS typedef typename point_type::type point_type; - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); BOOST_CONCEPT_ASSERT( (boost::RandomAccessRangeConcept) ); @@ -93,7 +93,7 @@ public : #endif }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_RING_CONCEPT_HPP diff --git a/include/boost/geometry/geometries/concepts/segment_concept.hpp b/include/boost/geometry/geometries/concepts/segment_concept.hpp index 8d2d30015..6a1c80486 100644 --- a/include/boost/geometry/geometries/concepts/segment_concept.hpp +++ b/include/boost/geometry/geometries/concepts/segment_concept.hpp @@ -23,7 +23,7 @@ #include -namespace boost { namespace geometry { namespace concept +namespace boost { namespace geometry { namespace concepts { @@ -51,7 +51,7 @@ class Segment #ifndef DOXYGEN_NO_CONCEPT_MEMBERS typedef typename point_type::type point_type; - BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); template @@ -96,7 +96,7 @@ class ConstSegment typedef typename point_type::type point_type; typedef typename coordinate_type::type coordinate_type; - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); template @@ -129,7 +129,7 @@ public : }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_GEOMETRIES_CONCEPTS_SEGMENT_CONCEPT_HPP diff --git a/include/boost/geometry/geometries/linestring.hpp b/include/boost/geometry/geometries/linestring.hpp index 22c9c99de..280c4be7a 100644 --- a/include/boost/geometry/geometries/linestring.hpp +++ b/include/boost/geometry/geometries/linestring.hpp @@ -59,7 +59,7 @@ template > class linestring : public Container > { - BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); typedef Container > base_type; diff --git a/include/boost/geometry/geometries/multi_linestring.hpp b/include/boost/geometry/geometries/multi_linestring.hpp index cd08fdbe1..67003522b 100644 --- a/include/boost/geometry/geometries/multi_linestring.hpp +++ b/include/boost/geometry/geometries/multi_linestring.hpp @@ -55,7 +55,7 @@ template > class multi_linestring : public Container > { - BOOST_CONCEPT_ASSERT( (concept::Linestring) ); + BOOST_CONCEPT_ASSERT( (concepts::Linestring) ); #ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST diff --git a/include/boost/geometry/geometries/multi_point.hpp b/include/boost/geometry/geometries/multi_point.hpp index ab4cd8817..9579f4f60 100644 --- a/include/boost/geometry/geometries/multi_point.hpp +++ b/include/boost/geometry/geometries/multi_point.hpp @@ -58,7 +58,7 @@ template > class multi_point : public Container > { - BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); typedef Container > base_type; diff --git a/include/boost/geometry/geometries/multi_polygon.hpp b/include/boost/geometry/geometries/multi_polygon.hpp index 9db74b4ec..94cd92271 100644 --- a/include/boost/geometry/geometries/multi_polygon.hpp +++ b/include/boost/geometry/geometries/multi_polygon.hpp @@ -54,7 +54,7 @@ template > class multi_polygon : public Container > { - BOOST_CONCEPT_ASSERT( (concept::Polygon) ); + BOOST_CONCEPT_ASSERT( (concepts::Polygon) ); #ifndef BOOST_NO_CXX11_HDR_INITIALIZER_LIST diff --git a/include/boost/geometry/geometries/pointing_segment.hpp b/include/boost/geometry/geometries/pointing_segment.hpp index 2c4284d10..f865a8a8c 100644 --- a/include/boost/geometry/geometries/pointing_segment.hpp +++ b/include/boost/geometry/geometries/pointing_segment.hpp @@ -44,8 +44,8 @@ class pointing_segment typename boost::mpl::if_ < boost::is_const, - concept::Point, - concept::ConstPoint + concepts::Point, + concepts::ConstPoint > ) ); diff --git a/include/boost/geometry/geometries/polygon.hpp b/include/boost/geometry/geometries/polygon.hpp index 5e6064e89..5d8a0f21f 100644 --- a/include/boost/geometry/geometries/polygon.hpp +++ b/include/boost/geometry/geometries/polygon.hpp @@ -75,7 +75,7 @@ template > class polygon { - BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); public: diff --git a/include/boost/geometry/geometries/ring.hpp b/include/boost/geometry/geometries/ring.hpp index 01bcf58cf..fda0be40b 100644 --- a/include/boost/geometry/geometries/ring.hpp +++ b/include/boost/geometry/geometries/ring.hpp @@ -63,7 +63,7 @@ template > class ring : public Container > { - BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); typedef Container > base_type; diff --git a/include/boost/geometry/geometries/segment.hpp b/include/boost/geometry/geometries/segment.hpp index af406aa09..aeb275b85 100644 --- a/include/boost/geometry/geometries/segment.hpp +++ b/include/boost/geometry/geometries/segment.hpp @@ -45,7 +45,7 @@ namespace model template class segment : public std::pair { - BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); public : @@ -89,8 +89,8 @@ class referring_segment typename boost::mpl::if_ < boost::is_const, - concept::Point, - concept::ConstPoint + concepts::Point, + concepts::ConstPoint > ) ); diff --git a/include/boost/geometry/index/detail/algorithms/bounds.hpp b/include/boost/geometry/index/detail/algorithms/bounds.hpp index 4d2416e98..a62fda070 100644 --- a/include/boost/geometry/index/detail/algorithms/bounds.hpp +++ b/include/boost/geometry/index/detail/algorithms/bounds.hpp @@ -44,7 +44,7 @@ struct bounds template inline void bounds(Geometry const& g, Bounds & b) { - concept::check_concepts_and_equal_dimensions(); + concepts::check_concepts_and_equal_dimensions(); dispatch::bounds::apply(g, b); } diff --git a/include/boost/geometry/io/dsv/write.hpp b/include/boost/geometry/io/dsv/write.hpp index f39a2489a..f74ae7f95 100644 --- a/include/boost/geometry/io/dsv/write.hpp +++ b/include/boost/geometry/io/dsv/write.hpp @@ -418,7 +418,7 @@ inline detail::dsv::dsv_manipulator dsv(Geometry const& geometry , std::string const& list_separator = ", " ) { - concept::check(); + concepts::check(); return detail::dsv::dsv_manipulator(geometry, detail::dsv::dsv_settings(coordinate_separator, diff --git a/include/boost/geometry/io/io.hpp b/include/boost/geometry/io/io.hpp index 934006077..caafccf2b 100644 --- a/include/boost/geometry/io/io.hpp +++ b/include/boost/geometry/io/io.hpp @@ -47,7 +47,7 @@ struct read template inline void read(Geometry& geometry, std::string const& wkt) { - geometry::concept::check(); + geometry::concepts::check(); dispatch::read::apply(geometry, wkt); } diff --git a/include/boost/geometry/io/svg/svg_mapper.hpp b/include/boost/geometry/io/svg/svg_mapper.hpp index f492f07cb..6302fd43b 100644 --- a/include/boost/geometry/io/svg/svg_mapper.hpp +++ b/include/boost/geometry/io/svg/svg_mapper.hpp @@ -45,28 +45,20 @@ #include -// Helper geometries (all points are transformed to integer-points) +// Helper geometries (all points are transformed to svg-points) #include namespace boost { namespace geometry { -#ifndef DOXYGEN_NO_DETAIL -namespace detail { namespace svg -{ - typedef model::point svg_point_type; -}} -#endif - #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { - -template +template struct svg_map { BOOST_MPL_ASSERT_MSG @@ -77,26 +69,26 @@ struct svg_map }; -template -struct svg_map +template +struct svg_map { template static inline void apply(std::ostream& stream, - std::string const& style, int size, + std::string const& style, double size, Point const& point, TransformStrategy const& strategy) { - detail::svg::svg_point_type ipoint; + SvgPoint ipoint; geometry::transform(point, ipoint, strategy); stream << geometry::svg(ipoint, style, size) << std::endl; } }; -template +template struct svg_map_box_seg { template static inline void apply(std::ostream& stream, - std::string const& style, int size, + std::string const& style, double size, BoxSeg1 const& box_seg, TransformStrategy const& strategy) { BoxSeg2 ibox_seg; @@ -111,23 +103,23 @@ struct svg_map_box_seg } }; -template -struct svg_map - : svg_map_box_seg > +template +struct svg_map + : svg_map_box_seg, SvgPoint> {}; -template -struct svg_map - : svg_map_box_seg > +template +struct svg_map + : svg_map_box_seg, SvgPoint> {}; -template +template struct svg_map_range { template static inline void apply(std::ostream& stream, - std::string const& style, int size, + std::string const& style, double size, Range1 const& range, TransformStrategy const& strategy) { Range2 irange; @@ -136,35 +128,35 @@ struct svg_map_range } }; -template -struct svg_map - : svg_map_range > +template +struct svg_map + : svg_map_range, SvgPoint> {}; -template -struct svg_map - : svg_map_range > +template +struct svg_map + : svg_map_range, SvgPoint> {}; -template -struct svg_map +template +struct svg_map { template static inline void apply(std::ostream& stream, - std::string const& style, int size, + std::string const& style, double size, Polygon const& polygon, TransformStrategy const& strategy) { - model::polygon ipoly; + model::polygon ipoly; geometry::transform(polygon, ipoly, strategy); stream << geometry::svg(ipoly, style, size) << std::endl; } }; -template -struct svg_map +template +struct svg_map { typedef typename single_tag_of < @@ -173,7 +165,7 @@ struct svg_map template static inline void apply(std::ostream& stream, - std::string const& style, int size, + std::string const& style, double size, Multi const& multi, TransformStrategy const& strategy) { for (typename boost::range_iterator::type it @@ -184,20 +176,21 @@ struct svg_map svg_map < stag, - typename boost::range_value::type + typename boost::range_value::type, + SvgPoint >::apply(stream, style, size, *it, strategy); } } }; -template +template struct devarianted_svg_map { template static inline void apply(std::ostream& stream, std::string const& style, - int size, + double size, Geometry const& geometry, TransformStrategy const& strategy) { @@ -208,25 +201,26 @@ struct devarianted_svg_map typename tag::type, multi_tag >::type, - typename boost::remove_const::type + typename boost::remove_const::type, + SvgPoint >::apply(stream, style, size, geometry, strategy); } }; -template -struct devarianted_svg_map > +template +struct devarianted_svg_map > { template struct visitor: static_visitor { std::ostream& m_os; std::string const& m_style; - int m_size; + double m_size; TransformStrategy const& m_strategy; visitor(std::ostream& os, std::string const& style, - int size, + double size, TransformStrategy const& strategy) : m_os(os) , m_style(style) @@ -237,14 +231,14 @@ struct devarianted_svg_map > template inline void operator()(Geometry const& geometry) const { - devarianted_svg_map::apply(m_os, m_style, m_size, geometry, m_strategy); + devarianted_svg_map::apply(m_os, m_style, m_size, geometry, m_strategy); } }; template static inline void apply(std::ostream& stream, std::string const& style, - int size, + double size, variant const& geometry, TransformStrategy const& strategy) { @@ -257,13 +251,13 @@ struct devarianted_svg_map > #endif -template +template inline void svg_map(std::ostream& stream, - std::string const& style, int size, + std::string const& style, double size, Geometry const& geometry, TransformStrategy const& strategy) { - dispatch::devarianted_svg_map::apply(stream, style, size, - geometry, strategy); + dispatch::devarianted_svg_map::apply(stream, + style, size, geometry, strategy); } @@ -272,13 +266,22 @@ inline void svg_map(std::ostream& stream, \tparam Point Point type, for input geometries. \tparam SameScale Boolean flag indicating if horizontal and vertical scale should be the same. The default value is true +\tparam SvgCoordinateType Coordinate type of SVG points. SVG is capable to + use floating point coordinates. Therefore the default value is double \ingroup svg \qbk{[include reference/io/svg.qbk]} */ -template +template +< + typename Point, + bool SameScale = true, + typename SvgCoordinateType = double +> class svg_mapper : boost::noncopyable { + typedef model::point svg_point_type; + typedef typename geometry::select_most_precise < typename coordinate_type::type, @@ -297,7 +300,7 @@ class svg_mapper : boost::noncopyable model::box m_bounding_box; boost::scoped_ptr m_matrix; std::ostream& m_stream; - int m_width, m_height; + SvgCoordinateType m_width, m_height; std::string m_width_height; // for tag only, defaults to 2x 100% void init_matrix() @@ -334,7 +337,9 @@ public : \param height Height of the SVG map (in SVG pixels) \param width_height Optional information to increase width and/or height */ - explicit svg_mapper(std::ostream& stream, int width, int height + svg_mapper(std::ostream& stream + , SvgCoordinateType width + , SvgCoordinateType height , std::string const& width_height = "width=\"100%\" height=\"100%\"") : m_stream(stream) , m_width(width) @@ -381,10 +386,10 @@ public : */ template void map(Geometry const& geometry, std::string const& style, - int size = -1) + double size = -1.0) { init_matrix(); - svg_map(m_stream, style, size, geometry, *m_matrix); + svg_map(m_stream, style, size, geometry, *m_matrix); } /*! @@ -400,10 +405,11 @@ public : template void text(TextPoint const& point, std::string const& s, std::string const& style, - int offset_x = 0, int offset_y = 0, int lineheight = 10) + double offset_x = 0.0, double offset_y = 0.0, + double lineheight = 10.0) { init_matrix(); - detail::svg::svg_point_type map_point; + svg_point_type map_point; transform(point, map_point, *m_matrix); m_stream << " static inline void apply(std::basic_ostream& os, - Point const& p, std::string const& style, int size) + Point const& p, std::string const& style, double size) { os << "(p) << "\" cy=\"" << geometry::get<1>(p) @@ -67,7 +67,7 @@ struct svg_box { template static inline void apply(std::basic_ostream& os, - Box const& box, std::string const& style, int ) + Box const& box, std::string const& style, double) { // Prevent invisible boxes, making them >=1, using "max" BOOST_USING_STD_MAX(); @@ -91,7 +91,7 @@ struct svg_segment { template static inline void apply(std::basic_ostream& os, - Segment const& segment, std::string const& style, int) + Segment const& segment, std::string const& style, double) { typedef typename coordinate_type::type ct; ct x1 = geometry::get<0, 0>(segment); @@ -114,7 +114,7 @@ struct svg_range { template static inline void apply(std::basic_ostream& os, - Range const& range, std::string const& style, int ) + Range const& range, std::string const& style, double) { typedef typename boost::range_iterator::type iterator; @@ -142,7 +142,7 @@ struct svg_poly { template static inline void apply(std::basic_ostream& os, - Polygon const& polygon, std::string const& style, int ) + Polygon const& polygon, std::string const& style, double) { typedef typename geometry::ring_type::type ring_type; typedef typename boost::range_iterator::type iterator_type; @@ -206,7 +206,7 @@ struct svg_multi { template static inline void apply(std::basic_ostream& os, - MultiGeometry const& multi, std::string const& style, int size) + MultiGeometry const& multi, std::string const& style, double size) { for (typename boost::range_iterator::type it = boost::begin(multi); @@ -316,7 +316,7 @@ struct devarianted_svg static inline void apply(OutputStream& os, Geometry const& geometry, std::string const& style, - int size) + double size) { svg::apply(os, geometry, style, size); } @@ -330,9 +330,9 @@ struct devarianted_svg > { OutputStream& m_os; std::string const& m_style; - int m_size; + double m_size; - visitor(OutputStream& os, std::string const& style, int size) + visitor(OutputStream& os, std::string const& style, double size) : m_os(os) , m_style(style) , m_size(size) @@ -350,7 +350,7 @@ struct devarianted_svg > OutputStream& os, variant const& geometry, std::string const& style, - int size + double size ) { boost::apply_visitor(visitor(os, style, size), geometry); @@ -371,7 +371,7 @@ class svg_manipulator { public: - inline svg_manipulator(Geometry const& g, std::string const& style, int size) + inline svg_manipulator(Geometry const& g, std::string const& style, double size) : m_geometry(g) , m_style(style) , m_size(size) @@ -392,7 +392,7 @@ public: private: Geometry const& m_geometry; std::string const& m_style; - int m_size; + double m_size; }; /*! @@ -405,9 +405,10 @@ private: \ingroup svg */ template -inline svg_manipulator svg(Geometry const& geometry, std::string const& style, int size = -1) +inline svg_manipulator svg(Geometry const& geometry, + std::string const& style, double size = -1.0) { - concept::check(); + concepts::check(); return svg_manipulator(geometry, style, size); } diff --git a/include/boost/geometry/io/wkt/read.hpp b/include/boost/geometry/io/wkt/read.hpp index 7924b7028..148a5769d 100644 --- a/include/boost/geometry/io/wkt/read.hpp +++ b/include/boost/geometry/io/wkt/read.hpp @@ -894,7 +894,7 @@ struct read_wkt template inline void read_wkt(std::string const& wkt, Geometry& geometry) { - geometry::concept::check(); + geometry::concepts::check(); dispatch::read_wkt::type, Geometry>::apply(wkt, geometry); } diff --git a/include/boost/geometry/io/wkt/write.hpp b/include/boost/geometry/io/wkt/write.hpp index a556aa440..b98c894b3 100644 --- a/include/boost/geometry/io/wkt/write.hpp +++ b/include/boost/geometry/io/wkt/write.hpp @@ -501,7 +501,7 @@ private: template inline wkt_manipulator wkt(Geometry const& geometry) { - concept::check(); + concepts::check(); return wkt_manipulator(geometry); } diff --git a/include/boost/geometry/strategies/cartesian/cart_intersect.hpp b/include/boost/geometry/strategies/cartesian/cart_intersect.hpp index 9bd7475e2..0cb5d7545 100644 --- a/include/boost/geometry/strategies/cartesian/cart_intersect.hpp +++ b/include/boost/geometry/strategies/cartesian/cart_intersect.hpp @@ -182,8 +182,8 @@ struct relate_cartesian_segments RobustPoint1 const& robust_a1, RobustPoint1 const& robust_a2, RobustPoint2 const& robust_b1, RobustPoint2 const& robust_b2) { - BOOST_CONCEPT_ASSERT( (concept::ConstSegment) ); - BOOST_CONCEPT_ASSERT( (concept::ConstSegment) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstSegment) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstSegment) ); using geometry::detail::equals::equals_point_point; bool const a_is_point = equals_point_point(robust_a1, robust_a2); diff --git a/include/boost/geometry/strategies/cartesian/distance_pythagoras.hpp b/include/boost/geometry/strategies/cartesian/distance_pythagoras.hpp index 665426ecb..8a8889dc9 100644 --- a/include/boost/geometry/strategies/cartesian/distance_pythagoras.hpp +++ b/include/boost/geometry/strategies/cartesian/distance_pythagoras.hpp @@ -91,8 +91,8 @@ public : static inline typename calculation_type::type apply(Point1 const& p1, Point2 const& p2) { - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); // Calculate distance using Pythagoras // (Leave comment above for Doxygen) diff --git a/include/boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp b/include/boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp index 8a4234282..4c1b6539b 100644 --- a/include/boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp +++ b/include/boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp @@ -115,9 +115,9 @@ public : apply(Box1 const& box1, Box2 const& box2) { BOOST_CONCEPT_ASSERT - ( (concept::ConstPoint::type>) ); + ( (concepts::ConstPoint::type>) ); BOOST_CONCEPT_ASSERT - ( (concept::ConstPoint::type>) ); + ( (concepts::ConstPoint::type>) ); // Calculate distance using Pythagoras // (Leave comment above for Doxygen) diff --git a/include/boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp b/include/boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp index 0ce1d422e..8423d16a6 100644 --- a/include/boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp +++ b/include/boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp @@ -109,9 +109,9 @@ public : static inline typename calculation_type::type apply(Point const& point, Box const& box) { - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); BOOST_CONCEPT_ASSERT - ( (concept::ConstPoint::type>) ); + ( (concepts::ConstPoint::type>) ); // Calculate distance using Pythagoras // (Leave comment above for Doxygen) diff --git a/include/boost/geometry/strategies/concepts/area_concept.hpp b/include/boost/geometry/strategies/concepts/area_concept.hpp index 75821b52a..4eec6d1fc 100644 --- a/include/boost/geometry/strategies/concepts/area_concept.hpp +++ b/include/boost/geometry/strategies/concepts/area_concept.hpp @@ -18,7 +18,7 @@ #include -namespace boost { namespace geometry { namespace concept +namespace boost { namespace geometry { namespace concepts { @@ -69,7 +69,7 @@ public : }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_AREA_CONCEPT_HPP diff --git a/include/boost/geometry/strategies/concepts/centroid_concept.hpp b/include/boost/geometry/strategies/concepts/centroid_concept.hpp index f493ef681..0bbe94ba7 100644 --- a/include/boost/geometry/strategies/concepts/centroid_concept.hpp +++ b/include/boost/geometry/strategies/concepts/centroid_concept.hpp @@ -19,7 +19,7 @@ #include -namespace boost { namespace geometry { namespace concept +namespace boost { namespace geometry { namespace concepts { @@ -72,7 +72,7 @@ public : }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CENTROID_CONCEPT_HPP diff --git a/include/boost/geometry/strategies/concepts/convex_hull_concept.hpp b/include/boost/geometry/strategies/concepts/convex_hull_concept.hpp index d6e42e95a..d4295ce47 100644 --- a/include/boost/geometry/strategies/concepts/convex_hull_concept.hpp +++ b/include/boost/geometry/strategies/concepts/convex_hull_concept.hpp @@ -25,7 +25,7 @@ #include -namespace boost { namespace geometry { namespace concept +namespace boost { namespace geometry { namespace concepts { @@ -74,7 +74,7 @@ public : }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_CONVEX_HULL_CONCEPT_HPP diff --git a/include/boost/geometry/strategies/concepts/distance_concept.hpp b/include/boost/geometry/strategies/concepts/distance_concept.hpp index 6e75fa95a..0064d438d 100644 --- a/include/boost/geometry/strategies/concepts/distance_concept.hpp +++ b/include/boost/geometry/strategies/concepts/distance_concept.hpp @@ -36,7 +36,7 @@ #include -namespace boost { namespace geometry { namespace concept +namespace boost { namespace geometry { namespace concepts { @@ -206,7 +206,7 @@ public : }; -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_DISTANCE_CONCEPT_HPP diff --git a/include/boost/geometry/strategies/concepts/segment_intersect_concept.hpp b/include/boost/geometry/strategies/concepts/segment_intersect_concept.hpp index 43bcccf37..87d901eb9 100644 --- a/include/boost/geometry/strategies/concepts/segment_intersect_concept.hpp +++ b/include/boost/geometry/strategies/concepts/segment_intersect_concept.hpp @@ -20,7 +20,7 @@ #include -namespace boost { namespace geometry { namespace concept +namespace boost { namespace geometry { namespace concepts { @@ -73,6 +73,6 @@ public : -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SEGMENT_INTERSECT_CONCEPT_HPP diff --git a/include/boost/geometry/strategies/concepts/simplify_concept.hpp b/include/boost/geometry/strategies/concepts/simplify_concept.hpp index d7f596cfe..06600bafc 100644 --- a/include/boost/geometry/strategies/concepts/simplify_concept.hpp +++ b/include/boost/geometry/strategies/concepts/simplify_concept.hpp @@ -24,7 +24,7 @@ #include -namespace boost { namespace geometry { namespace concept +namespace boost { namespace geometry { namespace concepts { @@ -63,7 +63,7 @@ private : BOOST_CONCEPT_ASSERT ( - (concept::PointSegmentDistanceStrategy) + (concepts::PointSegmentDistanceStrategy) ); Strategy *str = 0; @@ -91,6 +91,6 @@ public : -}}} // namespace boost::geometry::concept +}}} // namespace boost::geometry::concepts #endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_SIMPLIFY_CONCEPT_HPP diff --git a/include/boost/geometry/strategies/concepts/within_concept.hpp b/include/boost/geometry/strategies/concepts/within_concept.hpp index 878640371..ab712ccd5 100644 --- a/include/boost/geometry/strategies/concepts/within_concept.hpp +++ b/include/boost/geometry/strategies/concepts/within_concept.hpp @@ -22,7 +22,7 @@ #include -namespace boost { namespace geometry { namespace concept +namespace boost { namespace geometry { namespace concepts { @@ -55,12 +55,12 @@ class WithinStrategyPolygonal // CHECK: apply-arguments should both fulfill point concept BOOST_CONCEPT_ASSERT ( - (concept::ConstPoint) + (concepts::ConstPoint) ); BOOST_CONCEPT_ASSERT ( - (concept::ConstPoint) + (concepts::ConstPoint) ); // CHECK: return types (result: int, apply: bool) @@ -130,12 +130,12 @@ class WithinStrategyPointBox // CHECK: apply-arguments should fulfill point/box concept BOOST_CONCEPT_ASSERT ( - (concept::ConstPoint) + (concepts::ConstPoint) ); BOOST_CONCEPT_ASSERT ( - (concept::ConstBox) + (concepts::ConstBox) ); // CHECK: return types (apply: bool) @@ -194,12 +194,12 @@ class WithinStrategyBoxBox // CHECK: apply-arguments should both fulfill box concept BOOST_CONCEPT_ASSERT ( - (concept::ConstBox) + (concepts::ConstBox) ); BOOST_CONCEPT_ASSERT ( - (concept::ConstBox) + (concepts::ConstBox) ); // CHECK: return types (apply: bool) @@ -236,7 +236,7 @@ public : #endif }; -// So now: boost::geometry::concept::within +// So now: boost::geometry::concepts::within namespace within { @@ -285,7 +285,7 @@ inline void check() } -}}}} // namespace boost::geometry::concept::within +}}}} // namespace boost::geometry::concepts::within #endif // BOOST_GEOMETRY_STRATEGIES_CONCEPTS_WITHIN_CONCEPT_HPP diff --git a/include/boost/geometry/strategies/spherical/distance_cross_track.hpp b/include/boost/geometry/strategies/spherical/distance_cross_track.hpp index 31b59e77f..7daafa4a1 100644 --- a/include/boost/geometry/strategies/spherical/distance_cross_track.hpp +++ b/include/boost/geometry/strategies/spherical/distance_cross_track.hpp @@ -367,7 +367,7 @@ public : #if !defined(BOOST_MSVC) BOOST_CONCEPT_ASSERT ( - (concept::PointDistanceStrategy) + (concepts::PointDistanceStrategy) ); #endif @@ -521,7 +521,7 @@ public : #if !defined(BOOST_MSVC) BOOST_CONCEPT_ASSERT ( - (concept::PointDistanceStrategy) + (concepts::PointDistanceStrategy) ); #endif typedef typename return_type::type return_type; diff --git a/include/boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp b/include/boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp index 59be3645f..ee805c36d 100644 --- a/include/boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp +++ b/include/boost/geometry/strategies/spherical/distance_cross_track_point_box.hpp @@ -96,7 +96,7 @@ public: #if !defined(BOOST_MSVC) BOOST_CONCEPT_ASSERT ( - (concept::PointSegmentDistanceStrategy + (concepts::PointSegmentDistanceStrategy < Strategy, Point, typename point_type::type >) diff --git a/include/boost/geometry/strategies/spherical/intersection.hpp b/include/boost/geometry/strategies/spherical/intersection.hpp index 2e113384b..4ffc853aa 100644 --- a/include/boost/geometry/strategies/spherical/intersection.hpp +++ b/include/boost/geometry/strategies/spherical/intersection.hpp @@ -161,8 +161,8 @@ struct relate_spherical_segments RobustPolicy const&, Point1 const& a1, Point1 const& a2, Point2 const& b1, Point2 const& b2) { - BOOST_CONCEPT_ASSERT( (concept::ConstSegment) ); - BOOST_CONCEPT_ASSERT( (concept::ConstSegment) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstSegment) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstSegment) ); // TODO: check only 2 first coordinates here? using geometry::detail::equals::equals_point_point; diff --git a/include/boost/geometry/util/for_each_coordinate.hpp b/include/boost/geometry/util/for_each_coordinate.hpp index 7a1f55b00..fb1e31856 100644 --- a/include/boost/geometry/util/for_each_coordinate.hpp +++ b/include/boost/geometry/util/for_each_coordinate.hpp @@ -66,7 +66,7 @@ struct coordinates_scanner template inline void for_each_coordinate(Point& point, Op operation) { - BOOST_CONCEPT_ASSERT( (concept::Point) ); + BOOST_CONCEPT_ASSERT( (concepts::Point) ); typedef typename detail::coordinates_scanner < @@ -79,7 +79,7 @@ inline void for_each_coordinate(Point& point, Op operation) template inline Op for_each_coordinate(Point const& point, Op operation) { - BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); typedef typename detail::coordinates_scanner < diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f8c1eac84..173284fa3 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -27,6 +27,7 @@ build-project concepts ; build-project geometries ; build-project arithmetic ; build-project algorithms ; +build-project formulas ; build-project iterators ; build-project strategies ; build-project policies ; diff --git a/test/algorithms/buffer/buffer_linestring.cpp b/test/algorithms/buffer/buffer_linestring.cpp index 395167490..3b27d1af1 100644 --- a/test/algorithms/buffer/buffer_linestring.cpp +++ b/test/algorithms/buffer/buffer_linestring.cpp @@ -285,10 +285,10 @@ void test_all() test_one("mysql_report_2015_09_08a", mysql_report_2015_09_08a, join_round32, end_round32, 0.0, 1.0); test_one("mysql_report_2015_09_08b", mysql_report_2015_09_08b, join_round32, end_round32, 0.0, 1099511627778.0); test_one("mysql_report_2015_09_08c", mysql_report_2015_09_08c, join_round32, end_round32, 0.0, 0xbe); +#endif test_one("mysql_23023665_1", mysql_23023665, join_round32, end_flat, 459.1051, 10); - test_one("mysql_23023665_2", mysql_23023665, join_round32, end_flat, 6877.6941, 50); -#endif + test_one("mysql_23023665_2", mysql_23023665, join_round32, end_flat, 6877.7097, 50); } template diff --git a/test/algorithms/buffer/buffer_multi_polygon.cpp b/test/algorithms/buffer/buffer_multi_polygon.cpp index 91a806258..b473c4601 100644 --- a/test/algorithms/buffer/buffer_multi_polygon.cpp +++ b/test/algorithms/buffer/buffer_multi_polygon.cpp @@ -473,9 +473,12 @@ void test_all() test_one("rt_u8", rt_u8, join_miter, end_flat, 70.9142, 1.0); test_one("rt_u9", rt_u9, join_miter, end_flat, 59.3063, 1.0); - test_one("rt_u10", rt_u10, join_miter, end_flat, 144.0858, 1.0); - test_one("rt_u10_50", rt_u10, join_miter, end_flat, 0.2145, -0.50); - test_one("rt_u10_25", rt_u10, join_miter, end_flat, 9.6682, -0.25); + test_one("rt_u10", rt_u10, join_miter, end_flat, 144.0858, 1.0); // PG: 144.085786772487 + test_one("rt_u10_51", rt_u10, join_miter, end_flat, 0.1674, -0.51); // PG: 0.167380307629637 + // TODO: now one small triangle missing due to clusters/uu turns + test_one("rt_u10_50", rt_u10, join_miter, end_flat, 0.2145, -0.50); // PG: 0.214466094067263 + test_one("rt_u10_45", rt_u10, join_miter, end_flat, 1.3000, -0.45); // PG: 1.30004221251301 + test_one("rt_u10_25", rt_u10, join_miter, end_flat, 9.6682, -0.25); // PG: 9.66820888343117 test_one("rt_u11", rt_u11, join_miter, end_flat, 131.3995, 1.0); test_one("rt_u11_50", rt_u11, join_miter, end_flat, 0.04289, -0.50); diff --git a/test/algorithms/buffer/buffer_polygon.cpp b/test/algorithms/buffer/buffer_polygon.cpp index 4769cd951..3bb61f192 100644 --- a/test/algorithms/buffer/buffer_polygon.cpp +++ b/test/algorithms/buffer/buffer_polygon.cpp @@ -510,7 +510,7 @@ void test_all() // Tickets test_one("ticket_10398_1_5", ticket_10398_1, join_miter, end_flat, 494.7192, 0.5, -999, false); test_one("ticket_10398_1_25", ticket_10398_1, join_miter, end_flat, 697.7798, 2.5, -999, false); - test_one("ticket_10398_1_84", ticket_10398_1, join_miter, end_flat, 1470.8096, 8.4, -999, false); + test_one("ticket_10398_1_84", ticket_10398_1, join_miter, end_flat, 1470.8096, 8.4, -999, false, 0.02); // qcc-arm reports 1470.79863681712281 test_one("ticket_10398_2_45", ticket_10398_2, join_miter, end_flat, 535.4780, 4.5, -999, false); test_one("ticket_10398_2_62", ticket_10398_2, join_miter, end_flat, 705.2046, 6.2, -999, false); diff --git a/test/algorithms/distance/distance.cpp b/test/algorithms/distance/distance.cpp index 2f9c74c39..76471557f 100644 --- a/test/algorithms/distance/distance.cpp +++ b/test/algorithms/distance/distance.cpp @@ -76,7 +76,7 @@ void test_distance_point() { // Test custom strategy - BOOST_CONCEPT_ASSERT( (bg::concept::PointDistanceStrategy) ); + BOOST_CONCEPT_ASSERT( (bg::concepts::PointDistanceStrategy) ); typedef typename services::return_type::type cab_return_type; BOOST_MPL_ASSERT((boost::is_same::type>)); diff --git a/test/algorithms/overlay/handle_touch.cpp b/test/algorithms/overlay/handle_touch.cpp deleted file mode 100644 index a39b26197..000000000 --- a/test/algorithms/overlay/handle_touch.cpp +++ /dev/null @@ -1,516 +0,0 @@ -// Boost.Geometry (aka GGL, Generic Geometry Library) -// Unit Test - -// Copyright (c) 2015 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) - -#define BOOST_GEOMETRY_DEBUG_IDENTIFIER -#define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER - -//#define BOOST_GEOMETRY_DEBUG_HANDLE_TOUCH - - -#include -#include -#include -#include -#include - - -#include - - -#include -#include -#include - -#include -#include -#include - -#include - -#include - -#include -#include -#include - -#include - -#include - - -#if defined(TEST_WITH_SVG) -# include -#endif - -#include -#include - - -namespace detail -{ - -template -< - typename G1, typename G2, - bg::detail::overlay::operation_type Direction, - bool Reverse1, bool Reverse2 - > -struct test_handle_touch -{ - - static void apply(std::string const& case_id, - std::size_t expected_traverse, - std::size_t expected_skipped, - std::size_t expected_start, - G1 const& g1, G2 const& g2) - { - - typedef typename bg::strategy::side::services::default_strategy - < - typename bg::cs_tag::type - >::type side_strategy_type; - - typedef typename bg::point_type::type point_type; - typedef typename bg::rescale_policy_type::type - rescale_policy_type; - - rescale_policy_type rescale_policy - = bg::get_rescale_policy(g1, g2); - - typedef bg::detail::overlay::traversal_turn_info - < - point_type, - typename bg::segment_ratio_type::type - > turn_info; - std::vector turns; - - bg::detail::get_turns::no_interrupt_policy policy; - bg::get_turns(g1, g2, rescale_policy, turns, policy); - bg::enrich_intersection_points(turns, - Direction == 1 ? bg::detail::overlay::operation_union - : bg::detail::overlay::operation_intersection, - g1, g2, rescale_policy, side_strategy_type()); - - typedef bg::model::ring::type> ring_type; - typedef std::vector out_vector; - -#ifdef BOOST_GEOMETRY_DEBUG_HANDLE_TOUCH - std::cout << "*** Case: " << case_id << std::endl; -#endif - - bg::detail::overlay::handle_touch(Direction, turns); - - // Check number of resulting u/u turns - - std::size_t uu_traverse = 0; - std::size_t uu_skipped = 0; - std::size_t uu_start = 0; - BOOST_FOREACH(turn_info const& turn, turns) - { - if (turn.both(bg::detail::overlay::operation_union)) - { - if (turn.switch_source) - { - uu_traverse++; - } - else - { - uu_skipped++; - } - if (turn.selectable_start) - { - uu_start++; - } - } - } - - BOOST_CHECK_MESSAGE(expected_traverse == uu_traverse, - "handle_touch: " << case_id - << " traverse expected: " << expected_traverse - << " detected: " << uu_traverse - << " type: " << string_from_type - ::type>::name()); - BOOST_CHECK_MESSAGE(expected_skipped == uu_skipped, - "handle_touch: " << case_id - << " skipped expected: " << expected_skipped - << " detected: " << uu_skipped - << " type: " << string_from_type - ::type>::name()); - BOOST_CHECK_MESSAGE(expected_start == uu_start, - "handle_touch: " << case_id - << " start expected: " << expected_start - << " detected: " << uu_skipped - << " type: " << string_from_type - ::type>::name()); - -#if defined(TEST_WITH_SVG) - { - std::ostringstream filename; - filename << "handle_touch" - << "_" << case_id - << "_" << string_from_type::type>::name() - << ".svg"; - - std::ofstream svg(filename.str().c_str()); - - bg::svg_mapper::type> mapper(svg, 500, 500); - mapper.add(g1); - mapper.add(g2); - - // Input shapes in green/blue - mapper.map(g1, "fill-opacity:0.5;fill:rgb(153,204,0);" - "stroke:rgb(153,204,0);stroke-width:3"); - mapper.map(g2, "fill-opacity:0.3;fill:rgb(51,51,153);" - "stroke:rgb(51,51,153);stroke-width:3"); - - - // turn points in orange, + enrichment/traversal info - typedef typename bg::coordinate_type::type coordinate_type; - - // Simple map to avoid two texts at same place (note that can still overlap!) - std::map, int> offsets; - int index = 0; - int const margin = 5; - - BOOST_FOREACH(turn_info const& turn, turns) - { - int lineheight = 8; - mapper.map(turn.point, "fill:rgb(255,128,0);" - "stroke:rgb(0,0,0);stroke-width:1", 3); - - { - coordinate_type half = 0.5; - coordinate_type ten = 10; - // Map characteristics - // Create a rounded off point - std::pair p - = std::make_pair( - boost::numeric_cast(half - + ten * bg::get<0>(turn.point)), - boost::numeric_cast(half - + ten * bg::get<1>(turn.point)) - ); - - std::string color = "fill:rgb(0,0,0);"; - std::string fontsize = "font-size:8px;"; - - if (turn.both(bg::detail::overlay::operation_union)) - { - // Adapt color to give visual feedback in SVG - if (turn.switch_source && turn.selectable_start) - { - color = "fill:rgb(0,0,255);"; // blue - } - else if (turn.switch_source) - { - color = "fill:rgb(0,128,0);"; // green - } - else - { - color = "fill:rgb(255,0,0);"; // red - } - } - else if (turn.discarded) - { - color = "fill:rgb(92,92,92);"; - fontsize = "font-size:6px;"; - lineheight = 6; - } - const std::string style = color + fontsize + "font-family:Arial;"; - - { - std::ostringstream out; - out << index - << ": " << bg::method_char(turn.method) - << std::endl - << "op: " << bg::operation_char(turn.operations[0].operation) - << " / " << bg::operation_char(turn.operations[1].operation) - << std::endl; - - if (turn.operations[0].enriched.next_ip_index != -1) - { - out << "ip: " << turn.operations[0].enriched.next_ip_index; - } - else - { - out << "vx: " << turn.operations[0].enriched.travels_to_vertex_index - << " -> ip: " << turn.operations[0].enriched.travels_to_ip_index; - } - out << " / "; - if (turn.operations[1].enriched.next_ip_index != -1) - { - out << "ip: " << turn.operations[1].enriched.next_ip_index; - } - else - { - out << "vx: " << turn.operations[1].enriched.travels_to_vertex_index - << " -> ip: " << turn.operations[1].enriched.travels_to_ip_index; - } - - out << std::endl; - - - - offsets[p] += lineheight; - int offset = offsets[p]; - offsets[p] += lineheight * 3; - mapper.text(turn.point, out.str(), style, margin, offset, lineheight); - } - index++; - } - } - } -#endif - } -}; -} - -template -< - typename G1, typename G2, - bg::detail::overlay::operation_type Direction, - bool Reverse1 = false, - bool Reverse2 = false - > -struct test_handle_touch -{ - typedef detail::test_handle_touch - < - G1, G2, Direction, Reverse1, Reverse2 - > detail_test_handle_touch; - - inline static void apply(std::string const& case_id, - std::size_t expected_traverse, - std::size_t expected_skipped, - std::size_t expected_start, - std::string const& wkt1, std::string const& wkt2) - { - if (wkt1.empty() || wkt2.empty()) - { - return; - } - - G1 g1; - bg::read_wkt(wkt1, g1); - - G2 g2; - bg::read_wkt(wkt2, g2); - - bg::correct(g1); - bg::correct(g2); - - detail_test_handle_touch::apply(case_id, - expected_traverse, - expected_skipped, - expected_start, - g1, g2); - - } -}; - -template -void test_geometries() -{ - namespace ov = bg::detail::overlay; - - typedef test_handle_touch - < - Polygon, Polygon, - ov::operation_union - > test_union; - - test_union::apply("case_36", 1, 0, 0, case_36[0], case_36[1]); - test_union::apply("case_80", 1, 0, 0, case_80[0], case_80[1]); - test_union::apply("case_81", 1, 0, 0, case_81[0], case_81[1]); - test_union::apply("case_82", 0, 2, 0, case_82[0], case_82[1]); - test_union::apply("case_83", 2, 0, 1, case_83[0], case_83[1]); - test_union::apply("case_84", 0, 3, 0, case_84[0], case_84[1]); - test_union::apply("case_85", 1, 0, 0, case_85[0], case_85[1]); -} - - -template -void test_multi_geometries() -{ - namespace ov = bg::detail::overlay; - - typedef test_handle_touch - < - MultiPolygon, MultiPolygon, - ov::operation_union - > test_union; - - test_union::apply - ( - "uu_case_1", 0, 1, 0, - "MULTIPOLYGON(((4 0,2 2,4 4,6 2,4 0)))", - "MULTIPOLYGON(((4 4,2 6,4 8,6 6,4 4)))" - ); - test_union::apply - ( - "uu_case_2", 0, 2, 0, - "MULTIPOLYGON(((0 0,0 2,2 4,4 2,6 4,8 2,8 0,0 0)))", - "MULTIPOLYGON(((0 8,8 8,8 6,6 4,4 6,2 4,0 6,0 8)))" - ); - - // Provided by Menelaos (1) - test_union::apply - ( - "uu_case_3", 0, 2, 0, - "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)),((15 5,15 10,20 10,20 5,15 5)))", - "MULTIPOLYGON(((10 0,15 5,15 0,10 0)),((10 5,10 10,15 10,15 5,10 5)))" - ); - // Provided by Menelaos (2) - test_union::apply - ( - "uu_case_4", 1, 0, 0, - "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)),((15 5,15 10,20 10,20 5,15 5)))", - "MULTIPOLYGON(((10 0,15 5,20 5,20 0,10 0)),((10 5,10 10,15 10,15 5,10 5)))" - ); - - // Mailed by Barend - test_union::apply - ( - "uu_case_5", 1, 0, 0, - "MULTIPOLYGON(((4 0,2 2,4 4,6 2,4 0)),((4 6,6 8,8 6,6 4,4 6)))", - "MULTIPOLYGON(((4 4,2 6,4 8,6 6,4 4)),((4 2,7 6,8 3,4 2)))" - ); - - // Formerly referred to as a - test_union::apply - ( - "uu_case_6", 2, 0, 0, - "MULTIPOLYGON(((4 8,4 10,6 10,6 8,4 8)),((7 7,7 11,10 11,10 7,7 7)))", - "MULTIPOLYGON(((6 6,6 8,8 8,8 6,6 6)),((6 10,6 12,8 12,8 10,6 10)),((9 9,11 9,11 2,3 2,3 9,5 9,5 3,9 3,9 9)))" - ); - // Should result in 1 polygon with 2 holes - // "POLYGON((4 9,4 10,6 10,6 12,8 12,8 11,10 11,10 9,11 9,11 2,3 2,3 9,4 9),(6 10,6 8,7 8,7 10,6 10),(6 8,5 8,5 3,9 3,9 7,8 7,8 6,6 6,6 8))" - - // Formerly referred to as b - test_union::apply - ( - "uu_case_7", 0, 2, 0, - "MULTIPOLYGON(((4 8,4 10,6 10,6 8,4 8)),((7 7,7 11,10 11,10 7,7 7)))", - "MULTIPOLYGON(((6 6,6 8,8 8,8 6,6 6)),((6 10,6 12,8 12,8 10,6 10)))" - ); - // Should result in 2 polygons - // "MULTIPOLYGON(((4 8,4 10,6 10,6 8,4 8)),((7 8,7 10,6 10,6 12,8 12,8 11,10 11,10 7,8 7,8 6,6 6,6 8,7 8)))" - - // Formerly referred to as c - test_union::apply - ( - "uu_case_8", 0, 4, 0, - "MULTIPOLYGON(((4 8,4 10,6 10,6 8,4 8)),((8 8,8 10,10 10,10 8,8 8)),((7 11,7 13,13 13,13 5,7 5,7 7,11 7,11 11,7 11)))", - "MULTIPOLYGON(((6 6,6 8,8 8,8 6,6 6)),((6 10,6 12,8 12,8 10,6 10)))" - ); - - // Shoud result in 3 polygons: - // "MULTIPOLYGON(((4 8,4 10,6 10,6 8,4 8)),((8 8,8 10,10 10,10 8,8 8)),((7 12,7 13,13 13,13 5,7 5,7 6,6 6,6 8,8 8,8 7,11 7,11 11,8 11,8 10,6 10,6 12,7 12)))" - - // Formerly referred to as d - test_union::apply - ( - "uu_case_9", 0, 2, 0, - "MULTIPOLYGON(((2 4,2 6,4 6,4 4,2 4)),((6 4,6 6,8 6,8 4,6 4)),((1 0,1 3,9 3,9 0,1 0)))", - "MULTIPOLYGON(((0 2,0 4,2 4,2 2,0 2)),((8 2,8 4,10 4,10 2,8 2)),((3 5,3 7,7 7,7 5,3 5)))" - ); - // Should result in 2 polygons: - // "MULTIPOLYGON(((2 4,2 6,3 6,3 7,7 7,7 6,8 6,8 4,6 4,6 5,4 5,4 4,2 4)),((1 0,1 2,0 2,0 4,2 4,2 3,8 3,8 4,10 4,10 2,9 2,9 0,1 0)))" - - // With a c/c turn - test_union::apply - ( - "uu_case_10", 1, 0, 0, - "MULTIPOLYGON(((6 4,6 9,9 9,9 6,11 6,11 4,6 4)),((10 7,10 10,12 10,12 7,10 7)))", - "MULTIPOLYGON(((10 5,10 8,12 8,12 5,10 5)),((6 10,8 12,10 10,8 8,6 10)))" - ); - - // With c/c turns in both involved polygons - test_union::apply - ( - "uu_case_11", 1, 0, 0, - "MULTIPOLYGON(((7 4,7 8,9 8,9 6,11 6,11 4,7 4)),((10 7,10 10,12 10,12 7,10 7)))", - "MULTIPOLYGON(((10 5,10 8,12 8,12 5,10 5)),((7 7,7 10,10 10,9 9,9 7,7 7)))" - ); - - // Same but here c/c not directly involved in the turns itself - // (This one breaks if continue is not checked in handle_touch) - test_union::apply - ( - "uu_case_12", 1, 0, 0, - "MULTIPOLYGON(((10 8,10 10,12 10,12 8,10 8)),((10 4,10 7,12 7,12 4,10 4)),((7 5,7 8,9 8,9 5,7 5)))", - "MULTIPOLYGON(((7 3,7 6,9 6,9 5,11 5,11 3,7 3)),((10 6,10 9,12 9,12 6,10 6)),((7 7,7 10,10 10,9 9,9 7,7 7)))" - ); - - test_union::apply - ( - "case_62_multi", 0, 1, 0, case_62_multi[0], case_62_multi[1] - ); - test_union::apply - ( - "case_63_multi", 0, 1, 0, case_63_multi[0], case_63_multi[1] - ); - test_union::apply - ( - "case_65_multi", 0, 2, 0, case_65_multi[0], case_65_multi[1] - ); - test_union::apply - ( - "case_66_multi", 0, 2, 0, case_66_multi[0], case_66_multi[1] - ); - test_union::apply - ( - "case_75_multi", 0, 4, 0, case_75_multi[0], case_75_multi[1] - ); - test_union::apply - ( - "case_76_multi", 0, 5, 0, case_76_multi[0], case_76_multi[1] - ); - test_union::apply - ( - "case_101_multi", 2, 0, 0, case_101_multi[0], case_101_multi[1] - ); - test_union::apply - ( - "case_108_multi", 0, 0, 0, case_108_multi[0], case_108_multi[1] - ); - - // NOTE: this result is still to be checked - test_union::apply - ( - "case_recursive_boxes_3", 8, 18, 0, - case_recursive_boxes_3[0], case_recursive_boxes_3[1] - ); - -} - - -template -void test_all() -{ - typedef bg::model::point point_type; - - test_multi_geometries - < - bg::model::multi_polygon - < - bg::model::polygon - > - >(); - - test_geometries >(); -} - - -int test_main(int, char* []) -{ - test_all(); - - return 0; -} diff --git a/test/algorithms/overlay/multi_overlay_cases.hpp b/test/algorithms/overlay/multi_overlay_cases.hpp index 531623915..4909d93e6 100644 --- a/test/algorithms/overlay/multi_overlay_cases.hpp +++ b/test/algorithms/overlay/multi_overlay_cases.hpp @@ -332,7 +332,7 @@ static std::string case_101_multi[2] = { // interior ring / union "MULTIPOLYGON(((7 2,7 3,8 2,7 2)),((9 3,9 4,10 3,9 3)),((10 1,10 0,8 0,8 1,9 2,10 2,10 1)),((9 3,9 2,8 2,8 3,7 3,7 4,8 4,9 3)),((8 4,8 7,9 6,9 4,8 4)))", - "MULTIPOLYGON(((6 1,5 1,5 2,6 3,6 4,7 5,6 5,7 6,8 6,8 5,9 5,8 4,9 4,9 5,10 5,10 1,8 1,8 3,7 3,7 2,6 2,7 1,8 1,7 0,5 0,5 1,5.5 0.5,6 1),(8.5 2.5,9 2,9 3,8.5 2.5)))" + "MULTIPOLYGON(((5 1,5 2,6 3,6 4,7 5,6 5,7 6,8 6,8 5,9 5,10 5,10 1,8 1,7 0,5 0,5 1),(9 5,8 4,9 4,9 5),(8 1,8 3,7 3,7 2,6 2,7 1,8 1),(5 1,5.5 0.5,6 1,5 1),(8.5 2.5,9 2,9 3,8.5 2.5)))" }; static std::string case_102_multi[4] = @@ -349,7 +349,7 @@ static std::string case_102_multi[4] = static std::string case_103_multi[2] = { // interior ring 'fit' (ix) / union / assemble - "MULTIPOLYGON(((0 0,0 5,5 5,5 0,2 0,2 1,3 1,3 2,2 2,2 3,1 2,2 2,2 1,1 0,0 0)))", + "MULTIPOLYGON(((0 0,0 5,5 5,5 0,2 0,2 1,1 0,0 0),(2 1,3 1,3 2,2 2,2 1),(2 2,2 3,1 2,2 2)))", "MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0),(2 1,2 2,1 1,2 1)))" }; @@ -364,14 +364,15 @@ static std::string case_105_multi[2] = { // interior ring 'fit' () / union / assemble "MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0),(2 2,3 2,3 3,1 3,2 2)))", - "MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0),(1 1,2 1,2 2,1 1),(2 1,3 1,3 2,2 1),(1 3,3 3,3 4,2 3,2 4,1 4,1 3)))" + "MULTIPOLYGON(((0 0,0 5,5 5,5 0,0 0),(1 1,2 1,2 2,1 1),(2 1,3 1,3 2,2 1),(1 3,2 3,2 4,1 4,1 3),(2 3,3 3,3 4,2 3)))" }; static std::string case_106_multi[2] = { // interior ring 'fit' () / union / assemble - "MULTIPOLYGON(((0 0,0 3,1 2,1 3,2 3,2 1,3 2,2 2,3 3,2 3,3 4,1 4,1 3,0 3,0 5,5 5,5 0,0 0)))", - "MULTIPOLYGON(((0 0,0 5,1 5,1 4,2 4,2 5,3 5,3 3,4 4,5 4,5 0,2 0,3 1,2 1,2 3,1 3,2 2,1.5 1.5,2 1,1 1,0 0)),((1 0,2 1,2 0,1 0)))" + // [1] is reported as invalid by BG, but not by postgis + "MULTIPOLYGON(((0 0,0 3,0 5,5 5,5 0,0 0),(0 3,1 2,1 3,0 3),(1 3,2 3,3 4,1 4,1 3),(2 3,2 2,3 3,2 3),(2 2,2 1,3 2,2 2)))", + "MULTIPOLYGON(((0 0,0 5,1 5,1 4,2 4,2 5,3 5,3 3,4 4,5 4,5 0,2 0,3 1,2 1,1 1,0 0),(2 1,2 2,1.5 1.5,2 1),(2 2,2 3,1 3,2 2)),((2 0,1 0,2 1,2 0)))" }; static std::string case_107_multi[4] = @@ -385,12 +386,11 @@ static std::string case_107_multi[4] = "MULTIPOLYGON(((4 5,4 11,9 11,9 5,4 5),(5 7,6 6,6 7,7 8,8 8,8 10,7 9,6 10,6 8,5 7)))" }; -static std::string case_108_multi[3] = +static std::string case_108_multi[2] = { // Missing intersection point in [0] / [1], [0] / [2] is OK - "MULTIPOLYGON(((3 4,4 4,4 2,4 1,1 1,1 2,2 2,2.5 1.5,3 2,2 2,3 3,1 3,1 2,0 1,0 6,1 6,2 5,2 4,1 4,1.5 3.5,2 4,3 4)))", - "MULTIPOLYGON(((0 3,0 4,1 4,0 3)),((3 6,3 5,5 5,5 0,4 0,4 1,1 1,1 2,2 3,2 4,2.5 3.5,3 4,4 3,3 3,3 2,4 2,4 4,2 4,1 3,1 5,2 6,3 6)),((1 3,1 2,0 2,0 3,1 3)))", - "MULTIPOLYGON(((0 3,0 4,1 4,0 3)),((3 6,3 5,5 5,5 1, 1 1,1 2,2 3,2 4,2.5 3.5,3 4,4 3,3 3,3 2,4 2,4 4,2 4,1 3,1 5,2 6,3 6)),((1 3,1 2,0 2,0 3,1 3)))" + "MULTIPOLYGON(((1 2,0 1,0 6,1 6,2 5,2 4,3 4,4 4,4 2,4 1,1 1,1 2),(1 2,2 2,3 3,1 3,1 2),(2 2,2.5 1.5,3 2,2 2),(2 4,1 4,1.5 3.5,2 4)))", + "MULTIPOLYGON(((1 2,2 3,2 4,1 3,1 4,1 5,2 6,3 6,3 5,5 5,5 0,4 0,4 1,1 1,1 2),(2 4,2.5 3.5,3 4,2 4),(3 4,4 3,4 4,3 4),(4 3,3 3,3 2,4 2,4 3)),((0 3,1 3,1 2,0 2,0 3)),((0 3,0 4,1 4,0 3)))" }; static std::string case_109_multi[2] = @@ -405,19 +405,110 @@ static std::string case_110_multi[2] = "MULTIPOLYGON(((15 10,10 15,10 17,15 10)),((15 10,10 20,10 22,15 10)),((15 10,10 25,10 27,15 10)),((25 10,30 17,30 15,25 10)),((25 10,30 22,30 20,25 10)),((25 10,30 27,30 25,25 10)),((18 10,20 30,19 10,18 10)),((21 10,20 30,22 10,21 10)))" }; + +// Cases 111 to 122 are for testing uu-cases, validity, touch, interior rings +static std::string case_111_multi[2] = +{ + "MULTIPOLYGON(((4 0,2 2,4 4,6 2,4 0)))", + "MULTIPOLYGON(((4 4,2 6,4 8,6 6,4 4)))" +}; + +static std::string case_112_multi[2] = +{ + "MULTIPOLYGON(((0 0,0 2,2 4,4 2,6 4,8 2,8 0,0 0)))", + "MULTIPOLYGON(((0 8,8 8,8 6,6 4,4 6,2 4,0 6,0 8)))" +}; + +// Provided by Menelaos (1) +static std::string case_113_multi[2] = +{ + "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)),((15 5,15 10,20 10,20 5,15 5)))", + "MULTIPOLYGON(((10 0,15 5,15 0,10 0)),((10 5,10 10,15 10,15 5,10 5)))" +}; + +// Provided by Menelaos (2) +static std::string case_114_multi[2] = +{ + "MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0)),((15 5,15 10,20 10,20 5,15 5)))", + "MULTIPOLYGON(((10 0,15 5,20 5,20 0,10 0)),((10 5,10 10,15 10,15 5,10 5)))" +}; + +// Mailed by Barend +static std::string case_115_multi[2] = +{ + "MULTIPOLYGON(((4 0,2 2,4 4,6 2,4 0)),((4 6,6 8,8 6,6 4,4 6)))", + "MULTIPOLYGON(((4 4,2 6,4 8,6 6,4 4)),((4 2,7 6,8 3,4 2)))" +}; + +// Formerly referred to as a +// Should result in 1 polygon with 2 holes +// "POLYGON((4 9,4 10,6 10,6 12,8 12,8 11,10 11,10 9,11 9,11 2,3 2,3 9,4 9),(6 10,6 8,7 8,7 10,6 10),(6 8,5 8,5 3,9 3,9 7,8 7,8 6,6 6,6 8))" +static std::string case_116_multi[2] = +{ + "MULTIPOLYGON(((4 8,4 10,6 10,6 8,4 8)),((7 7,7 11,10 11,10 7,7 7)))", + "MULTIPOLYGON(((6 6,6 8,8 8,8 6,6 6)),((6 10,6 12,8 12,8 10,6 10)),((9 9,11 9,11 2,3 2,3 9,5 9,5 3,9 3,9 9)))" +}; + +// Formerly referred to as b +// Should result in 2 polygons +// "MULTIPOLYGON(((4 8,4 10,6 10,6 8,4 8)),((7 8,7 10,6 10,6 12,8 12,8 11,10 11,10 7,8 7,8 6,6 6,6 8,7 8)))" +static std::string case_117_multi[2] = +{ + "MULTIPOLYGON(((4 8,4 10,6 10,6 8,4 8)),((7 7,7 11,10 11,10 7,7 7)))", + "MULTIPOLYGON(((6 6,6 8,8 8,8 6,6 6)),((6 10,6 12,8 12,8 10,6 10)))" +}; + +// Formerly referred to as c +// Shoud result in 3 polygons: +// "MULTIPOLYGON(((4 8,4 10,6 10,6 8,4 8)),((8 8,8 10,10 10,10 8,8 8)),((7 12,7 13,13 13,13 5,7 5,7 6,6 6,6 8,8 8,8 7,11 7,11 11,8 11,8 10,6 10,6 12,7 12)))" +static std::string case_118_multi[2] = +{ + "MULTIPOLYGON(((4 8,4 10,6 10,6 8,4 8)),((8 8,8 10,10 10,10 8,8 8)),((7 11,7 13,13 13,13 5,7 5,7 7,11 7,11 11,7 11)))", + "MULTIPOLYGON(((6 6,6 8,8 8,8 6,6 6)),((6 10,6 12,8 12,8 10,6 10)))" +}; + +// Formerly referred to as d +// Should result in 2 polygons: +// "MULTIPOLYGON(((2 4,2 6,3 6,3 7,7 7,7 6,8 6,8 4,6 4,6 5,4 5,4 4,2 4)),((1 0,1 2,0 2,0 4,2 4,2 3,8 3,8 4,10 4,10 2,9 2,9 0,1 0)))" +static std::string case_119_multi[2] = +{ + "MULTIPOLYGON(((2 4,2 6,4 6,4 4,2 4)),((6 4,6 6,8 6,8 4,6 4)),((1 0,1 3,9 3,9 0,1 0)))", + "MULTIPOLYGON(((0 2,0 4,2 4,2 2,0 2)),((8 2,8 4,10 4,10 2,8 2)),((3 5,3 7,7 7,7 5,3 5)))" +}; + +// With a c/c turn +static std::string case_120_multi[2] = +{ + "MULTIPOLYGON(((6 4,6 9,9 9,9 6,11 6,11 4,6 4)),((10 7,10 10,12 10,12 7,10 7)))", + "MULTIPOLYGON(((10 5,10 8,12 8,12 5,10 5)),((6 10,8 12,10 10,8 8,6 10)))" +}; + +// With c/c turns in both involved polygons +static std::string case_121_multi[2] = +{ + "MULTIPOLYGON(((7 4,7 8,9 8,9 6,11 6,11 4,7 4)),((10 7,10 10,12 10,12 7,10 7)))", + "MULTIPOLYGON(((10 5,10 8,12 8,12 5,10 5)),((7 7,7 10,10 10,9 9,9 7,7 7)))" +}; + +// Same but here c/c not directly involved in the turns itself +// (This one breaks if continue is not checked in handle_touch) +static std::string case_122_multi[2] = +{ + "MULTIPOLYGON(((10 8,10 10,12 10,12 8,10 8)),((10 4,10 7,12 7,12 4,10 4)),((7 5,7 8,9 8,9 5,7 5)))", + "MULTIPOLYGON(((7 3,7 6,9 6,9 5,11 5,11 3,7 3)),((10 6,10 9,12 9,12 6,10 6)),((7 7,7 10,10 10,9 9,9 7,7 7)))" +}; + static std::string case_recursive_boxes_1[2] = { - // == 70 - // Used in blog. KEEP - "MULTIPOLYGON(((1 0,0 0,0 1,1 1,1 2,0 2,0 4,2 4,2 5,3 5,3 6,1 6,1 5,0 5,0 10,9 10,9 9,7 9,7 8,6 8,6 7,8 7,8 6,9 6,9 4,8 4,8 5,7 5,7 6,6 6,6 5,5 5,5 4,4 4,4 3,5 3,5 2,7 2,7 3,6 3,6 4,8 4,8 3,10 3,10 0,6 0,6 1,5 1,5 0,1 0),(4 7,4 9,3 9,3 7,4 7),(8 1,9 1,9 2,8 2,8 1)),((10 7,10 6,9 6,9 7,8 7,8 8,9 8,9 9,10 9,10 7)))", - "MULTIPOLYGON(((1 0,0 0,0 7,2 7,2 6,5 6,5 5,4 5,4 4,5 4,5 3,7 3,7 2,6 2,6 0,1 0),(2 1,2 2,3 2,3 3,1 3,1 1,2 1)),((7 0,7 2,10 2,10 0,9 0,9 1,8 1,8 0,7 0)),((6 4,6 6,5 6,5 7,6 7,6 8,5 8,5 7,3 7,3 9,2 9,2 8,1 8,1 10,4 10,4 9,6 9,6 10,10 10,10 9,9 9,9 8,10 8,10 6,9 6,9 5,10 5,10 3,7 3,7 4,6 4),(7 7,7 6,8 6,8 7,7 7)))" + "MULTIPOLYGON(((1 0,0 0,0 1,1 1,1 2,0 2,0 4,2 4,2 5,3 5,3 6,1 6,1 5,0 5,0 10,9 10,9 9,7 9,7 8,6 8,6 7,8 7,8 6,9 6,9 4,8 4,8 3,10 3,10 0,6 0,6 1,5 1,5 0,1 0),(8 4,8 5,7 5,7 6,6 6,6 5,5 5,5 4,4 4,4 3,5 3,5 2,7 2,7 3,6 3,6 4,8 4),(8 1,9 1,9 2,8 2,8 1),(4 7,4 9,3 9,3 7,4 7)),((9 9,10 9,10 7,10 6,9 6,9 7,8 7,8 8,9 8,9 9)))", + "MULTIPOLYGON(((5 6,5 7,3 7,3 9,2 9,2 8,1 8,1 10,4 10,4 9,6 9,6 10,10 10,10 9,9 9,9 8,10 8,10 6,9 6,9 5,10 5,10 3,7 3,7 4,6 4,6 6,5 6),(5 7,6 7,6 8,5 8,5 7),(7 7,7 6,8 6,8 7,7 7)),((1 0,0 0,0 7,2 7,2 6,5 6,5 5,4 5,4 4,5 4,5 3,7 3,7 2,6 2,6 0,1 0),(2 1,2 2,3 2,3 3,1 3,1 1,2 1)),((7 2,10 2,10 0,9 0,9 1,8 1,8 0,7 0,7 2)))" }; static std::string case_recursive_boxes_2[2] = { // Traversal problem; Many ii-cases -> formerly caused "Endless loop" // So it appears that there might be more decisions than intersection points - "MULTIPOLYGON(((1 0,0 0,0 4,1 4,1 5,0 5,0 10,3 10,3 9,4 9,4 10,6 10,6 9,5 9,5 8,6 8,6 9,7 9,7 10,10 10,10 0,1 0),(7 6,8 6,8 7,9 7,9 8,8 8,8 7,7 7,7 6),(9 1,9 2,8 2,8 1,9 1)))", + "MULTIPOLYGON(((1 0,0 0,0 4,1 4,1 5,0 5,0 10,3 10,3 9,4 9,4 10,6 10,6 9,7 9,7 10,10 10,10 0,1 0),(6 9,5 9,5 8,6 8,6 9),(7 6,8 6,8 7,7 7,7 6),(8 7,9 7,9 8,8 8,8 7),(9 1,9 2,8 2,8 1,9 1)))", "MULTIPOLYGON(((0 0,0 10,10 10,10 0,8 0,8 1,7 1,7 0,0 0),(7 3,6 3,6 2,7 2,7 3),(6 7,7 7,7 8,6 8,6 7)))" }; @@ -426,31 +517,31 @@ static std::string case_recursive_boxes_3[2] = { // Previously a iu/ux problem causing union to fail. // For CCW polygon it also reports a iu/iu problem. - // KEEP "MULTIPOLYGON(((8 3,9 4,9 3,8 3)),((5 9,5 10,6 10,5 9)),((2 0,2 1,3 0,2 0)),((2 5,2 6,3 6,3 5,2 5)),((2 2,1 2,1 3,2 3,3 2,3 1,2 1,2 2)),((6 8,7 9,7 7,8 7,7 6,6 6,6 8)),((4 6,5 7,5 6,4 6)),((4 8,4 9,5 9,5 8,4 8)),((0 3,1 4,1 3,0 3)),((8 7,9 8,9 7,8 7)),((9 6,9 7,10 7,9 6)),((7 0,8 1,8 0,7 0)),((0 4,0 5,1 5,1 4,0 4)),((4 2,5 3,5 2,4 1,4 2)),((4 10,4 9,2 9,3 10,4 10)),((5 2,6 3,7 3,7 2,6 2,6 1,5 0,5 2)),((5 3,4 3,4 4,2 4,4 6,4 5,4.5 4.5,6 6,6 5,7 4,5 4,5 3)),((10 2,9 1,9 3,10 2)),((8 4,7 4,8 5,7 5,7 6,9 6,9 5,10 5,10 4,8 4)),((1 7,0 7,0 8,1 8,1 7)),((1 10,2 10,1 9,0 9,0 10,1 10)),((6.5 9.5,7 10,7 9,6 9,6 10,6.5 9.5)),((8 8,8 9,10 9,9 8,8 8)))", - "MULTIPOLYGON(((0 7,0 8,1 8,1 7,0 7)),((5 3,4 3,4 4,6 4,6 3,7 3,6 2,5 2,5 3)),((8 2,8 3,9 2,8 2)),((1 1,2 2,2 1,1 1)),((2 1,3 1,2 0,1 0,2 1)),((2 3,3 4,3 3,2 3)),((1 9,2 8,1 8,1 9)),((2 10,2 9,1 9,1 10,2 10)),((9 7,9 8,10 8,10 7,9 7)),((6 0,6 1,7 1,7 0,6 0)),((8 0,9 1,9 0,8 0)),((1 6,1 5,0 5,1 6)),((0 2,1 1,0 1,0 2)),((1 3,2 3,2 2,1 2,1 3)),((5 1,5 0,4 0,4 1,3 1,4 2,5 2,6 1,5 1)),((1 3,0 3,0 4,1 4,1 3)),((3 6,4 5,2 5,3 6)),((9 2,10 2,10 1,9 1,9 2)),((7 5,6 4,6 5,7 6,8 6,8 5,7 5)),((7 4,8 5,8.5 4.5,9 5,9 4,8 4,8.5 3.5,9 4,10 3,7 3,7 4)),((1 6,1 7,3 7,3 8,4 7,5 7,6 8,6 10,7 9,8 10,9 10,9 9,8 9,8 8,7 8,6 7,6 6,1 6)))" + "MULTIPOLYGON(((7 3,7 4,8 5,8.5 4.5,9 5,9 4,10 3,8 3,7 3),(9 4,8 4,8.5 3.5,9 4)),((0 2,1 1,0 1,0 2)),((1 1,2 2,2 1,1 1)),((2 2,1 2,1 3,2 3,2 2)),((2 1,3 1,2 0,1 0,2 1)),((3 1,4 2,5 2,6 1,5 1,5 0,4 0,4 1,3 1)),((5 2,5 3,4 3,4 4,6 4,6 3,7 3,6 2,5 2)),((6 1,7 1,7 0,6 0,6 1)),((6 4,6 5,7 6,8 6,8 5,7 5,6 4)),((8 3,9 2,8 2,8 3)),((9 2,10 2,10 1,9 1,9 2)),((9 1,9 0,8 0,9 1)),((1 3,0 3,0 4,1 4,1 3)),((2 3,3 4,3 3,2 3)),((9 7,9 8,10 8,10 7,9 7)),((0 7,0 8,1 8,1 7,0 7)),((1 8,1 9,2 8,1 8)),((1 7,3 7,3 8,4 7,5 7,6 8,6 10,7 9,8 10,9 10,9 9,8 9,8 8,7 8,6 7,6 6,3 6,1 6,1 7)),((1 6,1 5,0 5,1 6)),((3 6,4 5,2 5,3 6)),((1 9,1 10,2 10,2 9,1 9)))" }; static std::string case_recursive_boxes_4[2] = { - // Occurred after refactoring assemble - not valid! - "MULTIPOLYGON(((9 3,10 4,10 3,9 3)),((9 9,10 10,10 9,9 9)),((0 1,0 3,1 4,0 4,0 5,1 6,0 6,0 8,1 9,1 8,2 9,2 7,1.5 6.5,2.5 5.5,3 6,3 5,4 6,2 6,2 7,3 8,2 8,3 9,0 9,0 10,6 10,5.5 9.5,6 9,6 10,7 10,7.5 9.5,8 10,8 9,7 9,7 8,6 8,6.5 7.5,7 8,8 8,8 9,9 9,9.5 8.5,10 9,10 8,9.5 7.5,10 7,10 5,8 5,8 4,7 3,7 2,8 3,8 4,9 5,9 3,10 2,10 1,8 1,8.5 0.5,9 1,10 0,4 0,4 1,3 1,3 0,1 0,1 1,0 0,0 1),(4 2,4.5 1.5,5 2,5 4,4.5 3.5,5 3,4 3,4 2),(3 3,4 4,2 4,2.5 3.5,3 4,3 3),(6 4,6.5 3.5,7 4,6 4),(5 7,5 9,4 9,4 8,5 7)))", - "MULTIPOLYGON(((1 0,2 1,2 0,1 0)),((7 9,7 10,8 10,7 9)),((1 0,0 0,0 3,1 3,2 2,2 3,1 3,1 4,2 4,2 5,1 4,0 4,0 8,1 7,1 6,2 7,1 7,1 9,0 9,0 10,7 10,6 9,6.5 8.5,7 9,8 9,9 8,8 8,9 7,9 6,10 7,10 5,9 5,9 4,10 5,10 0,7 0,8 1,7 1,6 0,3 0,3 1,1 1,1 0),(5 1,5.5 0.5,6 1,6 2,6.5 1.5,7 2,8 2,8 4,7 3,6 3,6 2,5 2,6 1,5 1),(4 4,5 4,5 5,4 4),(4 6,4 7,3 7,2 6,3 6,3 7,4 6),(6 5,6.5 4.5,7 5,6 5,7 6,7 7,6 7,6 5),(3.5 7.5,4 8,4 9,3 8,3.5 7.5)),((9 8,9 9,8 9,9 10,10 10,10 8,9 8)))" + // Occurred after refactoring assemble + "MULTIPOLYGON(((0 1,0 3,1 4,0 4,0 5,1 6,0 6,0 8,1 9,0 9,0 10,6 10,7 10,7.5 9.5,8 10,8 9,9 9,9.5 8.5,10 9,10 8,9.5 7.5,10 7,10 5,9 5,9 3,10 2,10 1,9 1,10 0,4 0,4 1,3 1,3 0,1 0,1 1,0 0,0 1),(1 9,1 8,2 9,1 9),(2 9,2 8,3 9,2 9),(2 8,2 7,3 8,2 8),(2 7,1.5 6.5,2 6,2 7),(2 6,2.5 5.5,3 6,2 6),(3 6,3 5,4 6,3 6),(6 10,5.5 9.5,6 9,6 10),(8 9,7 9,7 8,8 8,8 9),(7 8,6 8,6.5 7.5,7 8),(9 5,8 5,8 4,9 5),(8 4,7 3,7 2,8 3,8 4),(9 1,8 1,8.5 0.5,9 1),(6 4,6.5 3.5,7 4,6 4),(4 2,4.5 1.5,5 2,5 3,4 3,4 2),(5 3,5 4,4.5 3.5,5 3),(5 7,5 9,4 9,4 8,5 7),(3 3,4 4,3 4,3 3),(3 4,2 4,2.5 3.5,3 4)),((9 3,10 4,10 3,9 3)),((10 9,9 9,10 10,10 9)))", + "MULTIPOLYGON(((1 0,0 0,0 3,1 3,1 4,0 4,0 8,1 7,1 9,0 9,0 10,7 10,6 9,6.5 8.5,7 9,8 9,9 8,8 8,9 7,9 6,10 7,10 5,10 0,7 0,8 1,7 1,6 0,3 0,3 1,2 1,1 1,1 0),(1 3,2 2,2 3,1 3),(1 4,2 4,2 5,1 4),(1 7,1 6,2 7,1 7),(10 5,9 5,9 4,10 5),(5 1,5.5 0.5,6 1,5 1),(6 1,6 2,5 2,6 1),(6 2,6.5 1.5,7 2,8 2,8 4,7 3,6 3,6 2),(6 5,7 6,7 7,6 7,6 5),(6 5,6.5 4.5,7 5,6 5),(4 4,5 4,5 5,4 4),(3 7,2 6,3 6,3 7),(3 7,4 6,4 7,3 7),(3.5 7.5,4 8,4 9,3 8,3.5 7.5)),((1 0,2 1,2 0,1 0)),((7 10,8 10,7 9,7 10)),((8 9,9 10,10 10,10 8,9 8,9 9,8 9)))" }; static std::string case_recursive_boxes_5[2] = { // Occurs after refactoring uu / handle_touch (not yet integrated) "MULTIPOLYGON(((0 9,0 10,1 10,1 9,0 9)),((9 0,9 1,10 1,10 0,9 0)),((5 6,5 7,6 7,6 6,7 6,7 4,6 4,6 5,5 5,5 6)),((5 3,7 3,7 2,4 2,4 3,5 3)),((5 8,5 9,7 9,7 8,5 8)),((4 0,1 0,1 1,5 1,5 0,4 0)),((3 5,3 4,4 4,4 3,2 3,2 2,1 2,1 3,0 3,0 4,2 4,2 5,1 5,1 6,4 6,4 5,3 5)),((0 2,1 2,1 1,0 1,0 2)),((4 10,4 7,1 7,1 6,0 6,0 8,1 8,1 9,2 9,2 10,4 10)),((9 4,9 3,8 3,8 5,9 5,9 4)),((7 2,8 2,8 0,7 0,7 2)),((8 7,10 7,10 6,7 6,7 8,8 8,8 7)))", - "MULTIPOLYGON(((2 3,2 4,3 4,3 3,2 3)),((1 5,1 6,2 6,2 5,1 5)),((2 1,2 2,3 2,3 1,2 1)),((8 1,9 1,9 0,8 0,8 1)),((9 7,10 7,10 6,9 6,9 7)),((1 4,1 3,0 3,0 5,1 5,1 4)),((7 6,7 7,8 7,8 6,7 6)),((7 1,7 2,8 2,8 1,7 1)),((6 2,6 3,7 3,7 2,6 2)),((6 8,6 9,7 9,7 8,6 8)),((5 0,3 0,3 1,4 1,4 2,6 2,6 1,7 1,7 0,5 0)),((5 5,5 6,6 6,6 5,8 5,8 6,9 6,9 4,8 4,8 3,7 3,7 4,6 4,6 3,5 3,5 4,3 4,3 6,2 6,2 8,3 8,3 7,5 7,5 6,4 6,4 5,5 5)),((1 1,2 1,2 0,1 0,1 1)),((1 3,2 3,2 2,1 2,1 3)),((3 10,4 10,4 9,2 9,2 8,0 8,0 10,3 10)),((10 3,10 1,9 1,9 2,8 2,8 3,9 3,9 4,10 4,10 3)),((9 9,10 9,10 8,9 8,9 7,8 7,8 10,9 10,9 9)))" + "MULTIPOLYGON(((2 6,2 8,3 8,3 7,5 7,5 6,6 6,6 5,8 5,8 6,9 6,9 4,8 4,8 3,7 3,7 4,6 4,6 3,5 3,5 4,3 4,3 6,2 6),(5 6,4 6,4 5,5 5,5 6)),((1 1,2 1,2 0,1 0,1 1)),((2 1,2 2,3 2,3 1,2 1)),((2 2,1 2,1 3,2 3,2 2)),((1 3,0 3,0 5,1 5,1 4,1 3)),((1 5,1 6,2 6,2 5,1 5)),((2 8,0 8,0 10,3 10,4 10,4 9,2 9,2 8)),((8 6,7 6,7 7,8 7,8 6)),((8 7,8 10,9 10,9 9,10 9,10 8,9 8,9 7,8 7)),((9 7,10 7,10 6,9 6,9 7)),((9 4,10 4,10 3,10 1,9 1,9 2,8 2,8 3,9 3,9 4)),((8 2,8 1,7 1,7 2,8 2)),((8 1,9 1,9 0,8 0,8 1)),((7 1,7 0,5 0,3 0,3 1,4 1,4 2,6 2,6 1,7 1)),((6 2,6 3,7 3,7 2,6 2)),((3 4,3 3,2 3,2 4,3 4)),((6 8,6 9,7 9,7 8,6 8)))" }; static std::string case_recursive_boxes_6[2] = { + // [1] is reported as invalid by BG, but not by postgis // Fixed by replacing handle_tangencies - "MULTIPOLYGON(((2 2,1.5 1.5,2 1,1 1,2 0,0 0,0 3,1 3,1 4,2 4,2 5,5 5,5 0,2 0,2 2,3 1,3 2,3.5 1.5,4 2,2 2)),((1 5,2 5,0 3,0 5,1 5)))", - "MULTIPOLYGON(((2 1,2 2,1 2,2 3,1 3,1 4,0 4,0 5,5 5,5 2,4 2,4 3,3 3,4 2,3 2,3 1,2 1)),((2 0,0 0,0 3,1 3,1 2,3 0,2 0)),((4 0,3 0,3 1,4 2,4 1,5 1,5 0,4 0)))" + "MULTIPOLYGON(((0 3,1 3,1 4,2 4,2 5,5 5,5 0,2 0,0 0,0 3),(2 0,2 1,1 1,2 0),(2 1,2 2,1.5 1.5,2 1),(2 2,3 1,3 2,2 2),(3 2,3.5 1.5,4 2,3 2)),((0 3,0 5,1 5,2 5,1 4,0 3)))", + "MULTIPOLYGON(((1 2,2 3,1 3,1 4,0 4,0 5,5 5,5 2,4 2,3 2,3 1,2 1,2 2,1 2),(4 2,4 3,3 3,4 2)),((1 2,2 1,3 0,2 0,0 0,0 3,1 3,1 2)),((3 0,3 1,4 2,4 1,5 1,5 0,4 0,3 0)))" }; static std::string case_recursive_boxes_7[2] = @@ -463,7 +554,7 @@ static std::string case_recursive_boxes_8[2] = { // Having colocated IP halfway segment "MULTIPOLYGON(((3 4,3 3,2 3,2 2,0 2,0 3,1 3,1 4,1.5 3.5,2 4,3 4)),((2 5,2 4,1 4,0 3,0 5,2 5)))", - "MULTIPOLYGON(((3 4,4 4,4 3,3 3,3 1,0 1,0 2,1 2,1 3,0 2,0 4,3 4)))" + "MULTIPOLYGON(((0 2,0 4,3 4,4 4,4 3,3 3,3 1,0 1,0 2),(0 2,1 2,1 3,0 2)))" }; static std::string case_recursive_boxes_9[2] = @@ -496,44 +587,63 @@ static std::string case_recursive_boxes_11[4] = }; static std::string case_recursive_boxes_12[2] = +{ + "MULTIPOLYGON(((0 3,1 3,0.5 2.5,1 2,0 2,0 3)),((1 2,2 2,2 1,1 1,1 2)),((2 1,3 2,3 1,2 1)),((2 2,2 3,3 3,2 2)),((0 0,0 1,1 0,0 0)))", + "MULTIPOLYGON(((0 1,0 2,1 2,0 1)),((0 1,1 1,1.5 0.5,2 1,2 0,0 0,0 1)),((1 3,1 4,2 3,1 2,1 3)))" +}; + +static std::string case_recursive_boxes_13[2] = +{ + "MULTIPOLYGON(((1 3,1 5,2 5,2 4,1.5 3.5,2 3,1 3)),((1 3,2 2,0 2,1 3)),((2 2,3 2,3 1,2 1,2 2)),((3 2,3 3,4 3,4 2,3 2)))", + "MULTIPOLYGON(((1 4,1 3,0 3,0 4,1 5,1 4)),((3 5,4 5,4 4,2 4,2 5,3 5)),((3 1,3 2,5 2,5 1,3 1)))" +}; + +static std::string case_recursive_boxes_14[2] = +{ + "MULTIPOLYGON(((2 2,2 3,3 2,2 2)),((2 3,3 4,3 3,2 3)),((2 3,1 3,1 4,2 4,2 3)))", + "MULTIPOLYGON(((3 3,4 4,4 3,3 3)),((1 2,2 3,2 2,1 2)),((2 1,2 2,3 1,2 1)),((1 4,1 5,2 5,2 4,1 4)))" +}; + +static std::string case_recursive_boxes_12_invalid[2] = { // One of them is invalid requiring discarding turns colocated with uu in these clusters "MULTIPOLYGON(((2 2,2 3,3 3,2 2)),((0 0,0 1,1 0,0 0)),((0 3,1 3,0.5 2.5,1 2,0 2,0 3)),((3 2,3 1,1 1,1 2,2 2,2 1,3 2)))", "MULTIPOLYGON(((0 1,0 2,1 2,0 1)),((0 1,1 1,1.5 0.5,2 1,2 0,0 0,0 1)),((1 3,1 4,2 3,1 2,1 3)))" }; -static std::string case_recursive_boxes_13[2] = +static std::string case_recursive_boxes_13_invalid[2] = { // Strictly invalid, requires checking seg_id while considering skipping to next turn "MULTIPOLYGON(((2 1,2 2,3 2,3 1,2 1)),((3 2,3 3,4 3,4 2,3 2)),((2 4,1.5 3.5,2 3,1 3,2 2,0 2,1 3,1 5,2 5,2 4)))", "MULTIPOLYGON(((1 4,1 3,0 3,0 4,1 5,1 4)),((3 5,4 5,4 4,2 4,2 5,3 5)),((3 1,3 2,5 2,5 1,3 1)))" }; -static std::string case_recursive_boxes_14[2] = +static std::string case_recursive_boxes_14_invalid[2] = { // Strictly invalid, requires skipping assignment of discarded turns for clusters "MULTIPOLYGON(((2 2,2 3,3 2,2 2)),((2 4,2 3,3 4,3 3,1 3,1 4,2 4)))", "MULTIPOLYGON(((3 3,4 4,4 3,3 3)),((1 2,2 3,2 2,1 2)),((2 1,2 2,3 1,2 1)),((1 4,1 5,2 5,2 4,1 4)))" }; + static std::string case_recursive_boxes_15[2] = { // Requires inspecting blocked operations in traversing cluster "MULTIPOLYGON(((3 2,3 3,4 3,3 2)),((4 1,4 2,5 2,5 1,4 1)),((4 2,4 3,5 3,4 2)),((3 5,4 4,2 4,2 5,3 5)))", - "MULTIPOLYGON(((3 4,4 3,4 4,5 4,5 3,4 3,3 2,3 3,2 3,2 4,3 4)))" + "MULTIPOLYGON(((3 4,4 3,3 2,3 3,2 3,2 4,3 4)),((4 3,4 4,5 4,5 3,4 3)))" }; static std::string case_recursive_boxes_16[2] = { // Requires inspecting if traverse is possible in selecting continue operation - "MULTIPOLYGON(((2 4,1 3,0 3,0 5,3 5,3 4,4 4,4 5,5 5,5 4,4 3,2 3,3 4,2 4)),((2.5 1.5,3 1,3 2,4 2,4 1,5 2,5 0,3 0,3 1,2.5 0.5,3 0,0 0,0 2,3 2,2.5 1.5)))", - "MULTIPOLYGON(((2 1,2 2,3 1,2 1)),((3 5,5 5,5 4,4 4,4 3,5 3,5 2,4 1,4 2,3 2,3 4,2 4,2 5,3 5)),((2 2,1 1,1 2,0 1,1 1,1 0,0 0,0 5,1 5,1 3,2 3,2 2)),((4 1,5 1,5 0,3 0,3 2,4 1)))" + "MULTIPOLYGON(((2 4,1 3,0 3,0 5,3 5,3 4,2 4)),((3 4,4 4,4 5,5 5,5 4,4 3,2 3,3 4)),((2.5 1.5,3 1,2.5 0.5,3 0,0 0,0 2,3 2,2.5 1.5)),((3 1,3 2,4 2,4 1,5 2,5 0,3 0,3 1)))", + "MULTIPOLYGON(((0 1,1 1,1 0,0 0,0 1)),((0 1,0 5,1 5,1 3,2 3,2 2,1 1,1 2,0 1)),((2 2,3 1,2 1,2 2)),((3 1,3 2,4 1,5 1,5 0,3 0,3 1)),((4 1,4 2,3 2,3 4,2 4,2 5,3 5,5 5,5 4,4 4,4 3,5 3,5 2,4 1)))" }; static std::string case_recursive_boxes_17[2] = { // Requires including uu turns, at least in clusters - "MULTIPOLYGON(((0 4,0 5,1 5,0 4)),((4 0,5 1,5 0,4 0)),((4 5,5 5,5 4,3 4,3 5,4 5)),((3 4,3 3,2 2,1 2,1 1,2 1,2 2,2.5 1.5,4 3,5 3,5 1,4 1,4 0,3 0,3 1,2 1,3 0,0 0,0 2,1 2,1 5,1.5 4.5,2 5,2 4,3 4),(2 3,2 4,1 3,2 3)))", + "MULTIPOLYGON(((0 4,0 5,1 5,0 4)),((1 5,1.5 4.5,2 5,2 4,1 3,1 5)),((2 4,3 4,3 3,2 2,1 2,1 3,2 3,2 4)),((1 2,1 1,2 1,3 0,0 0,0 2,1 2)),((2 1,2 2,2.5 1.5,4 3,5 3,5 1,4 1,4 0,3 0,3 1,2 1)),((4 0,5 1,5 0,4 0)),((3 4,3 5,4 5,5 5,5 4,3 4)))", "MULTIPOLYGON(((2 5,3 5,2 4,2 5)),((3 1,4 2,4 0,3 0,3 1)),((2 0,0 0,0 1,1 2,0 2,1 3,2 2,2 3,3 2,3 1,2 0)),((1 4,0.5 3.5,1 3,0 3,0 4,1 4)),((4 3,3 3,3 5,4 5,4 4,5 4,5 2,4 2,4 3)))" }; @@ -569,15 +679,14 @@ static std::string case_recursive_boxes_21[2] = static std::string case_recursive_boxes_22[2] = { // Requires including ux turns for intersections to block paths - "MULTIPOLYGON(((2.5 1.5,3 1,2 1,2 3,3 3,2 2,3 2,2.5 1.5)))", + "MULTIPOLYGON(((2 2,3 2,2.5 1.5,3 1,2 1,2 2)),((2 2,2 3,3 3,2 2)))", "MULTIPOLYGON(((1 2,0 2,0 3,1 2)),((1 2,2 3,2 1,1 1,1 2)))" }; static std::string case_recursive_boxes_23[2] = { - // [0] is invalid, [1] is valid // Requires discarding turns with uu for intersection/difference too - "MULTIPOLYGON(((4.5 3.5,5 4,5 3,4 3,5 2,4 2,4 4,4.5 3.5)))", + "MULTIPOLYGON(((4 3,4 4,4.5 3.5,5 4,5 3,4 3)),((4 3,5 2,4 2,4 3)))", "MULTIPOLYGON(((4 3,5 4,5 3,4 3)),((3 3,3 4,4 3,3 3)))" }; @@ -627,7 +736,7 @@ static std::string case_recursive_boxes_30[2] = { // Requires not discarding turns colocated with uu/invalid polygons (now not necessary anymore because of startable) "MULTIPOLYGON(((2 2,2 3,4 3,4 4,4.5 3.5,5 4,5 0,3 0,3 1,4 1,4 2,2 2)),((1 5,3 5,4 4,0 4,0 5,1 5)))", - "MULTIPOLYGON(((2 1,2 3,1 3,1 4,2 5,2 4,3 4,3 5,5 5,5 4,4 4,3.5 3.5,4 3,4 4,5 3,4.5 2.5,5 2,5 0,4 0,4 2,3 2,3 3,2.5 2.5,4 1,3 1,3 0,1 0,2 1)))" + "MULTIPOLYGON(((2 1,2 3,1 3,1 4,2 5,2 4,3 4,3 5,5 5,5 4,4 4,5 3,4.5 2.5,5 2,5 0,4 0,4 1,3 1,3 0,1 0,2 1),(4 4,3.5 3.5,4 3,4 4),(4 1,4 2,3 2,4 1),(3 2,3 3,2.5 2.5,3 2)))" }; static std::string case_recursive_boxes_31[2] = @@ -655,14 +764,14 @@ static std::string case_recursive_boxes_34[2] = { // Requires detecting finished arcs during cluster traversal "MULTIPOLYGON(((2 0,0 0,0 5,2 5,2 4,3 5,5 5,5 0,2 0)))", - "MULTIPOLYGON(((3 3,2 3,2 2,3 2,3 1,2 0,1 0,2 1,1 1,1 0,0 0,0 5,1 4,1 5,4 5,3 4,3.5 3.5,4 4,4 5,5 4,5 1,4 1,4 3,3 3)),((3 1,4 1,3 0,3 1)))" + "MULTIPOLYGON(((1 0,0 0,0 5,1 4,1 5,4 5,5 4,5 1,4 1,4 3,3 3,2 3,2 2,3 2,3 1,2 0,1 0),(1 0,2 1,1 1,1 0),(4 5,3 4,3.5 3.5,4 4,4 5)),((4 1,3 0,3 1,4 1)))" }; static std::string case_recursive_boxes_35[2] = { // Requires detecting finished arcs during cluster traversal - "MULTIPOLYGON(((3 1,2 1,3 0,0 0,0 2,1 2,1 3,0 2,0 5,4 5,4 4,5 4,5 1,4 1,5 0,3 0,3 1),(2.5 1.5,3 2,2 2,2.5 1.5),(2 4,1 4,2 3,2 4)))", - "MULTIPOLYGON(((2 2,1.5 1.5,2 1,1 1,1 0,0 0,0 5,3 5,2.5 4.5,3 4,3 5,5 5,5 0,1 0,2 1,2 2),(3 2,3 3,2.5 2.5,3 2),(2 3,2 4,1 4,1 3,2 3)))" + "MULTIPOLYGON(((0 2,0 5,4 5,4 4,5 4,5 1,4 1,5 0,3 0,0 0,0 2),(0 2,1 2,1 3,0 2),(3 0,3 1,2 1,3 0),(2.5 1.5,3 2,2 2,2.5 1.5),(2 4,1 4,2 3,2 4)))", + "MULTIPOLYGON(((1 0,0 0,0 5,3 5,5 5,5 0,1 0),(1 0,2 1,1 1,1 0),(2 1,2 2,1.5 1.5,2 1),(3 5,2.5 4.5,3 4,3 5),(3 2,3 3,2.5 2.5,3 2),(2 3,2 4,1 4,1 3,2 3)))" }; static std::string case_recursive_boxes_36[2] = @@ -674,9 +783,17 @@ static std::string case_recursive_boxes_36[2] = static std::string case_recursive_boxes_37[2] = { + // [1] is reported as invalid by BG, but not by postgis // Requires skipping arc for union too, to avoid duplicate hole "MULTIPOLYGON(((4 0,5 1,5 0,4 0)),((2 0,3 1,3 0,2 0)),((2 3,2 2,1 2,1 3,2 3)),((2 1,2 2,4 2,3 1,2 1)))", - "MULTIPOLYGON(((2 3,1 2,1 3,2 3)),((3 1,3.5 0.5,4 1,3 1,4 2,4 3,5 3,5 0,3 0,3 1)),((3 1,2 0,2 1,3 1)))" + "MULTIPOLYGON(((3 1,4 2,4 3,5 3,5 0,3 0,3 1),(3 1,3.5 0.5,4 1,3 1)),((3 1,2 0,2 1,3 1)),((2 3,1 2,1 3,2 3)))" +}; + +static std::string case_recursive_boxes_38[2] = +{ + // Smaller version of 29, removing generated lower interior in a union + "MULTIPOLYGON(((2 3,2 4,1 4,2 5,4 5,4 4,3 4,3 3,2 3)),((3 3,4 3,4 1,5 1,5 0,3 0,3 2,2 2,3 3)),((1 2,0 2,0 3,1 3,1 2)),((1 1,0 1,1 2,2 2,2 1,1 1)))", + "MULTIPOLYGON(((2 2,4 2,4 1,2 1,2 2)),((0 4,0 5,1 4,0 4)),((2 3,2 4,4 4,4 3,2 3)),((2 2,1 2,1 3,2 3,2 2)),((1 2,0 2,0 3,1 3,0.5 2.5,1 2)))" }; static std::string pie_21_7_21_0_3[2] = @@ -791,6 +908,17 @@ static std::string ticket_11984[2] = "MULTIPOLYGON(((-31 6,-51 220,-84 241,-120 249,-146 224,-67 56,-74 52,-95 60,-38 10,-38 9)))", }; +static std::string ticket_12118[2] = + { + "MULTIPOLYGON(((13.08940410614013671875 -70.98416137695312500000,12.81384754180908203125 -67.55441284179687500000,12.60483169555664062500 -63.57923889160156250000,13.56438255310058593750 -54.91608428955078125000,13.80568027496337890625 -43.62073516845703125000,13.00057315826416015625 -33.85240554809570312500,9.29664993286132812500 -33.23409271240234375000,19.66869926452636718750 -14.42036247253417968750,-5.96064376831054687500 -17.19871711730957031250,-14.87041568756103515625 -6.99879980087280273438,-22.50806808471679687500 -27.92480468750000000000,-22.16161727905273437500 -45.15484619140625000000,-22.42436790466308593750 -54.01613616943359375000,-23.13828659057617187500 -59.28628540039062500000,-23.18314933776855468750 -68.01937866210937500000,-22.86939430236816406250 -72.78530883789062500000,-23.02970123291015625000 -72.76760864257812500000,-22.81921195983886718750 -73.54760742187500000000,-18.65677833557128906250 -73.25045776367187500000,3.16641521453857421875 -75.66014099121093750000,12.75282478332519531250 -76.71865844726562500000,13.08940410614013671875 -70.98416137695312500000)))", + "MULTIPOLYGON(((3.16641521453857421875 -75.66014099121093750000,12.75282478332519531250 -76.71865844726562500000,12.95001888275146484375 -74.61856842041015625000,3.16641521453857421875 -75.66014099121093750000)),((-22.84768676757812500000 -78.42963409423828125000,-20.92837524414062500000 -78.22530364990234375000,3.16641521453857421875 -75.66014099121093750000,-23.02970123291015625000 -72.76760864257812500000,-22.84768676757812500000 -78.42963409423828125000)))", + }; + +static std::string ticket_12125[2] = + { + "MULTIPOLYGON(((-5.96064376831054687500 -17.19871711730957031250,7.83307075500488281250 -32.98977279663085937500,8.81292819976806640625 -34.11151504516601562500,19.66869926452636718750 -14.42036247253417968750,-5.96064376831054687500 -17.19871711730957031250)),((-14.87041568756103515625 -6.99879980087280273438,-16.12161636352539062500 -18.30021858215332031250,-5.96064376831054687500 -17.19871711730957031250,-14.87041568756103515625 -6.99879980087280273438)))", + "MULTIPOLYGON(((7.83307075500488281250 -32.98977279663085937500,8.81292819976806640625 -34.11151504516601562500,13.00057315826416015625 -33.85240554809570312500,7.83307075500488281250 -32.98977279663085937500)),((-22.50806808471679687500 -27.92480468750000000000,7.83307075500488281250 -32.98977279663085937500,-14.87041568756103515625 -6.99879980087280273438,-22.50806808471679687500 -27.92480468750000000000))) ", + }; static std::string bug_21155501[2] = { diff --git a/test/algorithms/overlay/overlay.cpp b/test/algorithms/overlay/overlay.cpp index ef10d7681..f45b211e4 100644 --- a/test/algorithms/overlay/overlay.cpp +++ b/test/algorithms/overlay/overlay.cpp @@ -129,8 +129,9 @@ struct map_visitor for (typename Clusters::const_iterator it = clusters.begin(); it != clusters.end(); ++it) { std::cout << " CLUSTER " << it->first << ": "; - for (typename std::set::const_iterator sit = it->second.begin(); - sit != it->second.end(); ++sit) + for (typename std::set::const_iterator sit + = it->second.turn_indices.begin(); + sit != it->second.turn_indices.end(); ++sit) { std::cout << " " << *sit; } diff --git a/test/algorithms/overlay/overlay_cases.hpp b/test/algorithms/overlay/overlay_cases.hpp index ee88b0a57..b31fb3358 100644 --- a/test/algorithms/overlay/overlay_cases.hpp +++ b/test/algorithms/overlay/overlay_cases.hpp @@ -508,6 +508,12 @@ static std::string case_99[2] = "POLYGON((10 10,10 30,30 30,30 10,10 10))" }; +static std::string case_100[2] = + { + "POLYGON((2 1,4 1,4 3,2 3,2 1),(3 1.5,4 3,2.5 2.5,3 1.5))", + "POLYGON((4 0,8 0,8 4,4 4,4 0))" + }; + static std::string case_many_situations[2] = { "POLYGON((2 6,2 14,10 18,18 14,18 6,16 5,14 4,12 3,10 2,8 3,6 4,4 5,2 6))", "POLYGON((2 6,2 7,2 8,2 9,2 10,2 11,2 12,1 14" @@ -1105,12 +1111,6 @@ static std::string mysql_23023665_3[2] = "POLYGON((6 0,-5 0,-1 -12,6 0))" }; -static std::string mysql_23023665_4[2] = - { - "POLYGON((7 0,10 -3,7 1,7 0))", - "POLYGON((7 4,-14 10,7 -17,7 4),(7 1,0 3,-2 4,7 1))" - }; - static std::string mysql_23023665_5[2] = { "POLYGON((8 6,5 7,-1 4,-8 -7,0 -17,8 6),(3 6,5 5,0 -2,3 6))", diff --git a/test/algorithms/overlay/traverse_multi.cpp b/test/algorithms/overlay/traverse_multi.cpp index 7c2f1090f..ef424763a 100644 --- a/test/algorithms/overlay/traverse_multi.cpp +++ b/test/algorithms/overlay/traverse_multi.cpp @@ -191,14 +191,9 @@ void test_geometries() test_traverse_intersection::apply ( - "case_108_multi_a", 7, 7.5, + "case_108_multi", 7, 7.5, case_108_multi[0], case_108_multi[1] ); - test_traverse_intersection::apply - ( - "case_108_multi_b", 7, 7.5, - case_108_multi[0], case_108_multi[2] - ); test_traverse_intersection::apply ( diff --git a/test/algorithms/set_operations/difference/difference.cpp b/test/algorithms/set_operations/difference/difference.cpp index 9d1c106f4..3e92f6848 100644 --- a/test/algorithms/set_operations/difference/difference.cpp +++ b/test/algorithms/set_operations/difference/difference.cpp @@ -17,10 +17,6 @@ #include #include -// If defined, tests are run without rescaling-to-integer or robustness policy -// Test which would fail then are disabled automatically -// #define BOOST_GEOMETRY_NO_ROBUSTNESS - #include #include @@ -48,10 +44,19 @@ void test_all() typedef typename bg::coordinate_type

::type ct; + ut_settings ignore_validity; + ignore_validity.test_validity = false; + + ut_settings sym_settings; +#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS) + sym_settings.sym_difference = false; +#endif + test_one("simplex_normal", simplex_normal[0], simplex_normal[1], 3, 12, 2.52636706856656, - 3, 12, 3.52636706856656); + 3, 12, 3.52636706856656, + sym_settings); test_one("simplex_with_empty", simplex_normal[0], polygon_empty, @@ -61,19 +66,19 @@ void test_all() test_one( "star_ring", example_star, example_ring, 5, 22, 1.1901714, - 5, 27, 1.6701714); + 5, 27, 1.6701714, + sym_settings); test_one("two_bends", two_bends[0], two_bends[1], 1, 5, 8.0, 1, 5, 8.0); -#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("star_comb_15", star_comb_15[0], star_comb_15[1], 30, 160, 227.658275102812, - 30, 198, 480.485775259312); -#endif + 30, 198, 480.485775259312, + sym_settings); test_one("new_hole", new_hole[0], new_hole[1], @@ -107,12 +112,14 @@ void test_all() test_one("only_hole_intersections1", only_hole_intersections[0], only_hole_intersections[1], 2, 10, 1.9090909, - 4, 16, 10.9090909); + 4, 16, 10.9090909, + sym_settings); test_one("only_hole_intersection2", only_hole_intersections[0], only_hole_intersections[2], 3, 20, 30.9090909, - 4, 16, 10.9090909); + 4, 16, 10.9090909, + sym_settings); test_one("first_within_second", first_within_second[1], first_within_second[0], @@ -145,11 +152,15 @@ void test_all() 3, 21, 16.25, 3, 17, 6.25); - test_one("intersect_holes_new_ring", - intersect_holes_new_ring[0], intersect_holes_new_ring[1], - 3, 15, 9.8961, - 4, 25, 121.8961, - tolerance(0.01)); + { + ut_settings settings = sym_settings; + settings.percentage = 0.01; + test_one("intersect_holes_new_ring", + intersect_holes_new_ring[0], intersect_holes_new_ring[1], + 3, 15, 9.8961, + 4, 25, 121.8961, + settings); + } test_one("first_within_hole_of_second", first_within_hole_of_second[0], first_within_hole_of_second[1], @@ -169,7 +180,8 @@ void test_all() test_one( "case4", case_4[0], case_4[1], 6, 28, 2.77878787878788, - 4, 22, 4.77878787878788); + 4, 22, 4.77878787878788, + sym_settings); test_one( "case5", case_5[0], case_5[1], @@ -188,7 +200,8 @@ void test_all() test_one("case_80", case_80[0], case_80[1], 1, 9, 44.5, - 1, 10, 84.5); + 1, 10, 84.5, + ignore_validity); #ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS // Fails, holes are not subtracted @@ -199,6 +212,13 @@ void test_all() 1, 12, 80.5 + 83.0); #endif + test_one("case_100", + case_100[0], case_100[1], + 1, 7, 3.125, + 1, 7, 16.0, + 1, 13, 16.0 + 3.125, + ignore_validity); + test_one("winded", winded[0], winded[1], 3, 37, 61, @@ -215,12 +235,12 @@ void test_all() 1, 5, 1, 1, 7, 2); -#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("buffer_mp1", buffer_mp1[0], buffer_mp1[1], 1, 61, 10.2717, 1, 61, 10.2717); +#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) if ( BOOST_GEOMETRY_CONDITION((boost::is_same::value)) ) { test_one("buffer_mp2", @@ -242,17 +262,23 @@ void test_all() 1, 0, 13); ***/ - // Isovist - the # output polygons differ per compiler/pointtype, (very) small - // rings might be discarded. We check area only - test_one("isovist", - isovist1[0], isovist1[1], - -1, -1, 0.279132, - -1, -1, 224.8892, + { + ut_settings settings; #if defined(BOOST_GEOMETRY_NO_ROBUSTNESS) - tolerance(0.1)); + settings.percentage = 0.1; + settings.test_validity = false; #else - tolerance(0.001)); + settings.percentage = 0.001; #endif + + // Isovist - the # output polygons differ per compiler/pointtype, (very) small + // rings might be discarded. We check area only + test_one("isovist", + isovist1[0], isovist1[1], + -1, -1, 0.279132, + -1, -1, 224.8892, + settings); + } // SQL Server gives: 0.279121891701124 and 224.889211358929 // PostGIS gives: 0.279121991127244 and 224.889205853156 // No robustness gives: 0.279121991127106 and 224.825363749290 @@ -272,30 +298,38 @@ void test_all() // PostGIS gives: 0.30859375 and 0.033203125 with 35/35 rings #endif -#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) - test_one("geos_2", - geos_2[0], geos_2[1], - 1, -1, 138.6923828, - 1, -1, 211.859375, - tolerance(0.01)); // MSVC 14 expects 138.69214 and 211.85913 + { + // MSVC 14 expects 138.69214 and 211.85913: increase percentage + + ut_settings settings = sym_settings; + settings.percentage = 0.01; + settings.test_validity = false; + + test_one("geos_2", + geos_2[0], geos_2[1], + 1, -1, 138.6923828, + 1, -1, 211.859375, + settings); + } test_one("geos_3", geos_3[0], geos_3[1], 1, -1, 16211128.5, 1, -1, 13180420.0, - 1, -1, 16211128.5 + 13180420.0); -#endif + 1, -1, 16211128.5 + 13180420.0, + sym_settings); test_one("geos_4", geos_4[0], geos_4[1], 1, -1, 971.9163115, - 1, -1, 1332.4163115); + 1, -1, 1332.4163115, + sym_settings); test_one("ggl_list_20110306_javier", ggl_list_20110306_javier[0], ggl_list_20110306_javier[1], 1, -1, 71495.3331, 2, -1, 8960.49049, - 1, -1, 71495.3331 + 8960.49049); + 2, -1, 71495.3331 + 8960.49049); test_one("ggl_list_20110307_javier", ggl_list_20110307_javier[0], ggl_list_20110307_javier[1], @@ -373,11 +407,15 @@ void test_all() ticket_9563[0], ticket_9563[1], 0, 0, 0, 6, 24, 20.096189); +#endif test_one("ticket_10108_a", ticket_10108_a[0], ticket_10108_a[1], 1, 4, 0.0145037, - 1, 4, 0.029019232); + 1, 4, 0.029019232, + sym_settings); + +#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("ticket_10108_b", ticket_10108_b[0], ticket_10108_b[1], 1, 5, 1081.68697, @@ -401,11 +439,15 @@ void test_all() { test_one( "star_ring_ring", example_star, example_ring, - 5, 22, 1.1901714, 5, 27, 1.6701714); + 5, 22, 1.1901714, + 5, 27, 1.6701714, + sym_settings); test_one( "ring_star_ring", example_ring, example_star, - 5, 27, 1.6701714, 5, 22, 1.1901714); + 5, 27, 1.6701714, + 5, 22, 1.1901714, + sym_settings); static std::string const clip = "POLYGON((2.5 0.5,5.5 2.5))"; @@ -423,13 +465,19 @@ void test_all() typedef bg::model::polygon polygon_ccw; test_one( "star_ring_ccw", example_star, example_ring, - 5, 22, 1.1901714, 5, 27, 1.6701714); + 5, 22, 1.1901714, + 5, 27, 1.6701714, + sym_settings); test_one( "star_ring_ccw1", example_star, example_ring, - 5, 22, 1.1901714, 5, 27, 1.6701714); + 5, 22, 1.1901714, + 5, 27, 1.6701714, + sym_settings); test_one( "star_ring_ccw2", example_star, example_ring, - 5, 22, 1.1901714, 5, 27, 1.6701714); + 5, 22, 1.1901714, + 5, 27, 1.6701714, + sym_settings); } // Multi/box (should be moved to multi) @@ -457,54 +505,65 @@ void test_all() 5, 27, 1.6701714); ***/ -#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS + // Should have 2 outputs + int const correction_for_invalidity = 1; // should be 0 test_one("mysql_21977775", mysql_21977775[0], mysql_21977775[1], - 2, -1, 160.856568913, 2, -1, 92.3565689126); + 2 - correction_for_invalidity, -1, 160.856568913, + 2, -1, 92.3565689126, + ignore_validity); // also mysql_23023665 test_one("mysql_21965285", mysql_21965285[0], mysql_21965285[1], - 1, 2, -1, 92.0, + 1, 2 - correction_for_invalidity, -1, 92.0, 1, 1, -1, 14.0, - 1, 2, -1, 92.0 + 14.0); + 1, 2, -1, 92.0 + 14.0, + ignore_validity); test_one("mysql_23023665_1", mysql_23023665_1[0], mysql_23023665_1[1], - 1, 2, -1, 92.0, - 1, 1, -1, 142.5); + 1, 2 - correction_for_invalidity, -1, 92.0, + 1, 1, -1, 142.5, + ignore_validity); test_one("mysql_23023665_2", mysql_23023665_2[0], mysql_23023665_2[1], - 1, 2, -1, 96.0, - 1, 1, -1, 16.0); + 1, 2 - correction_for_invalidity, -1, 96.0, + 1, 1, -1, 16.0, + ignore_validity); test_one("mysql_23023665_3", mysql_23023665_3[0], mysql_23023665_3[1], - 1, 2, -1, 225.0, - 1, 1, -1, 66.0); + 1, 2 - correction_for_invalidity, -1, 225.0, + 1, 1, -1, 66.0, + ignore_validity); - test_one("mysql_23023665_4", - mysql_23023665_4[0], mysql_23023665_4[1], - 1, 1, -1, 1.5, - 1, 2, -1, 219.0, - 1, 2, -1, 1.5 + 219.0); +// Case mysql_23023665_4 is not yet included! +// test_one("mysql_23023665_4", +// mysql_23023665_4[0], mysql_23023665_4[1], +// 1, 1, -1, 1.5, +// 1, 2, -1, 219.0, +// 1, 2, -1, 1.5 + 219.0); test_one("mysql_23023665_5", mysql_23023665_5[0], mysql_23023665_5[1], - 2, 2, -1, 165.23735, - 2, 2, -1, 105.73735); -#endif + 2 - correction_for_invalidity, 2 - correction_for_invalidity, -1, 165.23735, + 2, 2, -1, 105.73735, + ignore_validity); test_one("mysql_23023665_6", mysql_23023665_6[0], mysql_23023665_6[1], 2, 2, -1, 105.68756, - 3, 3, -1, 10.18756); -#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS + 3, 3, -1, 10.18756 +#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS) + , ignore_validity +#endif + ); test_one("mysql_23023665_13", mysql_23023665_13[0], mysql_23023665_13[1], - 3, 3, -1, 99.74526, - 3, 3, -1, 37.74526); -#endif + 3 - correction_for_invalidity, 3 - correction_for_invalidity, -1, 99.74526, + 3, 3, -1, 37.74526, + ignore_validity); } @@ -514,30 +573,25 @@ void test_specific() { typedef bg::model::polygon polygon; - ut_settings settings; - settings.test_validity = true; - test_one("ggl_list_20120717_volker", ggl_list_20120717_volker[0], ggl_list_20120717_volker[1], 1, 11, 3371540, 1, 4, 385, - 1, 16, 3371540 + 385, - settings); + 1, 16, 3371540 + 385); test_one("ticket_10658", ticket_10658[0], ticket_10658[1], 1, 6, 1510434, - 0, 0, 0, - settings); + 0, 0, 0); test_one("ticket_11121", ticket_11121[0], ticket_11121[1], 2, 8, 489763.5, - 1, 4, 6731652.0, - settings); + 1, 4, 6731652.0); { ut_settings settings; + settings.test_validity = false; #ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS settings.test_validity = true; #endif @@ -547,7 +601,7 @@ void test_specific() ticket_11676[0], ticket_11676[1], 1, 18, 2537992.5, 2, 11, 294963.5, - 1, -1, 2537992.5 + 294963.5, + 2, -1, 2537992.5 + 294963.5, settings); } } diff --git a/test/algorithms/set_operations/difference/difference_multi.cpp b/test/algorithms/set_operations/difference/difference_multi.cpp index 3621f15d4..e84930ad8 100644 --- a/test/algorithms/set_operations/difference/difference_multi.cpp +++ b/test/algorithms/set_operations/difference/difference_multi.cpp @@ -10,19 +10,6 @@ #include #include -// If defined, tests are run without rescaling-to-integer or robustness policy -// This multi_difference currently contains no tests for double which then fail -// #define BOOST_GEOMETRY_NO_ROBUSTNESS - -//#define HAVE_TTMATH -//#define BOOST_GEOMETRY_DEBUG_ASSEMBLE -//#define BOOST_GEOMETRY_CHECK_WITH_SQLSERVER - -//#define BOOST_GEOMETRY_DEBUG_SEGMENT_IDENTIFIER -//#define BOOST_GEOMETRY_DEBUG_FOLLOW -//#define BOOST_GEOMETRY_DEBUG_TRAVERSE - - #include "test_difference.hpp" #include #include @@ -39,6 +26,14 @@ template void test_areal() { + ut_settings ignore_validity; + ignore_validity.test_validity = false; + + ut_settings sym_settings; +#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS) + sym_settings.sym_difference = false; +#endif + test_one("simplex_multi", case_multi_simplex[0], case_multi_simplex[1], 5, 21, 5.58, 4, 17, 2.58); @@ -79,19 +74,33 @@ void test_areal() test_one("case_72_multi", case_72_multi[0], case_72_multi[1], - 3, 13, 1.65, 3, 17, 6.15); + 3, 13, 1.65, 3, 17, 6.15, ignore_validity); - // 77_b, fixed by sorting colocated ix/ix turns like ux/ux test_one("case_77_multi", case_77_multi[0], case_77_multi[1], 6, 31, 7.0, 5, 36, 13.0, - 4, 43, 7.0 + 13.0); + 5, 43, 7.0 + 13.0); test_one("case_78_multi", case_78_multi[0], case_78_multi[1], 1, 5, 1.0, 1, 5, 1.0); + { + ut_settings settings; + +#if !defined(BOOST_GEOMETRY_NO_ROBUSTNESS) + settings.sym_difference = false; +#endif + + test_one("case_108_multi", + case_108_multi[0], case_108_multi[1], + 7, 32, 5.5, + 4, 28, 9.75, + 7, 45, 15.25, + settings); + } + // Ticket on GGL list 2011/10/25 // to mix polygon/multipolygon in call to difference test_one("ggl_list_20111025_vd_pp", @@ -118,10 +127,16 @@ void test_areal() ggl_list_20120915_h2[0], ggl_list_20120915_h2[2], 2, 13, 17.0, 0, 0, 0.0); - test_one("ggl_list_20120221_volker", - ggl_list_20120221_volker[0], ggl_list_20120221_volker[1], - 2, 12, 7962.66, 1, 18, 2775258.93, - tolerance(0.001)); + { + ut_settings settings; + settings.percentage = 0.001; + settings.test_validity = false; + + test_one("ggl_list_20120221_volker", + ggl_list_20120221_volker[0], ggl_list_20120221_volker[1], + 2, 12, 7962.66, 1, 18, 2775258.93, + settings); + } #if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("ticket_9081", @@ -129,31 +144,21 @@ void test_areal() 2, 28, 0.0907392476356186, 4, 25, 0.126018011439877, 4, 42, 0.0907392476356186 + 0.126018011439877, tolerance(0.001)); + + // POSTGIS areas: 3.75893745345145, 2.5810000723917e-15 + test_one("bug_21155501", + bug_21155501[0], bug_21155501[1], + 1, 9, 3.758937, + 0, 0, 0.0, + ignore_validity); #endif - { - // Bug 21155501 - - // POSTGIS areas: 3.75893745345145, 2.5810000723917e-15 - - ut_settings settings; -#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS - settings.test_validity = true; -#endif - test_one("bug_21155501", - bug_21155501[0], bug_21155501[1], - 1, 9, 3.758937, - 0, 0, 0.0, - settings); - - } - // Areas and #clips correspond with POSTGIS (except sym case) test_one("case_101_multi", case_101_multi[0], case_101_multi[1], 5, 23, 4.75, 5, 40, 12.75, - 4, 48, 4.75 + 12.75); + 5, 48, 4.75 + 12.75); // Areas and #clips correspond with POSTGIS test_one("case_102_multi", @@ -162,33 +167,35 @@ void test_areal() 6, 25, 3.75, 6, 27, 0.75 + 3.75); - // Areas and #clips correspond with POSTGIS (except sym case) + // Areas and #clips correspond with POSTGIS test_one("case_107_multi", case_107_multi[0], case_107_multi[1], 2, 11, 2.25, 3, 14, 3.0, - 3, 21, 5.25); + 4, 21, 5.25); // Areas correspond with POSTGIS, // #clips in PostGIS is 11,11,5 but should most probably be be 12,12,6 test_one("case_recursive_boxes_1", case_recursive_boxes_1[0], case_recursive_boxes_1[1], - 10, 75, 26.0, - 11, 77, 24.0, - 3, 98, 50.0); + 11, 75, 26.0, + 12, 77, 24.0, + 5, 98, 50.0, + ignore_validity); // Areas and #clips correspond with POSTGIS test_one("case_recursive_boxes_2", case_recursive_boxes_2[0], case_recursive_boxes_2[1], 3, 15, 3.0, - 5, 33, 7.0); + 7, 33, 7.0, + 10, 48, 10.0); // Areas and #clips by POSTGIS (except sym case) test_one("case_recursive_boxes_3", case_recursive_boxes_3[0], case_recursive_boxes_3[1], 24, -1, 21.5, 25, -1, 22.5, - 18, -1, 44.0); + 37, -1, 44.0); // 4, input is not valid @@ -196,31 +203,33 @@ void test_areal() case_recursive_boxes_5[0], case_recursive_boxes_5[1], 15, -1, 22.0, // #clips should be 16 11, -1, 27.0, // #clips should be 12 - 7, -1, 49.0); + 8, -1, 49.0, + ignore_validity); test_one("case_recursive_boxes_6", case_recursive_boxes_6[0], case_recursive_boxes_6[1], 6, -1, 3.5, 3, -1, 1.5, - 7, -1, 5.0); + 8, -1, 5.0, + ignore_validity); test_one("case_recursive_boxes_7", case_recursive_boxes_7[0], case_recursive_boxes_7[1], 3, 15, 2.75, 4, 19, 2.75, - 2, 22, 5.5); + 3, 22, 5.5); test_one("case_recursive_boxes_8", case_recursive_boxes_8[0], case_recursive_boxes_8[1], 2, -1, 2.50, 4, -1, 5.75, - 3, -1, 8.25); + 4, -1, 8.25); test_one("case_recursive_boxes_9", case_recursive_boxes_9[0], case_recursive_boxes_9[1], 3, -1, 1.5, 4, -1, 2.5, - 4, -1, 4.0); + 6, -1, 4.0); test_one("case_recursive_boxes_10", case_recursive_boxes_10[0], case_recursive_boxes_10[1], @@ -232,13 +241,14 @@ void test_areal() case_recursive_boxes_11[0], case_recursive_boxes_11[1], 3, -1, 2.5, 3, -1, 4.5, - 2, -1, 7.0); + 3, -1, 7.0); test_one("mysql_21965285_b", mysql_21965285_b[0], mysql_21965285_b[1], 2, -1, 183.71376870369406, - 2, -1, 131.21376870369406); + 2, -1, 131.21376870369406, + sym_settings); } @@ -264,6 +274,7 @@ void test_specific() ut_settings settings; settings.sym_difference = false; + settings.test_validity = false; #ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS settings.test_validity = true; settings.sym_difference = true; diff --git a/test/algorithms/set_operations/difference/difference_multi_spike.cpp b/test/algorithms/set_operations/difference/difference_multi_spike.cpp index 7ec3d2ce0..932fb8739 100644 --- a/test/algorithms/set_operations/difference/difference_multi_spike.cpp +++ b/test/algorithms/set_operations/difference/difference_multi_spike.cpp @@ -18,6 +18,9 @@ template void test_spikes_in_ticket_8364() { + ut_settings ignore_validity; + ignore_validity.test_validity = false; + // See: https://svn.boost.org/trac/boost/ticket/8364 //_TPolygon polygon( "MULTIPOLYGON(((1031 1056,3232 1056,3232 2856,1031 2856)))" ); //polygon -= _TPolygon( "MULTIPOLYGON(((1032 1458,1032 1212,2136 2328,3234 2220,3234 2412,2136 2646)))" ); @@ -46,7 +49,8 @@ void test_spikes_in_ticket_8364() if_typed(7893.0, 7810.487954), // SQL Server: 7810.48711165739 if_typed(1, 5), -1, - if_typed(2783349.5, 2775256.487954 + 7810.487954)); + if_typed(2783349.5, 2775256.487954 + 7810.487954), + ignore_validity); test_one("ticket_8364_step4", "MULTIPOLYGON(((2567 2688,2136 2790,2052 2712,1032 2130,1032 1764,1032 1458,1032 1212,2136 2328,3232 2220,3232 1056,1031 1056,1031 2856,3232 2856,3232 2580,2567 2688)))", @@ -59,7 +63,8 @@ void test_spikes_in_ticket_8364() if_typed(161133.5, 161054.559567), // SQL Server: 161054.560110092 if_typed(1, 2), if_typed(25, 31), - if_typed(2776875.5, 2616029.559567 + 161054.559567)); + if_typed(2776875.5, 2616029.559567 + 161054.559567), + ignore_validity); } template diff --git a/test/algorithms/set_operations/difference/test_difference.hpp b/test/algorithms/set_operations/difference/test_difference.hpp index 0059bcdd4..947d09131 100644 --- a/test/algorithms/set_operations/difference/test_difference.hpp +++ b/test/algorithms/set_operations/difference/test_difference.hpp @@ -62,14 +62,13 @@ struct ut_settings bool sym_difference; bool remove_spikes; - // TODO: set by default to true when all tests pass bool test_validity; ut_settings() : percentage(0.0001) , sym_difference(true) , remove_spikes(false) - , test_validity(false) + , test_validity(true) {} }; diff --git a/test/algorithms/set_operations/intersection/intersection.cpp b/test/algorithms/set_operations/intersection/intersection.cpp index ee1e16894..504bc3233 100644 --- a/test/algorithms/set_operations/intersection/intersection.cpp +++ b/test/algorithms/set_operations/intersection/intersection.cpp @@ -21,10 +21,6 @@ #include #include -// If defined, tests are run without rescaling-to-integer or robustness policy -// Test which would fail then are disabled automatically -// #define BOOST_GEOMETRY_NO_ROBUSTNESS - #include #include @@ -54,6 +50,10 @@ void test_areal() bool const ccw = bg::point_order::value == bg::counterclockwise; bool const open = bg::closure::value == bg::open; + ut_settings ignore_validity; + ignore_validity.test_validity = false; + + test_one("simplex_with_empty_1", simplex_normal[0], polygon_empty, 0, 0, 0.0); @@ -167,17 +167,24 @@ void test_areal() pie_2_3_23_0[0], pie_2_3_23_0[1], 1, 4, 163292.679042133, ut_settings(0.1)); +#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS) + test_one("isovist", + isovist1[0], isovist1[1], + 1, 19, 88.4178, + ignore_validity); +#else + // SQL Server gives: 88.1920416352664 + // PostGIS gives: 88.19203677911 test_one("isovist", isovist1[0], isovist1[1], 1, 19, 88.19203, ut_settings(if_typed_tt(0.01, 0.1))); - - // SQL Server gives: 88.1920416352664 - // PostGIS gives: 88.19203677911 +#endif test_one("geos_1", geos_1[0], geos_1[1], - 1, -1, 3461.0214843, ut_settings(0.005)); // MSVC 14 reports 3461.025390625 + 1, -1, 3461.0214843, // MSVC 14 reports 3461.025390625 + ut_settings(0.005, false)); // Expectations: // In most cases: 0 (no intersection) @@ -250,23 +257,17 @@ void test_areal() #if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("buffer_rt_f", buffer_rt_f[0], buffer_rt_f[1], 1, 4, 0.00029437899183903937, ut_settings(0.01)); -#endif test_one("buffer_rt_g", buffer_rt_g[0], buffer_rt_g[1], 1, 0, 2.914213562373); +#endif -#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("ticket_8254", ticket_8254[0], ticket_8254[1], 1, 4, 3.635930e-08, ut_settings(0.01)); -#endif - test_one("ticket_6958", ticket_6958[0], ticket_6958[1], 1, 4, 4.34355e-05, ut_settings(0.01)); - -#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("ticket_8652", ticket_8652[0], ticket_8652[1], 1, 4, 0.0003); -#endif test_one("ticket_8310a", ticket_8310a[0], ticket_8310a[1], 1, 5, 0.3843747); @@ -311,16 +312,11 @@ void test_areal() ticket_11576[0], ticket_11576[1], 1, 0, 5.585617332907136e-07); -#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("ticket_9563", ticket_9563[0], ticket_9563[1], 1, 8, 129.90381); -#endif -#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("buffer_mp1", buffer_mp1[0], buffer_mp1[1], 1, 31, 2.271707796); -#endif - test_one("buffer_mp2", buffer_mp2[0], buffer_mp2[1], 1, 29, 0.457126); @@ -349,27 +345,26 @@ void test_areal() mysql_21965285_b_inv[1], 2, -1, 183.71376870369406); -#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS test_one("mysql_23023665_6", mysql_23023665_6[0], mysql_23023665_6[1], - 2, -1, 11.812440191387557); + 1, -1, 11.812440191387557, + ignore_validity); test_one("mysql_23023665_10", mysql_23023665_10[0], mysql_23023665_10[1], - 1, 1, -1, 54.701340543162523); + 1, 0, -1, 54.701340543162523, + ignore_validity); test_one("mysql_23023665_11", mysql_23023665_11[0], mysql_23023665_11[1], - 1, 1, -1, 35.933385462482065); -#endif + 1, 0, -1, 35.933385462482065, + ignore_validity); - return; - - test_one( - "polygon_pseudo_line", - "Polygon((0 0,0 4,4 4,4 0,0 0))", - "Polygon((2 -2,2 -1,2 6,2 -2))", - 5, 22, 1.1901714); +// test_one( +// "polygon_pseudo_line", +// "Polygon((0 0,0 4,4 4,4 0,0 0))", +// "Polygon((2 -2,2 -1,2 6,2 -2))", +// 5, 22, 1.1901714); } template @@ -622,6 +617,9 @@ void test_all() typedef bg::model::polygon polygon_ccw_open; boost::ignore_unused(); + ut_settings ignore_validity; + ignore_validity.test_validity = false; + std::string clip = "box(2 2,8 8)"; test_areal_linear(); @@ -674,8 +672,7 @@ void test_all() test_one("llbo", "LINESTRING(9 9,10 10)", clip, 0, 0, 0.0); // Touching with point (-> output linestring with ONE point) - //std::cout << "Note: the output line is degenerate! Might be removed!" << std::endl; - test_one("llb_touch", "LINESTRING(8 8,10 10)", clip, 1, 1, 0.0); + test_one("llb_touch", "LINESTRING(8 8,10 10)", clip, 1, 1, 0.0, ignore_validity); // Along border test_one("llb_along", "LINESTRING(2 2,2 8)", clip, 1, 2, 6.0); diff --git a/test/algorithms/set_operations/intersection/intersection_multi.cpp b/test/algorithms/set_operations/intersection/intersection_multi.cpp index 379ede648..2e46408ca 100644 --- a/test/algorithms/set_operations/intersection/intersection_multi.cpp +++ b/test/algorithms/set_operations/intersection/intersection_multi.cpp @@ -14,12 +14,6 @@ #include #include -// If defined, tests are run without rescaling-to-integer or robustness policy -// This multi_intersection currently contains no tests for double then failing -// #define BOOST_GEOMETRY_NO_ROBUSTNESS - -// #define BOOST_GEOMETRY_DEBUG_ASSEMBLE - #include "test_intersection.hpp" #include #include @@ -37,6 +31,9 @@ template void test_areal() { + ut_settings ignore_validity; + ignore_validity.test_validity = false; + test_one("simplex_multi", case_multi_simplex[0], case_multi_simplex[1], 2, 12, 6.42); @@ -105,13 +102,15 @@ void test_areal() 3, 14, 2.85); test_one("case_72_multi_inv_b", case_72_multi[1], case_72_multi[2], - 3, 16, 6.15); + 3, 16, 6.15, + ignore_validity); test_one("case_77_multi", case_77_multi[0], case_77_multi[1], 5, 33, 9.0); test_one("case_78_multi", case_78_multi[0], case_78_multi[1], - 1, 0, 22.0); // In "get_turns" using partitioning, #points went from 17 to 16 + 1, 16, 22.0, + ignore_validity); test_one("case_101_multi", case_101_multi[0], case_101_multi[1], 4, 22, 4.75); @@ -120,26 +119,38 @@ void test_areal() 3, 26, 19.75); test_one("case_102_multi_inv_b", case_102_multi[1], case_102_multi[2], - 6, 25, 3.75); + 3, 25, 3.75, + ignore_validity); test_one("case_107_multi", case_107_multi[0], case_107_multi[1], 2, 10, 1.5); test_one("case_107_multi_inv_b", case_107_multi[1], case_107_multi[2], 3, 13, 3.0); + +#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS + // One intersection is missing (by rescaling) + test_one("case_108_multi", + case_108_multi[0], case_108_multi[1], + 5, 33, 7.5, + ignore_validity); +#endif test_one("case_recursive_boxes_1", case_recursive_boxes_1[0], case_recursive_boxes_1[1], - 10, 97, 47.0); + 8, 97, 47.0, + ignore_validity); test_one("case_recursive_boxes_2", case_recursive_boxes_2[0], case_recursive_boxes_2[1], - 1, 47, 90.0); // Area from SQL Server + 1, 50, 90.0, // Area from SQL Server + ignore_validity); test_one("case_recursive_boxes_3", case_recursive_boxes_3[0], case_recursive_boxes_3[1], 19, 87, 12.5); // Area from SQL Server test_one("case_recursive_boxes_4", case_recursive_boxes_4[0], case_recursive_boxes_4[1], - 13, 157, 67.0); // Area from SQL Server + 8, 174, 67.0, // Area from SQL Server + ignore_validity); // Fixed by replacing handle_tangencies in less_by_segment_ratio sort order test_one("case_recursive_boxes_6", @@ -180,7 +191,7 @@ void test_areal() 9, 43, 10.0); test_one("case_recursive_boxes_17", case_recursive_boxes_17[0], case_recursive_boxes_17[1], - 6, -1, 7.75); + 7, -1, 7.75); test_one("case_recursive_boxes_18", case_recursive_boxes_18[0], case_recursive_boxes_18[1], 0, 0, 0.0); @@ -231,10 +242,12 @@ void test_areal() 3, 0, 2.0); test_one("case_recursive_boxes_34", case_recursive_boxes_34[0], case_recursive_boxes_34[1], - 2, 0, 17.25); + 2, 0, 17.25, + ignore_validity); test_one("case_recursive_boxes_35", case_recursive_boxes_35[0], case_recursive_boxes_35[1], - 2, 0, 20.0); + 1, 0, 20.0, + ignore_validity); test_one("case_recursive_boxes_36", case_recursive_boxes_36[0], case_recursive_boxes_36[1], 1, 0, 0.5); @@ -253,19 +266,26 @@ void test_areal() ticket_9081[0], ticket_9081[1], 2, 10, 0.0019812556); + // qcc-arm reports 1.7791215549400884e-14 test_one("ticket_11018", ticket_11018[0], ticket_11018[1], - 1, 4, 1.7791170511070893e-14); + 1, 4, +#ifdef BOOST_GEOMETRY_NO_ROBUSTNESS + 9.896437631745599e-09 +#else + 1.7791170511070893e-14, ut_settings(0.001) +#endif + + ); test_one("mysql_23023665_7", mysql_23023665_7[0], mysql_23023665_7[1], 2, 11, 9.80505786783); -#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS test_one("mysql_23023665_12", mysql_23023665_12[0], mysql_23023665_12[1], - 2, -1, 11.812440191387557); -#endif + 1, -1, 11.812440191387557, + ignore_validity); } template diff --git a/test/algorithms/set_operations/intersection/test_intersection.hpp b/test/algorithms/set_operations/intersection/test_intersection.hpp index bdd0459a4..adface270 100644 --- a/test/algorithms/set_operations/intersection/test_intersection.hpp +++ b/test/algorithms/set_operations/intersection/test_intersection.hpp @@ -48,9 +48,9 @@ struct ut_settings bool test_validity; bool debug; - explicit ut_settings(double p = 0.0001) + explicit ut_settings(double p = 0.0001, bool tv = true) : percentage(p) - , test_validity(false) + , test_validity(tv) , debug(false) {} diff --git a/test/algorithms/set_operations/union/test_union.hpp b/test/algorithms/set_operations/union/test_union.hpp index 90050a8be..810c7c353 100644 --- a/test/algorithms/set_operations/union/test_union.hpp +++ b/test/algorithms/set_operations/union/test_union.hpp @@ -50,11 +50,25 @@ struct ut_settings ut_settings() : percentage(0.001) - , test_validity(false) + , test_validity(true) {} }; +#if defined(BOOST_GEOMETRY_TEST_CHECK_VALID_INPUT) +template +inline void check_input_validity(std::string const& caseid, int case_index, + Geometry const& geometry) +{ + std::string message; + if (!bg::is_valid(geometry, message)) + { + std::cout << caseid << " Input [" + << case_index << "] not valid" << std::endl + << " (" << message << ")" << std::endl; + } +} +#endif template void test_union(std::string const& caseid, G1 const& g1, G2 const& g2, @@ -74,6 +88,11 @@ void test_union(std::string const& caseid, G1 const& g1, G2 const& g2, std::cout << "*** UNION " << caseid << std::endl; #endif +#if defined(BOOST_GEOMETRY_TEST_CHECK_VALID_INPUT) + check_input_validity(caseid, 0, g1); + check_input_validity(caseid, 1, g2); +#endif + bg::union_(g1, g2, clip); typename bg::default_area_result::type area = 0; diff --git a/test/algorithms/set_operations/union/union.cpp b/test/algorithms/set_operations/union/union.cpp index 0c5a8e8bd..f2b7cf0ee 100644 --- a/test/algorithms/set_operations/union/union.cpp +++ b/test/algorithms/set_operations/union/union.cpp @@ -19,10 +19,6 @@ #include #include -// If defined, tests are run without rescaling-to-integer or robustness policy -// Test which would fail then are disabled automatically -// #define BOOST_GEOMETRY_NO_ROBUSTNESS - #include "test_union.hpp" #include @@ -36,6 +32,9 @@ void test_areal() { typedef typename bg::coordinate_type::type ct; + ut_settings ignore_validity; + ignore_validity.test_validity = false; + test_one("simplex_normal", simplex_normal[0], simplex_normal[1], 1, 0, 13, 11.526367); @@ -186,9 +185,8 @@ void test_areal() test_one("59_iet", case_59[0], case_59[2], 1, 1, 14, 17.20833); - // #holes should be 2 test_one("80", - case_80[0], case_80[1], 2, 0, 18, 129.0); + case_80[0], case_80[1], 2, 2, 18, 129.0); test_one("81", case_81[0], case_81[1], 1, 2, 15, 163.5); @@ -230,6 +228,9 @@ void test_areal() test_one("99", case_99[0], case_99[1], 1, 0, 5, 1600.0); + test_one("100", + case_100[0], case_100[1], 1, 1, 13, 19.125); + /* test_one(102, simplex_normal[0], simplex_reversed[1], @@ -293,6 +294,9 @@ void test_areal() { ut_settings settings; settings.percentage = 0.1; +#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS) + settings.test_validity = false; +#endif test_one("isovist", isovist1[0], isovist1[1], @@ -333,23 +337,21 @@ void test_areal() ticket_9081_15[0], ticket_9081_15[1], 1, 0, 10, 0.0403425433); -#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("ticket_9563", ticket_9563[0], ticket_9563[1], 1, 0, 13, 150.0); -#endif test_one("ticket_9756", ticket_9756[0], ticket_9756[1], 1, 0, 10, 1289.08374); #if defined(BOOST_GEOMETRY_NO_ROBUSTNESS) - // The number of clips is reversed here test_one("ticket_10108_a", ticket_10108_a[0], ticket_10108_a[1], 1, 0, 8, 0.0435229); - test_one("ticket_10108_b", ticket_10108_b[0], ticket_10108_b[1], - 2, 0, 10, 2424.3449); #else test_one("ticket_10108_a", ticket_10108_a[0], ticket_10108_a[1], 2, 0, 8, 0.0435229); +#endif + +#if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("ticket_10108_b", ticket_10108_b[0], ticket_10108_b[1], 1, 0, 10, 2424.3449); #endif @@ -361,7 +363,8 @@ void test_areal() 1, 1, 10, 7.5); test_one("geos_1", geos_1[0], geos_1[1], - 1, 0, -1, 3461.3203125); + 1, 0, -1, 3461.3203125, + ignore_validity); test_one("geos_2", geos_2[0], geos_2[1], 1, 0, -1, 350.55102539); test_one("geos_3", geos_3[0], geos_3[1], @@ -375,9 +378,11 @@ void test_areal() // Robustness issues, followed out buffer-robustness-tests, test them also reverse #if ! defined(BOOST_GEOMETRY_NO_ROBUSTNESS) test_one("buffer_rt_f", buffer_rt_f[0], buffer_rt_f[1], - 1, 0, if_typed(18, 23), 4.60853); + 1, 0, if_typed(18, 23), 4.60853, + ignore_validity); test_one("buffer_rt_f_rev", buffer_rt_f[1], buffer_rt_f[0], - 1, 0, if_typed(18, 23), 4.60853); + 1, 0, if_typed(18, 23), 4.60853, + ignore_validity); #endif test_one("buffer_rt_g", buffer_rt_g[0], buffer_rt_g[1], @@ -437,18 +442,19 @@ void test_areal() 1, 0, if_typed_tt(93, 91), 22.815); test_one("buffer_mp2", buffer_mp2[0], buffer_mp2[1], +#if defined(BOOST_GEOMETRY_NO_ROBUSTNESS) + 1, 0, 217, 36.752837, ignore_validity); +#else 1, 1, 217, 36.752837); +#endif -#ifdef BOOST_GEOMETRY_TEST_INCLUDE_FAILING_TESTS test_one("mysql_21964079_1", mysql_21964079_1[0], mysql_21964079_1[1], 2, 1, -1, 234.5); test_one("mysql_21964079_2", mysql_21964079_2[0], mysql_21964079_2[1], 2, 1, -1, 112.0); - test_one("mysql_21964049", - mysql_21964049[0], mysql_21964049[1], - 1, 1, -1, 220.5); + test_one("mysql_23023665_1", mysql_23023665_1[0], mysql_23023665_1[1], 2, 1, -1, 92.0 + 142.5); @@ -458,10 +464,9 @@ void test_areal() test_one("mysql_23023665_3", mysql_23023665_3[0], mysql_23023665_3[1], 2, 1, -1, 225.0 + 66.0); - test_one("mysql_23023665_4", - mysql_23023665_4[0], mysql_23023665_4[1], - 1, 1, -1, 1.5 + 219.0); -#endif + test_one("mysql_21964049", + mysql_21964049[0], mysql_21964049[1], + 1, 1, -1, 220.5); } template diff --git a/test/algorithms/set_operations/union/union_multi.cpp b/test/algorithms/set_operations/union/union_multi.cpp index 19dd3d76c..419ed8377 100644 --- a/test/algorithms/set_operations/union/union_multi.cpp +++ b/test/algorithms/set_operations/union/union_multi.cpp @@ -14,10 +14,6 @@ #include #include -// If defined, tests are run without rescaling-to-integer or robustness policy -// This multi_union currently contains no tests for double which then fail -// #define BOOST_GEOMETRY_NO_ROBUSTNESS - #include "test_union.hpp" #include #include @@ -36,6 +32,12 @@ template void test_areal() { + ut_settings ignore_validity; + ignore_validity.test_validity = false; + + // Some output is only invalid for CCW + bool const ccw = bg::point_order::value == bg::counterclockwise; + test_one("simplex_multi", case_multi_simplex[0], case_multi_simplex[1], 1, 0, 20, 14.58); @@ -67,10 +69,9 @@ void test_areal() case_58_multi[0], case_58_multi[3], 2, 0, 21, 19.83333333); - // (#holes should be 3) test_one("case_58_multi_b", case_58_multi[1], case_58_multi[2], - 1, 1, 17, 48.333333); + 1, 3, 17, 48.333333); // Constructed cases for multi/touch/equal/etc test_one("case_61_multi", @@ -99,13 +100,13 @@ void test_areal() 5, 0, 25, 5.0); test_one("case_76_multi", case_76_multi[0], case_76_multi[1], - 4, 0, 31, 8.0); + 5, 0, 31, 8.0); test_one("case_89_multi", case_89_multi[0], case_89_multi[1], 1, 0, 13, 6); test_one("case_101_multi", case_101_multi[0], case_101_multi[1], - 1, 0, 32, 22.25); + 1, 3, 35, 22.25); test_one("case_103_multi", case_103_multi[0], case_103_multi[1], 1, 0, 7, 25); @@ -123,17 +124,58 @@ void test_areal() 1, 0, 15, 6.75); test_one("case_108_multi", case_108_multi[0], case_108_multi[1], - 1, 0, 20, 22.75); + 1, 1, 20, 22.75); // Should have 2 holes + // To make it valid, it is necessary to calculate and use self turns + // for each input. Now the two holes are connected because a turn is missing + // there. test_one("case_109_multi", case_109_multi[0], case_109_multi[1], - 1, 1, 14, 1400); + 1, 1, 14, 1400, + ignore_validity); // Should have 9 holes, they are all separate and touching test_one("case_110_multi", case_110_multi[0], case_110_multi[1], - 1, 1, 37, 1250); + 1, 9, 45, 1250); + + test_one("case_111_multi", + case_111_multi[0], case_111_multi[1], + 2, 0, 10, 16); + test_one("case_112_multi", + case_112_multi[0], case_112_multi[1], + 2, 0, 16, 48); + test_one("case_113_multi", + case_113_multi[0], case_113_multi[1], + 2, 0, 13, 162.5); + test_one("case_114_multi", + case_114_multi[0], case_114_multi[1], + 1, 1, 13, 187.5); + test_one("case_115_multi", + case_115_multi[0], case_115_multi[1], + 1, 1, 18, 26.7036); + test_one("case_116_multi", + case_116_multi[0], case_116_multi[1], + 1, 2, 27, 51); + test_one("case_117_multi", + case_117_multi[0], case_117_multi[1], + 2, 0, 18, 22); + test_one("case_118_multi", + case_118_multi[0], case_118_multi[1], + 3, 0, 27, 46); + test_one("case_119_multi", + case_119_multi[0], case_119_multi[1], + 2, 0, 26, 44); + test_one("case_120_multi", + case_120_multi[0], case_120_multi[1], + 1, 1, 20, 35); + test_one("case_121_multi", + case_121_multi[0], case_121_multi[1], + 1, 1, 21, 25.5); + test_one("case_122_multi", + case_122_multi[0], case_122_multi[1], + 1, 1, 28, 29.5); test_one("case_recursive_boxes_1", case_recursive_boxes_1[0], case_recursive_boxes_1[1], @@ -143,19 +185,24 @@ void test_areal() 1, 0, 14, 100.0); // Area from SQL Server test_one("case_recursive_boxes_3", case_recursive_boxes_3[0], case_recursive_boxes_3[1], - 14, 0, 159, 56.5); // Area from SQL Server + 17, 6, 166, 56.5); // Area from SQL Server test_one("case_recursive_boxes_4", case_recursive_boxes_4[0], case_recursive_boxes_4[1], - 1, 1, 42, 96.75); + 1, 2, 42, 96.75); + + // Should have 10 holes. + // For making #5 valid, it is necessary to calculate and use self turns + // for each input. Now one hole is connected to another hole because a turn + // missing there. test_one("case_recursive_boxes_5", case_recursive_boxes_5[0], case_recursive_boxes_5[1], - 3, 2, 110, 70.0); + 3, 9, 115, 70.0, + ignore_validity); - // TODO: fix self touching interior ring (should get 3 interior rings) test_one("case_recursive_boxes_6", case_recursive_boxes_6[0], case_recursive_boxes_6[1], - 1, 2, 25, 24.0); + 1, 3, 25, 24.0); test_one("case_recursive_boxes_7", case_recursive_boxes_7[0], case_recursive_boxes_7[1], @@ -177,22 +224,49 @@ void test_areal() 1, 0, -1, 8.0); test_one("case_recursive_boxes_12", case_recursive_boxes_12[0], case_recursive_boxes_12[1], - 3, 0, -1, 6.0); + 6, 0, -1, 6.0); test_one("case_recursive_boxes_13", case_recursive_boxes_13[0], case_recursive_boxes_13[1], 3, 0, -1, 10.25); + test_one("case_recursive_boxes_14", case_recursive_boxes_14[0], case_recursive_boxes_14[1], - 4, 0, -1, 4.5); + 5, 0, -1, 4.5); + + // Invalid versions of 12/13/14 + test_one("case_recursive_boxes_12_invalid", + case_recursive_boxes_12_invalid[0], case_recursive_boxes_12_invalid[1], + 6, 0, -1, 6.0); + + if (! ccw) + { + // Handling this invalid input delivers invalid results for CCW + test_one("case_recursive_boxes_13_invalid", + case_recursive_boxes_13_invalid[0], case_recursive_boxes_13_invalid[1], + 3, 0, -1, 10.25); + } + else + { + test_one("case_recursive_boxes_13_invalid", + case_recursive_boxes_13_invalid[0], case_recursive_boxes_13_invalid[1], + 2, 0, -1, 10.25, + ignore_validity); + } + + test_one("case_recursive_boxes_14_invalid", + case_recursive_boxes_14_invalid[0], case_recursive_boxes_14_invalid[1], + 5, 0, -1, 4.5); + + test_one("case_recursive_boxes_15", case_recursive_boxes_15[0], case_recursive_boxes_15[1], - 2, 0, -1, 6.0); + 3, 0, -1, 6.0); test_one("case_recursive_boxes_16", case_recursive_boxes_16[0], case_recursive_boxes_16[1], - 1, 1, -1, 22.0); + 1, 4, -1, 22.0); test_one("case_recursive_boxes_17", case_recursive_boxes_17[0], case_recursive_boxes_17[1], - 3, 1, -1, 21.0); + 5, 2, -1, 21.0); test_one("case_recursive_boxes_18", case_recursive_boxes_18[0], case_recursive_boxes_18[1], 3, 0, -1, 2.5); @@ -228,10 +302,10 @@ void test_areal() 2, 0, -1, 6.5); test_one("case_recursive_boxes_29", case_recursive_boxes_29[0], case_recursive_boxes_29[1], - 1, 0, -1, 15.5); + 2, 2, -1, 15.5); test_one("case_recursive_boxes_30", case_recursive_boxes_30[0], case_recursive_boxes_30[1], - 1, 2, -1, 17.5); + 1, 3, -1, 17.5); test_one("case_recursive_boxes_31", case_recursive_boxes_31[0], case_recursive_boxes_31[1], 3, 0, -1, 5.0); @@ -240,7 +314,7 @@ void test_areal() 2, 0, -1, 5.75); test_one("case_recursive_boxes_33", case_recursive_boxes_33[0], case_recursive_boxes_33[1], - 1, 0, -1, 11.0); + 1, 1, -1, 11.0); test_one("case_recursive_boxes_34", case_recursive_boxes_34[0], case_recursive_boxes_34[1], 1, 0, -1, 25.0); @@ -249,10 +323,13 @@ void test_areal() 1, 1, -1, 24.5); test_one("case_recursive_boxes_36", case_recursive_boxes_36[0], case_recursive_boxes_36[1], - 2, 0, -1, 3.0); + 3, 0, -1, 3.0); test_one("case_recursive_boxes_37", case_recursive_boxes_37[0], case_recursive_boxes_37[1], 2, 1, -1, 7.75); + test_one("case_recursive_boxes_38", + case_recursive_boxes_38[0], case_recursive_boxes_38[1], + 2, 1, -1, 14.0); test_one("ggl_list_20120915_h2_a", ggl_list_20120915_h2[0], ggl_list_20120915_h2[1], @@ -281,17 +358,32 @@ void test_areal() ticket_11984[0], ticket_11984[1], 1, 2, 134, 60071.08077); -#ifdef BOOST_GEOMETRY_ENABLE_FAILING_TESTS + test_one("ticket_12118", + ticket_12118[0], ticket_12118[1], + 1, 1, 27, 2221.38713); + +#if defined(BOOST_GEOMETRY_ENABLE_FAILING_TESTS) || defined(BOOST_GEOMETRY_NO_ROBUSTNESS) + // No output if rescaling is done + test_one("ticket_12125", + ticket_12125[0], ticket_12125[1], + 1, 0, -1, 575.831180350007); +#endif + + // TODO: solve validity, it needs calculating self-turns + // Should have 1 hole test_one("mysql_23023665_7", mysql_23023665_7[0], mysql_23023665_7[1], - 1, 1, -1, 99.19494); + 1, 0, -1, 99.19494, + ignore_validity); + // Should have 2 holes test_one("mysql_23023665_8", mysql_23023665_8[0], mysql_23023665_8[1], - 1, 2, -1, 1400.0); + 1, 1, -1, 1400.0, + ignore_validity); + test_one("mysql_23023665_9", mysql_23023665_9[0], mysql_23023665_9[1], 1, 9, -1, 1250.0); -#endif } // Test cases (generic) diff --git a/test/algorithms/test_simplify.hpp b/test/algorithms/test_simplify.hpp index a7b9ce6af..d80da5653 100644 --- a/test/algorithms/test_simplify.hpp +++ b/test/algorithms/test_simplify.hpp @@ -128,7 +128,7 @@ void test_geometry(std::string const& wkt, check_geometry(v, expected, distance); - BOOST_CONCEPT_ASSERT( (bg::concept::SimplifyStrategy) ); + BOOST_CONCEPT_ASSERT( (bg::concepts::SimplifyStrategy) ); check_geometry(geometry, expected, distance, dp()); check_geometry(v, expected, distance, dp()); @@ -155,7 +155,7 @@ void test_geometry(std::string const& wkt, less_comparator > douglass_peucker_with_less; - BOOST_CONCEPT_ASSERT( (bg::concept::SimplifyStrategy) ); + BOOST_CONCEPT_ASSERT( (bg::concepts::SimplifyStrategy) ); check_geometry(geometry, expected, distance, douglass_peucker_with_less(less)); check_geometry(v, expected, distance, douglass_peucker_with_less(less)); @@ -172,7 +172,7 @@ void test_geometry(std::string const& wkt, bg::read_wkt(wkt, geometry); boost::variant v(geometry); - BOOST_CONCEPT_ASSERT( (bg::concept::SimplifyStrategy::type>) ); check_geometry(geometry, expected, distance, strategy); diff --git a/test/concepts/function_asserting_a_point.hpp b/test/concepts/function_asserting_a_point.hpp index 8ff84d449..802d19852 100644 --- a/test/concepts/function_asserting_a_point.hpp +++ b/test/concepts/function_asserting_a_point.hpp @@ -20,8 +20,8 @@ namespace test template void function_asserting_a_point(P& p1, const CP& p2) { - BOOST_CONCEPT_ASSERT((bg::concept::Point

)); - BOOST_CONCEPT_ASSERT((bg::concept::ConstPoint

)); + BOOST_CONCEPT_ASSERT((bg::concepts::Point

)); + BOOST_CONCEPT_ASSERT((bg::concepts::ConstPoint

)); bg::get<0>(p1) = bg::get<0>(p2); } diff --git a/test/concepts/function_requiring_a_point.hpp b/test/concepts/function_requiring_a_point.hpp index 77e7bdd12..d8628e940 100644 --- a/test/concepts/function_requiring_a_point.hpp +++ b/test/concepts/function_requiring_a_point.hpp @@ -19,8 +19,8 @@ namespace test template inline void function_requiring_a_point(P& p1, const C& p2) { - BOOST_CONCEPT_ASSERT((bg::concept::Point

)); - BOOST_CONCEPT_ASSERT((bg::concept::ConstPoint)); + BOOST_CONCEPT_ASSERT((bg::concepts::Point

)); + BOOST_CONCEPT_ASSERT((bg::concepts::ConstPoint)); bg::set<0>(p1, bg::get<0>(p2)); } diff --git a/test/concepts/linestring_concept.cpp b/test/concepts/linestring_concept.cpp index 9b202f1e2..06f3dfcf9 100644 --- a/test/concepts/linestring_concept.cpp +++ b/test/concepts/linestring_concept.cpp @@ -31,8 +31,8 @@ template void test_linestring() { - BOOST_CONCEPT_ASSERT( (bg::concept::Linestring) ); - BOOST_CONCEPT_ASSERT( (bg::concept::ConstLinestring) ); + BOOST_CONCEPT_ASSERT( (bg::concepts::Linestring) ); + BOOST_CONCEPT_ASSERT( (bg::concepts::ConstLinestring) ); Geometry geometry; typedef typename bg::point_type::type P; diff --git a/test/concepts/point_concept_checker.cpp b/test/concepts/point_concept_checker.cpp index 0750972f4..ea51a2e96 100644 --- a/test/concepts/point_concept_checker.cpp +++ b/test/concepts/point_concept_checker.cpp @@ -71,6 +71,6 @@ template <> struct access int main() { - boost::geometry::concept::check(); - boost::geometry::concept::check(); + boost::geometry::concepts::check(); + boost::geometry::concepts::check(); } diff --git a/test/concepts/point_geographic_custom_with_wrong_units.cpp b/test/concepts/point_geographic_custom_with_wrong_units.cpp index f2985b841..5ac6e03e7 100644 --- a/test/concepts/point_geographic_custom_with_wrong_units.cpp +++ b/test/concepts/point_geographic_custom_with_wrong_units.cpp @@ -20,7 +20,7 @@ struct dummy {}; int main() { - bg::concept::check + bg::concepts::check < ro_lon_lat_point > const >(); diff --git a/test/concepts/point_geographic_with_wrong_units.cpp b/test/concepts/point_geographic_with_wrong_units.cpp index ab5fdc704..9ea423181 100644 --- a/test/concepts/point_geographic_with_wrong_units.cpp +++ b/test/concepts/point_geographic_with_wrong_units.cpp @@ -20,7 +20,7 @@ namespace bg = boost::geometry; int main() { - bg::concept::check + bg::concepts::check < bg::model::point > >(); diff --git a/test/concepts/point_spherical_custom_with_wrong_units.cpp b/test/concepts/point_spherical_custom_with_wrong_units.cpp index f5c5bb573..4a44f3236 100644 --- a/test/concepts/point_spherical_custom_with_wrong_units.cpp +++ b/test/concepts/point_spherical_custom_with_wrong_units.cpp @@ -19,7 +19,7 @@ namespace bg = boost::geometry; int main() { - bg::concept::check + bg::concepts::check < rw_lon_lat_point > >(); diff --git a/test/concepts/point_well_formed_non_cartesian.cpp b/test/concepts/point_well_formed_non_cartesian.cpp index e6817adb3..adbc14ce0 100644 --- a/test/concepts/point_well_formed_non_cartesian.cpp +++ b/test/concepts/point_well_formed_non_cartesian.cpp @@ -30,19 +30,19 @@ inline void test_coordinate_system() typedef rw_lon_lat_point rw_int_point; typedef ro_lon_lat_point ro_int_point; - bg::concept::check(); - bg::concept::check(); + bg::concepts::check(); + bg::concepts::check(); - bg::concept::check(); - bg::concept::check(); + bg::concepts::check(); + bg::concepts::check(); - bg::concept::check(); - bg::concept::check(); - bg::concept::check(); + bg::concepts::check(); + bg::concepts::check(); + bg::concepts::check(); - bg::concept::check(); - bg::concept::check(); - bg::concept::check(); + bg::concepts::check(); + bg::concepts::check(); + bg::concepts::check(); } diff --git a/test/formulas/Jamfile.v2 b/test/formulas/Jamfile.v2 new file mode 100644 index 000000000..18587bc24 --- /dev/null +++ b/test/formulas/Jamfile.v2 @@ -0,0 +1,16 @@ +# Boost.Geometry +# +# 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, +# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +test-suite boost-geometry-formulas + : + [ run inverse.cpp : : : : formulas_inverse ] + [ run direct.cpp : : : : formulas_direct ] + [ run intersection.cpp : : : : formulas_intersection ] + ; diff --git a/test/formulas/direct.cpp b/test/formulas/direct.cpp new file mode 100644 index 000000000..1f0254925 --- /dev/null +++ b/test/formulas/direct.cpp @@ -0,0 +1,66 @@ +// Boost.Geometry +// Unit Test + +// 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, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "test_formula.hpp" +#include "direct_cases.hpp" + +#include +#include + +template +void check_direct(Result const& result, expected_result const& expected, expected_result const& reference, double reference_error) +{ + check_one(result.lon2, expected.lon2, reference.lon2, reference_error); + check_one(result.lat2, expected.lat2, reference.lat2, reference_error); + check_one(result.reverse_azimuth, expected.reverse_azimuth, reference.reverse_azimuth, reference_error, true); + check_one(result.reduced_length, expected.reduced_length, reference.reduced_length, reference_error); + check_one(result.geodesic_scale, expected.geodesic_scale, reference.geodesic_scale, reference_error); +} + +void test_all(expected_results const& results) +{ + double const d2r = bg::math::d2r(); + double const r2d = bg::math::r2d(); + + double lon1r = results.p1.lon * d2r; + double lat1r = results.p1.lat * d2r; + double distance = results.distance; + double azi12r = results.azimuth12 * d2r; + + // WGS84 + bg::srs::spheroid spheroid(6378137.0, 6356752.3142451793); + + bg::formula::result_direct result; + + typedef bg::formula::vincenty_direct vi_t; + result = vi_t::apply(lon1r, lat1r, distance, azi12r, spheroid); + result.lon2 *= r2d; + result.lat2 *= r2d; + result.reverse_azimuth *= r2d; + check_direct(result, results.vincenty, results.karney, 0.00000001); + + typedef bg::formula::thomas_direct th_t; + result = th_t::apply(lon1r, lat1r, distance, azi12r, spheroid); + result.lon2 *= r2d; + result.lat2 *= r2d; + result.reverse_azimuth *= r2d; + check_direct(result, results.thomas, results.karney, 0.0000001); +} + +int test_main(int, char*[]) +{ + for (size_t i = 0; i < expected_size; ++i) + { + test_all(expected[i]); + } + + return 0; +} diff --git a/test/formulas/direct_cases.hpp b/test/formulas/direct_cases.hpp new file mode 100644 index 000000000..d62e65d28 --- /dev/null +++ b/test/formulas/direct_cases.hpp @@ -0,0 +1,452 @@ +// Boost.Geometry +// Unit Test + +// 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, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_TEST_DIRECT_CASES_HPP +#define BOOST_GEOMETRY_TEST_DIRECT_CASES_HPP + +struct coordinates +{ + double lon; + double lat; +}; + +struct expected_result +{ + double lon2; + double lat2; + double reverse_azimuth; + double reduced_length; + double geodesic_scale; +}; + +struct expected_results +{ + coordinates p1; + double distance; + double azimuth12; + expected_result karney; + expected_result vincenty; + expected_result thomas; +}; + +expected_results expected[] = +{ + { + { 0, 0 }, 250000, 0, + { 0.00000000000000000000, 2.26091191238511868278, 0.00000000000000000000, 249935.55905595037620514631, 0.99922674639115516282 }, + { 0.00000000000000000000, 2.26091191236402178077, 0.00000000000000000000, 249935.55905951990280300379, 0.99922674639116959572 }, + { 0.00000000000000000000, 2.26091189386641744363, 0.00000000000000000000, 249935.55701571033569052815, 0.99922674640382092015 } + },{ + { 0, 0 }, 250000, 45, + { 1.58842150169031337548, 1.59850419267109766785, 45.02216068943542381930, 249935.55885449703782796860, 0.99922674504834751996 }, + { 1.58842150168977558344, 1.59850419267017707092, 45.02216068943540250302, 249935.55886070139240473509, 0.99922674504834840814 }, + { 1.58842149958854261804, 1.59850419056543535667, 45.02216068937701010100, 249935.55853169565671123564, 0.99922674505038500126 } + },{ + { 0, 0 }, 250000, 90, + { 2.24578821029880382198, 0.00000000000000000000, 90.00000000000000000000, 249935.55865304186590947211, 0.99922674370552955203 }, + { 2.24578821029880382198, 0.00000000000000013841, 90.00000000000000000000, 249935.55865304186590947211, 0.99922674370552955203 }, + { 2.24578821029880382198, 0.00000000000000013841, 90.00000000000000000000, 249935.55865304186590947211, 0.99922674370552955203 } + },{ + { 0, 0 }, 250000, 135, + { 1.58842150169031337548, -1.59850419267109766785, 134.97783931056457618070, 249935.55885449703782796860, 0.99922674504834751996 }, + { 1.58842150168977580549, -1.59850419267017707092, 134.97783931056460460240, 249935.55886070139240473509, 0.99922674504834840814 }, + { 1.58842149958854261804, -1.59850419056543602281, 134.97783931062298279357, 249935.55853169583133421838, 0.99922674505038500126 } + },{ + { 0, 0 }, 250000, 180, + { 0.00000000000000000000, -2.26091191238511868278, -180.00000000000000000000, 249935.55905595037620514631, 0.99922674639115516282 }, + { 0.00000000000000027517, -2.26091191236402178077, 180.00000000000000000000, 249935.55905951990280300379, 0.99922674639116959572 }, + { 0.00000000000000000000, -2.26091189386641744363, 180.00000000000000000000, 249935.55701571033569052815, 0.99922674640382092015 } + },{ + { 0, 0 }, 250000, -45, + { -1.58842150169031337548, 1.59850419267109766785, -45.02216068943542381930, 249935.55885449703782796860, 0.99922674504834751996 }, + { -1.58842150168977558344, 1.59850419267017707092, -45.02216068943540250302, 249935.55886070139240473509, 0.99922674504834840814 }, + { -1.58842149958854261804, 1.59850419056543535667, -45.02216068937701010100, 249935.55853169565671123564, 0.99922674505038500126 } + },{ + { 0, 0 }, 250000, -90, + { -2.24578821029880382198, 0.00000000000000000000, -90.00000000000000000000, 249935.55865304186590947211, 0.99922674370552955203 }, + { -2.24578821029880382198, 0.00000000000000013841, -90.00000000000000000000, 249935.55865304186590947211, 0.99922674370552955203 }, + { -2.24578821029880382198, 0.00000000000000013841, -90.00000000000000000000, 249935.55865304186590947211, 0.99922674370552955203 } + },{ + { 0, 0 }, 250000, -135, + { -1.58842150169031337548, -1.59850419267109766785, -134.97783931056457618070, 249935.55885449703782796860, 0.99922674504834751996 }, + { -1.58842150168977580549, -1.59850419267017707092, -134.97783931056460460240, 249935.55886070139240473509, 0.99922674504834840814 }, + { -1.58842149958854261804, -1.59850419056543602281, -134.97783931062298279357, 249935.55853169583133421838, 0.99922674505038500126 } + },{ + { 0, 0 }, 250000, -180, + { 0.00000000000000000000, -2.26091191238511868278, -180.00000000000000000000, 249935.55905595037620514631, 0.99922674639115516282 }, + { -0.00000000000000027517, -2.26091191236402178077, -180.00000000000000000000, 249935.55905951990280300379, 0.99922674639116959572 }, + { 0.00000000000000000000, -2.26091189386641744363, -180.00000000000000000000, 249935.55701571033569052815, 0.99922674640382092015 } + },{ + { -1, 0 }, 250000, 0, + { -1.00000000000000000000, 2.26091191238511868278, 0.00000000000000000000, 249935.55905595037620514631, 0.99922674639115516282 }, + { -1.00000000000000000000, 2.26091191236402178077, 0.00000000000000000000, 249935.55905951990280300379, 0.99922674639116959572 }, + { -1.00000000000000000000, 2.26091189386641744363, 0.00000000000000000000, 249935.55701571033569052815, 0.99922674640382092015 } + },{ + { -1, 0 }, 250000, 45, + { 0.58842150169031337548, 1.59850419267109766785, 45.02216068943542381930, 249935.55885449703782796860, 0.99922674504834751996 }, + { 0.58842150168977558344, 1.59850419267017707092, 45.02216068943540250302, 249935.55886070139240473509, 0.99922674504834840814 }, + { 0.58842149958854272906, 1.59850419056543535667, 45.02216068937701010100, 249935.55853169565671123564, 0.99922674505038500126 } + },{ + { -1, 0 }, 250000, 90, + { 1.24578821029880382198, 0.00000000000000000000, 90.00000000000000000000, 249935.55865304186590947211, 0.99922674370552955203 }, + { 1.24578821029880382198, 0.00000000000000013841, 90.00000000000000000000, 249935.55865304186590947211, 0.99922674370552955203 }, + { 1.24578821029880382198, 0.00000000000000013841, 90.00000000000000000000, 249935.55865304186590947211, 0.99922674370552955203 } + },{ + { -1, 0 }, 250000, 135, + { 0.58842150169031337548, -1.59850419267109766785, 134.97783931056457618070, 249935.55885449703782796860, 0.99922674504834751996 }, + { 0.58842150168977569447, -1.59850419267017707092, 134.97783931056460460240, 249935.55886070139240473509, 0.99922674504834840814 }, + { 0.58842149958854272906, -1.59850419056543602281, 134.97783931062298279357, 249935.55853169583133421838, 0.99922674505038500126 } + },{ + { -1, 0 }, 250000, 180, + { -1.00000000000000000000, -2.26091191238511868278, -180.00000000000000000000, 249935.55905595037620514631, 0.99922674639115516282 }, + { -0.99999999999999977796, -2.26091191236402178077, 180.00000000000000000000, 249935.55905951990280300379, 0.99922674639116959572 }, + { -1.00000000000000000000, -2.26091189386641744363, 180.00000000000000000000, 249935.55701571033569052815, 0.99922674640382092015 } + },{ + { -1, 0 }, 250000, -45, + { -2.58842150169031359752, 1.59850419267109766785, -45.02216068943542381930, 249935.55885449703782796860, 0.99922674504834751996 }, + { -2.58842150168977536140, 1.59850419267017707092, -45.02216068943540250302, 249935.55886070139240473509, 0.99922674504834840814 }, + { -2.58842149958854284009, 1.59850419056543535667, -45.02216068937701010100, 249935.55853169565671123564, 0.99922674505038500126 } + },{ + { -1, 0 }, 250000, -90, + { -3.24578821029880382198, 0.00000000000000000000, -90.00000000000000000000, 249935.55865304186590947211, 0.99922674370552955203 }, + { -3.24578821029880382198, 0.00000000000000013841, -90.00000000000000000000, 249935.55865304192411713302, 0.99922674370552955203 }, + { -3.24578821029880382198, 0.00000000000000013841, -90.00000000000000000000, 249935.55865304192411713302, 0.99922674370552955203 } + },{ + { -1, 0 }, 250000, -135, + { -2.58842150169031359752, -1.59850419267109766785, -134.97783931056457618070, 249935.55885449703782796860, 0.99922674504834751996 }, + { -2.58842150168977580549, -1.59850419267017707092, -134.97783931056460460240, 249935.55886070139240473509, 0.99922674504834840814 }, + { -2.58842149958854284009, -1.59850419056543602281, -134.97783931062298279357, 249935.55853169583133421838, 0.99922674505038500126 } + },{ + { -1, 0 }, 250000, -180, + { -1.00000000000000000000, -2.26091191238511868278, -180.00000000000000000000, 249935.55905595037620514631, 0.99922674639115516282 }, + { -1.00000000000000022204, -2.26091191236402178077, -180.00000000000000000000, 249935.55905951990280300379, 0.99922674639116959572 }, + { -1.00000000000000000000, -2.26091189386641744363, -180.00000000000000000000, 249935.55701571033569052815, 0.99922674640382092015 } + },{ + { 1, 0 }, 250000, 0, + { 1.00000000000000000000, 2.26091191238511868278, 0.00000000000000000000, 249935.55905595037620514631, 0.99922674639115516282 }, + { 1.00000000000000000000, 2.26091191236402178077, 0.00000000000000000000, 249935.55905951990280300379, 0.99922674639116959572 }, + { 1.00000000000000000000, 2.26091189386641744363, 0.00000000000000000000, 249935.55701571033569052815, 0.99922674640382092015 } + },{ + { 1, 0 }, 250000, 45, + { 2.58842150169031359752, 1.59850419267109766785, 45.02216068943542381930, 249935.55885449703782796860, 0.99922674504834751996 }, + { 2.58842150168977536140, 1.59850419267017707092, 45.02216068943540250302, 249935.55886070139240473509, 0.99922674504834840814 }, + { 2.58842149958854284009, 1.59850419056543535667, 45.02216068937701010100, 249935.55853169565671123564, 0.99922674505038500126 } + },{ + { 1, 0 }, 250000, 90, + { 3.24578821029880382198, 0.00000000000000000000, 90.00000000000000000000, 249935.55865304186590947211, 0.99922674370552955203 }, + { 3.24578821029880382198, 0.00000000000000013841, 90.00000000000000000000, 249935.55865304192411713302, 0.99922674370552955203 }, + { 3.24578821029880382198, 0.00000000000000013841, 90.00000000000000000000, 249935.55865304192411713302, 0.99922674370552955203 } + },{ + { 1, 0 }, 250000, 135, + { 2.58842150169031359752, -1.59850419267109766785, 134.97783931056457618070, 249935.55885449703782796860, 0.99922674504834751996 }, + { 2.58842150168977580549, -1.59850419267017707092, 134.97783931056460460240, 249935.55886070139240473509, 0.99922674504834840814 }, + { 2.58842149958854284009, -1.59850419056543602281, 134.97783931062298279357, 249935.55853169583133421838, 0.99922674505038500126 } + },{ + { 1, 0 }, 250000, 180, + { 1.00000000000000000000, -2.26091191238511868278, -180.00000000000000000000, 249935.55905595037620514631, 0.99922674639115516282 }, + { 1.00000000000000022204, -2.26091191236402178077, 180.00000000000000000000, 249935.55905951990280300379, 0.99922674639116959572 }, + { 1.00000000000000000000, -2.26091189386641744363, 180.00000000000000000000, 249935.55701571033569052815, 0.99922674640382092015 } + },{ + { 1, 0 }, 250000, -45, + { -0.58842150169031337548, 1.59850419267109766785, -45.02216068943542381930, 249935.55885449703782796860, 0.99922674504834751996 }, + { -0.58842150168977558344, 1.59850419267017707092, -45.02216068943540250302, 249935.55886070139240473509, 0.99922674504834840814 }, + { -0.58842149958854272906, 1.59850419056543535667, -45.02216068937701010100, 249935.55853169565671123564, 0.99922674505038500126 } + },{ + { 1, 0 }, 250000, -90, + { -1.24578821029880382198, 0.00000000000000000000, -90.00000000000000000000, 249935.55865304186590947211, 0.99922674370552955203 }, + { -1.24578821029880382198, 0.00000000000000013841, -90.00000000000000000000, 249935.55865304186590947211, 0.99922674370552955203 }, + { -1.24578821029880382198, 0.00000000000000013841, -90.00000000000000000000, 249935.55865304186590947211, 0.99922674370552955203 } + },{ + { 1, 0 }, 250000, -135, + { -0.58842150169031337548, -1.59850419267109766785, -134.97783931056457618070, 249935.55885449703782796860, 0.99922674504834751996 }, + { -0.58842150168977569447, -1.59850419267017707092, -134.97783931056460460240, 249935.55886070139240473509, 0.99922674504834840814 }, + { -0.58842149958854272906, -1.59850419056543602281, -134.97783931062298279357, 249935.55853169583133421838, 0.99922674505038500126 } + },{ + { 1, 0 }, 250000, -180, + { 1.00000000000000000000, -2.26091191238511868278, -180.00000000000000000000, 249935.55905595037620514631, 0.99922674639115516282 }, + { 0.99999999999999977796, -2.26091191236402178077, -180.00000000000000000000, 249935.55905951990280300379, 0.99922674639116959572 }, + { 1.00000000000000000000, -2.26091189386641744363, -180.00000000000000000000, 249935.55701571033569052815, 0.99922674640382092015 } + },{ + { 0, -1 }, 250000, 0, + { 0.00000000000000000000, 1.26092062918498104551, 0.00000000000000000000, 249935.55872467698645778000, 0.99922674479230122468 }, + { 0.00000000000000000000, 1.26092062916373448545, 0.00000000000000000000, 249935.55872643628390505910, 0.99922674479075712650 }, + { 0.00000000000000000000, 1.26092061053506587776, 0.00000000000000000000, 249935.55666816755547188222, 0.99922674480349771287 } + },{ + { 0, -1 }, 250000, 45, + { 1.58789352027561725400, 0.59889382252477618707, 44.99444098733987829064, 249935.55869720416376367211, 0.99922674484119022864 }, + { 1.58789352027508279264, 0.59889382252384637528, 44.99444098733987118521, 249935.55869934445945546031, 0.99922674484277662632 }, + { 1.58789351816042789700, 0.59889382039736038799, 44.99444098731778751699, 249935.55836710281437262893, 0.99922674484483320345 } + },{ + { 0, -1 }, 250000, 90, + { 2.24612766651409989649, -0.99922666842209439952, 89.96080977150054991398, 249935.55891569345840252936, 0.99922674685767398639 }, + { 2.24612766651347328661, -0.99922666842209439952, 89.96080977150054991398, 249935.55891513984533958137, 0.99922674686822765544 }, + { 2.24612766651409945240, -0.99922666842208529570, 89.96080977150032254031, 249935.55891660030465573072, 0.99922674686821844059 } + },{ + { 0, -1 }, 250000, 135, + { 1.58943065821228057821, -2.59810442478829362045, 134.95009296248679220298, 249935.55953696221695281565, 0.99922675155892082266 }, + { 1.58943065821171258811, -2.59810442478739078709, 134.95009296248684904640, 249935.55953448649961501360, 0.99922675162094776180 }, + { 1.58943065613921019619, -2.59810442273856878614, 134.95009296257936171060, 249935.55921406237757764757, 0.99922675162293117523 } + },{ + { 0, -1 }, 250000, 180, + { 0.00000000000000000000, -3.26088938011404927408, -180.00000000000000000000, 249935.55991226507467217743, 0.99922675429255258805 }, + { 0.00000000000000027540, -3.26088938009322193423, 180.00000000000000000000, 249935.55988221566076390445, 0.99922675435769237051 }, + { 0.00000000000000000000, -3.26088936183515265554, 180.00000000000000000000, 249935.55786483851261436939, 0.99922675437017982603 } + },{ + { 0, -1 }, 250000, -45, + { -1.58789352027561725400, 0.59889382252477618707, -44.99444098733987829064, 249935.55869720416376367211, 0.99922674484119022864 }, + { -1.58789352027508279264, 0.59889382252384637528, -44.99444098733987118521, 249935.55869934445945546031, 0.99922674484277662632 }, + { -1.58789351816042789700, 0.59889382039736038799, -44.99444098731778751699, 249935.55836710281437262893, 0.99922674484483320345 } + },{ + { 0, -1 }, 250000, -90, + { -2.24612766651409989649, -0.99922666842209439952, -89.96080977150054991398, 249935.55891569345840252936, 0.99922674685767398639 }, + { -2.24612766651347328661, -0.99922666842209439952, -89.96080977150054991398, 249935.55891513984533958137, 0.99922674686822765544 }, + { -2.24612766651409945240, -0.99922666842208529570, -89.96080977150032254031, 249935.55891660030465573072, 0.99922674686821844059 } + },{ + { 0, -1 }, 250000, -135, + { -1.58943065821228057821, -2.59810442478829362045, -134.95009296248679220298, 249935.55953696221695281565, 0.99922675155892082266 }, + { -1.58943065821171258811, -2.59810442478739078709, -134.95009296248684904640, 249935.55953448649961501360, 0.99922675162094776180 }, + { -1.58943065613921019619, -2.59810442273856878614, -134.95009296257936171060, 249935.55921406237757764757, 0.99922675162293117523 } + },{ + { 0, -1 }, 250000, -180, + { 0.00000000000000000000, -3.26088938011404927408, -180.00000000000000000000, 249935.55991226507467217743, 0.99922675429255258805 }, + { -0.00000000000000027540, -3.26088938009322193423, -180.00000000000000000000, 249935.55988221566076390445, 0.99922675435769237051 }, + { 0.00000000000000000000, -3.26088936183515265554, -180.00000000000000000000, 249935.55786483851261436939, 0.99922675437017982603 } + },{ + { 0, 1 }, 250000, 0, + { 0.00000000000000000000, 3.26088938011404927408, 0.00000000000000000000, 249935.55991226507467217743, 0.99922675429255258805 }, + { 0.00000000000000000000, 3.26088938009322193423, 0.00000000000000000000, 249935.55988221566076390445, 0.99922675435769237051 }, + { 0.00000000000000000000, 3.26088936183515265554, 0.00000000000000000000, 249935.55786483851261436939, 0.99922675437017982603 } + },{ + { 0, 1 }, 250000, 45, + { 1.58943065821228057821, 2.59810442478829362045, 45.04990703751319358616, 249935.55953696221695281565, 0.99922675155892082266 }, + { 1.58943065821171236607, 2.59810442478739123118, 45.04990703751315805903, 249935.55953448649961501360, 0.99922675162094765078 }, + { 1.58943065613921019619, 2.59810442273856923023, 45.04990703742064539483, 249935.55921406255220063031, 0.99922675162293117523 } + },{ + { 0, 1 }, 250000, 90, + { 2.24612766651409989649, 0.99922666842209439952, 90.03919022849945008602, 249935.55891569345840252936, 0.99922674685767398639 }, + { 2.24612766651347328661, 0.99922666842209484361, 90.03919022849945008602, 249935.55891513981623575091, 0.99922674686822765544 }, + { 2.24612766651409945240, 0.99922666842208562876, 90.03919022849967745969, 249935.55891660030465573072, 0.99922674686821866263 } + },{ + { 0, 1 }, 250000, 135, + { 1.58789352027561725400, -0.59889382252477618707, 135.00555901266011460393, 249935.55869720416376367211, 0.99922674484119022864 }, + { 1.58789352027508301468, -0.59889382252384604222, 135.00555901266014302564, 249935.55869934437214396894, 0.99922674484277662632 }, + { 1.58789351816042789700, -0.59889382039736038799, 135.00555901268222669387, 249935.55836710284347645938, 0.99922674484483320345 } + },{ + { 0, 1 }, 250000, 180, + { 0.00000000000000000000, -1.26092062918498104551, -180.00000000000000000000, 249935.55872467698645778000, 0.99922674479230122468 }, + { 0.00000000000000027502, -1.26092062916373448545, 180.00000000000000000000, 249935.55872643628390505910, 0.99922674479075712650 }, + { 0.00000000000000000000, -1.26092061053506587776, 180.00000000000000000000, 249935.55666816755547188222, 0.99922674480349771287 } + },{ + { 0, 1 }, 250000, -45, + { -1.58943065821228057821, 2.59810442478829362045, -45.04990703751319358616, 249935.55953696221695281565, 0.99922675155892082266 }, + { -1.58943065821171236607, 2.59810442478739123118, -45.04990703751315805903, 249935.55953448649961501360, 0.99922675162094765078 }, + { -1.58943065613921019619, 2.59810442273856923023, -45.04990703742064539483, 249935.55921406255220063031, 0.99922675162293117523 } + },{ + { 0, 1 }, 250000, -90, + { -2.24612766651409989649, 0.99922666842209439952, -90.03919022849945008602, 249935.55891569345840252936, 0.99922674685767398639 }, + { -2.24612766651347328661, 0.99922666842209484361, -90.03919022849945008602, 249935.55891513981623575091, 0.99922674686822765544 }, + { -2.24612766651409945240, 0.99922666842208562876, -90.03919022849967745969, 249935.55891660030465573072, 0.99922674686821866263 } + },{ + { 0, 1 }, 250000, -135, + { -1.58789352027561725400, -0.59889382252477618707, -135.00555901266011460393, 249935.55869720416376367211, 0.99922674484119022864 }, + { -1.58789352027508301468, -0.59889382252384604222, -135.00555901266014302564, 249935.55869934437214396894, 0.99922674484277662632 }, + { -1.58789351816042789700, -0.59889382039736038799, -135.00555901268222669387, 249935.55836710284347645938, 0.99922674484483320345 } + },{ + { 0, 1 }, 250000, -180, + { 0.00000000000000000000, -1.26092062918498104551, -180.00000000000000000000, 249935.55872467698645778000, 0.99922674479230122468 }, + { -0.00000000000000027502, -1.26092062916373448545, -180.00000000000000000000, 249935.55872643628390505910, 0.99922674479075712650 }, + { 0.00000000000000000000, -1.26092061053506587776, -180.00000000000000000000, 249935.55666816755547188222, 0.99922674480349771287 } + },{ + { -1, -1 }, 250000, 0, + { -1.00000000000000000000, 1.26092062918498104551, 0.00000000000000000000, 249935.55872467698645778000, 0.99922674479230122468 }, + { -1.00000000000000000000, 1.26092062916373448545, 0.00000000000000000000, 249935.55872643628390505910, 0.99922674479075712650 }, + { -1.00000000000000000000, 1.26092061053506587776, 0.00000000000000000000, 249935.55666816755547188222, 0.99922674480349771287 } + },{ + { -1, -1 }, 250000, 45, + { 0.58789352027561725400, 0.59889382252477618707, 44.99444098733987829064, 249935.55869720416376367211, 0.99922674484119022864 }, + { 0.58789352027508279264, 0.59889382252384637528, 44.99444098733987118521, 249935.55869934445945546031, 0.99922674484277662632 }, + { 0.58789351816042800802, 0.59889382039736038799, 44.99444098731778751699, 249935.55836710281437262893, 0.99922674484483320345 } + },{ + { -1, -1 }, 250000, 90, + { 1.24612766651409989649, -0.99922666842209439952, 89.96080977150054991398, 249935.55891569345840252936, 0.99922674685767398639 }, + { 1.24612766651347328661, -0.99922666842209439952, 89.96080977150054991398, 249935.55891513984533958137, 0.99922674686822765544 }, + { 1.24612766651409945240, -0.99922666842208529570, 89.96080977150032254031, 249935.55891660030465573072, 0.99922674686821844059 } + },{ + { -1, -1 }, 250000, 135, + { 0.58943065821228057821, -2.59810442478829362045, 134.95009296248679220298, 249935.55953696221695281565, 0.99922675155892082266 }, + { 0.58943065821171258811, -2.59810442478739078709, 134.95009296248684904640, 249935.55953448649961501360, 0.99922675162094776180 }, + { 0.58943065613921030721, -2.59810442273856878614, 134.95009296257936171060, 249935.55921406237757764757, 0.99922675162293117523 } + },{ + { -1, -1 }, 250000, 180, + { -1.00000000000000000000, -3.26088938011404927408, -180.00000000000000000000, 249935.55991226507467217743, 0.99922675429255258805 }, + { -0.99999999999999977796, -3.26088938009322193423, 180.00000000000000000000, 249935.55988221566076390445, 0.99922675435769237051 }, + { -1.00000000000000000000, -3.26088936183515265554, 180.00000000000000000000, 249935.55786483851261436939, 0.99922675437017982603 } + },{ + { -1, -1 }, 250000, -45, + { -2.58789352027561747605, 0.59889382252477618707, -44.99444098733987829064, 249935.55869720416376367211, 0.99922674484119022864 }, + { -2.58789352027508279264, 0.59889382252384637528, -44.99444098733987118521, 249935.55869934445945546031, 0.99922674484277662632 }, + { -2.58789351816042811905, 0.59889382039736038799, -44.99444098731778751699, 249935.55836710281437262893, 0.99922674484483320345 } + },{ + { -1, -1 }, 250000, -90, + { -3.24612766651409989649, -0.99922666842209439952, -89.96080977150054991398, 249935.55891569345840252936, 0.99922674685767398639 }, + { -3.24612766651347328661, -0.99922666842209439952, -89.96080977150054991398, 249935.55891513984533958137, 0.99922674686822765544 }, + { -3.24612766651409989649, -0.99922666842208529570, -89.96080977150032254031, 249935.55891660030465573072, 0.99922674686821844059 } + },{ + { -1, -1 }, 250000, -135, + { -2.58943065821228035617, -2.59810442478829362045, -134.95009296248679220298, 249935.55953696221695281565, 0.99922675155892082266 }, + { -2.58943065821171281016, -2.59810442478739078709, -134.95009296248684904640, 249935.55953448649961501360, 0.99922675162094776180 }, + { -2.58943065613921019619, -2.59810442273856878614, -134.95009296257936171060, 249935.55921406237757764757, 0.99922675162293117523 } + },{ + { -1, -1 }, 250000, -180, + { -1.00000000000000000000, -3.26088938011404927408, -180.00000000000000000000, 249935.55991226507467217743, 0.99922675429255258805 }, + { -1.00000000000000022204, -3.26088938009322193423, -180.00000000000000000000, 249935.55988221566076390445, 0.99922675435769237051 }, + { -1.00000000000000000000, -3.26088936183515265554, -180.00000000000000000000, 249935.55786483851261436939, 0.99922675437017982603 } + },{ + { -1, 1 }, 250000, 0, + { -1.00000000000000000000, 3.26088938011404927408, 0.00000000000000000000, 249935.55991226507467217743, 0.99922675429255258805 }, + { -1.00000000000000000000, 3.26088938009322193423, 0.00000000000000000000, 249935.55988221566076390445, 0.99922675435769237051 }, + { -1.00000000000000000000, 3.26088936183515265554, 0.00000000000000000000, 249935.55786483851261436939, 0.99922675437017982603 } + },{ + { -1, 1 }, 250000, 45, + { 0.58943065821228057821, 2.59810442478829362045, 45.04990703751319358616, 249935.55953696221695281565, 0.99922675155892082266 }, + { 0.58943065821171236607, 2.59810442478739123118, 45.04990703751315805903, 249935.55953448649961501360, 0.99922675162094765078 }, + { 0.58943065613921030721, 2.59810442273856923023, 45.04990703742064539483, 249935.55921406255220063031, 0.99922675162293117523 } + },{ + { -1, 1 }, 250000, 90, + { 1.24612766651409989649, 0.99922666842209439952, 90.03919022849945008602, 249935.55891569345840252936, 0.99922674685767398639 }, + { 1.24612766651347328661, 0.99922666842209484361, 90.03919022849945008602, 249935.55891513981623575091, 0.99922674686822765544 }, + { 1.24612766651409945240, 0.99922666842208562876, 90.03919022849967745969, 249935.55891660030465573072, 0.99922674686821866263 } + },{ + { -1, 1 }, 250000, 135, + { 0.58789352027561725400, -0.59889382252477618707, 135.00555901266011460393, 249935.55869720416376367211, 0.99922674484119022864 }, + { 0.58789352027508301468, -0.59889382252384604222, 135.00555901266014302564, 249935.55869934437214396894, 0.99922674484277662632 }, + { 0.58789351816042800802, -0.59889382039736038799, 135.00555901268222669387, 249935.55836710284347645938, 0.99922674484483320345 } + },{ + { -1, 1 }, 250000, 180, + { -1.00000000000000000000, -1.26092062918498104551, -180.00000000000000000000, 249935.55872467698645778000, 0.99922674479230122468 }, + { -0.99999999999999977796, -1.26092062916373448545, 180.00000000000000000000, 249935.55872643628390505910, 0.99922674479075712650 }, + { -1.00000000000000000000, -1.26092061053506587776, 180.00000000000000000000, 249935.55666816755547188222, 0.99922674480349771287 } + },{ + { -1, 1 }, 250000, -45, + { -2.58943065821228035617, 2.59810442478829362045, -45.04990703751319358616, 249935.55953696221695281565, 0.99922675155892082266 }, + { -2.58943065821171236607, 2.59810442478739123118, -45.04990703751315805903, 249935.55953448649961501360, 0.99922675162094765078 }, + { -2.58943065613921019619, 2.59810442273856923023, -45.04990703742064539483, 249935.55921406255220063031, 0.99922675162293117523 } + },{ + { -1, 1 }, 250000, -90, + { -3.24612766651409989649, 0.99922666842209439952, -90.03919022849945008602, 249935.55891569345840252936, 0.99922674685767398639 }, + { -3.24612766651347328661, 0.99922666842209484361, -90.03919022849945008602, 249935.55891513981623575091, 0.99922674686822765544 }, + { -3.24612766651409989649, 0.99922666842208562876, -90.03919022849967745969, 249935.55891660030465573072, 0.99922674686821866263 } + },{ + { -1, 1 }, 250000, -135, + { -2.58789352027561747605, -0.59889382252477618707, -135.00555901266011460393, 249935.55869720416376367211, 0.99922674484119022864 }, + { -2.58789352027508279264, -0.59889382252384604222, -135.00555901266014302564, 249935.55869934437214396894, 0.99922674484277662632 }, + { -2.58789351816042811905, -0.59889382039736038799, -135.00555901268222669387, 249935.55836710284347645938, 0.99922674484483320345 } + },{ + { -1, 1 }, 250000, -180, + { -1.00000000000000000000, -1.26092062918498104551, -180.00000000000000000000, 249935.55872467698645778000, 0.99922674479230122468 }, + { -1.00000000000000022204, -1.26092062916373448545, -180.00000000000000000000, 249935.55872643628390505910, 0.99922674479075712650 }, + { -1.00000000000000000000, -1.26092061053506587776, -180.00000000000000000000, 249935.55666816755547188222, 0.99922674480349771287 } + },{ + { 1, 1 }, 250000, 0, + { 1.00000000000000000000, 3.26088938011404927408, 0.00000000000000000000, 249935.55991226507467217743, 0.99922675429255258805 }, + { 1.00000000000000000000, 3.26088938009322193423, 0.00000000000000000000, 249935.55988221566076390445, 0.99922675435769237051 }, + { 1.00000000000000000000, 3.26088936183515265554, 0.00000000000000000000, 249935.55786483851261436939, 0.99922675437017982603 } + },{ + { 1, 1 }, 250000, 45, + { 2.58943065821228035617, 2.59810442478829362045, 45.04990703751319358616, 249935.55953696221695281565, 0.99922675155892082266 }, + { 2.58943065821171236607, 2.59810442478739123118, 45.04990703751315805903, 249935.55953448649961501360, 0.99922675162094765078 }, + { 2.58943065613921019619, 2.59810442273856923023, 45.04990703742064539483, 249935.55921406255220063031, 0.99922675162293117523 } + },{ + { 1, 1 }, 250000, 90, + { 3.24612766651409989649, 0.99922666842209439952, 90.03919022849945008602, 249935.55891569345840252936, 0.99922674685767398639 }, + { 3.24612766651347328661, 0.99922666842209484361, 90.03919022849945008602, 249935.55891513981623575091, 0.99922674686822765544 }, + { 3.24612766651409989649, 0.99922666842208562876, 90.03919022849967745969, 249935.55891660030465573072, 0.99922674686821866263 } + },{ + { 1, 1 }, 250000, 135, + { 2.58789352027561747605, -0.59889382252477618707, 135.00555901266011460393, 249935.55869720416376367211, 0.99922674484119022864 }, + { 2.58789352027508279264, -0.59889382252384604222, 135.00555901266014302564, 249935.55869934437214396894, 0.99922674484277662632 }, + { 2.58789351816042811905, -0.59889382039736038799, 135.00555901268222669387, 249935.55836710284347645938, 0.99922674484483320345 } + },{ + { 1, 1 }, 250000, 180, + { 1.00000000000000000000, -1.26092062918498104551, -180.00000000000000000000, 249935.55872467698645778000, 0.99922674479230122468 }, + { 1.00000000000000022204, -1.26092062916373448545, 180.00000000000000000000, 249935.55872643628390505910, 0.99922674479075712650 }, + { 1.00000000000000000000, -1.26092061053506587776, 180.00000000000000000000, 249935.55666816755547188222, 0.99922674480349771287 } + },{ + { 1, 1 }, 250000, -45, + { -0.58943065821228057821, 2.59810442478829362045, -45.04990703751319358616, 249935.55953696221695281565, 0.99922675155892082266 }, + { -0.58943065821171236607, 2.59810442478739123118, -45.04990703751315805903, 249935.55953448649961501360, 0.99922675162094765078 }, + { -0.58943065613921030721, 2.59810442273856923023, -45.04990703742064539483, 249935.55921406255220063031, 0.99922675162293117523 } + },{ + { 1, 1 }, 250000, -90, + { -1.24612766651409989649, 0.99922666842209439952, -90.03919022849945008602, 249935.55891569345840252936, 0.99922674685767398639 }, + { -1.24612766651347328661, 0.99922666842209484361, -90.03919022849945008602, 249935.55891513981623575091, 0.99922674686822765544 }, + { -1.24612766651409945240, 0.99922666842208562876, -90.03919022849967745969, 249935.55891660030465573072, 0.99922674686821866263 } + },{ + { 1, 1 }, 250000, -135, + { -0.58789352027561725400, -0.59889382252477618707, -135.00555901266011460393, 249935.55869720416376367211, 0.99922674484119022864 }, + { -0.58789352027508301468, -0.59889382252384604222, -135.00555901266014302564, 249935.55869934437214396894, 0.99922674484277662632 }, + { -0.58789351816042800802, -0.59889382039736038799, -135.00555901268222669387, 249935.55836710284347645938, 0.99922674484483320345 } + },{ + { 1, 1 }, 250000, -180, + { 1.00000000000000000000, -1.26092062918498104551, -180.00000000000000000000, 249935.55872467698645778000, 0.99922674479230122468 }, + { 0.99999999999999977796, -1.26092062916373448545, -180.00000000000000000000, 249935.55872643628390505910, 0.99922674479075712650 }, + { 1.00000000000000000000, -1.26092061053506587776, -180.00000000000000000000, 249935.55666816755547188222, 0.99922674480349771287 } + },{ + { 1, -1 }, 250000, 0, + { 1.00000000000000000000, 1.26092062918498104551, 0.00000000000000000000, 249935.55872467698645778000, 0.99922674479230122468 }, + { 1.00000000000000000000, 1.26092062916373448545, 0.00000000000000000000, 249935.55872643628390505910, 0.99922674479075712650 }, + { 1.00000000000000000000, 1.26092061053506587776, 0.00000000000000000000, 249935.55666816755547188222, 0.99922674480349771287 } + },{ + { 1, -1 }, 250000, 45, + { 2.58789352027561747605, 0.59889382252477618707, 44.99444098733987829064, 249935.55869720416376367211, 0.99922674484119022864 }, + { 2.58789352027508279264, 0.59889382252384637528, 44.99444098733987118521, 249935.55869934445945546031, 0.99922674484277662632 }, + { 2.58789351816042811905, 0.59889382039736038799, 44.99444098731778751699, 249935.55836710281437262893, 0.99922674484483320345 } + },{ + { 1, -1 }, 250000, 90, + { 3.24612766651409989649, -0.99922666842209439952, 89.96080977150054991398, 249935.55891569345840252936, 0.99922674685767398639 }, + { 3.24612766651347328661, -0.99922666842209439952, 89.96080977150054991398, 249935.55891513984533958137, 0.99922674686822765544 }, + { 3.24612766651409989649, -0.99922666842208529570, 89.96080977150032254031, 249935.55891660030465573072, 0.99922674686821844059 } + },{ + { 1, -1 }, 250000, 135, + { 2.58943065821228035617, -2.59810442478829362045, 134.95009296248679220298, 249935.55953696221695281565, 0.99922675155892082266 }, + { 2.58943065821171281016, -2.59810442478739078709, 134.95009296248684904640, 249935.55953448649961501360, 0.99922675162094776180 }, + { 2.58943065613921019619, -2.59810442273856878614, 134.95009296257936171060, 249935.55921406237757764757, 0.99922675162293117523 } + },{ + { 1, -1 }, 250000, 180, + { 1.00000000000000000000, -3.26088938011404927408, -180.00000000000000000000, 249935.55991226507467217743, 0.99922675429255258805 }, + { 1.00000000000000022204, -3.26088938009322193423, 180.00000000000000000000, 249935.55988221566076390445, 0.99922675435769237051 }, + { 1.00000000000000000000, -3.26088936183515265554, 180.00000000000000000000, 249935.55786483851261436939, 0.99922675437017982603 } + },{ + { 1, -1 }, 250000, -45, + { -0.58789352027561725400, 0.59889382252477618707, -44.99444098733987829064, 249935.55869720416376367211, 0.99922674484119022864 }, + { -0.58789352027508279264, 0.59889382252384637528, -44.99444098733987118521, 249935.55869934445945546031, 0.99922674484277662632 }, + { -0.58789351816042800802, 0.59889382039736038799, -44.99444098731778751699, 249935.55836710281437262893, 0.99922674484483320345 } + },{ + { 1, -1 }, 250000, -90, + { -1.24612766651409989649, -0.99922666842209439952, -89.96080977150054991398, 249935.55891569345840252936, 0.99922674685767398639 }, + { -1.24612766651347328661, -0.99922666842209439952, -89.96080977150054991398, 249935.55891513984533958137, 0.99922674686822765544 }, + { -1.24612766651409945240, -0.99922666842208529570, -89.96080977150032254031, 249935.55891660030465573072, 0.99922674686821844059 } + },{ + { 1, -1 }, 250000, -135, + { -0.58943065821228057821, -2.59810442478829362045, -134.95009296248679220298, 249935.55953696221695281565, 0.99922675155892082266 }, + { -0.58943065821171258811, -2.59810442478739078709, -134.95009296248684904640, 249935.55953448649961501360, 0.99922675162094776180 }, + { -0.58943065613921030721, -2.59810442273856878614, -134.95009296257936171060, 249935.55921406237757764757, 0.99922675162293117523 } + },{ + { 1, -1 }, 250000, -180, + { 1.00000000000000000000, -3.26088938011404927408, -180.00000000000000000000, 249935.55991226507467217743, 0.99922675429255258805 }, + { 0.99999999999999977796, -3.26088938009322193423, -180.00000000000000000000, 249935.55988221566076390445, 0.99922675435769237051 }, + { 1.00000000000000000000, -3.26088936183515265554, -180.00000000000000000000, 249935.55786483851261436939, 0.99922675437017982603 } + } +}; + +size_t const expected_size = sizeof(expected) / sizeof(expected_results); + +#endif // BOOST_GEOMETRY_TEST_DIRECT_CASES_HPP diff --git a/test/formulas/intersection.cpp b/test/formulas/intersection.cpp new file mode 100644 index 000000000..f0b1b49d7 --- /dev/null +++ b/test/formulas/intersection.cpp @@ -0,0 +1,87 @@ +// Boost.Geometry +// Unit Test + +// 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, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "test_formula.hpp" +#include "intersection_cases.hpp" + +#include +#include +#include +#include +#include +#include +#include + +void check_inverse(expected_result const& result, expected_result const& expected, expected_result const& reference, double reference_error) +{ + check_one(result.lon, expected.lon, reference.lon, reference_error); + check_one(result.lat, expected.lat, reference.lat, reference_error); +} + +void test_all(expected_results const& results) +{ + double const d2r = bg::math::d2r(); + double const r2d = bg::math::r2d(); + + double lona1r = results.p1.lon * d2r; + double lata1r = results.p1.lat * d2r; + double lona2r = results.p2.lon * d2r; + double lata2r = results.p2.lat * d2r; + double lonb1r = results.q1.lon * d2r; + double latb1r = results.q1.lat * d2r; + double lonb2r = results.q2.lon * d2r; + double latb2r = results.q2.lat * d2r; + + expected_result result; + + // WGS84 + bg::srs::spheroid spheroid(6378137.0, 6356752.3142451793); + + bg::formula::gnomonic_intersection + ::apply(lona1r, lata1r, lona2r, lata2r, lonb1r, latb1r, lonb2r, latb2r, result.lon, result.lat, spheroid); + result.lon *= r2d; + result.lat *= r2d; + check_inverse(result, results.gnomonic_vincenty, results.gnomonic_karney, 0.00000001); + + bg::formula::gnomonic_intersection + ::apply(lona1r, lata1r, lona2r, lata2r, lonb1r, latb1r, lonb2r, latb2r, result.lon, result.lat, spheroid); + result.lon *= r2d; + result.lat *= r2d; + check_inverse(result, results.gnomonic_thomas, results.gnomonic_karney, 0.0000001); + + bg::formula::sjoberg_intersection + ::apply(lona1r, lata1r, lona2r, lata2r, lonb1r, latb1r, lonb2r, latb2r, result.lon, result.lat, spheroid); + result.lon *= r2d; + result.lat *= r2d; + check_inverse(result, results.sjoberg_vincenty, results.sjoberg_karney, 0.00000001); + + bg::formula::sjoberg_intersection + ::apply(lona1r, lata1r, lona2r, lata2r, lonb1r, latb1r, lonb2r, latb2r, result.lon, result.lat, spheroid); + result.lon *= r2d; + result.lat *= r2d; + check_inverse(result, results.sjoberg_thomas, results.sjoberg_karney, 0.0000001); + + bg::formula::sjoberg_intersection + ::apply(lona1r, lata1r, lona2r, lata2r, lonb1r, latb1r, lonb2r, latb2r, result.lon, result.lat, spheroid); + result.lon *= r2d; + result.lat *= r2d; + check_inverse(result, results.sjoberg_andoyer, results.sjoberg_karney, 0.0001); +} + +int test_main(int, char*[]) +{ + for (size_t i = 0; i < expected_size; ++i) + { + test_all(expected[i]); + } + + return 0; +} diff --git a/test/formulas/intersection_cases.hpp b/test/formulas/intersection_cases.hpp new file mode 100644 index 000000000..d3d148db3 --- /dev/null +++ b/test/formulas/intersection_cases.hpp @@ -0,0 +1,129 @@ +// Boost.Geometry +// Unit Test + +// 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, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_TEST_INTERSECTION_CASES_HPP +#define BOOST_GEOMETRY_TEST_INTERSECTION_CASES_HPP + +struct coordinates +{ + double lon; + double lat; +}; + +struct expected_result +{ + double lon; + double lat; +}; + +struct expected_results +{ + coordinates p1; + coordinates p2; + coordinates q1; + coordinates q2; + expected_result gnomonic_karney; + expected_result gnomonic_vincenty; + expected_result gnomonic_thomas; + expected_result sjoberg_karney; + expected_result sjoberg_vincenty; + expected_result sjoberg_thomas; + expected_result sjoberg_andoyer; +}; + +expected_results expected[] = +{ + { + { -1, -1 },{ 1, 1 }, + { -1, 1 },{ 1, -1 }, + { 0.0000000000000000, 0.0000000000000002 }, + { 0.0000000000000000, 0.0000000000000000 }, + { 0.0000000000000000, 0.0000000000000000 }, + { 0.0000000000633173, 0.0000000000000003 }, + { 0.0000000000626537, -0.0000000000000000 }, + { -0.0000000187861002, -0.0000000000000000 }, + { -0.0000055778585615, -0.0000000000000000 } + },{ + { 1, 1 },{ -1, -1 }, + { -1, 1 },{ 1, -1 }, + { 0.0000000000000000, 0.0000000000000002 }, + { 0.0000000000000000, 0.0000000000000000 }, + { 0.0000000000000000, 0.0000000000000000 }, + { 0.0000000000000000, 0.0000000000633274 }, + { 0.0000000000000000, 0.0000000000626632 }, + { -0.0000000000000006, -0.0000000187889745 }, + { -0.0000000000000001, -0.0000055787431353 } + },{ + { -1, -1 },{ 1, 1 }, + { 1, -1 },{ -1, 1 }, + { 0.0000000000000000, 0.0000000000000002 }, + { 0.0000000000000000, 0.0000000000000000 }, + { 0.0000000000000000, 0.0000000000000000 }, + { -0.0000000000000000, -0.0000000000633268 }, + { -0.0000000000000000, -0.0000000000626632 }, + { -0.0000000000000004, 0.0000000187889746 }, + { 0.0000000000000001, 0.0000055787431353 } + },{ + { 1, 1 },{ -1, -1 }, + { 1, -1 },{ -1, 1 }, + { 0.0000000000000000, 0.0000000000000002 }, + { 0.0000000000000000, 0.0000000000000000 }, + { 0.0000000000000000, 0.0000000000000000 }, + { -0.0000000000633173, 0.0000000000000003 }, + { -0.0000000000626537, -0.0000000000000000 }, + { 0.0000000187860994, 0.0000000000000001 }, + { 0.0000055778585615, -0.0000000000000000 } + },{ + { 0, 0 },{ 1, 1 }, + { 0, 1 },{ 1, 0 }, + { 0.5000000000000000, 0.5000573755188484 }, + { 0.5000000000000000, 0.5000573755188470 }, + { 0.5000000000000000, 0.5000573755109839 }, + { 0.5000000000316606, 0.5000573755188390 }, + { 0.5000000000313266, 0.5000573755188389 }, + { 0.4999999906069524, 0.5000573755152582 }, + { 0.4999972102164753, 0.5000573755151276 } + },{ + { 1, 1 },{ 0, 0 }, + { 0, 1 },{ 1, 0 }, + { 0.5000000000000000, 0.5000573755188484 }, + { 0.5000000000000000, 0.5000573755188470 }, + { 0.5000000000000000, 0.5000573755109839 }, + { 0.5000000000000000, 0.5000573755505008 }, + { 0.5000000000000000, 0.5000573755501669 }, + { 0.4999999999999996, 0.5000573661218464 }, + { 0.4999999999999999, 0.5000545856093679 } + },{ + { 0, 0 },{ 1, 1 }, + { 1, 0 },{ 0, 1 }, + { 0.5000000000000000, 0.5000573755188484 }, + { 0.5000000000000000, 0.5000573755188470 }, + { 0.5000000000000000, 0.5000573755109839 }, + { 0.5000000000000001, 0.5000573754871773 }, + { 0.4999999999999999, 0.5000573754875109 }, + { 0.4999999999999999, 0.5000573849086647 }, + { 0.5000000000000000, 0.5000601654208935 } + },{ + { 1, 1 },{ 0, 0 }, + { 1, 0 },{ 0, 1 }, + { 0.5000000000000000, 0.5000573755188484 }, + { 0.5000000000000000, 0.5000573755188470 }, + { 0.5000000000000000, 0.5000573755109839 }, + { 0.4999999999683394, 0.5000573755188390 }, + { 0.4999999999686731, 0.5000573755188389 }, + { 0.5000000093930521, 0.5000573755152582 }, + { 0.5000027897835244, 0.5000573755151276 } + } +}; + +size_t const expected_size = sizeof(expected) / sizeof(expected_results); + +#endif // BOOST_GEOMETRY_TEST_INTERSECTION_CASES_HPP diff --git a/test/formulas/inverse.cpp b/test/formulas/inverse.cpp new file mode 100644 index 000000000..4c33cae28 --- /dev/null +++ b/test/formulas/inverse.cpp @@ -0,0 +1,71 @@ +// Boost.Geometry +// Unit Test + +// 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, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include "test_formula.hpp" +#include "inverse_cases.hpp" + +#include +#include +#include + +template +void check_inverse(Result const& result, expected_result const& expected, expected_result const& reference, double reference_error) +{ + check_one(result.distance, expected.distance, reference.distance, reference_error); + check_one(result.azimuth, expected.azimuth, reference.azimuth, reference_error, true); + check_one(result.reverse_azimuth, expected.reverse_azimuth, reference.reverse_azimuth, reference_error, true); + check_one(result.reduced_length, expected.reduced_length, reference.reduced_length, reference_error); + check_one(result.geodesic_scale, expected.geodesic_scale, reference.geodesic_scale, reference_error); +} + +void test_all(expected_results const& results) +{ + double const d2r = bg::math::d2r(); + double const r2d = bg::math::r2d(); + + double lon1r = results.p1.lon * d2r; + double lat1r = results.p1.lat * d2r; + double lon2r = results.p2.lon * d2r; + double lat2r = results.p2.lat * d2r; + + // WGS84 + bg::srs::spheroid spheroid(6378137.0, 6356752.3142451793); + + bg::formula::result_inverse result; + + typedef bg::formula::vincenty_inverse vi_t; + result = vi_t::apply(lon1r, lat1r, lon2r, lat2r, spheroid); + result.azimuth *= r2d; + result.reverse_azimuth *= r2d; + check_inverse(result, results.vincenty, results.karney, 0.00000001); + + typedef bg::formula::thomas_inverse th_t; + result = th_t::apply(lon1r, lat1r, lon2r, lat2r, spheroid); + result.azimuth *= r2d; + result.reverse_azimuth *= r2d; + check_inverse(result, results.thomas, results.karney, 0.0000001); + + typedef bg::formula::andoyer_inverse an_t; + result = an_t::apply(lon1r, lat1r, lon2r, lat2r, spheroid); + result.azimuth *= r2d; + result.reverse_azimuth *= r2d; + check_inverse(result, results.andoyer, results.karney, 0.0001); +} + +int test_main(int, char*[]) +{ + for (size_t i = 0; i < expected_size; ++i) + { + test_all(expected[i]); + } + + return 0; +} diff --git a/test/formulas/inverse_cases.hpp b/test/formulas/inverse_cases.hpp new file mode 100644 index 000000000..1abc01e85 --- /dev/null +++ b/test/formulas/inverse_cases.hpp @@ -0,0 +1,480 @@ +// Boost.Geometry +// Unit Test + +// 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, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_TEST_INVERSE_CASES_HPP +#define BOOST_GEOMETRY_TEST_INVERSE_CASES_HPP + +struct coordinates +{ + double lon; + double lat; +}; + +struct expected_result +{ + double distance; + double azimuth; + double reverse_azimuth; + double reduced_length; + double geodesic_scale; +}; + +struct expected_results +{ + coordinates p1; + coordinates p2; + expected_result karney; + expected_result vincenty; + expected_result thomas; + expected_result andoyer; +}; + +expected_results expected[] = +{ + { + { 0, 0 },{ 2, 0 }, + { 222638.98158654713188298047, 90.00000000000000000000, 90.00000000000000000000, 222593.46652303214068524539, 0.99938672191946420487 }, + { 222638.98158645280636847019, 90.00000000000000000000, 90.00000000000000000000, 222593.46652303214068524539, 0.99938672191946420487 }, + { 222638.98158654122380539775, 90.00000000000000000000, 90.00000000000000000000, 222593.46652303214068524539, 0.99938672191946420487 }, + { 222638.98158654125290922821, 90.00000000000000000000, 90.00000000000000000000, 222593.46652303214068524539, 0.99938672191946420487 } + },{ + { 0, 0 },{ 2, 2 }, + { 313775.70942918420769274235, 45.17488858648466987233, 45.20980230803674970730, 313648.30600607168162241578, 0.99878199603375228399 }, + { 313775.70929574419278651476, 45.17488858646600391467, 45.20980230801805532792, 313648.30601466231746599078, 0.99878199603375328319 }, + { 313775.70869052573107182980, 45.17488750916628958976, 45.20980122940459722258, 313648.30008120078127831221, 0.99878199607986462016 }, + { 313772.17715740547282621264, 45.17456700769592004008, 45.20948072916769433505, 313646.54128309490624815226, 0.99878200978130526888 } + },{ + { 0, 0 },{ 0, 2 }, + { 221149.45337213488528504968, 0.00000000000000000000, 0.00000000000000000000, 221104.84592454897938296199, 0.99939490135383823866 }, + { 221149.45318342180689796805, 0.00000000000000000000, 0.00000000000000000000, 221104.84593068063259124756, 0.99939490135383812763 }, + { 221149.45337045041378587484, 0.00000000000000000000, 0.00000000000000000000, 221104.84593068063259124756, 0.99939490135383812763 }, + { 221146.95820782837108708918, 0.00000000000000002350, 0.00000000000000002350, 221104.84893554644077084959, 0.99939490135383812763 } + },{ + { 0, 0 },{ -2, 2 }, + { 313775.70942918420769274235, -45.17488858648466987233, -45.20980230803674970730, 313648.30600607168162241578, 0.99878199603375228399 }, + { 313775.70929574419278651476, -45.17488858646600391467, -45.20980230801805532792, 313648.30601466231746599078, 0.99878199603375328319 }, + { 313775.70869052573107182980, -45.17488750916629669518, -45.20980122940459722258, 313648.30008120078127831221, 0.99878199607986462016 }, + { 313772.17715740547282621264, -45.17456700769592004008, -45.20948072916767301876, 313646.54128309484804049134, 0.99878200978130526888 } + },{ + { 0, 0 },{ -2, 0 }, + { 222638.98158654713188298047, -90.00000000000000000000, -90.00000000000000000000, 222593.46652303214068524539, 0.99938672191946420487 }, + { 222638.98158645280636847019, -90.00000000000000000000, -90.00000000000000000000, 222593.46652303214068524539, 0.99938672191946420487 }, + { 222638.98158654122380539775, -90.00000000000000000000, -90.00000000000000000000, 222593.46652303214068524539, 0.99938672191946420487 }, + { 222638.98158654125290922821, -90.00000000000000000000, -90.00000000000000000000, 222593.46652303214068524539, 0.99938672191946420487 } + },{ + { 0, 0 },{ -2, -2 }, + { 313775.70942918420769274235, -134.82511141351534433852, -134.79019769196324318727, 313648.30600607168162241578, 0.99878199603375228399 }, + { 313775.70929574419278651476, -134.82511141353401740162, -134.79019769198197309379, 313648.30601466225925832987, 0.99878199603375317217 }, + { 313775.70869052573107182980, -134.82511249083370330482, -134.79019877059539567199, 313648.30008120083948597312, 0.99878199607986462016 }, + { 313772.17715740547282621264, -134.82543299230408706535, -134.79051927083230566495, 313646.54128309502266347408, 0.99878200978130537990 } + },{ + { 0, 0 },{ 0, -2 }, + { 221149.45337213488528504968, -180.00000000000000000000, -180.00000000000000000000, 221104.84592454897938296199, 0.99939490135383823866 }, + { 221149.45318342180689796805, 180.00000000000000000000, 180.00000000000000000000, 221104.84593068063259124756, 0.99939490135383812763 }, + { 221149.45337045041378587484, 180.00000000000000000000, 180.00000000000000000000, 221104.84593068063259124756, 0.99939490135383812763 }, + { 221146.95820782837108708918, 180.00000000000000000000, 180.00000000000000000000, 221104.84893554644077084959, 0.99939490135383812763 } + },{ + { 0, 0 },{ 2, -2 }, + { 313775.70942918420769274235, 134.82511141351534433852, 134.79019769196324318727, 313648.30600607168162241578, 0.99878199603375228399 }, + { 313775.70929574419278651476, 134.82511141353401740162, 134.79019769198197309379, 313648.30601466225925832987, 0.99878199603375317217 }, + { 313775.70869052573107182980, 134.82511249083370330482, 134.79019877059539567199, 313648.30008120083948597312, 0.99878199607986462016 }, + { 313772.17715740547282621264, 134.82543299230408706535, 134.79051927083230566495, 313646.54128309502266347408, 0.99878200978130537990 } + },{ + { -1, 0 },{ 2, 0 }, + { 333958.47237982071237638593, 90.00000000000000000000, 90.00000000000000000000, 333804.87081722758011892438, 0.99862030063297502203 }, + { 333958.47237967920955270529, 90.00000000000000000000, 90.00000000000000000000, 333804.87081722758011892438, 0.99862030063297502203 }, + { 333958.47237982566002756357, 90.00000000000000000000, 90.00000000000000000000, 333804.87081722758011892438, 0.99862030063297502203 }, + { 333958.47237982566002756357, 90.00000000000000000000, 90.00000000000000000000, 333804.87081722758011892438, 0.99862030063297502203 } + },{ + { -1, 0 },{ 2, 2 }, + { 400487.62166116386651992798, 56.46443555420994186989, 56.51681282834063324572, 400222.73679570353124290705, 0.99801604059094650712 }, + { 400487.62155657896073535085, 56.46443555419775606197, 56.51681282832842612152, 400222.73680666065774857998, 0.99801604059094761734 }, + { 400487.62116943788714706898, 56.46443456250134573793, 56.51681183466060787168, 400222.72635490150423720479, 0.99801604069467231284 }, + { 400484.31980028707766905427, 56.46436757836366382435, 56.51674485214859089410, 400222.02724612434394657612, 0.99801604768666130063 } + },{ + { -1, 0 },{ 0, 2 }, + { 247576.47264764847932383418, 26.70874628270370010341, 26.72620180544743817563, 247513.88750887679634615779, 0.99924166327570262958 }, + { 247576.47247877591871656477, 26.70874628267113948255, 26.72620180541484202763, 247513.88751566910650581121, 0.99924166327570307367 }, + { 247576.47204536388744600117, 26.70874541733553186873, 26.72620093942252594843, 247513.88563483985490165651, 0.99924166328723251773 }, + { 247573.34468778557493351400, 26.70817834948789482041, 26.72563387223648589952, 247512.65741612159763462842, 0.99924167083675718981 } + },{ + { -1, 0 },{ -2, 2 }, + { 247576.47264764847932383418, -26.70874628270370010341, -26.72620180544743817563, 247513.88750887679634615779, 0.99924166327570262958 }, + { 247576.47247877591871656477, -26.70874628267113948255, -26.72620180541484202763, 247513.88751566910650581121, 0.99924166327570307367 }, + { 247576.47204536388744600117, -26.70874541733554607958, -26.72620093942252594843, 247513.88563483985490165651, 0.99924166328723251773 }, + { 247573.34468778557493351400, -26.70817834948789482041, -26.72563387223651432123, 247512.65741612159763462842, 0.99924167083675718981 } + },{ + { -1, 0 },{ -2, 0 }, + { 111319.49079327356594149023, -90.00000000000000000000, -90.00000000000000000000, 111313.80114861292531713843, 0.99984666872462601983 }, + { 111319.49079322640318423510, -90.00000000000000000000, -90.00000000000000000000, 111313.80114861292531713843, 0.99984666872462601983 }, + { 111319.49079326246283017099, -90.00000000000000000000, -90.00000000000000000000, 111313.80114861292531713843, 0.99984666872462601983 }, + { 111319.49079326246283017099, -90.00000000000000000000, -90.00000000000000000000, 111313.80114861292531713843, 0.99984666872462601983 } + },{ + { -1, 0 },{ -2, -2 }, + { 247576.47264764847932383418, -153.29125371729628568573, -153.27379819455256892979, 247513.88750887679634615779, 0.99924166327570262958 }, + { 247576.47247877591871656477, -153.29125371732885696474, -153.27379819458516863051, 247513.88751566907740198076, 0.99924166327570307367 }, + { 247576.47204536388744600117, -153.29125458266443615685, -153.27379906057745984072, 247513.88563483985490165651, 0.99924166328723251773 }, + { 247573.34468778557493351400, -153.29182165051210517959, -153.27436612776349988962, 247512.65741612162673845887, 0.99924167083675718981 } + },{ + { -1, 0 },{ 0, -2 }, + { 247576.47264764847932383418, 153.29125371729628568573, 153.27379819455256892979, 247513.88750887679634615779, 0.99924166327570262958 }, + { 247576.47247877591871656477, 153.29125371732885696474, 153.27379819458516863051, 247513.88751566907740198076, 0.99924166327570307367 }, + { 247576.47204536388744600117, 153.29125458266446457856, 153.27379906057745984072, 247513.88563483985490165651, 0.99924166328723251773 }, + { 247573.34468778557493351400, 153.29182165051210517959, 153.27436612776349988962, 247512.65741612162673845887, 0.99924167083675718981 } + },{ + { -1, 0 },{ 2, -2 }, + { 400487.62166116386651992798, 123.53556444579005813011, 123.48318717165936675428, 400222.73679570353124290705, 0.99801604059094650712 }, + { 400487.62155657896073535085, 123.53556444580226525431, 123.48318717167158808934, 400222.73680666059954091907, 0.99801604059094761734 }, + { 400487.62116943788714706898, 123.53556543749867557835, 123.48318816533939923374, 400222.72635490150423720479, 0.99801604069467231284 }, + { 400484.31980028707766905427, 123.53563242163632196480, 123.48325514785142331675, 400222.02724612434394657612, 0.99801604768666130063 } + },{ + { 1, 0 },{ 2, 0 }, + { 111319.49079327356594149023, 90.00000000000000000000, 90.00000000000000000000, 111313.80114861292531713843, 0.99984666872462601983 }, + { 111319.49079322640318423510, 90.00000000000000000000, 90.00000000000000000000, 111313.80114861292531713843, 0.99984666872462601983 }, + { 111319.49079326246283017099, 90.00000000000000000000, 90.00000000000000000000, 111313.80114861292531713843, 0.99984666872462601983 }, + { 111319.49079326246283017099, 90.00000000000000000000, 90.00000000000000000000, 111313.80114861292531713843, 0.99984666872462601983 } + },{ + { 1, 0 },{ 2, 2 }, + { 247576.47264764847932383418, 26.70874628270370010341, 26.72620180544743817563, 247513.88750887679634615779, 0.99924166327570262958 }, + { 247576.47247877591871656477, 26.70874628267113948255, 26.72620180541484202763, 247513.88751566910650581121, 0.99924166327570307367 }, + { 247576.47204536388744600117, 26.70874541733553186873, 26.72620093942252594843, 247513.88563483985490165651, 0.99924166328723251773 }, + { 247573.34468778557493351400, 26.70817834948789482041, 26.72563387223648589952, 247512.65741612159763462842, 0.99924167083675718981 } + },{ + { 1, 0 },{ 0, 2 }, + { 247576.47264764847932383418, -26.70874628270370010341, -26.72620180544743817563, 247513.88750887679634615779, 0.99924166327570262958 }, + { 247576.47247877591871656477, -26.70874628267113948255, -26.72620180541484202763, 247513.88751566910650581121, 0.99924166327570307367 }, + { 247576.47204536388744600117, -26.70874541733554607958, -26.72620093942252594843, 247513.88563483985490165651, 0.99924166328723251773 }, + { 247573.34468778557493351400, -26.70817834948789482041, -26.72563387223651432123, 247512.65741612159763462842, 0.99924167083675718981 } + },{ + { 1, 0 },{ -2, 2 }, + { 400487.62166116386651992798, -56.46443555420994186989, -56.51681282834063324572, 400222.73679570353124290705, 0.99801604059094650712 }, + { 400487.62155657896073535085, -56.46443555419775606197, -56.51681282832842612152, 400222.73680666065774857998, 0.99801604059094761734 }, + { 400487.62116943788714706898, -56.46443456250133863250, -56.51681183466062918797, 400222.72635490167886018753, 0.99801604069467231284 }, + { 400484.31980028707766905427, -56.46436757836366382435, -56.51674485214855536697, 400222.02724612399470061064, 0.99801604768666130063 } + },{ + { 1, 0 },{ -2, 0 }, + { 333958.47237982071237638593, -90.00000000000000000000, -90.00000000000000000000, 333804.87081722758011892438, 0.99862030063297502203 }, + { 333958.47237967920955270529, -90.00000000000000000000, -90.00000000000000000000, 333804.87081722758011892438, 0.99862030063297502203 }, + { 333958.47237982566002756357, -90.00000000000000000000, -90.00000000000000000000, 333804.87081722758011892438, 0.99862030063297502203 }, + { 333958.47237982566002756357, -90.00000000000000000000, -90.00000000000000000000, 333804.87081722758011892438, 0.99862030063297502203 } + },{ + { 1, 0 },{ -2, -2 }, + { 400487.62166116386651992798, -123.53556444579005813011, -123.48318717165936675428, 400222.73679570353124290705, 0.99801604059094650712 }, + { 400487.62155657896073535085, -123.53556444580226525431, -123.48318717167158808934, 400222.73680666059954091907, 0.99801604059094761734 }, + { 400487.62116943788714706898, -123.53556543749867557835, -123.48318816533941344460, 400222.72635490121319890022, 0.99801604069467231284 }, + { 400484.31980028707766905427, -123.53563242163632196480, -123.48325514785139489504, 400222.02724612463498488069, 0.99801604768666130063 } + },{ + { 1, 0 },{ 0, -2 }, + { 247576.47264764847932383418, -153.29125371729628568573, -153.27379819455256892979, 247513.88750887679634615779, 0.99924166327570262958 }, + { 247576.47247877591871656477, -153.29125371732885696474, -153.27379819458516863051, 247513.88751566907740198076, 0.99924166327570307367 }, + { 247576.47204536388744600117, -153.29125458266443615685, -153.27379906057745984072, 247513.88563483985490165651, 0.99924166328723251773 }, + { 247573.34468778557493351400, -153.29182165051210517959, -153.27436612776349988962, 247512.65741612162673845887, 0.99924167083675718981 } + },{ + { 1, 0 },{ 2, -2 }, + { 247576.47264764847932383418, 153.29125371729628568573, 153.27379819455256892979, 247513.88750887679634615779, 0.99924166327570262958 }, + { 247576.47247877591871656477, 153.29125371732885696474, 153.27379819458516863051, 247513.88751566907740198076, 0.99924166327570307367 }, + { 247576.47204536388744600117, 153.29125458266446457856, 153.27379906057745984072, 247513.88563483985490165651, 0.99924166328723251773 }, + { 247573.34468778557493351400, 153.29182165051210517959, 153.27436612776349988962, 247512.65741612162673845887, 0.99924167083675718981 } + },{ + { 0, -1 },{ 2, 0 }, + { 248575.56516798117081634700, 63.59904041930798257454, 63.58158489649751743400, 248512.21908866314333863556, 0.99923553066716652715 }, + { 248575.56515735003631561995, 63.59904041929794260568, 63.58158489648748457057, 248512.21909045605571009219, 0.99923553066715220528 }, + { 248575.56501938513247296214, 63.59903955892717419829, 63.58158403677443004653, 248512.21158473053947091103, 0.99923553071334769715 }, + { 248574.11260137573117390275, 63.59909262487922632090, 63.58163710212382113696, 248512.67536870032199658453, 0.99923552785888392069 } + },{ + { 0, -1 },{ 2, 2 }, + { 399491.95531813317211344838, 33.86382331638844789268, 33.88128418166377286980, 399229.04036820423789322376, 0.99802588852441009859 }, + { 399491.95525925338733941317, 33.86382331636024645150, 33.88128418163555721776, 399229.04037646017968654633, 0.99802588850630413742 }, + { 399491.95420239900704473257, 33.86382231856556046523, 33.88128318318352683036, 399229.03571708954405039549, 0.99802588855242924115 }, + { 399486.91562757542124018073, 33.86329689027443379246, 33.88075775553439683563, 399226.58732164395041763783, 0.99802591281687313973 } + },{ + { 0, -1 },{ 0, 2 }, + { 331723.84192993369651958346, 0.00000000000000000000, 0.00000000000000000000, 331573.30333569750655442476, 0.99863870153788791839 }, + { 331723.84185956208966672421, 0.00000000000000000000, 0.00000000000000000000, 331573.30334328504977747798, 0.99863870152539924163 }, + { 331723.84192803525365889072, 0.00000000000000000000, 0.00000000000000000000, 331573.30334328504977747798, 0.99863870152539924163 }, + { 331720.09633564797695726156, 0.00000000000000002351, 0.00000000000000002350, 331573.30672345001948997378, 0.99863870151614875237 } + },{ + { 0, -1 },{ -2, 2 }, + { 399491.95531813317211344838, -33.86382331638844789268, -33.88128418166377286980, 399229.04036820423789322376, 0.99802588852441009859 }, + { 399491.95525925338733941317, -33.86382331636024645150, -33.88128418163555721776, 399229.04037646017968654633, 0.99802588850630413742 }, + { 399491.95420239900704473257, -33.86382231856555335980, -33.88128318318355525207, 399229.03571708960225805640, 0.99802588855242924115 }, + { 399486.91562757542124018073, -33.86329689027443379246, -33.88075775553439683563, 399226.58732164395041763783, 0.99802591281687313973 } + },{ + { 0, -1 },{ -2, 0 }, + { 248575.56516798117081634700, -63.59904041930798257454, -63.58158489649751743400, 248512.21908866314333863556, 0.99923553066716652715 }, + { 248575.56515735003631561995, -63.59904041929794260568, -63.58158489648748457057, 248512.21909045605571009219, 0.99923553066715220528 }, + { 248575.56501938513247296214, -63.59903955892717419829, -63.58158403677445846824, 248512.21158473053947091103, 0.99923553071334769715 }, + { 248574.11260137573117390275, -63.59909262487922632090, -63.58163710212379271525, 248512.67536870032199658453, 0.99923552785888392069 } + },{ + { 0, -1 },{ -2, -2 }, + { 248515.52773222429095767438, -116.44291541236518128244, -116.39055416434335654685, 248452.22805491264443844557, 0.99923590400821504787 }, + { 248515.52763759149820543826, -116.44291541237451781399, -116.39055416435273571096, 248452.22805559608968906105, 0.99923590407101092747 }, + { 248515.52758369332877919078, -116.44291626924928095832, -116.39055502319511958831, 248452.22057304141344502568, 0.99923590411705243142 }, + { 248514.07922688819235190749, -116.44286383106521043374, -116.39050258320843056481, 248452.68231273870333097875, 0.99923590134832673826 } + },{ + { 0, -1 },{ 0, -2 }, + { 110575.06481433614681009203, -180.00000000000000000000, -180.00000000000000000000, 110569.48860416181560140103, 0.99984871368918792900 }, + { 110575.06460189135395921767, 180.00000000000000000000, 180.00000000000000000000, 110569.48860883565794210881, 0.99984871370166705784 }, + { 110575.06481286860071122646, 180.00000000000000000000, 180.00000000000000000000, 110569.48860883565794210881, 0.99984871370166705784 }, + { 110573.82008000080531928688, 180.00000000000000000000, 180.00000000000000000000, 110569.49123749321734067053, 0.99984871370886085895 } + },{ + { 0, -1 },{ 2, -2 }, + { 248515.52773222429095767438, 116.44291541236518128244, 116.39055416434335654685, 248452.22805491264443844557, 0.99923590400821504787 }, + { 248515.52763759149820543826, 116.44291541237451781399, 116.39055416435273571096, 248452.22805559608968906105, 0.99923590407101092747 }, + { 248515.52758369332877919078, 116.44291626924930938003, 116.39055502319511958831, 248452.22057304164627566934, 0.99923590411705243142 }, + { 248514.07922688819235190749, 116.44286383106521043374, 116.39050258320843056481, 248452.68231273870333097875, 0.99923590134832673826 } + },{ + { 0, 1 },{ 2, 0 }, + { 248575.56516798117081634700, 116.40095958069201742546, 116.41841510350248256600, 248512.21908866314333863556, 0.99923553066716652715 }, + { 248575.56515735003631561995, 116.40095958070207871060, 116.41841510351252964028, 248512.21909045602660626173, 0.99923553066715220528 }, + { 248575.56501938513247296214, 116.40096044107282580171, 116.41841596322554153176, 248512.21158473062678240240, 0.99923553071334780817 }, + { 248574.11260137573117390275, 116.40090737512078078453, 116.41836289787615044133, 248512.67536870026378892362, 0.99923552785888392069 } + },{ + { 0, 1 },{ 2, 2 }, + { 248515.52773222429095767438, 63.55708458763482582299, 63.60944583565664345315, 248452.22805491264443844557, 0.99923590400821504787 }, + { 248515.52763759149820543826, 63.55708458762548218601, 63.60944583564726428904, 248452.22805559608968906105, 0.99923590407101092747 }, + { 248515.52758369332877919078, 63.55708373075069061997, 63.60944497680485909541, 248452.22057304115151055157, 0.99923590411705243142 }, + { 248514.07922688819235190749, 63.55713616893478246084, 63.60949741679156232976, 248452.68231273847050033510, 0.99923590134832684928 } + },{ + { 0, 1 },{ 0, 2 }, + { 110575.06481433614681009203, 0.00000000000000000000, 0.00000000000000000000, 110569.48860416181560140103, 0.99984871368918792900 }, + { 110575.06460189135395921767, 0.00000000000000000000, 0.00000000000000000000, 110569.48860883565794210881, 0.99984871370166705784 }, + { 110575.06481286860071122646, 0.00000000000000000000, 0.00000000000000000000, 110569.48860883565794210881, 0.99984871370166705784 }, + { 110573.82008000080531928688, 0.00000000000000002350, 0.00000000000000002350, 110569.49123749321734067053, 0.99984871370886085895 } + },{ + { 0, 1 },{ -2, 2 }, + { 248515.52773222429095767438, -63.55708458763482582299, -63.60944583565664345315, 248452.22805491264443844557, 0.99923590400821504787 }, + { 248515.52763759149820543826, -63.55708458762548218601, -63.60944583564726428904, 248452.22805559608968906105, 0.99923590407101092747 }, + { 248515.52758369332877919078, -63.55708373075070483083, -63.60944497680488041169, 248452.22057304150075651705, 0.99923590411705254244 }, + { 248514.07922688819235190749, -63.55713616893478246084, -63.60949741679156943519, 248452.68231273873243480921, 0.99923590134832684928 } + },{ + { 0, 1 },{ -2, 0 }, + { 248575.56516798117081634700, -116.40095958069201742546, -116.41841510350248256600, 248512.21908866314333863556, 0.99923553066716652715 }, + { 248575.56515735003631561995, -116.40095958070207871060, -116.41841510351252964028, 248512.21909045602660626173, 0.99923553066715220528 }, + { 248575.56501938513247296214, -116.40096044107282580171, -116.41841596322554153176, 248512.21158473062678240240, 0.99923553071334780817 }, + { 248574.11260137573117390275, -116.40090737512078078453, -116.41836289787615044133, 248512.67536870026378892362, 0.99923552785888392069 } + },{ + { 0, 1 },{ -2, -2 }, + { 399491.95531813317211344838, -146.13617668361155210732, -146.11871581833622713020, 399229.04036820423789322376, 0.99802588852441009859 }, + { 399491.95525925338733941317, -146.13617668363974644308, -146.11871581836444988767, 399229.04037646006327122450, 0.99802588850630413742 }, + { 399491.95420239900704473257, -146.13617768143444664020, -146.11871681681645895878, 399229.03571708971867337823, 0.99802588855242924115 }, + { 399486.91562757542124018073, -146.13670310972554489126, -146.11924224446559605894, 399226.58732164406683295965, 0.99802591281687325075 } + },{ + { 0, 1 },{ 0, -2 }, + { 331723.84192993369651958346, -180.00000000000000000000, -180.00000000000000000000, 331573.30333569750655442476, 0.99863870153788791839 }, + { 331723.84185956208966672421, 180.00000000000000000000, 180.00000000000000000000, 331573.30334328504977747798, 0.99863870152539924163 }, + { 331723.84192803525365889072, 180.00000000000000000000, 180.00000000000000000000, 331573.30334328504977747798, 0.99863870152539924163 }, + { 331720.09633564797695726156, 180.00000000000000000000, 180.00000000000000000000, 331573.30672345001948997378, 0.99863870151614875237 } + },{ + { 0, 1 },{ 2, -2 }, + { 399491.95531813317211344838, 146.13617668361155210732, 146.11871581833622713020, 399229.04036820423789322376, 0.99802588852441009859 }, + { 399491.95525925338733941317, 146.13617668363974644308, 146.11871581836444988767, 399229.04037646006327122450, 0.99802588850630413742 }, + { 399491.95420239900704473257, 146.13617768143444664020, 146.11871681681645895878, 399229.03571708971867337823, 0.99802588855242924115 }, + { 399486.91562757542124018073, 146.13670310972554489126, 146.11924224446559605894, 399226.58732164406683295965, 0.99802591281687325075 } + }, + { + { -1, -1 },{ 2, 0 }, + { 351772.23553088010521605611, 71.69677339271241578444, 71.67058676207953737958, 351592.72256732499226927757, 0.99846922689201267342 }, + { 351772.23552330053644254804, 71.69677339270522509196, 71.67058676207236089795, 351592.72256738768192008138, 0.99846922689200567902 }, + { 351772.23547190619865432382, 71.69677274795321864076, 71.67058611830732672843, 351592.71064292185474187136, 0.99846922699591911243 }, + { 351771.13000385620398446918, 71.69688960494077889507, 71.67070297450321447741, 351594.87308142206165939569, 0.99846920815167106156 } + }, { + { -1, -1 },{ 2, 2 }, + { 470675.27496387914288789034, 45.18799532476352709409, 45.21418997011227247640, 470245.32092262554215267301, 0.99726004843767979136 }, + { 470675.27491378918057307601, 45.18799532474472613330, 45.21418997009345730476, 470245.32093124865787103772, 0.99726004841255500022 }, + { 470675.27385581465205177665, 45.18799424651773222195, 45.21418889088008796762, 470245.31203990190988406539, 0.99726004851631100401 }, + { 470669.97387331607751548290, 45.18767381182056652733, 45.21386845703356982540, 470242.67608062457293272018, 0.99726007931332938394 } + }, { + { -1, -1 },{ 0, 2 }, + { 349898.53698544885264709592, 18.54804530050607525027, 18.55677506382081531910, 349721.87727315956726670265, 0.99848548653821667109 }, + { 349898.53691851865733042359, 18.54804530047409016902, 18.55677506378881247429, 349721.87728093314217403531, 0.99848548652432367323 }, + { 349898.53644461580552160740, 18.54804465014367664821, 18.55677441312981201804, 349721.87595040485030040145, 0.99848548653585678103 }, + { 349894.27001174906035885215, 18.54754137243966738424, 18.55627113576925424354, 349720.85020991315832361579, 0.99848549544738174344 } + }, { + { -1, -1 },{ -2, 2 }, + { 349898.53698544885264709592, -18.54804530050607525027, -18.55677506382081531910, 349721.87727315956726670265, 0.99848548653821667109 }, + { 349898.53691851865733042359, -18.54804530047409016902, -18.55677506378881247429, 349721.87728093314217403531, 0.99848548652432367323 }, + { 349898.53644461580552160740, -18.54804465014367664821, -18.55677441312981201804, 349721.87595040485030040145, 0.99848548653585678103 }, + { 349894.27001174906035885215, -18.54754137243966738424, -18.55627113576928266525, 349720.85020991315832361579, 0.99848549544738174344 } + }, { + { -1, -1 },{ -2, 0 }, + { 156899.56829134028521366417, -45.19676732164486310239, -45.18804022935886877121, 156883.63778222308610565960, 0.99969540695122460772 }, + { 156899.56827460310887545347, -45.19676732162573529195, -45.18804022933975517162, 156883.63778401838499121368, 0.99969540695121617002 }, + { 156899.56792193598812445998, -45.19676624219880523015, -45.18803915024161454994, 156883.63480984271154738963, 0.99969540696276681935 }, + { 156897.79947260793414898217, -45.19644594033049145310, -45.18771884804953486992, 156882.75281389255542308092, 0.99969541038810816325 } + }, { + { -1, -1 },{ -2, -2 }, + { 156876.14940188667969778180, -134.82952991582811819171, -134.80335129773999369718, 156860.22615479407249949872, 0.99969549952259184611 }, + { 156876.14925185780157335103, -134.82952991584656388113, -134.80335129775846780831, 156860.22615983051946386695, 0.99969549954768643918 }, + { 156876.14903264911845326424, -134.82953099167991695140, -134.80335237457535413341, 156860.22319510785746388137, 0.99969549955919845274 }, + { 156874.38594904550700448453, -134.82985169207830722371, -134.80367307400518939176, 156859.34477911840076558292, 0.99969550299904519353 } + }, { + { -1, -1 },{ 0, -2 }, + { 156876.14940188667969778180, 134.82952991582811819171, 134.80335129773999369718, 156860.22615479407249949872, 0.99969549952259184611 }, + { 156876.14925185780157335103, 134.82952991584656388113, 134.80335129775846780831, 156860.22615983051946386695, 0.99969549954768643918 }, + { 156876.14903264911845326424, 134.82953099167994537311, 134.80335237457538255512, 156860.22319510785746388137, 0.99969549955919856377 }, + { 156874.38594904550700448453, 134.82985169207830722371, 134.80367307400518939176, 156859.34477911840076558292, 0.99969550299904519353 } + }, { + { -1, -1 },{ 2, -2 }, + { 351676.50043935602298006415, 108.36087395536006283692, 108.28232205125480902552, 351497.13544799503870308399, 0.99847006808788085763 }, + { 351676.50037266127765178680, 108.36087395536665667350, 108.28232205126143128382, 351497.13543194788508117199, 0.99847006821303718738 }, + { 351676.50038040406070649624, 108.36087459655153963922, 108.28232269539883247944, 351497.12354394816793501377, 0.99847006831660412018 }, + { 351675.39839278126601129770, 108.36075825022818719390, 108.28220634670809374711, 351499.26940269087208434939, 0.99847004976658149111 } + }, { + { -1, 1 },{ 2, 0 }, + { 351772.23553088010521605611, 108.30322660728758421556, 108.32941323792046262042, 351592.72256732499226927757, 0.99846922689201267342 }, + { 351772.23552330053644254804, 108.30322660729477490804, 108.32941323792763910205, 351592.72256738756550475955, 0.99846922689200567902 }, + { 351772.23547190619865432382, 108.30322725204678135924, 108.32941388169267327157, 351592.71064292197115719318, 0.99846922699591911243 }, + { 351771.13000385620398446918, 108.30311039505922110493, 108.32929702549677131174, 351594.87308142217807471752, 0.99846920815167106156 } + }, { + { -1, 1 },{ 2, 2 }, + { 351676.50043935602298006415, 71.63912604463993716308, 71.71767794874519097448, 351497.13544799503870308399, 0.99847006808788085763 }, + { 351676.50037266127765178680, 71.63912604463332911564, 71.71767794873858292704, 351497.13543194829253479838, 0.99847006821303718738 }, + { 351676.50038040406070649624, 71.63912540344847457163, 71.71767730460115330970, 351497.12354394729482010007, 0.99847006831660423121 }, + { 351675.39839278126601129770, 71.63924174977181280610, 71.71779365329189204203, 351499.26940269029000774026, 0.99847004976658149111 } + }, { + { -1, 1 },{ 0, 2 }, + { 156876.14940188667969778180, 45.17047008417186759743, 45.19664870225999919739, 156860.22615479407249949872, 0.99969549952259184611 }, + { 156876.14925185780157335103, 45.17047008415342190801, 45.19664870224154640255, 156860.22615983063587918878, 0.99969549954768632816 }, + { 156876.14903264911845326424, 45.17046900832006883775, 45.19664762542461744488, 156860.22319510774104855955, 0.99969549955919845274 }, + { 156874.38594904550700448453, 45.17014830792169988172, 45.19632692599481060824, 156859.34477911831345409155, 0.99969550299904519353 } + }, { + { -1, 1 },{ -2, 2 }, + { 156876.14940188667969778180, -45.17047008417186759743, -45.19664870225999919739, 156860.22615479407249949872, 0.99969549952259184611 }, + { 156876.14925185780157335103, -45.17047008415342190801, -45.19664870224154640255, 156860.22615983063587918878, 0.99969549954768632816 }, + { 156876.14903264911845326424, -45.17046900832009015403, -45.19664762542463876116, 156860.22319510785746388137, 0.99969549955919856377 }, + { 156874.38594904550700448453, -45.17014830792169988172, -45.19632692599484613538, 156859.34477911848807707429, 0.99969550299904519353 } + }, { + { -1, 1 },{ -2, 0 }, + { 156899.56829134028521366417, -134.80323267835512979218, -134.81195977064112412336, 156883.63778222308610565960, 0.99969540695122460772 }, + { 156899.56827460310887545347, -134.80323267837425760263, -134.81195977066025193380, 156883.63778401838499121368, 0.99969540695121617002 }, + { 156899.56792193598812445998, -134.80323375780119476985, -134.81196084975837834463, 156883.63480984274065122008, 0.99969540696276681935 }, + { 156897.79947260793414898217, -134.80355405966952275776, -134.81228115195048644637, 156882.75281389255542308092, 0.99969541038810816325 } + }, { + { -1, 1 },{ -2, -2 }, + { 349898.53698544885264709592, -161.45195469949391053888, -161.44322493617917757547, 349721.87727315956726670265, 0.99848548653821667109 }, + { 349898.53691851865733042359, -161.45195469952594180540, -161.44322493621118042029, 349721.87728093314217403531, 0.99848548652432367323 }, + { 349898.53644461580552160740, -161.45195534985634822078, -161.44322558687019864010, 349721.87595040485030040145, 0.99848548653585678103 }, + { 349894.27001174906035885215, -161.45245862756033261576, -161.44372886423073509832, 349720.85020991315832361579, 0.99848549544738174344 } + }, { + { -1, 1 },{ 0, -2 }, + { 349898.53698544885264709592, 161.45195469949391053888, 161.44322493617917757547, 349721.87727315956726670265, 0.99848548653821667109 }, + { 349898.53691851865733042359, 161.45195469952594180540, 161.44322493621118042029, 349721.87728093314217403531, 0.99848548652432367323 }, + { 349898.53644461580552160740, 161.45195534985634822078, 161.44322558687019864010, 349721.87595040485030040145, 0.99848548653585678103 }, + { 349894.27001174906035885215, 161.45245862756033261576, 161.44372886423073509832, 349720.85020991315832361579, 0.99848549544738174344 } + }, { + { -1, 1 },{ 2, -2 }, + { 470675.27496387914288789034, 134.81200467523646580048, 134.78581002988772752360, 470245.32092262554215267301, 0.99726004843767979136 }, + { 470675.27491378918057307601, 134.81200467525528097212, 134.78581002990657111695, 470245.32093124854145571589, 0.99726004841255500022 }, + { 470675.27385581465205177665, 134.81200575348228198891, 134.78581110911991913781, 470245.31203990190988406539, 0.99726004851631100401 }, + { 470669.97387331607751548290, 134.81232618817941215639, 134.78613154296644438546, 470242.67608062474755570292, 0.99726007931332960599 } + }, { + { 1, 1 },{ 2, 0 }, + { 156899.56829134028521366417, 134.80323267835512979218, 134.81195977064112412336, 156883.63778222308610565960, 0.99969540695122460772 }, + { 156899.56827460310887545347, 134.80323267837425760263, 134.81195977066025193380, 156883.63778401838499121368, 0.99969540695121617002 }, + { 156899.56792193598812445998, 134.80323375780122319156, 134.81196084975840676634, 156883.63480984268244355917, 0.99969540696276681935 }, + { 156897.79947260793414898217, 134.80355405966952275776, 134.81228115195048644637, 156882.75281389255542308092, 0.99969541038810816325 } + }, { + { 1, 1 },{ 2, 2 }, + { 156876.14940188667969778180, 45.17047008417186759743, 45.19664870225999919739, 156860.22615479407249949872, 0.99969549952259184611 }, + { 156876.14925185780157335103, 45.17047008415342190801, 45.19664870224154640255, 156860.22615983063587918878, 0.99969549954768632816 }, + { 156876.14903264911845326424, 45.17046900832006883775, 45.19664762542461744488, 156860.22319510774104855955, 0.99969549955919845274 }, + { 156874.38594904550700448453, 45.17014830792169988172, 45.19632692599481060824, 156859.34477911831345409155, 0.99969550299904519353 } + }, { + { 1, 1 },{ 0, 2 }, + { 156876.14940188667969778180, -45.17047008417186759743, -45.19664870225999919739, 156860.22615479407249949872, 0.99969549952259184611 }, + { 156876.14925185780157335103, -45.17047008415342190801, -45.19664870224154640255, 156860.22615983063587918878, 0.99969549954768632816 }, + { 156876.14903264911845326424, -45.17046900832009015403, -45.19664762542463876116, 156860.22319510785746388137, 0.99969549955919856377 }, + { 156874.38594904550700448453, -45.17014830792169988172, -45.19632692599484613538, 156859.34477911848807707429, 0.99969550299904519353 } + }, { + { 1, 1 },{ -2, 2 }, + { 351676.50043935602298006415, -71.63912604463993716308, -71.71767794874519097448, 351497.13544799503870308399, 0.99847006808788085763 }, + { 351676.50037266127765178680, -71.63912604463332911564, -71.71767794873858292704, 351497.13543194829253479838, 0.99847006821303718738 }, + { 351676.50038040406070649624, -71.63912540344847457163, -71.71767730460118173141, 351497.12354394828435033560, 0.99847006831660412018 }, + { 351675.39839278126601129770, -71.63924174977181280610, -71.71779365329184940947, 351499.26940268895123153925, 0.99847004976658171316 } + }, { + { 1, 1 },{ -2, 0 }, + { 351772.23553088010521605611, -108.30322660728758421556, -108.32941323792046262042, 351592.72256732499226927757, 0.99846922689201267342 }, + { 351772.23552330053644254804, -108.30322660729477490804, -108.32941323792763910205, 351592.72256738756550475955, 0.99846922689200567902 }, + { 351772.23547190619865432382, -108.30322725204673872668, -108.32941388169263063901, 351592.71064292272785678506, 0.99846922699591933448 }, + { 351771.13000385620398446918, -108.30311039505922110493, -108.32929702549677131174, 351594.87308142217807471752, 0.99846920815167106156 } + }, { + { 1, 1 },{ -2, -2 }, + { 470675.27496387914288789034, -134.81200467523646580048, -134.78581002988772752360, 470245.32092262554215267301, 0.99726004843767979136 }, + { 470675.27491378918057307601, -134.81200467525528097212, -134.78581002990657111695, 470245.32093124854145571589, 0.99726004841255500022 }, + { 470675.27385581465205177665, -134.81200575348222514549, -134.78581110911991913781, 470245.31203990196809172630, 0.99726004851631100401 }, + { 470669.97387331607751548290, -134.81232618817941215639, -134.78613154296644438546, 470242.67608062474755570292, 0.99726007931332960599 } + }, { + { 1, 1 },{ 0, -2 }, + { 349898.53698544885264709592, -161.45195469949391053888, -161.44322493617917757547, 349721.87727315956726670265, 0.99848548653821667109 }, + { 349898.53691851865733042359, -161.45195469952594180540, -161.44322493621118042029, 349721.87728093314217403531, 0.99848548652432367323 }, + { 349898.53644461580552160740, -161.45195534985634822078, -161.44322558687019864010, 349721.87595040485030040145, 0.99848548653585678103 }, + { 349894.27001174906035885215, -161.45245862756033261576, -161.44372886423073509832, 349720.85020991315832361579, 0.99848549544738174344 } + }, { + { 1, 1 },{ 2, -2 }, + { 349898.53698544885264709592, 161.45195469949391053888, 161.44322493617917757547, 349721.87727315956726670265, 0.99848548653821667109 }, + { 349898.53691851865733042359, 161.45195469952594180540, 161.44322493621118042029, 349721.87728093314217403531, 0.99848548652432367323 }, + { 349898.53644461580552160740, 161.45195534985634822078, 161.44322558687019864010, 349721.87595040485030040145, 0.99848548653585678103 }, + { 349894.27001174906035885215, 161.45245862756033261576, 161.44372886423073509832, 349720.85020991315832361579, 0.99848549544738174344 } + }, { + { 1, -1 },{ 2, 0 }, + { 156899.56829134028521366417, 45.19676732164486310239, 45.18804022935886877121, 156883.63778222308610565960, 0.99969540695122460772 }, + { 156899.56827460310887545347, 45.19676732162573529195, 45.18804022933975517162, 156883.63778401838499121368, 0.99969540695121617002 }, + { 156899.56792193598812445998, 45.19676624219878391386, 45.18803915024158612823, 156883.63480984268244355917, 0.99969540696276681935 }, + { 156897.79947260793414898217, 45.19644594033049145310, 45.18771884804951355363, 156882.75281389255542308092, 0.99969541038810816325 } + }, { + { 1, -1 },{ 2, 2 }, + { 349898.53698544885264709592, 18.54804530050607525027, 18.55677506382081531910, 349721.87727315956726670265, 0.99848548653821667109 }, + { 349898.53691851865733042359, 18.54804530047409016902, 18.55677506378881247429, 349721.87728093314217403531, 0.99848548652432367323 }, + { 349898.53644461580552160740, 18.54804465014367664821, 18.55677441312981201804, 349721.87595040485030040145, 0.99848548653585678103 }, + { 349894.27001174906035885215, 18.54754137243966738424, 18.55627113576925424354, 349720.85020991315832361579, 0.99848549544738174344 } + }, { + { 1, -1 },{ 0, 2 }, + { 349898.53698544885264709592, -18.54804530050607525027, -18.55677506382081531910, 349721.87727315956726670265, 0.99848548653821667109 }, + { 349898.53691851865733042359, -18.54804530047409016902, -18.55677506378881247429, 349721.87728093314217403531, 0.99848548652432367323 }, + { 349898.53644461580552160740, -18.54804465014367664821, -18.55677441312981201804, 349721.87595040485030040145, 0.99848548653585678103 }, + { 349894.27001174906035885215, -18.54754137243966738424, -18.55627113576928266525, 349720.85020991315832361579, 0.99848549544738174344 } + }, { + { 1, -1 },{ -2, 2 }, + { 470675.27496387914288789034, -45.18799532476352709409, -45.21418997011227247640, 470245.32092262554215267301, 0.99726004843767979136 }, + { 470675.27491378918057307601, -45.18799532474472613330, -45.21418997009345730476, 470245.32093124865787103772, 0.99726004841255500022 }, + { 470675.27385581465205177665, -45.18799424651773932737, -45.21418889088011638933, 470245.31203990196809172630, 0.99726004851631100401 }, + { 470669.97387331607751548290, -45.18767381182056652733, -45.21386845703356271997, 470242.67608062445651739836, 0.99726007931332938394 } + }, { + { 1, -1 },{ -2, 0 }, + { 351772.23553088010521605611, -71.69677339271241578444, -71.67058676207953737958, 351592.72256732499226927757, 0.99846922689201267342 }, + { 351772.23552330053644254804, -71.69677339270522509196, -71.67058676207236089795, 351592.72256738768192008138, 0.99846922689200567902 }, + { 351772.23547190619865432382, -71.69677274795323285161, -71.67058611830736936099, 351592.71064292214578017592, 0.99846922699591911243 }, + { 351771.13000385620398446918, -71.69688960494077889507, -71.67070297450322868826, 351594.87308142206165939569, 0.99846920815167106156 } + }, { + { 1, -1 },{ -2, -2 }, + { 351676.50043935602298006415, -108.36087395536006283692, -108.28232205125480902552, 351497.13544799503870308399, 0.99847006808788085763 }, + { 351676.50037266127765178680, -108.36087395536665667350, -108.28232205126143128382, 351497.13543194788508117199, 0.99847006821303718738 }, + { 351676.50038040406070649624, -108.36087459655152542837, -108.28232269539881826859, 351497.12354394845897331834, 0.99847006831660412018 }, + { 351675.39839278126601129770, -108.36075825022818719390, -108.28220634670809374711, 351499.26940269087208434939, 0.99847004976658149111 } + }, { + { 1, -1 },{ 0, -2 }, + { 156876.14940188667969778180, -134.82952991582811819171, -134.80335129773999369718, 156860.22615479407249949872, 0.99969549952259184611 }, + { 156876.14925185780157335103, -134.82952991584656388113, -134.80335129775846780831, 156860.22615983051946386695, 0.99969549954768643918 }, + { 156876.14903264911845326424, -134.82953099167991695140, -134.80335237457535413341, 156860.22319510785746388137, 0.99969549955919845274 }, + { 156874.38594904550700448453, -134.82985169207830722371, -134.80367307400518939176, 156859.34477911840076558292, 0.99969550299904519353 } + }, { + { 1, -1 },{ 2, -2 }, + { 156876.14940188667969778180, 134.82952991582811819171, 134.80335129773999369718, 156860.22615479407249949872, 0.99969549952259184611 }, + { 156876.14925185780157335103, 134.82952991584656388113, 134.80335129775846780831, 156860.22615983051946386695, 0.99969549954768643918 }, + { 156876.14903264911845326424, 134.82953099167994537311, 134.80335237457538255512, 156860.22319510785746388137, 0.99969549955919856377 }, + { 156874.38594904550700448453, 134.82985169207830722371, 134.80367307400518939176, 156859.34477911840076558292, 0.99969550299904519353 } + } +}; + +size_t const expected_size = sizeof(expected) / sizeof(expected_results); + +#endif // BOOST_GEOMETRY_TEST_INVERSE_CASES_HPP diff --git a/test/formulas/test_formula.hpp b/test/formulas/test_formula.hpp new file mode 100644 index 000000000..92f690bd3 --- /dev/null +++ b/test/formulas/test_formula.hpp @@ -0,0 +1,59 @@ +// Boost.Geometry +// Unit Test + +// 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, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GEOMETRY_TEST_FORMULA_HPP +#define BOOST_GEOMETRY_TEST_FORMULA_HPP + +#include + +#include + +void normalize_deg(double & deg) +{ + while (deg > 180.0) + deg -= 360.0; + while (deg <= -180.0) + deg += 360.0; +} + +void check_one(double result, double expected, double reference, double reference_error, bool normalize = false) +{ + if (normalize) + { + normalize_deg(result); + normalize_deg(expected); + normalize_deg(reference); + } + + double res_max = (std::max)(bg::math::abs(result), bg::math::abs(expected)); + if (res_max > 100 * std::numeric_limits::epsilon()) + { + BOOST_CHECK_CLOSE(result, expected, 0.001); + } + else if (res_max > 10 * std::numeric_limits::epsilon()) + { + BOOST_CHECK_CLOSE(result, expected, 0.1); + } + else if (res_max > std::numeric_limits::epsilon()) + { + BOOST_CHECK_CLOSE(result, expected, 10); + } + + // NOTE: in some cases it probably will be necessary to normalize + // the differences between the result and expected result + double ref_diff = bg::math::abs(result - reference); + double ref_max = (std::max)(bg::math::abs(result), bg::math::abs(reference)); + bool is_ref_close = ref_diff <= reference_error || ref_diff <= reference_error * ref_max; + + BOOST_CHECK_MESSAGE((is_ref_close), std::setprecision(16) << "{" << result << "} and {" << reference << "} not close enough."); +} + +#endif // BOOST_GEOMETRY_TEST_FORMULA_HPP diff --git a/test/geometries/adapted.cpp b/test/geometries/adapted.cpp index 4dd8c8923..173314396 100644 --- a/test/geometries/adapted.cpp +++ b/test/geometries/adapted.cpp @@ -61,11 +61,11 @@ template void test_geometry(G const& geometry, std::size_t expected_size = 0) { #if defined(BOOST_GEOMETRY_TEST_RING) - BOOST_CONCEPT_ASSERT( (bg::concept::ConstRing) ); + BOOST_CONCEPT_ASSERT( (bg::concepts::ConstRing) ); #elif defined(BOOST_GEOMETRY_TEST_MULTI_POINT) - BOOST_CONCEPT_ASSERT( (bg::concept::ConstMultiPoint) ); + BOOST_CONCEPT_ASSERT( (bg::concepts::ConstMultiPoint) ); #else - BOOST_CONCEPT_ASSERT( (bg::concept::ConstLinestring) ); + BOOST_CONCEPT_ASSERT( (bg::concepts::ConstLinestring) ); #endif typedef typename bg::point_type::type P; diff --git a/test/geometries/boost_polygon.cpp b/test/geometries/boost_polygon.cpp index 42dc2c5a8..c535b22d1 100644 --- a/test/geometries/boost_polygon.cpp +++ b/test/geometries/boost_polygon.cpp @@ -73,7 +73,7 @@ template void test_coordinate_type() { // 1a: Check if Boost.Polygon's point fulfills Boost.Geometry's point concept - bg::concept::check >(); + bg::concepts::check >(); // 1b: use a Boost.Polygon point in Boost.Geometry, calc. distance with two point types boost::polygon::point_data boost_polygon_point(1, 2); @@ -84,7 +84,7 @@ void test_coordinate_type() 2 * std::sqrt(2.0)); // 2a: Check if Boost.Polygon's box fulfills Boost.Geometry's box concept - bg::concept::check >(); + bg::concepts::check >(); // 2b: use a Boost.Polygon rectangle in Boost.Geometry, compare with boxes boost::polygon::rectangle_data boost_polygon_box; @@ -99,7 +99,7 @@ void test_coordinate_type() BOOST_CHECK_EQUAL(boost_polygon_area, boost_polygon_area_by_boost_polygon); // 3a: Check if Boost.Polygon's polygon fulfills Boost.Geometry's ring concept - bg::concept::check >(); + bg::concepts::check >(); // 3b: use a Boost.Polygon polygon (ring) boost::polygon::polygon_data boost_polygon_ring; diff --git a/test/geometries/concepts/check.cpp b/test/geometries/concepts/check.cpp index c4996a7a5..07b344295 100644 --- a/test/geometries/concepts/check.cpp +++ b/test/geometries/concepts/check.cpp @@ -71,6 +71,6 @@ template <> struct access int main() { - bg::concept::check(); - bg::concept::check(); + bg::concepts::check(); + bg::concepts::check(); } diff --git a/test/geometries/custom_linestring.cpp b/test/geometries/custom_linestring.cpp index 35315503a..66feef665 100644 --- a/test/geometries/custom_linestring.cpp +++ b/test/geometries/custom_linestring.cpp @@ -80,8 +80,8 @@ namespace boost { namespace geometry { namespace traits { template void test_linestring() { - BOOST_CONCEPT_ASSERT( (bg::concept::Linestring) ); - BOOST_CONCEPT_ASSERT( (bg::concept::ConstLinestring) ); + BOOST_CONCEPT_ASSERT( (bg::concepts::Linestring) ); + BOOST_CONCEPT_ASSERT( (bg::concepts::ConstLinestring) ); G geometry; typedef typename bg::point_type::type P; diff --git a/test/geometries/segment.cpp b/test/geometries/segment.cpp index c6cef3e10..dcbb2ed18 100644 --- a/test/geometries/segment.cpp +++ b/test/geometries/segment.cpp @@ -49,8 +49,8 @@ void test_all() BOOST_CHECK_EQUAL(&s.second, &p2); // Compilation tests, all things should compile. - BOOST_CONCEPT_ASSERT( (bg::concept::ConstSegment) ); - BOOST_CONCEPT_ASSERT( (bg::concept::Segment) ); + BOOST_CONCEPT_ASSERT( (bg::concepts::ConstSegment) ); + BOOST_CONCEPT_ASSERT( (bg::concepts::Segment) ); typedef typename bg::coordinate_type::type T; typedef typename bg::point_type::type SP; @@ -59,7 +59,7 @@ void test_all() //std::cout << sizeof(typename coordinate_type::type) << std::endl; typedef bg::model::referring_segment

refseg_t; - //BOOST_CONCEPT_ASSERT( (concept::ConstSegment) ); + //BOOST_CONCEPT_ASSERT( (concepts::ConstSegment) ); refseg_t seg(p1, p2); diff --git a/test/strategies/andoyer.cpp b/test/strategies/andoyer.cpp index 271d593c5..01b31c73d 100644 --- a/test/strategies/andoyer.cpp +++ b/test/strategies/andoyer.cpp @@ -79,7 +79,7 @@ void test_distance(double lon1, double lat1, double lon2, double lat2, double ex BOOST_CONCEPT_ASSERT ( - (bg::concept::PointDistanceStrategy) + (bg::concepts::PointDistanceStrategy) ); andoyer_type andoyer; diff --git a/test/strategies/cross_track.cpp b/test/strategies/cross_track.cpp index 1b02c8835..861251e4e 100644 --- a/test/strategies/cross_track.cpp +++ b/test/strategies/cross_track.cpp @@ -83,7 +83,7 @@ void test_distance( BOOST_CONCEPT_ASSERT ( - (bg::concept::PointSegmentDistanceStrategy) + (bg::concepts::PointSegmentDistanceStrategy) ); diff --git a/test/strategies/haversine.cpp b/test/strategies/haversine.cpp index 9aaae3386..b6853954d 100644 --- a/test/strategies/haversine.cpp +++ b/test/strategies/haversine.cpp @@ -43,7 +43,7 @@ struct test_distance BOOST_CONCEPT_ASSERT ( - (bg::concept::PointDistanceStrategy) + (bg::concepts::PointDistanceStrategy) ); diff --git a/test/strategies/pythagoras.cpp b/test/strategies/pythagoras.cpp index 3b81bf144..de1101e46 100644 --- a/test/strategies/pythagoras.cpp +++ b/test/strategies/pythagoras.cpp @@ -145,7 +145,7 @@ void test_services() typedef bgsd::pythagoras strategy_type; - BOOST_CONCEPT_ASSERT( (bg::concept::PointDistanceStrategy) ); + BOOST_CONCEPT_ASSERT( (bg::concepts::PointDistanceStrategy) ); typedef typename bgsd::services::return_type::type return_type; diff --git a/test/strategies/pythagoras_point_box.cpp b/test/strategies/pythagoras_point_box.cpp index 9b1e817f3..31810e1cb 100644 --- a/test/strategies/pythagoras_point_box.cpp +++ b/test/strategies/pythagoras_point_box.cpp @@ -206,7 +206,7 @@ inline void test_services() typedef bgsd::pythagoras_point_box strategy_type; BOOST_CONCEPT_ASSERT - ( (bg::concept::PointDistanceStrategy) ); + ( (bg::concepts::PointDistanceStrategy) ); typedef typename bgsd::services::return_type < diff --git a/test/strategies/test_projected_point.hpp b/test/strategies/test_projected_point.hpp index 0abde3ced..72a0d906d 100644 --- a/test/strategies/test_projected_point.hpp +++ b/test/strategies/test_projected_point.hpp @@ -81,7 +81,7 @@ void test_services() typedef bgsd::projected_point strategy_type; - BOOST_CONCEPT_ASSERT( (bg::concept::PointSegmentDistanceStrategy) ); + BOOST_CONCEPT_ASSERT( (bg::concepts::PointSegmentDistanceStrategy) ); typedef typename services::return_type::type return_type; @@ -140,11 +140,11 @@ void test_2d(std::string const& wkt_p, BOOST_CONCEPT_ASSERT ( - (bg::concept::PointSegmentDistanceStrategy) + (bg::concepts::PointSegmentDistanceStrategy) ); BOOST_CONCEPT_ASSERT ( - (bg::concept::PointSegmentDistanceStrategy) + (bg::concepts::PointSegmentDistanceStrategy) ); { diff --git a/test/strategies/test_within.hpp b/test/strategies/test_within.hpp index 4ceb2608e..d47080ccf 100644 --- a/test/strategies/test_within.hpp +++ b/test/strategies/test_within.hpp @@ -72,7 +72,7 @@ void test_point_in_polygon(std::string const& case_id, bool expected, bool use_within = true) { - BOOST_CONCEPT_ASSERT( (bg::concept::WithinStrategyPolygonal) ); + BOOST_CONCEPT_ASSERT( (bg::concepts::WithinStrategyPolygonal) ); bool detected = use_within ? bg::within(point, polygon, strategy) : bg::covered_by(point, polygon, strategy); diff --git a/test/strategies/thomas.cpp b/test/strategies/thomas.cpp index cac10ac51..5770dc0b1 100644 --- a/test/strategies/thomas.cpp +++ b/test/strategies/thomas.cpp @@ -52,7 +52,7 @@ void test_distance(double lon1, double lat1, double lon2, double lat2, double ex BOOST_CONCEPT_ASSERT ( - (bg::concept::PointDistanceStrategy) + (bg::concepts::PointDistanceStrategy) ); thomas_type thomas; diff --git a/test/strategies/vincenty.cpp b/test/strategies/vincenty.cpp index 64f150f1d..b3b17936b 100644 --- a/test/strategies/vincenty.cpp +++ b/test/strategies/vincenty.cpp @@ -169,7 +169,7 @@ void test_vincenty(double lon1, double lat1, double lon2, double lat2, BOOST_CONCEPT_ASSERT( ( - bg::concept::PointDistanceStrategy) + bg::concepts::PointDistanceStrategy) ); vincenty_type vincenty(spheroid);