diff --git a/doc/release_notes.qbk b/doc/release_notes.qbk index 8d98af080..c63f4a1f8 100644 --- a/doc/release_notes.qbk +++ b/doc/release_notes.qbk @@ -19,6 +19,18 @@ [section:release_notes Release Notes] +[/=================] +[heading Boost 1.72] +[/=================] + +[*Improvements] + +* Various improvements related to robustness of set and relational operation. + +[*Bugfixes] + +* Fixed errors in generation of asymmetric one-sided buffer + [/=================] [heading Boost 1.71] [/=================] diff --git a/example/ml03_distance_formula.cpp b/example/ml03_distance_formula.cpp new file mode 100644 index 000000000..6ddd9fc42 --- /dev/null +++ b/example/ml03_distance_formula.cpp @@ -0,0 +1,37 @@ +// Boost.Geometry + +// Copyright (c) 2018 Adeel Ahmad, Islamabad, Pakistan. + +// Contributed and/or modified by Adeel Ahmad, as part of Google Summer of Code 2018 program. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Formula example - Show how to use Karney's direct method. + +#include +#include + +using namespace boost::geometry; + +int main() +{ + double lon1_deg = 0.; + double lat1_deg = 73.114273316483; + double distance_m = 19992866.6147806; + double azi12_deg = 78.154765899661; + + // Create an alias of the formula. + typedef formula::karney_direct karney_direct; + + // Structure to hold the resulting values. + formula::result_direct result; + + // WGS-84 spheroid. + srs::spheroid spheroid(6378137.0, 6356752.3142451793); + + result = karney_direct::apply(lon1_deg, lat1_deg, distance_m, azi12_deg, spheroid); + + return 0; +} diff --git a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp index c79abcc7a..c921f4759 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp @@ -97,7 +97,7 @@ struct buffer_range typename JoinStrategy, typename EndStrategy, typename RobustPolicy, - typename Strategy + typename SideStrategy > static inline void add_join(Collection& collection, @@ -113,13 +113,13 @@ struct buffer_range JoinStrategy const& join_strategy, EndStrategy const& end_strategy, RobustPolicy const& , - Strategy const& strategy) // side strategy + SideStrategy const& side_strategy) // side strategy { output_point_type intersection_point; geometry::assign_zero(intersection_point); geometry::strategy::buffer::join_selector join - = get_join_type(penultimate_input, previous_input, input, strategy); + = get_join_type(penultimate_input, previous_input, input, side_strategy); if (join == geometry::strategy::buffer::join_convex) { // Calculate the intersection-point formed by the two sides. @@ -187,14 +187,14 @@ struct buffer_range return arithmetic::similar_direction(p, q); } - template + template static inline geometry::strategy::buffer::join_selector get_join_type( output_point_type const& p0, output_point_type const& p1, output_point_type const& p2, - Strategy const& strategy) // side strategy + SideStrategy const& side_strategy) { - int const side = strategy.apply(p0, p1, p2); + int const side = side_strategy.apply(p0, p1, p2); return side == -1 ? geometry::strategy::buffer::join_convex : side == 1 ? geometry::strategy::buffer::join_concave : similar_direction(p0, p1, p2) @@ -972,7 +972,7 @@ inline void buffer_inserter(GeometryInput const& geometry_input, OutputIterator end_strategy, point_strategy, robust_policy, intersection_strategy.get_side_strategy()); - collection.get_turns(); + collection.get_turns(distance_strategy); collection.classify_turns(); if (BOOST_GEOMETRY_CONDITION(areal)) { 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 de3f3c2b4..470eb8d3c 100644 --- a/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/buffered_piece_collection.hpp @@ -167,7 +167,7 @@ struct buffered_piece_collection robust_point_type >::type robust_area_result_type; - typedef typename strategy::point_in_geometry::services::default_strategy + typedef typename IntersectionStrategy::template point_in_geometry_strategy < robust_point_type, robust_ring_type @@ -348,6 +348,7 @@ struct buffered_piece_collection area_strategy_type m_area_strategy; envelope_strategy_type m_envelope_strategy; expand_strategy_type m_expand_strategy; + point_in_geometry_strategy_type m_point_in_geometry_strategy; robust_area_strategy_type m_robust_area_strategy; RobustPolicy const& m_robust_policy; @@ -367,10 +368,15 @@ struct buffered_piece_collection , m_has_deflated(false) , m_intersection_strategy(intersection_strategy) , m_side_strategy(intersection_strategy.get_side_strategy()) - , m_area_strategy(intersection_strategy.template get_area_strategy()) + , m_area_strategy(intersection_strategy + .template get_area_strategy()) , m_envelope_strategy(intersection_strategy.get_envelope_strategy()) , m_expand_strategy(intersection_strategy.get_expand_strategy()) - , m_robust_area_strategy(intersection_strategy.template get_area_strategy()) + , m_point_in_geometry_strategy(intersection_strategy + .template get_point_in_geometry_strategy()) + , m_robust_area_strategy(intersection_strategy + .template get_area_strategy()) , m_robust_policy(robust_policy) {} @@ -541,10 +547,6 @@ struct buffered_piece_collection { it->location = inside_buffer; } - if (it->count_on_original_boundary > 0) - { - it->location = inside_buffer; - } if (it->count_within_near_offsetted > 0) { // Within can have in rare cases a rounding issue. We don't discard this @@ -658,7 +660,12 @@ struct buffered_piece_collection typename IntersectionStrategy::disjoint_box_box_strategy_type > original_ovelaps_box_type; - turn_in_original_visitor visitor(m_turns); + turn_in_original_visitor + < + turn_vector_type, + point_in_geometry_strategy_type + > visitor(m_turns, m_point_in_geometry_strategy); + geometry::partition < robust_box_type, @@ -808,14 +815,14 @@ struct buffered_piece_collection } } - static inline void determine_properties(piece& pc) + inline void determine_properties(piece& pc) const { pc.is_monotonic_increasing[0] = true; pc.is_monotonic_increasing[1] = true; pc.is_monotonic_decreasing[0] = true; pc.is_monotonic_decreasing[1] = true; - pc.is_convex = geometry::is_convex(pc.robust_ring); + pc.is_convex = geometry::is_convex(pc.robust_ring, m_side_strategy); if (pc.offsetted_count < 2) { @@ -909,7 +916,8 @@ struct buffered_piece_collection } } - inline void get_turns() + template + inline void get_turns(DistanceStrategy const& distance_strategy) { for(typename boost::range_iterator::type it = boost::begin(monotonic_sections); @@ -962,8 +970,13 @@ struct buffered_piece_collection < typename geometry::cs_tag::type, turn_vector_type, piece_vector_type, - point_in_geometry_strategy_type - > visitor(m_turns, m_pieces, point_in_geometry_strategy_type()); + DistanceStrategy, + point_in_geometry_strategy_type, + side_strategy_type + > visitor(m_turns, m_pieces, + distance_strategy, + m_point_in_geometry_strategy, + m_side_strategy); typedef turn_ovelaps_box < @@ -1421,11 +1434,7 @@ struct buffered_piece_collection enrich_intersection_points(m_turns, m_clusters, offsetted_rings, offsetted_rings, m_robust_policy, - m_intersection_strategy.template get_point_in_geometry_strategy - < - buffered_ring, - buffered_ring - >()); + m_intersection_strategy); } // Discards all rings which do have not-OK intersection points only. @@ -1476,7 +1485,7 @@ struct buffered_piece_collection int const geometry_code = detail::within::point_in_geometry(any_point, - original.m_ring, point_in_geometry_strategy_type()); + original.m_ring, m_point_in_geometry_strategy); if (geometry_code == -1) { diff --git a/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp b/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp index b2af001be..1b7d3f02c 100644 --- a/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/get_piece_turns.hpp @@ -19,7 +19,6 @@ #include #include -#include #include #include #include diff --git a/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp b/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp index 5236da1da..6b7635ec4 100644 --- a/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/turn_in_original_visitor.hpp @@ -150,16 +150,11 @@ inline bool point_in_section(Strategy& strategy, State& state, } -template -inline int point_in_original(Point const& point, Original const& original) +template +inline int point_in_original(Point const& point, Original const& original, + PointInGeometryStrategy const& strategy) { - // The winding strategy is scanning in x direction - // therefore it's critical to pass direction calculated - // for x dimension below. - typedef strategy::within::winding strategy_type; - - typename strategy_type::state_type state; - strategy_type strategy; + typename PointInGeometryStrategy::state_type state; if (boost::size(original.m_sections) == 0 || boost::size(original.m_ring) - boost::size(original.m_sections) < 16) @@ -207,12 +202,13 @@ inline int point_in_original(Point const& point, Original const& original) } -template +template class turn_in_original_visitor { public: - turn_in_original_visitor(Turns& turns) + turn_in_original_visitor(Turns& turns, PointInGeometryStrategy const& strategy) : m_mutable_turns(turns) + , m_point_in_geometry_strategy(strategy) {} template @@ -232,7 +228,7 @@ public: return true; } - int const code = point_in_original(turn.robust_point, original); + int const code = point_in_original(turn.robust_point, original, m_point_in_geometry_strategy); if (code == -1) { @@ -269,6 +265,7 @@ public: private : Turns& m_mutable_turns; + PointInGeometryStrategy const& m_point_in_geometry_strategy; }; diff --git a/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp b/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp index 5e2258dfc..73b3fdf5f 100644 --- a/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp +++ b/include/boost/geometry/algorithms/detail/buffer/turn_in_piece_visitor.hpp @@ -36,7 +36,6 @@ #include #include -#include namespace boost { namespace geometry @@ -123,6 +122,24 @@ inline bool in_box(Point const& previous, return geometry::covered_by(point, box); } +template +inline bool is_one_sided(NumericType const& left, NumericType const& right) +{ + static NumericType const zero = 0; + return geometry::math::equals(left, zero) + || geometry::math::equals(right, zero); +} + +template +inline bool has_zero_distance_at(Point const& point, + DistanceStrategy const& distance_strategy) +{ + return is_one_sided(distance_strategy.apply(point, point, + strategy::buffer::buffer_side_left), + distance_strategy.apply(point, point, + strategy::buffer::buffer_side_right)); +} + // meta-programming-structure defining if to use side-of-intersection // (only for cartesian / only necessary with rescaling) template @@ -151,10 +168,11 @@ struct check_segment {}; template <> struct check_segment { - template + template static inline analyse_result apply(Point const& previous, Point const& current, Turn const& turn, - bool from_monotonic) + bool from_monotonic, + SideStrategy const& ) { typedef geometry::model::referring_segment segment_type; segment_type const p(turn.rob_pi, turn.rob_pj); @@ -182,17 +200,13 @@ struct check_segment template <> struct check_segment { - template + template static inline analyse_result apply(Point const& previous, Point const& current, Turn const& turn, - bool from_monotonic) + bool from_monotonic, + SideStrategy const& side_strategy) { - typedef typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type side_strategy; - - int const side = side_strategy::apply(previous, current, turn.robust_point); + int const side = side_strategy.apply(previous, current, turn.robust_point); if (side == 0) { @@ -234,8 +248,10 @@ template <> class analyse_turn_wrt_point_piece { public : - template - static inline analyse_result apply(Turn const& turn, Piece const& piece) + template + static inline analyse_result apply(Turn const& turn, Piece const& piece, + PointInGeometryStrategy const& , + SideStrategy const& ) { typedef typename Piece::section_type section_type; typedef typename Turn::robust_point_type point_type; @@ -307,17 +323,16 @@ template <> class analyse_turn_wrt_point_piece { public : - template - static inline analyse_result apply(Turn const& turn, Piece const& piece) + template + static inline analyse_result apply(Turn const& turn, Piece const& piece, + PointInGeometryStrategy const& point_in_geometry_strategy, + SideStrategy const& side_strategy) { typedef typename Piece::section_type section_type; typedef typename Turn::robust_point_type point_type; typedef typename geometry::coordinate_type::type coordinate_type; - typedef strategy::within::winding strategy_type; - - typename strategy_type::state_type state; - strategy_type strategy; + typename PointInGeometryStrategy::state_type state; BOOST_GEOMETRY_ASSERT(! piece.sections.empty()); @@ -337,7 +352,7 @@ public : point_type const& previous = piece.robust_ring[i - 1]; point_type const& current = piece.robust_ring[i]; - analyse_result code = check_segment::apply(previous, current, turn, false); + analyse_result code = check_segment::apply(previous, current, turn, false, side_strategy); if (code != analyse_continue) { return code; @@ -345,12 +360,12 @@ public : // Get the state (to determine it is within), we don't have // to cover the on-segment case (covered above) - strategy.apply(turn.robust_point, previous, current, state); + point_in_geometry_strategy.apply(turn.robust_point, previous, current, state); } } } - int const code = strategy.result(state); + int const code = point_in_geometry_strategy.result(state); if (code == 1) { return analyse_within; @@ -372,14 +387,16 @@ struct check_helper_segment {}; template <> struct check_helper_segment { - template + template static inline analyse_result apply(Point const& s1, Point const& s2, Turn const& turn, bool is_original, - Point const& offsetted) + analyse_result result_for_original, + Point const& offsetted, + SideStrategy const& ) { - boost::ignore_unused(offsetted); - boost::ignore_unused(is_original); + boost::ignore_unused(offsetted, is_original); + typedef geometry::model::referring_segment segment_type; segment_type const p(turn.rob_pi, turn.rob_pj); segment_type const q(turn.rob_qi, turn.rob_qj); @@ -404,9 +421,7 @@ struct check_helper_segment if (geometry::covered_by(turn.robust_point, box)) { - // Points on helper-segments (and not on its corners) - // are considered as within - return analyse_within; + return result_for_original; } // It is collinear but not on the segment. Because these @@ -425,19 +440,15 @@ struct check_helper_segment template <> struct check_helper_segment { - template + template static inline analyse_result apply(Point const& s1, Point const& s2, Turn const& turn, bool is_original, - Point const& offsetted) + analyse_result result_for_original, + Point const& offsetted, + SideStrategy const& side_strategy) { - boost::ignore_unused(offsetted); - typedef typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type side_strategy; - - switch(side_strategy::apply(s1, s2, turn.robust_point)) + switch(side_strategy.apply(s1, s2, turn.robust_point)) { case 1 : return analyse_disjoint; // left of segment @@ -457,16 +468,14 @@ struct check_helper_segment if (! is_original && geometry::comparable_distance(turn.robust_point, offsetted) <= 1) { - // It is close to the offsetted-boundary, take - // any rounding-issues into account + // It is within, and close to the offsetted-boundary, + // take any rounding-issues into account return analyse_near_offsetted; } // Points on helper-segments are considered as within // Points on original boundary are processed differently - return is_original - ? analyse_on_original_boundary - : analyse_within; + return result_for_original; } // It is collinear but not on the segment. Because these @@ -486,8 +495,17 @@ struct check_helper_segment template class analyse_turn_wrt_piece { - template - static inline analyse_result check_helper_segments(Turn const& turn, Piece const& piece) + template + < + typename Turn, + typename Piece, + typename DistanceStrategy, + typename SideStrategy + > + static inline analyse_result + check_helper_segments(Turn const& turn, Piece const& piece, + DistanceStrategy const& distance_strategy, + SideStrategy const& side_strategy) { typedef typename Turn::robust_point_type point_type; geometry::equal_to comparator; @@ -526,6 +544,16 @@ class analyse_turn_wrt_piece return analyse_continue; } + // If a turn is located on the original, it is considered as within, + // unless it is at a flat start or end, or the buffer (at that point) + // is one-sided (zero-distance) + bool const one_sided = has_zero_distance_at(turn.point, distance_strategy); + + analyse_result const result_for_original + = one_sided || piece.is_flat_end || piece.is_flat_start + ? analyse_on_original_boundary + : analyse_within; + // First check point-equality point_type const& point = turn.robust_point; if (comparator(point, points[0]) || comparator(point, points[3])) @@ -534,37 +562,40 @@ class analyse_turn_wrt_piece } if (comparator(point, points[1])) { - // On original, right corner - return piece.is_flat_end ? analyse_continue : analyse_on_original_boundary; + // On original, with right corner of piece + return result_for_original; } if (comparator(point, points[2])) { - // On original, left corner - return piece.is_flat_start ? analyse_continue : analyse_on_original_boundary; + // On original, with left corner of piece + return result_for_original; } - // Right side of the piece + // Right side of the piece (never an original) analyse_result result = check_helper_segment::apply(points[0], points[1], turn, - false, points[0]); + false, analyse_within, points[0], side_strategy); if (result != analyse_continue) { return result; } - // Left side of the piece + // Left side of the piece (never an original) result = check_helper_segment::apply(points[2], points[3], turn, - false, points[3]); + false, analyse_within, points[3], side_strategy); if (result != analyse_continue) { return result; } + // Side of the piece at side of original geometry + // (here flat start/end will result in within) if (! comparator(points[1], points[2])) { - // Side of the piece at side of original geometry - result = check_helper_segment::apply(points[1], points[2], turn, - true, point); + result = check_helper_segment::apply(points[1], + points[2], turn, true, + one_sided ? analyse_on_original_boundary : analyse_within, + point, side_strategy); if (result != analyse_continue) { return result; @@ -576,12 +607,7 @@ class analyse_turn_wrt_piece if (! geometry::covered_by(point, piece.robust_offsetted_envelope)) { // Not in offsetted-area. This makes a cheap check possible - typedef typename strategy::side::services::default_strategy - < - typename cs_tag::type - >::type side_strategy; - - switch(side_strategy::apply(points[3], points[0], point)) + switch(side_strategy.apply(points[3], points[0], point)) { case 1 : return analyse_disjoint; case -1 : return analyse_within; @@ -592,8 +618,8 @@ class analyse_turn_wrt_piece return analyse_continue; } - template - static inline analyse_result check_monotonic(Turn const& turn, Piece const& piece, Compare const& compare) + template + static inline analyse_result check_monotonic(Turn const& turn, Piece const& piece, Compare const& compare, SideStrategy const& side_strategy) { typedef typename Piece::piece_robust_ring_type ring_type; typedef typename ring_type::const_iterator it_type; @@ -610,17 +636,25 @@ class analyse_turn_wrt_piece // w.r.t. specified direction, and prev points to a point smaller // We now know if it is inside/outside it_type prev = it - 1; - return check_segment::apply(*prev, *it, turn, true); + return check_segment::apply(*prev, *it, turn, true, side_strategy); } return analyse_continue; } public : - template - static inline analyse_result apply(Turn const& turn, Piece const& piece) + template + < + typename Turn, + typename Piece, + typename DistanceStrategy, + typename SideStrategy + > + static inline analyse_result apply(Turn const& turn, Piece const& piece, + DistanceStrategy const& distance_strategy, + SideStrategy const& side_strategy) { typedef typename Turn::robust_point_type point_type; - analyse_result code = check_helper_segments(turn, piece); + analyse_result code = check_helper_segments(turn, piece, distance_strategy, side_strategy); if (code != analyse_continue) { return code; @@ -635,22 +669,22 @@ public : // We try it only once. if (piece.is_monotonic_increasing[0]) { - code = check_monotonic(turn, piece, geometry::less()); + code = check_monotonic(turn, piece, geometry::less(), side_strategy); if (code != analyse_continue) return code; } else if (piece.is_monotonic_increasing[1]) { - code = check_monotonic(turn, piece, geometry::less()); + code = check_monotonic(turn, piece, geometry::less(), side_strategy); if (code != analyse_continue) return code; } else if (piece.is_monotonic_decreasing[0]) { - code = check_monotonic(turn, piece, geometry::greater()); + code = check_monotonic(turn, piece, geometry::greater(), side_strategy); if (code != analyse_continue) return code; } else if (piece.is_monotonic_decreasing[1]) { - code = check_monotonic(turn, piece, geometry::greater()); + code = check_monotonic(turn, piece, geometry::greater(), side_strategy); if (code != analyse_continue) return code; } } @@ -667,7 +701,7 @@ public : // (on which any side or side-value would return 0) if (! comparator(previous, current)) { - code = check_segment::apply(previous, current, turn, false); + code = check_segment::apply(previous, current, turn, false, side_strategy); if (code != analyse_continue) { return code; @@ -780,13 +814,18 @@ template typename CsTag, typename Turns, typename Pieces, - typename PointInGeometryStrategy + typename DistanceStrategy, + typename PointInGeometryStrategy, + typename SideStrategy + > class turn_in_piece_visitor { Turns& m_turns; // because partition is currently operating on const input only Pieces const& m_pieces; // to check for piece-type + DistanceStrategy const& m_distance_strategy; // to check if point is on original PointInGeometryStrategy const& m_point_in_geometry_strategy; + SideStrategy const& m_side_strategy; template inline bool skip(Operation const& op, Piece const& piece) const @@ -819,10 +858,14 @@ class turn_in_piece_visitor public: inline turn_in_piece_visitor(Turns& turns, Pieces const& pieces, - PointInGeometryStrategy const& strategy) + DistanceStrategy const& distance_strategy, + PointInGeometryStrategy const& strategy, + SideStrategy const& side_strategy) : m_turns(turns) , m_pieces(pieces) + , m_distance_strategy(distance_strategy) , m_point_in_geometry_strategy(strategy) + , m_side_strategy(side_strategy) {} template @@ -884,10 +927,10 @@ public: static const bool use_soi = use_side_of_intersection::value; boost::ignore_unused(use_soi); - analyse_result analyse_code = + analyse_result const analyse_code = piece.type == geometry::strategy::buffer::buffered_point - ? analyse_turn_wrt_point_piece::apply(turn, piece) - : analyse_turn_wrt_piece::apply(turn, piece); + ? analyse_turn_wrt_point_piece::apply(turn, piece, m_point_in_geometry_strategy, m_side_strategy) + : analyse_turn_wrt_piece::apply(turn, piece, m_distance_strategy, m_side_strategy); switch(analyse_code) { diff --git a/include/boost/geometry/algorithms/detail/overlay/follow.hpp b/include/boost/geometry/algorithms/detail/overlay/follow.hpp index 5d62e0c47..ac9978b49 100644 --- a/include/boost/geometry/algorithms/detail/overlay/follow.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/follow.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland. -// This file was modified by Oracle on 2014, 2017, 2018. -// Modifications copyright (c) 2014-2018 Oracle and/or its affiliates. +// This file was modified by Oracle on 2014, 2017, 2018, 2019. +// Modifications copyright (c) 2014-2019 Oracle and/or its affiliates. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle @@ -428,6 +428,8 @@ public : typedef following::action_selector action; + typedef typename Strategy::cs_tag cs_tag; + typename Strategy::template point_in_geometry_strategy < LineString, Polygon @@ -442,7 +444,10 @@ public : #ifdef BOOST_GEOMETRY_SETOPS_LA_OLD_BEHAVIOR std::sort(boost::begin(turns), boost::end(turns), sort_on_segment()); #else - typedef relate::turns::less<0, relate::turns::less_op_linear_areal_single<0> > turn_less; + typedef relate::turns::less + < + 0, relate::turns::less_op_linear_areal_single<0>, cs_tag + > turn_less; std::sort(boost::begin(turns), boost::end(turns), turn_less()); #endif diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp index 7404dabb4..12e2b0d35 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info.hpp @@ -593,6 +593,36 @@ struct equal : public base_turn_handler int const side_pk_p = has_pk ? side.pk_wrt_p1() : 0; int const side_qk_p = has_qk ? side.qk_wrt_p1() : 0; +#if ! defined(BOOST_GEOMETRY_USE_RESCALING) + + if (has_pk && has_qk && side_pk_p == side_qk_p) + { + // They turn to the same side, or continue both collinearly + // Without rescaling, to check for union/intersection, + // try to check side values (without any thresholds) + typedef typename select_coordinate_type + < + typename UniqueSubRange1::point_type, + typename UniqueSubRange2::point_type + >::type coordinate_type; + + typedef detail::distance_measure dm_type; + + dm_type const dm_qk_p + = get_distance_measure(range_q.at(1), range_q.at(2), range_p.at(2)); + dm_type const dm_pk_q + = get_distance_measure(range_p.at(1), range_p.at(2), range_q.at(2)); + + if (dm_pk_q.measure != dm_qk_p.measure) + { + // A (possibly very small) difference is detected, which + // can be used to distinguish between union/intersection + ui_else_iu(dm_pk_q.measure < dm_qk_p.measure, ti); + return; + } + } +#endif + // If pk is collinear with qj-qk, they continue collinearly. // This can be on either side of p1 (== q1), or collinear // The second condition checks if they do not continue diff --git a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp index 521744df8..40e19ec71 100644 --- a/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/get_turn_info_for_endpoint.hpp @@ -55,7 +55,7 @@ namespace detail { namespace overlay { // <----| // |-------> 2 0 0 1 -1 F and i/i x/u -// |-------> 2 0 0 -1 1 F symetric i/i u/x +// |-------> 2 0 0 -1 1 F symmetric i/i u/x // |-------> // // |-------> 2 0 0 -1 -1 T i/u u/i @@ -74,7 +74,7 @@ namespace detail { namespace overlay { // <-----| // // |-----> 1 -1 0 -1 0 F and u/x -// |-----> 1 0 -1 0 -1 F symetric x/u +// |-----> 1 0 -1 0 -1 F symmetric x/u // |-----> // D0 or D1 != 0 @@ -82,7 +82,7 @@ namespace detail { namespace overlay { // ^ // | // + 1 -1 1 -1 1 F and u/x (P is vertical) -// |--------> 1 1 -1 1 -1 F symetric x/u (P is horizontal) +// |--------> 1 1 -1 1 -1 F symmetric x/u (P is horizontal) // ^ // | // + diff --git a/include/boost/geometry/algorithms/detail/overlay/segment_as_subrange.hpp b/include/boost/geometry/algorithms/detail/overlay/segment_as_subrange.hpp index deac13ba4..610d2e13e 100644 --- a/include/boost/geometry/algorithms/detail/overlay/segment_as_subrange.hpp +++ b/include/boost/geometry/algorithms/detail/overlay/segment_as_subrange.hpp @@ -41,6 +41,11 @@ struct segment_as_subrange return index == 0 ? m_p1 : m_p2; } + static inline bool is_last_segment() + { + return true; + } + point_type m_p1, m_p2; Segment const& m_segment; diff --git a/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp b/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp index 06192e38d..18be9a255 100644 --- a/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp +++ b/include/boost/geometry/algorithms/detail/relate/areal_areal.hpp @@ -235,6 +235,8 @@ struct areal_areal if ( BOOST_GEOMETRY_CONDITION(result.interrupt) ) return; + typedef typename IntersectionStrategy::cs_tag cs_tag; + typedef typename IntersectionStrategy::template point_in_geometry_strategy < Geometry1, Geometry2 @@ -270,7 +272,7 @@ struct areal_areal || may_update(result) ) { // sort turns - typedef turns::less<0, turns::less_op_areal_areal<0> > less; + typedef turns::less<0, turns::less_op_areal_areal<0>, cs_tag> less; std::sort(turns.begin(), turns.end(), less()); /*if ( may_update(result) @@ -311,7 +313,7 @@ struct areal_areal || may_update(result) ) { // sort turns - typedef turns::less<1, turns::less_op_areal_areal<1> > less; + typedef turns::less<1, turns::less_op_areal_areal<1>, cs_tag> less; std::sort(turns.begin(), turns.end(), less()); /*if ( may_update(result) diff --git a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp index 018565f2e..ad43ed638 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_areal.hpp @@ -263,6 +263,7 @@ struct linear_areal typedef typename IntersectionStrategy::template point_in_geometry_strategy::type within_strategy_type; within_strategy_type const within_strategy = intersection_strategy.template get_point_in_geometry_strategy(); + typedef typename IntersectionStrategy::cs_tag cs_tag; typedef typename within_strategy_type::equals_point_point_strategy_type eq_pp_strategy_type; typedef boundary_checker @@ -302,7 +303,7 @@ struct linear_areal return; { - sort_dispatch(turns.begin(), turns.end(), is_multi()); + sort_dispatch(turns.begin(), turns.end(), is_multi()); turns_analyser analyser; analyse_each_turn(result, analyser, @@ -399,7 +400,7 @@ struct linear_areal else { // u, c - typedef turns::less<1, turns::less_op_areal_linear<1> > less; + typedef turns::less<1, turns::less_op_areal_linear<1>, cs_tag> less; std::sort(it, next, less()); eq_pp_strategy_type const eq_pp_strategy = within_strategy.get_equals_point_point_strategy(); @@ -529,11 +530,11 @@ struct linear_areal } }; - template + template static void sort_dispatch(TurnIt first, TurnIt last, boost::true_type const& /*is_multi*/) { // sort turns by Linear seg_id, then by fraction, then by other multi_index - typedef turns::less<0, turns::less_other_multi_index<0> > less; + typedef turns::less<0, turns::less_other_multi_index<0>, CSTag> less; std::sort(first, last, less()); // For the same IP and multi_index - the same other's single geometry @@ -547,19 +548,19 @@ struct linear_areal // When priorities for single geometries are set now sort turns for the same IP // if multi_index is the same sort them according to the single-less // else use priority of the whole single-geometry set earlier - typedef turns::less<0, turns::less_op_linear_areal_single<0> > single_less; + typedef turns::less<0, turns::less_op_linear_areal_single<0>, CSTag> single_less; for_each_equal_range(first, last, sort_turns_group(), same_ip()); } - template + template static void sort_dispatch(TurnIt first, TurnIt last, boost::false_type const& /*is_multi*/) { // sort turns by Linear seg_id, then by fraction, then // for same ring id: x, u, i, c // for different ring id: c, i, u, x - typedef turns::less<0, turns::less_op_linear_areal_single<0> > less; + typedef turns::less<0, turns::less_op_linear_areal_single<0>, CSTag> less; std::sort(first, last, less()); } diff --git a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp index 7be6bc788..ec8fe428d 100644 --- a/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp +++ b/include/boost/geometry/algorithms/detail/relate/linear_linear.hpp @@ -127,6 +127,8 @@ struct linear_linear Result & result, IntersectionStrategy const& intersection_strategy) { + typedef typename IntersectionStrategy::cs_tag cs_tag; + // The result should be FFFFFFFFF relate::set::value>(result);// FFFFFFFFd, d in [1,9] or T if ( BOOST_GEOMETRY_CONDITION( result.interrupt ) ) @@ -186,7 +188,7 @@ struct linear_linear || may_update(result) || may_update(result) ) { - typedef turns::less<0, turns::less_op_linear_linear<0> > less; + typedef turns::less<0, turns::less_op_linear_linear<0>, cs_tag> less; std::sort(turns.begin(), turns.end(), less()); turns_analyser analyser; @@ -206,7 +208,7 @@ struct linear_linear || may_update(result) || may_update(result) ) { - typedef turns::less<1, turns::less_op_linear_linear<1> > less; + typedef turns::less<1, turns::less_op_linear_linear<1>, cs_tag> less; std::sort(turns.begin(), turns.end(), less()); turns_analyser analyser; diff --git a/include/boost/geometry/algorithms/detail/relate/turns.hpp b/include/boost/geometry/algorithms/detail/relate/turns.hpp index d4439c64a..0bc532be1 100644 --- a/include/boost/geometry/algorithms/detail/relate/turns.hpp +++ b/include/boost/geometry/algorithms/detail/relate/turns.hpp @@ -23,6 +23,9 @@ #include #include +#include +#include + #include @@ -282,9 +285,8 @@ struct less_other_multi_index }; // sort turns by G1 - source_index == 0 by: -// seg_id -> distance -> operation -template > > +// seg_id -> distance and coordinates -> operation +template struct less { BOOST_STATIC_ASSERT(OpId < 2); @@ -292,16 +294,27 @@ struct less template static inline bool use_fraction(Turn const& left, Turn const& right) { + typedef typename geometry::strategy::within::services::default_strategy + < + typename Turn::point_type, typename Turn::point_type, + point_tag, point_tag, + pointlike_tag, pointlike_tag, + typename tag_cast::type, + typename tag_cast::type + >::type eq_pp_strategy_type; + static LessOp less_op; - return - geometry::math::equals(left.operations[OpId].fraction, - right.operations[OpId].fraction) - ? - less_op(left, right) - : - (left.operations[OpId].fraction < right.operations[OpId].fraction) - ; + // NOTE: Assuming fraction is more permissive and faster than + // comparison of points with strategy. + return geometry::math::equals(left.operations[OpId].fraction, + right.operations[OpId].fraction) + && eq_pp_strategy_type::apply(left.point, right.point) + ? + less_op(left, right) + : + (left.operations[OpId].fraction < right.operations[OpId].fraction) + ; } template diff --git a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp index 6ece756cd..dca1181b1 100644 --- a/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp +++ b/include/boost/geometry/algorithms/detail/sections/sectionalize.hpp @@ -33,6 +33,8 @@ #include #include +#include + #include #include #include @@ -56,7 +58,11 @@ #include #include +#if defined(BOOST_GEOMETRY_USE_RESCALING) #include +#else +#include +#endif #include #include @@ -775,22 +781,30 @@ struct sectionalize_multi template inline void enlarge_sections(Sections& sections) { - // Robustness issue. Increase sections a tiny bit such that all points are really within (and not on border) - // Reason: turns might, rarely, be missed otherwise (case: "buffer_mp1") - // Drawback: not really, range is now completely inside the section. Section is a tiny bit too large, - // which might cause (a small number) of more comparisons + // Enlarge sections slightly, this should be consistent with math::equals() + // and with the tolerances used in general_form intersections. + // This avoids missing turns. - // NOTE: above is old comment to the not used code expanding the Boxes by relaxed_epsilon(10) - - // Enlarge sections by scaled epsilon, this should be consistent with math::equals(). // Points and Segments are equal-compared WRT machine epsilon, but Boxes aren't // Enlarging Boxes ensures that they correspond to the bound objects, // Segments in this case, since Sections are collections of Segments. + + // It makes section a tiny bit too large, which might cause (a small number) + // of more comparisons for (typename boost::range_iterator::type it = boost::begin(sections); it != boost::end(sections); ++it) { +#if defined(BOOST_GEOMETRY_USE_RESCALING) detail::expand_by_epsilon(it->bounding_box); + +#else + // Expand the box to avoid missing any intersection. The amount is + // should be larger than epsilon. About the value itself: the smaller + // it is, the higher the risk to miss intersections. The larger it is, + // the more comparisons are made. So it should be on the high side. + detail::buffer::buffer_box(it->bounding_box, 0.001, it->bounding_box); +#endif } } diff --git a/include/boost/geometry/formulas/karney_direct.hpp b/include/boost/geometry/formulas/karney_direct.hpp index 7a89061fd..0a5f86df2 100644 --- a/include/boost/geometry/formulas/karney_direct.hpp +++ b/include/boost/geometry/formulas/karney_direct.hpp @@ -102,11 +102,11 @@ public: CT const ep2 = e2 / math::sqr(one_minus_f); CT sin_alpha1, cos_alpha1; - math::sin_cos_degrees(math::round_angle(azi12), sin_alpha1, cos_alpha1); + math::sin_cos_degrees(azi12, sin_alpha1, cos_alpha1); // Find the reduced latitude. CT sin_beta1, cos_beta1; - math::sin_cos_degrees(math::round_angle(lat1), sin_beta1, cos_beta1); + math::sin_cos_degrees(lat1, sin_beta1, cos_beta1); sin_beta1 *= one_minus_f; math::normalize_unit_vector(sin_beta1, cos_beta1); diff --git a/include/boost/geometry/formulas/karney_inverse.hpp b/include/boost/geometry/formulas/karney_inverse.hpp new file mode 100644 index 000000000..5ae608a12 --- /dev/null +++ b/include/boost/geometry/formulas/karney_inverse.hpp @@ -0,0 +1,904 @@ +// Boost.Geometry + +// Copyright (c) 2018 Adeel Ahmad, Islamabad, Pakistan. + +// Contributed and/or modified by Adeel Ahmad, as part of Google Summer of Code 2018 program. + +// Use, modification and distribution is subject to the Boost Software License, +// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// This file is converted from GeographicLib, https://geographiclib.sourceforge.io +// GeographicLib is originally written by Charles Karney. + +// Author: Charles Karney (2008-2017) + +// Last updated version of GeographicLib: 1.49 + +// Original copyright notice: + +// Copyright (c) Charles Karney (2008-2017) and licensed +// under the MIT/X11 License. For more information, see +// https://geographiclib.sourceforge.io + +#ifndef BOOST_GEOMETRY_FORMULAS_KARNEY_INVERSE_HPP +#define BOOST_GEOMETRY_FORMULAS_KARNEY_INVERSE_HPP + + +#include +#include + +#include +#include +#include + +#include +#include + + +namespace boost { namespace geometry { namespace formula +{ + +namespace se = series_expansion; + +/*! +\brief The solution of the inverse problem of geodesics on latlong coordinates, + after Karney (2011). +\author See +- Charles F.F Karney, Algorithms for geodesics, 2011 +https://arxiv.org/pdf/1109.4448.pdf +*/ +template < + typename CT, + bool EnableDistance, + bool EnableAzimuth, + bool EnableReverseAzimuth = false, + bool EnableReducedLength = false, + bool EnableGeodesicScale = false, + size_t SeriesOrder = 8 +> +class karney_inverse +{ + static const bool CalcQuantities = EnableReducedLength || EnableGeodesicScale; + static const bool CalcAzimuths = EnableAzimuth || EnableReverseAzimuth || CalcQuantities; + static const bool CalcFwdAzimuth = EnableAzimuth || CalcQuantities; + static const bool CalcRevAzimuth = EnableReverseAzimuth || CalcQuantities; + +public: + typedef result_inverse result_type; + static CT constexpr c0 = 0; + static CT constexpr c0_001 = 0.001; + static CT constexpr c0_01 = 0.01; + static CT constexpr c0_1 = 0.1; + static CT constexpr c0_5 = 0.5; + static CT constexpr c1 = 1; + static CT constexpr c2 = 2; + static CT constexpr c3 = 3; + static CT constexpr c4 = 4; + static CT constexpr c6 = 6; + static CT constexpr c8 = 8; + static CT constexpr c10 = 10; + static CT constexpr c16 = 16; + static CT constexpr c20 = 20; + static CT constexpr c90 = 90; + static CT constexpr c180 = 180; + static CT constexpr c200 = 200; + static CT constexpr c1000 = 1000; + + template + static inline result_type apply(T1 const& lo1, + T1 const& la1, + T2 const& lo2, + T2 const& la2, + Spheroid const& spheroid) + { + result_type result; + + CT lat1 = la1; + CT lat2 = la2; + + CT lon1 = lo1; + CT lon2 = lo2; + + CT const a = CT(get_radius<0>(spheroid)); + CT const b = CT(get_radius<2>(spheroid)); + CT const f = formula::flattening(spheroid); + CT const one_minus_f = c1 - f; + CT const two_minus_f = c2 - f; + + CT const tol0 = std::numeric_limits::epsilon(); + CT const tol1 = c200 * tol0; + CT const tol2 = sqrt(tol0); + + // Check on bisection interval. + CT const tol_bisection = tol0 * tol2; + + CT const etol2 = c0_1 * tol2 / + sqrt(std::max(CT(0.001), std::abs(f)) * std::min(CT(1), CT(1) - f / CT(2)) / c2); + + CT tiny = std::sqrt(std::numeric_limits::min()); + + CT const n = f / two_minus_f; + CT const e2 = f * two_minus_f; + CT const ep2 = e2 / math::sqr(one_minus_f); + + // Compute the longitudinal difference. + CT lon12_error; + CT lon12 = math::difference_angle(lon1, lon2, lon12_error); + + int lon12_sign = lon12 >= 0 ? 1 : -1; + + // Make points close to the meridian to lie on it. + lon12 = lon12_sign * lon12; + lon12_error = (c180 - lon12) - lon12_sign * lon12_error; + + // Convert to radians. + CT lam12 = lon12 * math::d2r(); + CT sin_lam12; + CT cos_lam12; + + if (lon12 > c90) + { + math::sin_cos_degrees(lon12_error, sin_lam12, cos_lam12); + cos_lam12 *= -c1; + } + else + { + math::sin_cos_degrees(lon12, sin_lam12, cos_lam12); + } + + // Make points close to the equator to lie on it. + lat1 = math::round_angle(std::abs(lat1) > c90 ? c90 : lat1); + lat2 = math::round_angle(std::abs(lat2) > c90 ? c90 : lat2); + + // Arrange points in a canonical form, as explained in + // paper, Algorithms for geodesics, Eq. (44): + // + // 0 <= lon12 <= 180 + // -90 <= lat1 <= 0 + // lat1 <= lat2 <= -lat1 + int swap_point = std::abs(lat1) < std::abs(lat2) ? -1 : 1; + + if (swap_point < 0) + { + lon12_sign *= -1; + swap(lat1, lat2); + } + + // Enforce lat1 to be <= 0. + int lat_sign = lat1 < 0 ? 1 : -1; + lat1 *= lat_sign; + lat2 *= lat_sign; + + CT sin_beta1, cos_beta1; + math::sin_cos_degrees(lat1, sin_beta1, cos_beta1); + sin_beta1 *= one_minus_f; + + math::normalize_unit_vector(sin_beta1, cos_beta1); + cos_beta1 = std::max(tiny, cos_beta1); + + CT sin_beta2, cos_beta2; + math::sin_cos_degrees(lat2, sin_beta2, cos_beta2); + sin_beta2 *= one_minus_f; + + math::normalize_unit_vector(sin_beta2, cos_beta2); + cos_beta2 = std::max(tiny, cos_beta2); + + // If cos_beta1 < -sin_beta1, then cos_beta2 - cos_beta1 is a + // sensitive measure of the |beta1| - |beta2|. Alternatively, + // (cos_beta1 >= -sin_beta1), abs(sin_beta2) + sin_beta1 is + // a better measure. + // Sometimes these quantities vanish and in that case we + // force beta2 = +/- bet1a exactly. + if (cos_beta1 < -sin_beta1) + { + if (cos_beta1 == cos_beta2) + { + sin_beta2 = sin_beta2 < 0 ? sin_beta1 : -sin_beta1; + } + } + else + { + if (std::abs(sin_beta2) == -sin_beta1) + { + cos_beta2 = cos_beta1; + } + } + + CT const dn1 = sqrt(c1 + ep2 * math::sqr(sin_beta1)); + CT const dn2 = sqrt(c1 + ep2 * math::sqr(sin_beta2)); + + CT sigma12; + CT m12x, s12x, M21; + + // Index zero element of coeffs_C1 is unused. + se::coeffs_C1 const coeffs_C1(n); + + bool meridian = lat1 == -90 || sin_lam12 == 0; + + CT cos_alpha1, sin_alpha1; + CT cos_alpha2, sin_alpha2; + + if (meridian) + { + // Endpoints lie on a single full meridian. + + // Point to the target latitude. + cos_alpha1 = cos_lam12; + sin_alpha1 = sin_lam12; + + // Heading north at the target. + cos_alpha2 = c1; + sin_alpha2 = c0; + + CT sin_sigma1 = sin_beta1; + CT cos_sigma1 = cos_alpha1 * cos_beta1; + + CT sin_sigma2 = sin_beta2; + CT cos_sigma2 = cos_alpha2 * cos_beta2; + + CT sigma12 = std::atan2(std::max(CT(0), cos_sigma1 * sin_sigma2 - sin_sigma1 * cos_sigma2), + cos_sigma1 * cos_sigma2 + sin_sigma1 * sin_sigma2); + + CT dummy; + meridian_length(n, ep2, sigma12, sin_sigma1, cos_sigma1, dn1, + sin_sigma2, cos_sigma2, dn2, + cos_beta1, cos_beta2, s12x, + m12x, dummy, result.geodesic_scale, + M21, coeffs_C1); + + if (sigma12 < c1 || m12x >= c0) + { + if (sigma12 < c3 * tiny) + { + sigma12 = m12x = s12x = c0; + } + + m12x *= b; + s12x *= b; + } + else + { + // m12 < 0, i.e., prolate and too close to anti-podal. + meridian = false; + } + } + + CT omega12; + + if (!meridian && sin_beta1 == c0 && + (f <= c0 || lon12_error >= f * c180)) + { + // Points lie on the equator. + cos_alpha1 = cos_alpha2 = c0; + sin_alpha1 = sin_alpha2 = c1; + + s12x = a * lam12; + sigma12 = omega12 = lam12 / one_minus_f; + m12x = b * sin(sigma12); + + if (BOOST_GEOMETRY_CONDITION(EnableGeodesicScale)) + { + result.geodesic_scale = cos(sigma12); + } + } + else if (!meridian) + { + // If point1 and point2 belong within a hemisphere bounded by a + // meridian and geodesic is neither meridional nor equatorial. + + // Find the starting point for Newton's method. + CT dnm; + sigma12 = newton_start(sin_beta1, cos_beta1, dn1, + sin_beta2, cos_beta2, dn2, + lam12, sin_lam12, cos_lam12, + sin_alpha1, cos_alpha1, + sin_alpha2, cos_alpha2, + dnm, coeffs_C1, ep2, + tol1, tol2, etol2, + n, f); + + if (sigma12 >= c0) + { + // Short lines case (newton_start sets sin_alpha2, cos_alpha2, dnm). + s12x = sigma12 * b * dnm; + m12x = math::sqr(dnm) * b * sin(sigma12 / dnm); + if (BOOST_GEOMETRY_CONDITION(EnableGeodesicScale)) + { + result.geodesic_scale = cos(sigma12 / dnm); + } + + // Convert to radians. + omega12 = lam12 / (one_minus_f * dnm); + } + else + { + // Apply the Newton's method. + CT sin_sigma1 = c0, cos_sigma1 = c0; + CT sin_sigma2 = c0, cos_sigma2 = c0; + CT eps = c0, diff_omega12 = c0; + + // Bracketing range. + CT sin_alpha1a = tiny, cos_alpha1a = c1; + CT sin_alpha1b = tiny, cos_alpha1b = -c1; + + size_t iteration = 0; + size_t max_iterations = 20 + std::numeric_limits::digits + 10; + + for (bool tripn = false, tripb = false; + iteration < max_iterations; + ++iteration) + { + CT dv; + CT v = lambda12(sin_beta1, cos_beta1, dn1, + sin_beta2, cos_beta2, dn2, + sin_alpha1, cos_alpha1, + sin_lam12, cos_lam12, + sin_alpha2, cos_alpha2, + sigma12, + sin_sigma1, cos_sigma1, + sin_sigma2, cos_sigma2, + eps, diff_omega12, + iteration < max_iterations, + dv, f, n, ep2, tiny, coeffs_C1); + + // Reversed test to allow escape with NaNs. + if (tripb || !(std::abs(v) >= (tripn ? c8 : c1) * tol0)) + break; + + // Update bracketing values. + if (v > c0 && (iteration > max_iterations || + cos_alpha1 / sin_alpha1 > cos_alpha1b / sin_alpha1b)) + { + sin_alpha1b = sin_alpha1; + cos_alpha1b = cos_alpha1; + } + else if (v < c0 && (iteration > max_iterations || + cos_alpha1 / sin_alpha1 < cos_alpha1a / sin_alpha1a)) + { + sin_alpha1a = sin_alpha1; + cos_alpha1a = cos_alpha1; + } + + if (iteration < max_iterations && dv > c0) + { + CT diff_alpha1 = -v / dv; + + CT sin_diff_alpha1 = sin(diff_alpha1); + CT cos_diff_alpha1 = cos(diff_alpha1); + + CT nsin_alpha1 = sin_alpha1 * cos_diff_alpha1 + + cos_alpha1 * sin_diff_alpha1; + + if (nsin_alpha1 > c0 && std::abs(diff_alpha1) < math::pi()) + { + cos_alpha1 = cos_alpha1 * cos_diff_alpha1 - sin_alpha1 * sin_diff_alpha1; + sin_alpha1 = nsin_alpha1; + math::normalize_unit_vector(sin_alpha1, cos_alpha1); + + // In some regimes we don't get quadratic convergence because + // slope -> 0. So use convergence conditions based on epsilon + // instead of sqrt(epsilon). + tripn = std::abs(v) <= c16 * tol0; + continue; + } + } + + // Either dv was not positive or updated value was outside legal + // range. Use the midpoint of the bracket as the next estimate. + // This mechanism is not needed for the WGS84 ellipsoid, but it does + // catch problems with more eeccentric ellipsoids. Its efficacy is + // such for the WGS84 test set with the starting guess set to alp1 = + // 90deg: + // the WGS84 test set: mean = 5.21, sd = 3.93, max = 24 + // WGS84 and random input: mean = 4.74, sd = 0.99 + sin_alpha1 = (sin_alpha1a + sin_alpha1b) / c2; + cos_alpha1 = (cos_alpha1a + cos_alpha1b) / c2; + math::normalize_unit_vector(sin_alpha1, cos_alpha1); + tripn = false; + tripb = (std::abs(sin_alpha1a - sin_alpha1) + (cos_alpha1a - cos_alpha1) < tol_bisection || + std::abs(sin_alpha1 - sin_alpha1b) + (cos_alpha1 - cos_alpha1b) < tol_bisection); + } + + CT dummy; + se::coeffs_C1 const coeffs_C1_eps(eps); + // Ensure that the reduced length and geodesic scale are computed in + // a "canonical" way, with the I2 integral. + meridian_length(eps, ep2, sigma12, sin_sigma1, cos_sigma1, dn1, + sin_sigma2, cos_sigma2, dn2, + cos_beta1, cos_beta2, s12x, + m12x, dummy, result.geodesic_scale, + M21, coeffs_C1_eps); + + m12x *= b; + s12x *= b; + } + } + + if (swap_point < 0) + { + swap(sin_alpha1, sin_alpha2); + swap(cos_alpha1, cos_alpha2); + swap(result.geodesic_scale, M21); + } + + sin_alpha1 *= swap_point * lon12_sign; + cos_alpha1 *= swap_point * lat_sign; + + sin_alpha2 *= swap_point * lon12_sign; + cos_alpha2 *= swap_point * lat_sign; + + if (BOOST_GEOMETRY_CONDITION(EnableReducedLength)) + { + result.reduced_length = m12x; + } + + if (BOOST_GEOMETRY_CONDITION(CalcAzimuths)) + { + if (BOOST_GEOMETRY_CONDITION(CalcFwdAzimuth)) + { + result.azimuth = atan2(sin_alpha1, cos_alpha1) * math::r2d(); + } + + if (BOOST_GEOMETRY_CONDITION(CalcRevAzimuth)) + { + result.reverse_azimuth = atan2(sin_alpha2, cos_alpha2) * math::r2d(); + } + } + + if (BOOST_GEOMETRY_CONDITION(EnableDistance)) + { + result.distance = s12x; + } + + return result; + } + + template + static inline void meridian_length(CT epsilon, CT ep2, CT sigma12, + CT sin_sigma1, CT cos_sigma1, CT dn1, + CT sin_sigma2, CT cos_sigma2, CT dn2, + CT cos_beta1, CT cos_beta2, + CT& s12x, CT& m12x, CT& m0, + CT& M12, CT& M21, + CoeffsC1 coeffs_C1) + { + CT A12x = 0, J12 = 0; + CT expansion_A1, expansion_A2; + + // Evaluate the coefficients for C2. + se::coeffs_C2 coeffs_C2(epsilon); + + if (BOOST_GEOMETRY_CONDITION(EnableDistance) || + BOOST_GEOMETRY_CONDITION(EnableReducedLength) || + BOOST_GEOMETRY_CONDITION(EnableGeodesicScale)) + { + // Find the coefficients for A1 by computing the + // series expansion using Horner scehme. + expansion_A1 = se::evaluate_A1(epsilon); + + if (BOOST_GEOMETRY_CONDITION(EnableReducedLength) || + BOOST_GEOMETRY_CONDITION(EnableGeodesicScale)) + { + // Find the coefficients for A2 by computing the + // series expansion using Horner scehme. + expansion_A2 = se::evaluate_A2(epsilon); + + A12x = expansion_A1 - expansion_A2; + expansion_A2 += c1; + } + expansion_A1 += c1; + } + + if (BOOST_GEOMETRY_CONDITION(EnableDistance)) + { + CT B1 = se::sin_cos_series(sin_sigma2, cos_sigma2, coeffs_C1) + - se::sin_cos_series(sin_sigma1, cos_sigma1, coeffs_C1); + + s12x = expansion_A1 * (sigma12 + B1); + + if (BOOST_GEOMETRY_CONDITION(EnableReducedLength) || + BOOST_GEOMETRY_CONDITION(EnableGeodesicScale)) + { + CT B2 = se::sin_cos_series(sin_sigma2, cos_sigma2, coeffs_C2) + - se::sin_cos_series(sin_sigma1, cos_sigma1, coeffs_C2); + + J12 = A12x * sigma12 + (expansion_A1 * B1 - expansion_A2 * B2); + } + } + else if (BOOST_GEOMETRY_CONDITION(EnableReducedLength) || + BOOST_GEOMETRY_CONDITION(EnableGeodesicScale)) + { + for (size_t i = 1; i <= SeriesOrder; ++i) + { + coeffs_C2[i] = expansion_A1 * coeffs_C1[i] - + expansion_A2 * coeffs_C2[i]; + } + + J12 = A12x * sigma12 + + (se::sin_cos_series(sin_sigma2, cos_sigma2, coeffs_C2) + - se::sin_cos_series(sin_sigma1, cos_sigma1, coeffs_C2)); + } + + if (BOOST_GEOMETRY_CONDITION(EnableReducedLength)) + { + m0 = A12x; + + m12x = dn2 * (cos_sigma1 * sin_sigma2) - + dn1 * (sin_sigma1 * cos_sigma2) - + cos_sigma1 * cos_sigma2 * J12; + } + + if (BOOST_GEOMETRY_CONDITION(EnableGeodesicScale)) + { + CT cos_sigma12 = cos_sigma1 * cos_sigma2 + sin_sigma1 * sin_sigma2; + CT t = ep2 * (cos_beta1 - cos_beta2) * + (cos_beta1 + cos_beta2) / (dn1 + dn2); + + M12 = cos_sigma12 + (t * sin_sigma2 - cos_sigma2 * J12) * sin_sigma1 / dn1; + M21 = cos_sigma12 - (t * sin_sigma1 - cos_sigma1 * J12) * sin_sigma2 / dn2; + } + } + + /* + Return a starting point for Newton's method in sin_alpha1 and + cos_alpha1 (function value is -1). If Newton's method + doesn't need to be used, return also sin_alpha2 and + cos_alpha2 and function value is sig12. + */ + template + static inline CT newton_start(CT sin_beta1, CT cos_beta1, CT dn1, + CT sin_beta2, CT cos_beta2, CT dn2, + CT lam12, CT sin_lam12, CT cos_lam12, + CT& sin_alpha1, CT& cos_alpha1, + CT& sin_alpha2, CT& cos_alpha2, + CT& dnm, CoeffsC1 coeffs_C1, CT ep2, + CT tol1, CT tol2, CT etol2, CT n, CT f) + { + CT const one_minus_f = c1 - f; + CT const x_thresh = c1000 * tol2; + + // Return a starting point for Newton's method in sin_alpha1 + // and cos_alpha1 (function value is -1). If Newton's method + // doesn't need to be used, return also sin_alpha2 and + // cos_alpha2 and function value is sig12. + CT sig12 = -c1; + + // bet12 = bet2 - bet1 in [0, pi); beta12a = bet2 + bet1 in (-pi, 0] + CT sin_beta12 = sin_beta2 * cos_beta1 - cos_beta2 * sin_beta1; + CT cos_beta12 = cos_beta2 * cos_beta1 + sin_beta2 * sin_beta1; + + CT sin_beta12a = sin_beta2 * cos_beta1 + cos_beta2 * sin_beta1; + + bool shortline = cos_beta12 >= c0 && sin_beta12 < c0_5 && + cos_beta2 * lam12 < c0_5; + + CT sin_omega12, cos_omega12; + + if (shortline) + { + CT sin_beta_m2 = math::sqr(sin_beta1 + sin_beta2); + + sin_beta_m2 /= sin_beta_m2 + math::sqr(cos_beta1 + cos_beta2); + dnm = math::sqrt(c1 + ep2 * sin_beta_m2); + + CT omega12 = lam12 / (one_minus_f * dnm); + + sin_omega12 = sin(omega12); + cos_omega12 = cos(omega12); + } + else + { + sin_omega12 = sin_lam12; + cos_omega12 = cos_lam12; + } + + sin_alpha1 = cos_beta2 * sin_omega12; + cos_alpha1 = cos_omega12 >= c0 ? + sin_beta12 + cos_beta2 * sin_beta1 * math::sqr(sin_omega12) / (c1 + cos_omega12) : + sin_beta12a - cos_beta2 * sin_beta1 * math::sqr(sin_omega12) / (c1 - cos_omega12); + + CT sin_sigma12 = boost::math::hypot(sin_alpha1, cos_alpha1); + CT cos_sigma12 = sin_beta1 * sin_beta2 + cos_beta1 * cos_beta2 * cos_omega12; + + if (shortline && sin_sigma12 < etol2) + { + sin_alpha2 = cos_beta1 * sin_omega12; + cos_alpha2 = sin_beta12 - cos_beta1 * sin_beta2 * + (cos_omega12 >= c0 ? math::sqr(sin_omega12) / + (c1 + cos_omega12) : c1 - cos_omega12); + + math::normalize_unit_vector(sin_alpha2, cos_alpha2); + // Set return value. + sig12 = atan2(sin_sigma12, cos_sigma12); + } + // Skip astroid calculation if too eccentric. + else if (std::abs(n) > c0_1 || + cos_sigma12 >= c0 || + sin_sigma12 >= c6 * std::abs(n) * math::pi() * + math::sqr(cos_beta1)) + { + // Nothing to do, zeroth order spherical approximation will do. + } + else + { + // Scale lam12 and bet2 to x, y coordinate system where antipodal + // point is at origin and singular point is at y = 0, x = -1. + CT lambda_scale, beta_scale; + + CT y; + volatile CT x; + + CT lam12x = atan2(-sin_lam12, -cos_lam12); + if (f >= c0) + { + CT k2 = math::sqr(sin_beta1) * ep2; + CT eps = k2 / (c2 * (c1 + sqrt(c1 + k2)) + k2); + + se::coeffs_A3 const coeffs_A3(n); + + CT const A3 = math::horner_evaluate(eps, coeffs_A3.begin(), coeffs_A3.end()); + + lambda_scale = f * cos_beta1 * A3 * math::pi(); + beta_scale = lambda_scale * cos_beta1; + + x = lam12x / lambda_scale; + y = sin_beta12a / beta_scale; + } + else + { + CT cos_beta12a = cos_beta2 * cos_beta1 - sin_beta2 * sin_beta1; + CT beta12a = atan2(sin_beta12a, cos_beta12a); + + CT m12b, m0, dummy; + meridian_length(n, ep2, math::pi() + beta12a, + sin_beta1, -cos_beta1, dn1, + sin_beta2, cos_beta2, dn2, + cos_beta1, cos_beta2, dummy, + m12b, m0, dummy, dummy, coeffs_C1); + + x = -c1 + m12b / (cos_beta1 * cos_beta2 * m0 * math::pi()); + beta_scale = x < -c0_01 ? sin_beta12a / x : + -f * math::sqr(cos_beta1) * math::pi(); + lambda_scale = beta_scale / cos_beta1; + + y = lam12x / lambda_scale; + } + + if (y > -tol1 && x > -c1 - x_thresh) + { + // Strip near cut. + if (f >= c0) + { + sin_alpha1 = std::min(CT(1), -CT(x)); + cos_alpha1 = - math::sqrt(c1 - math::sqr(sin_alpha1)); + } + else + { + cos_alpha1 = std::max(CT(x > -tol1 ? c0 : -c1), CT(x)); + sin_alpha1 = math::sqrt(c1 - math::sqr(cos_alpha1)); + } + } + else + { + // Solve the astroid problem. + CT k = astroid(x, y); + + CT omega12a = lambda_scale * (f >= c0 ? -x * k / + (c1 + k) : -y * (c1 + k) / k); + + sin_omega12 = sin(omega12a); + cos_omega12 = -cos(omega12a); + + // Update spherical estimate of alpha1 using omgega12 instead of lam12. + sin_alpha1 = cos_beta2 * sin_omega12; + cos_alpha1 = sin_beta12a - cos_beta2 * sin_beta1 * + math::sqr(sin_omega12) / (c1 - cos_omega12); + } + } + + // Sanity check on starting guess. Backwards check allows NaN through. + if (!(sin_alpha1 <= c0)) + { + math::normalize_unit_vector(sin_alpha1, cos_alpha1); + } + else + { + sin_alpha1 = c1; + cos_alpha1 = c0; + } + + return sig12; + } + + /* + Solve the astroid problem using the equation: + κ4 + 2κ3 + (1 − x2 − y 2 )κ2 − 2y 2 κ − y 2 = 0. + + For details, please refer to Eq. (65) in, + Geodesics on an ellipsoid of revolution, Charles F.F Karney, + https://arxiv.org/abs/1102.1215 + */ + static inline CT astroid(CT x, CT y) + { + CT k; + + CT p = math::sqr(x); + CT q = math::sqr(y); + CT r = (p + q - c1) / c6; + + if (!(q == c0 && r <= c0)) + { + // Avoid possible division by zero when r = 0 by multiplying + // equations for s and t by r^3 and r, respectively. + CT S = p * q / c4; + CT r2 = math::sqr(r); + CT r3 = r * r2; + + // The discriminant of the quadratic equation for T3. This is + // zero on the evolute curve p^(1/3)+q^(1/3) = 1. + CT discriminant = S * (S + c2 * r3); + + CT u = r; + + if (discriminant >= c0) + { + CT T3 = S + r3; + + // Pick the sign on the sqrt to maximize abs(T3). This minimizes + // loss of precision due to cancellation. The result is unchanged + // because of the way the T is used in definition of u. + T3 += T3 < c0 ? -std::sqrt(discriminant) : std::sqrt(discriminant); + + CT T = std::cbrt(T3); + + // T can be zero; but then r2 / T -> 0. + u += T + (T != c0 ? r2 / T : c0); + } + else + { + CT ang = std::atan2(std::sqrt(-discriminant), -(S + r3)); + + // There are three possible cube roots. We choose the root which avoids + // cancellation. Note that discriminant < 0 implies that r < 0. + u += c2 * r * cos(ang / c3); + } + + CT v = std::sqrt(math::sqr(u) + q); + + // Avoid loss of accuracy when u < 0. + CT uv = u < c0 ? q / (v - u) : u + v; + CT w = (uv - q) / (c2 * v); + + // Rearrange expression for k to avoid loss of accuracy due to + // subtraction. Division by 0 not possible because uv > 0, w >= 0. + k = uv / (std::sqrt(uv + math::sqr(w)) + w); + } + else // q == 0 && r <= 0 + { + // y = 0 with |x| <= 1. Handle this case directly. + // For y small, positive root is k = abs(y)/sqrt(1-x^2). + k = c0; + } + return k; + } + + template + static inline CT lambda12(CT sin_beta1, CT cos_beta1, CT dn1, + CT sin_beta2, CT cos_beta2, CT dn2, + CT sin_alpha1, CT cos_alpha1, + CT sin_lam120, CT cos_lam120, + CT& sin_alpha2, CT& cos_alpha2, + CT& sigma12, + CT& sin_sigma1, CT& cos_sigma1, + CT& sin_sigma2, CT& cos_sigma2, + CT& eps, CT& diff_omega12, + bool diffp, CT& diff_lam12, + CT f, CT n, CT ep2, CT tiny, + CoeffsC1 coeffs_C1) + { + CT const one_minus_f = c1 - f; + + if (sin_beta1 == c0 && cos_alpha1 == c0) + { + // Break degeneracy of equatorial line. + cos_alpha1 = -tiny; + } + + + CT sin_alpha0 = sin_alpha1 * cos_beta1; + CT cos_alpha0 = boost::math::hypot(cos_alpha1, sin_alpha1 * sin_beta1); + + CT sin_omega1, cos_omega1; + CT sin_omega2, cos_omega2; + CT sin_omega12, cos_omega12; + + CT lam12; + + sin_sigma1 = sin_beta1; + sin_omega1 = sin_alpha0 * sin_beta1; + + cos_sigma1 = cos_omega1 = cos_alpha1 * cos_beta1; + + math::normalize_unit_vector(sin_sigma1, cos_sigma1); + + // Enforce symmetries in the case abs(beta2) = -beta1. + // Otherwise, this can yield singularities in the Newton iteration. + + // sin(alpha2) * cos(beta2) = sin(alpha0). + sin_alpha2 = cos_beta2 != cos_beta1 ? + sin_alpha0 / cos_beta2 : sin_alpha1; + + cos_alpha2 = cos_beta2 != cos_beta1 || std::abs(sin_beta2) != -sin_beta1 ? + sqrt(math::sqr(cos_alpha1 * cos_beta1) + + (cos_beta1 < -sin_beta1 ? + (cos_beta2 - cos_beta1) * (cos_beta1 + cos_beta2) : + (sin_beta1 - sin_beta2) * (sin_beta1 + sin_beta2))) / cos_beta2 : + std::abs(cos_alpha1); + + sin_sigma2 = sin_beta2; + sin_omega2 = sin_alpha0 * sin_beta2; + + cos_sigma2 = cos_omega2 = + (cos_alpha2 * cos_beta2); + + // Break degeneracy of equatorial line. + math::normalize_unit_vector(sin_sigma2, cos_sigma2); + + + // sig12 = sig2 - sig1, limit to [0, pi]. + sigma12 = atan2(std::max(CT(0), cos_sigma1 * sin_sigma2 - sin_sigma1 * cos_sigma2), + cos_sigma1 * cos_sigma2 + sin_sigma1 * sin_sigma2); + + // omg12 = omg2 - omg1, limit to [0, pi]. + sin_omega12 = std::max(CT(0), cos_omega1 * sin_omega2 - sin_omega1 * cos_omega2); + cos_omega12 = cos_omega1 * cos_omega2 + sin_omega1 * sin_omega2; + + // eta = omg12 - lam120. + CT eta = atan2(sin_omega12 * cos_lam120 - cos_omega12 * sin_lam120, + cos_omega12 * cos_lam120 + sin_omega12 * sin_lam120); + + CT B312; + CT k2 = math::sqr(cos_alpha0) * ep2; + + eps = k2 / (c2 * (c1 + std::sqrt(c1 + k2)) + k2); + + se::coeffs_C3 const coeffs_C3(n, eps); + + B312 = se::sin_cos_series(sin_sigma2, cos_sigma2, coeffs_C3) + - se::sin_cos_series(sin_sigma1, cos_sigma1, coeffs_C3); + + se::coeffs_A3 const coeffs_A3(n); + + CT const A3 = math::horner_evaluate(eps, coeffs_A3.begin(), coeffs_A3.end()); + + diff_omega12 = -f * A3 * sin_alpha0 * (sigma12 + B312); + lam12 = eta + diff_omega12; + + if (diffp) + { + if (cos_alpha2 == c0) + { + diff_lam12 = - c2 * one_minus_f * dn1 / sin_beta1; + } + else + { + CT dummy; + meridian_length(eps, ep2, sigma12, sin_sigma1, cos_sigma1, dn1, + sin_sigma2, cos_sigma2, dn2, + cos_beta1, cos_beta2, dummy, + diff_lam12, dummy, dummy, + dummy, coeffs_C1); + + diff_lam12 *= one_minus_f / (cos_alpha2 * cos_beta2); + } + } + return lam12; + } + +}; + +}}} // namespace boost::geometry::formula + + +#endif // BOOST_GEOMETRY_FORMULAS_KARNEY_INVERSE_HPP diff --git a/include/boost/geometry/formulas/sjoberg_intersection.hpp b/include/boost/geometry/formulas/sjoberg_intersection.hpp index 49358fcc1..12abb7675 100644 --- a/include/boost/geometry/formulas/sjoberg_intersection.hpp +++ b/include/boost/geometry/formulas/sjoberg_intersection.hpp @@ -884,7 +884,7 @@ private: // 3. f1-f2 may be 0 which means that the intermediate point is on the vertex // In this case it's not possible to check if this is the correct result // 4. f1-f2 may also be 0 in other cases, e.g. - // geodesics are symetrical wrt equator and longitude directions are different + // geodesics are symmetrical wrt equator and longitude directions are different CT const dbeta_denom = f1 - f2; //CT const dbeta_denom = math::abs(f1) + math::abs(f2); diff --git a/include/boost/geometry/srs/projection.hpp b/include/boost/geometry/srs/projection.hpp index c5a5674de..0a7d123e6 100644 --- a/include/boost/geometry/srs/projection.hpp +++ b/include/boost/geometry/srs/projection.hpp @@ -338,7 +338,7 @@ class proj_wrapper typedef typename projections::detail::promote_to_double::type calc_t; typedef projections::parameters parameters_type; - typedef projections::detail::base_v vprj_t; + typedef projections::detail::dynamic_wrapper_b vprj_t; public: template diff --git a/include/boost/geometry/srs/projections/factory.hpp b/include/boost/geometry/srs/projections/factory.hpp index 773d2bbcb..599c4bf4d 100644 --- a/include/boost/geometry/srs/projections/factory.hpp +++ b/include/boost/geometry/srs/projections/factory.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017. -// Modifications copyright (c) 2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2019. +// Modifications copyright (c) 2017, 2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -127,6 +126,43 @@ namespace boost { namespace geometry { namespace projections namespace detail { +template +struct factory_key +{ + BOOST_MPL_ASSERT_MSG((false), INVALID_PARAMETERS_TYPE, (Params)); +}; + +template <> +struct factory_key +{ + typedef std::string type; + template + static type const& get(ProjParams const& par) + { + return par.id.name; + } + static const char* get(const char* name, srs::dpar::value_proj id) + { + return name; + } +}; + +template +struct factory_key > +{ + typedef srs::dpar::value_proj type; + template + static type const& get(ProjParams const& par) + { + return par.id.id; + } + static srs::dpar::value_proj get(const char* name, srs::dpar::value_proj id) + { + return id; + } +}; + + template class factory { @@ -138,7 +174,8 @@ private: ProjParams > entry_base; - typedef typename factory_key_util::type key_type; + typedef factory_key key; + typedef typename key::type key_type; typedef boost::shared_ptr entry_ptr; typedef std::map entries_map; @@ -249,17 +286,17 @@ public: detail::wink2_init(*this); } - void add_to_factory(key_type const& key, entry_base* entry) + void add_to_factory(const char* name, srs::dpar::value_proj id, entry_base* entry) { // The pointer has to be owned before std::map::operator[] in case it thrown an exception. entry_ptr ptr(entry); - m_entries[key] = ptr; + m_entries[key::get(name, id)] = ptr; } - detail::base_v* create_new(Params const& params, ProjParams const& proj_par) const + detail::dynamic_wrapper_b* create_new(Params const& params, ProjParams const& proj_par) const { - typename factory_key_util::type key = factory_key_util::get(proj_par); - typename entries_map::const_iterator it = m_entries.find(key); + typedef typename entries_map::const_iterator const_iterator; + const_iterator it = m_entries.find(key::get(proj_par)); if (it != m_entries.end()) { return it->second->create_new(params, proj_par); @@ -270,7 +307,7 @@ public: }; template -inline detail::base_v >* +inline detail::dynamic_wrapper_b >* create_new(srs::detail::proj4_parameters const& params, projections::parameters const& parameters) { @@ -279,7 +316,7 @@ inline detail::base_v >* } template -inline detail::base_v >* +inline detail::dynamic_wrapper_b >* create_new(srs::dpar::parameters const& params, projections::parameters const& parameters) { diff --git a/include/boost/geometry/srs/projections/factory_key.hpp b/include/boost/geometry/srs/projections/factory_key.hpp deleted file mode 100644 index 924f92415..000000000 --- a/include/boost/geometry/srs/projections/factory_key.hpp +++ /dev/null @@ -1,83 +0,0 @@ -// Boost.Geometry - -// Copyright (c) 2018, 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_PROJECTIONS_FACTORY_KEY_HPP -#define BOOST_GEOMETRY_PROJECTIONS_FACTORY_KEY_HPP - -#include - -#include -#include - -namespace boost { namespace geometry { namespace projections -{ - -namespace detail -{ - -template -struct factory_key_util -{ - BOOST_MPL_ASSERT_MSG((false), INVALID_PARAMETERS_TYPE, (Params)); -}; - -template <> -struct factory_key_util -{ - typedef std::string type; - template - static type const& get(ProjParams const& par) - { - return par.id.name; - } -}; - -template -struct factory_key_util > -{ - typedef srs::dpar::value_proj type; - template - static type const& get(ProjParams const& par) - { - return par.id.id; - } -}; - -struct factory_key -{ - factory_key(const char* name, srs::dpar::value_proj id) - : m_name(name), m_id(id) - {} - - operator const char*() const - { - return m_name; - } - - operator std::string() const - { - return std::string(m_name); - } - - operator srs::dpar::value_proj() const - { - return m_id; - } - -private: - const char* m_name; - srs::dpar::value_proj m_id; -}; - - -} // namespace detail - -}}} // namespace boost::geometry::projections - -#endif // BOOST_GEOMETRY_PROJECTIONS_FACTORY_KEY_HPP diff --git a/include/boost/geometry/srs/projections/grids.hpp b/include/boost/geometry/srs/projections/grids.hpp index 611344ccd..315ac4a06 100644 --- a/include/boost/geometry/srs/projections/grids.hpp +++ b/include/boost/geometry/srs/projections/grids.hpp @@ -1,7 +1,7 @@ // Boost.Geometry -// This file was modified by Oracle on 2018. -// Modifications copyright (c) 2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2018, 2019. +// Modifications copyright (c) 2018, 2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -20,37 +20,14 @@ namespace boost { namespace geometry { -namespace srs -{ -// Forward declarations for functions declarations below -class grids; - -template -class projection_grids; - -} // namespace srs namespace projections { namespace detail { -// Forward declaratios of grids friends -template -inline bool pj_gridlist_merge_gridfile(std::string const& gridname, - StreamPolicy const& stream_policy, - srs::grids & grids, - std::vector & gridindexes); -template -inline bool pj_apply_gridshift_3(StreamPolicy const& stream_policy, - Range & range, - srs::grids & grids, - std::vector const& gridindexes); -// Forward declaratios of projection_grids friends -template -inline void pj_gridlist_from_nadgrids(Par const& defn, - srs::projection_grids & grids); -template -inline bool pj_apply_gridshift_2(Par const& defn, Range & range, Grids const& grids); +struct grids_tag {}; +struct shared_grids_tag {}; + }} // namespace projections::detail @@ -70,22 +47,9 @@ public: return gridinfo.empty(); } -private: - template - friend inline bool projections::detail::pj_gridlist_merge_gridfile( - std::string const& gridname, - StreamPolicy const& stream_policy, - srs::grids & grids, - std::vector & gridindexes); - template - friend inline bool projections::detail::pj_apply_gridshift_3( - StreamPolicy const& stream_policy, - Range & range, - srs::grids & grids, - std::vector const& gridindexes); + typedef projections::detail::grids_tag tag; projections::detail::pj_gridinfo gridinfo; - }; struct ifstream_policy @@ -125,29 +89,20 @@ class projection_grids { public: projection_grids(GridsStorage & storage) - : storage_ptr(boost::addressof(storage)) + : m_storage_ptr(boost::addressof(storage)) {} - std::size_t size() const - { - return hindexes.size(); - } + typedef GridsStorage grids_storage_type; - bool empty() const + GridsStorage & grids_storage() const { - return hindexes.empty(); + return *m_storage_ptr; } private: - template - friend inline void projections::detail::pj_gridlist_from_nadgrids( - Par const& defn, - srs::projection_grids & grids); - template - friend inline bool projections::detail::pj_apply_gridshift_2( - Par const& defn, Range & range, Grids const& grids); + GridsStorage * const m_storage_ptr; - GridsStorage * const storage_ptr; +public: std::vector hindexes; }; diff --git a/include/boost/geometry/srs/projections/impl/base_dynamic.hpp b/include/boost/geometry/srs/projections/impl/base_dynamic.hpp index 5eeba47ba..05a103ecb 100644 --- a/include/boost/geometry/srs/projections/impl/base_dynamic.hpp +++ b/include/boost/geometry/srs/projections/impl/base_dynamic.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -33,16 +33,28 @@ namespace detail \tparam P parameters type */ template -class base_v +class dynamic_wrapper_b { public : + dynamic_wrapper_b(P const& par) + : m_par(par) + {} + + virtual ~dynamic_wrapper_b() {} + + /// Forward projection using lon / lat and x / y separately + virtual void fwd(P const& par, CT const& lp_lon, CT const& lp_lat, CT& xy_x, CT& xy_y) const = 0; + + /// Inverse projection using x / y and lon / lat + virtual void inv(P const& par, CT const& xy_x, CT const& xy_y, CT& lp_lon, CT& lp_lat) const = 0; + /// Forward projection, from Latitude-Longitude to Cartesian template inline bool forward(LL const& lp, XY& xy) const { try { - pj_fwd(*this, this->params(), lp, xy); + pj_fwd(*this, m_par, lp, xy); return true; } catch (...) @@ -57,7 +69,7 @@ public : { try { - pj_inv(*this, this->params(), xy, lp); + pj_inv(*this, m_par, xy, lp); return true; } catch (projection_not_invertible_exception &) @@ -70,87 +82,74 @@ public : } } - /// Forward projection using lon / lat and x / y separately - virtual void fwd(CT const& lp_lon, CT const& lp_lat, CT& xy_x, CT& xy_y) const = 0; - - /// Inverse projection using x / y and lon / lat - virtual void inv(CT const& xy_x, CT const& xy_y, CT& lp_lon, CT& lp_lat) const = 0; - /// Returns name of projection - virtual std::string name() const = 0; + std::string name() const { return m_par.id.name; } /// Returns parameters of projection - virtual P const& params() const = 0; + P const& params() const { return m_par; } /// Returns mutable parameters of projection - virtual P& mutable_params() = 0; - - virtual ~base_v() {} -}; - -// Base-virtual-forward -template -class base_v_f : public base_v -{ -public: - explicit base_v_f(P const& p) - : m_proj(p) - {} - - template - base_v_f(P1 const& p1, P2 const& p2) - : m_proj(p1, p2) - {} - - template - base_v_f(P1 const& p1, P2 const& p2, P3 const& p3) - : m_proj(p1, p2, p3) - {} - - virtual void fwd(CT const& lp_lon, CT const& lp_lat, CT& xy_x, CT& xy_y) const - { - m_proj.fwd(lp_lon, lp_lat, xy_x, xy_y); - } - - virtual void inv(CT const& , CT const& , CT& , CT& ) const - { - BOOST_THROW_EXCEPTION(projection_not_invertible_exception(params().id.name)); - } - - virtual std::string name() const { return m_proj.name(); } - - virtual P const& params() const { return m_proj.params(); } - - virtual P& mutable_params() { return m_proj.mutable_params(); } + P& mutable_params() { return m_par; } protected: - Prj m_proj; + P m_par; }; -// Base-virtual-forward/inverse +// Forward template -class base_v_fi : public base_v_f +class dynamic_wrapper_f + : public dynamic_wrapper_b + , protected Prj { - typedef base_v_f base_t; + typedef dynamic_wrapper_b base_t; public: - explicit base_v_fi(P const& p) - : base_t(p) + template + dynamic_wrapper_f(Params const& params, P const& par) + : base_t(par) + , Prj(params, this->m_par) // prj can modify parameters {} - template - base_v_fi(P1 const& p1, P2 const& p2) - : base_t(p1, p2) + template + dynamic_wrapper_f(Params const& params, P const& par, P3 const& p3) + : base_t(par) + , Prj(params, this->m_par, p3) // prj can modify parameters {} - template - base_v_fi(P1 const& p1, P2 const& p2, P3 const& p3) - : base_t(p1, p2, p3) - {} - - virtual void inv(CT const& xy_x, CT const& xy_y, CT& lp_lon, CT& lp_lat) const + virtual void fwd(P const& par, CT const& lp_lon, CT const& lp_lat, CT& xy_x, CT& xy_y) const { - this->m_proj.inv(xy_x, xy_y, lp_lon, lp_lat); + prj().fwd(par, lp_lon, lp_lat, xy_x, xy_y); + } + + virtual void inv(P const& , CT const& , CT const& , CT& , CT& ) const + { + BOOST_THROW_EXCEPTION(projection_not_invertible_exception(this->name())); + } + +protected: + Prj const& prj() const { return *this; } +}; + +// Forward/inverse +template +class dynamic_wrapper_fi : public dynamic_wrapper_f +{ + typedef dynamic_wrapper_f base_t; + +public: + template + dynamic_wrapper_fi(Params const& params, P const& par) + : base_t(params, par) + {} + + template + dynamic_wrapper_fi(Params const& params, P const& par, P3 const& p3) + : base_t(params, par, p3) + {} + + virtual void inv(P const& par, CT const& xy_x, CT const& xy_y, CT& lp_lon, CT& lp_lat) const + { + this->prj().inv(par, xy_x, xy_y, lp_lon, lp_lat); } }; diff --git a/include/boost/geometry/srs/projections/impl/base_static.hpp b/include/boost/geometry/srs/projections/impl/base_static.hpp index 9aba3dcb3..99f7a2383 100644 --- a/include/boost/geometry/srs/projections/impl/base_static.hpp +++ b/include/boost/geometry/srs/projections/impl/base_static.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -21,6 +21,7 @@ #include +#include #include #include @@ -45,73 +46,105 @@ struct static_projection_type (Prj, CSTag)); }; -#define BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(PROJ, P_SPHERE, P_SPHEROID) \ +#define BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_F(PROJ, P_SPHXXX) \ template \ struct static_projection_type \ { \ - typedef P_SPHERE type; \ + typedef projections::detail::static_wrapper_f, P> type; \ }; \ template \ struct static_projection_type \ { \ - typedef P_SPHEROID type; \ + typedef projections::detail::static_wrapper_f, P> type; \ }; \ -// Base-template-forward -template -struct base_t_f -{ -public: +#define BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(PROJ, P_SPHXXX) \ +template \ +struct static_projection_type \ +{ \ + typedef projections::detail::static_wrapper_fi, P> type; \ +}; \ +template \ +struct static_projection_type \ +{ \ + typedef projections::detail::static_wrapper_fi, P> type; \ +}; \ - inline base_t_f(Prj const& prj, P const& params) - : m_par(params), m_prj(prj) +#define BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(PROJ, P_SPHERE, P_SPHEROID) \ +template \ +struct static_projection_type \ +{ \ + typedef projections::detail::static_wrapper_fi, P> type; \ +}; \ +template \ +struct static_projection_type \ +{ \ + typedef projections::detail::static_wrapper_fi, P> type; \ +}; \ + +template +struct static_wrapper_b +{ + inline explicit static_wrapper_b(P const& par) + : m_par(par) {} - inline P const& params() const { return m_par; } + std::string name() const { return m_par.id.name; } - inline P& mutable_params() { return m_par; } + P const& params() const { return m_par; } + + P& mutable_params() { return m_par; } + +protected: + P m_par; +}; + +// Forward +template +struct static_wrapper_f + : public static_wrapper_b

+ , public Prj +{ +public: + template + inline static_wrapper_f(Params const& params, P const& par) + : static_wrapper_b

(par) + , Prj(params, this->m_par) // prj can modify parameters + {} template inline bool forward(LL const& lp, XY& xy) const { try { - pj_fwd(m_prj, m_par, lp, xy); + pj_fwd(*this, this->m_par, lp, xy); return true; } - catch(...) + catch (...) { return false; } } template - inline bool inverse(XY const& , LL& ) const + inline bool inverse(XY const&, LL&) const { BOOST_MPL_ASSERT_MSG((false), - PROJECTION_IS_NOT_INVERTABLE, - (Prj)); + PROJECTION_IS_NOT_INVERTABLE, + (Prj)); return false; } - - inline std::string name() const - { - return this->m_par.id.name; - } - -protected: - - P m_par; - const Prj& m_prj; }; -// Base-template-forward/inverse -template -struct base_t_fi : public base_t_f +// Forward/inverse +template +struct static_wrapper_fi + : public static_wrapper_f { -public : - inline base_t_fi(Prj const& prj, P const& params) - : base_t_f(prj, params) +public: + template + inline static_wrapper_fi(Params const& params, P const& par) + : static_wrapper_f(params, par) {} template @@ -119,10 +152,10 @@ public : { try { - pj_inv(this->m_prj, this->m_par, xy, lp); + pj_inv(*this, this->m_par, xy, lp); return true; } - catch(...) + catch (...) { return false; } diff --git a/include/boost/geometry/srs/projections/impl/factory_entry.hpp b/include/boost/geometry/srs/projections/impl/factory_entry.hpp index 7a21bbbef..a22fe950b 100644 --- a/include/boost/geometry/srs/projections/impl/factory_entry.hpp +++ b/include/boost/geometry/srs/projections/impl/factory_entry.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -15,7 +15,6 @@ #include -#include #include namespace boost { namespace geometry { namespace projections @@ -32,7 +31,7 @@ template struct factory_entry { virtual ~factory_entry() {} - virtual base_v* create_new(Params const& , Parameters const& ) const = 0; + virtual dynamic_wrapper_b* create_new(Params const& , Parameters const& ) const = 0; }; // Macros for entries definition @@ -41,22 +40,22 @@ struct factory_entry template \ struct ENTRY : projections::detail::factory_entry \ { \ - projections::detail::base_v* create_new(Params const& params, \ - Parameters const& parameters) const + projections::detail::dynamic_wrapper_b* create_new(Params const& params, \ + Parameters const& parameters) const #define BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_END }; #define BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(ENTRY, PROJ) \ BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_BEGIN(ENTRY) \ { \ - return new projections::detail::base_v_f, T, Parameters>(params, parameters); \ + return new projections::detail::dynamic_wrapper_f, T, Parameters>(params, parameters); \ } \ BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_END #define BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(ENTRY, PROJ) \ BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_BEGIN(ENTRY) \ { \ - return new projections::detail::base_v_fi, T, Parameters>(params, parameters); \ + return new projections::detail::dynamic_wrapper_fi, T, Parameters>(params, parameters); \ } \ BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_END @@ -64,9 +63,9 @@ BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_END BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_BEGIN(ENTRY) \ { \ if (parameters.es != 0.0) \ - return new projections::detail::base_v_fi, T, Parameters>(params, parameters); \ + return new projections::detail::dynamic_wrapper_fi, T, Parameters>(params, parameters); \ else \ - return new projections::detail::base_v_fi, T, Parameters>(params, parameters); \ + return new projections::detail::dynamic_wrapper_fi, T, Parameters>(params, parameters); \ } \ BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_END @@ -76,8 +75,8 @@ template \ inline void FUN_NAME(projections::detail::factory& factory) #define BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_INIT_ENTRY(PROJ_NAME, ENTRY) \ - factory.add_to_factory(projections::detail::factory_key(#PROJ_NAME, \ - srs::dpar::proj_##PROJ_NAME), \ + factory.add_to_factory(#PROJ_NAME, \ + srs::dpar::proj_##PROJ_NAME, \ new ENTRY); } // namespace detail diff --git a/include/boost/geometry/srs/projections/impl/pj_apply_gridshift.hpp b/include/boost/geometry/srs/projections/impl/pj_apply_gridshift.hpp index e56fecc8b..e9e4c9e5b 100644 --- a/include/boost/geometry/srs/projections/impl/pj_apply_gridshift.hpp +++ b/include/boost/geometry/srs/projections/impl/pj_apply_gridshift.hpp @@ -329,11 +329,13 @@ inline bool load_grid(StreamPolicy const& stream_policy, pj_gi_load & gi) /* This is the real workhorse, given a gridlist. */ /************************************************************************/ -template +// Generic stream policy and standard grids +template inline bool pj_apply_gridshift_3(StreamPolicy const& stream_policy, Range & range, - srs::grids & grids, - std::vector const& gridindexes) + Grids & grids, + std::vector const& gridindexes, + grids_tag) { typedef typename boost::range_size::type size_type; @@ -381,6 +383,103 @@ inline bool pj_apply_gridshift_3(StreamPolicy const& stream_policy, return true; } +// Generic stream policy and shared grids +template +inline bool pj_apply_gridshift_3(StreamPolicy const& stream_policy, + Range & range, + SharedGrids & grids, + std::vector const& gridindexes, + shared_grids_tag) +{ + typedef typename boost::range_size::type size_type; + + // If the grids are empty the indexes are as well + if (gridindexes.empty()) + { + //pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); + //return PJD_ERR_FAILED_TO_LOAD_GRID; + return false; + } + + size_type point_count = boost::size(range); + + // local storage + pj_gi_load local_gi; + + for (size_type i = 0 ; i < point_count ; ) + { + bool load_needed = false; + + CalcT in_lon = 0; + CalcT in_lat = 0; + + { + typename SharedGrids::read_locked lck_grids(grids); + + for ( ; i < point_count ; ++i ) + { + typename boost::range_reference::type + point = range::at(range, i); + + in_lon = geometry::get_as_radian<0>(point); + in_lat = geometry::get_as_radian<1>(point); + + pj_gi * gip = find_grid(in_lon, in_lat, lck_grids.gridinfo, gridindexes); + + if (gip == NULL) + { + // do nothing + } + else if (! gip->ct.cvs.empty()) + { + // TODO: use set_invalid_point() or similar mechanism + CalcT out_lon = HUGE_VAL; + CalcT out_lat = HUGE_VAL; + + nad_cvt(in_lon, in_lat, out_lon, out_lat, *gip); + + // TODO: check differently + if (out_lon != HUGE_VAL) + { + geometry::set_from_radian<0>(point, out_lon); + geometry::set_from_radian<1>(point, out_lat); + } + } + else + { + // loading is needed + local_gi = *gip; + load_needed = true; + break; + } + } + } + + if (load_needed) + { + if (load_grid(stream_policy, local_gi)) + { + typename SharedGrids::write_locked lck_grids(grids); + + // check again in case other thread already loaded the grid. + pj_gi * gip = find_grid(in_lon, in_lat, lck_grids.gridinfo, gridindexes); + + if (gip != NULL && gip->ct.cvs.empty()) + { + // swap loaded local storage with empty grid + local_gi.swap(*gip); + } + } + else + { + ++i; + } + } + } + + return true; +} + /************************************************************************/ /* pj_apply_gridshift_2() */ @@ -392,7 +491,7 @@ inline bool pj_apply_gridshift_3(StreamPolicy const& stream_policy, /************************************************************************/ template -inline bool pj_apply_gridshift_2(Par const& /*defn*/, Range & range, ProjGrids const& grids) +inline bool pj_apply_gridshift_2(Par const& /*defn*/, Range & range, ProjGrids const& proj_grids) { /*if( defn->catalog_name != NULL ) return pj_gc_apply_gridshift( defn, inverse, point_count, point_offset, @@ -404,19 +503,18 @@ inline bool pj_apply_gridshift_2(Par const& /*defn*/, Range & range, ProjGrids c grids.storage_ptr->grids, gridindexes);*/ - BOOST_GEOMETRY_ASSERT(grids.storage_ptr != NULL); - // At this point the grids should be initialized - if (grids.hindexes.empty()) + if (proj_grids.hindexes.empty()) return false; return pj_apply_gridshift_3 < Inverse, typename Par::type - >(grids.storage_ptr->stream_policy, + >(proj_grids.grids_storage().stream_policy, range, - grids.storage_ptr->hgrids, - grids.hindexes); + proj_grids.grids_storage().hgrids, + proj_grids.hindexes, + typename ProjGrids::grids_storage_type::grids_type::tag()); } template diff --git a/include/boost/geometry/srs/projections/impl/pj_apply_gridshift_shared.hpp b/include/boost/geometry/srs/projections/impl/pj_apply_gridshift_shared.hpp deleted file mode 100644 index c83c1bc51..000000000 --- a/include/boost/geometry/srs/projections/impl/pj_apply_gridshift_shared.hpp +++ /dev/null @@ -1,157 +0,0 @@ -// Boost.Geometry -// This file is manually converted from PROJ4 - -// This file was modified by Oracle on 2018, 2019. -// Modifications copyright (c) 2018-2019, Oracle and/or its affiliates. -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// This file is converted from PROJ4, http://trac.osgeo.org/proj -// PROJ4 is originally written by Gerald Evenden (then of the USGS) -// PROJ4 is maintained by Frank Warmerdam -// This file was converted to Geometry Library by Adam Wulkiewicz - -// Original copyright notice: -// Author: Frank Warmerdam, warmerdam@pobox.com - -// Copyright (c) 2000, Frank Warmerdam - -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef BOOST_GEOMETRY_SRS_PROJECTIONS_IMPL_PJ_APPLY_GRIDSHIFT_SHARED_HPP -#define BOOST_GEOMETRY_SRS_PROJECTIONS_IMPL_PJ_APPLY_GRIDSHIFT_SHARED_HPP - - -#include -#include - -#include -#include - - -namespace boost { namespace geometry { namespace projections -{ - -namespace detail -{ - -template -inline bool pj_apply_gridshift_3(StreamPolicy const& stream_policy, - Range & range, - shared_grids & grids, - std::vector const& gridindexes) -{ - typedef typename boost::range_size::type size_type; - - // If the grids are empty the indexes are as well - if (gridindexes.empty()) - { - //pj_ctx_set_errno(ctx, PJD_ERR_FAILED_TO_LOAD_GRID); - //return PJD_ERR_FAILED_TO_LOAD_GRID; - return false; - } - - size_type point_count = boost::size(range); - - // local storage - pj_gi_load local_gi; - - for (size_type i = 0 ; i < point_count ; ) - { - bool load_needed = false; - - CalcT in_lon = 0; - CalcT in_lat = 0; - - { - boost::shared_lock lock(grids.mutex); - - for ( ; i < point_count ; ++i ) - { - typename boost::range_reference::type - point = range::at(range, i); - - in_lon = geometry::get_as_radian<0>(point); - in_lat = geometry::get_as_radian<1>(point); - - pj_gi * gip = find_grid(in_lon, in_lat, grids.gridinfo, gridindexes); - - if (gip == NULL) - { - // do nothing - } - else if (! gip->ct.cvs.empty()) - { - // TODO: use set_invalid_point() or similar mechanism - CalcT out_lon = HUGE_VAL; - CalcT out_lat = HUGE_VAL; - - nad_cvt(in_lon, in_lat, out_lon, out_lat, *gip); - - // TODO: check differently - if (out_lon != HUGE_VAL) - { - geometry::set_from_radian<0>(point, out_lon); - geometry::set_from_radian<1>(point, out_lat); - } - } - else - { - // loading is needed - local_gi = *gip; - load_needed = true; - break; - } - } - } - - if (load_needed) - { - if (load_grid(stream_policy, local_gi)) - { - boost::unique_lock lock(grids.mutex); - - // check again in case other thread already loaded the grid. - pj_gi * gip = find_grid(in_lon, in_lat, grids.gridinfo, gridindexes); - - if (gip != NULL && gip->ct.cvs.empty()) - { - // swap loaded local storage with empty grid - local_gi.swap(*gip); - } - } - else - { - ++i; - } - } - } - - return true; -} - - -} // namespace detail - -}}} // namespace boost::geometry::projections - -#endif // BOOST_GEOMETRY_SRS_PROJECTIONS_IMPL_PJ_APPLY_GRIDSHIFT_SHARED_HPP diff --git a/include/boost/geometry/srs/projections/impl/pj_datums.hpp b/include/boost/geometry/srs/projections/impl/pj_datums.hpp index 5c156bf35..2343194d3 100644 --- a/include/boost/geometry/srs/projections/impl/pj_datums.hpp +++ b/include/boost/geometry/srs/projections/impl/pj_datums.hpp @@ -147,7 +147,7 @@ inline std::pair*, int> pj_get_datums() srs::dpar::ellps_airy} }; - return std::make_pair(pj_datums, sizeof(pj_datums) / sizeof(pj_datums[0])); + return std::make_pair(pj_datums, (int)(sizeof(pj_datums) / sizeof(pj_datums[0]))); } static const pj_prime_meridians_type pj_prime_meridians[] = diff --git a/include/boost/geometry/srs/projections/impl/pj_ellps.hpp b/include/boost/geometry/srs/projections/impl/pj_ellps.hpp index 1a6f824ee..af6bc864c 100644 --- a/include/boost/geometry/srs/projections/impl/pj_ellps.hpp +++ b/include/boost/geometry/srs/projections/impl/pj_ellps.hpp @@ -121,7 +121,7 @@ inline std::pair*, int> pj_get_ellps() BOOST_GEOMETRY_PROJECTIONS_DETAIL_PJ_ELLPS_B ("sphere", 6370997.0, 6370997.0, "Normal Sphere (r=6370997)") }; - return std::make_pair(pj_ellps, sizeof(pj_ellps) / sizeof(pj_ellps[0])); + return std::make_pair(pj_ellps, (int)(sizeof(pj_ellps) / sizeof(pj_ellps[0]))); } } // namespace detail diff --git a/include/boost/geometry/srs/projections/impl/pj_fwd.hpp b/include/boost/geometry/srs/projections/impl/pj_fwd.hpp index c1725b0a8..01b7b97a2 100644 --- a/include/boost/geometry/srs/projections/impl/pj_fwd.hpp +++ b/include/boost/geometry/srs/projections/impl/pj_fwd.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -90,7 +90,8 @@ inline void pj_fwd(Prj const& prj, P const& par, LL const& ll, XY& xy) calc_t x = 0; calc_t y = 0; - prj.fwd(lp_lon, lp_lat, x, y); + prj.fwd(par, lp_lon, lp_lat, x, y); + geometry::set<0>(xy, par.fr_meter * (par.a * x + par.x0)); geometry::set<1>(xy, par.fr_meter * (par.a * y + par.y0)); } diff --git a/include/boost/geometry/srs/projections/impl/pj_gridlist.hpp b/include/boost/geometry/srs/projections/impl/pj_gridlist.hpp index deccdd39f..6407142f9 100644 --- a/include/boost/geometry/srs/projections/impl/pj_gridlist.hpp +++ b/include/boost/geometry/srs/projections/impl/pj_gridlist.hpp @@ -1,8 +1,8 @@ // Boost.Geometry // This file is manually converted from PROJ4 -// This file was modified by Oracle on 2018. -// Modifications copyright (c) 2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2018, 2019. +// Modifications copyright (c) 2018-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -92,11 +92,12 @@ inline void pj_gridlist_add_seq_inc(std::vector & gridindexes, } // Generic stream policy and standard grids -template +template inline bool pj_gridlist_merge_gridfile(std::string const& gridname, StreamPolicy const& stream_policy, - srs::grids & grids, - std::vector & gridindexes) + Grids & grids, + std::vector & gridindexes, + grids_tag) { // Try to find in the existing list of loaded grids. Add all // matching grids as with NTv2 we can get many grids from one @@ -121,6 +122,61 @@ inline bool pj_gridlist_merge_gridfile(std::string const& gridname, return true; } +// Generic stream policy and shared grids +template +inline bool pj_gridlist_merge_gridfile(std::string const& gridname, + StreamPolicy const& stream_policy, + SharedGrids & grids, + std::vector & gridindexes, + shared_grids_tag) +{ + // Try to find in the existing list of loaded grids. Add all + // matching grids as with NTv2 we can get many grids from one + // file (one shared gridname). + { + typename SharedGrids::read_locked lck_grids(grids); + + if (pj_gridlist_find_all(gridname, lck_grids.gridinfo, gridindexes)) + return true; + } + + // Try to load the named grid. + typename StreamPolicy::stream_type is; + stream_policy.open(is, gridname); + + pj_gridinfo new_grids; + + if (! pj_gridinfo_init(gridname, is, new_grids)) + { + return false; + } + + // Add the grid now that it is loaded. + + std::size_t orig_size = 0; + std::size_t new_size = 0; + + { + typename SharedGrids::write_locked lck_grids(grids); + + // Try to find in the existing list of loaded grids again + // in case other thread already added it. + if (pj_gridlist_find_all(gridname, lck_grids.gridinfo, gridindexes)) + return true; + + orig_size = lck_grids.gridinfo.size(); + new_size = orig_size + new_grids.size(); + + lck_grids.gridinfo.resize(new_size); + for (std::size_t i = 0 ; i < new_grids.size() ; ++ i) + new_grids[i].swap(lck_grids.gridinfo[i + orig_size]); + } + + pj_gridlist_add_seq_inc(gridindexes, orig_size, new_size); + + return true; +} + /************************************************************************/ /* pj_gridlist_from_nadgrids() */ @@ -147,7 +203,8 @@ inline void pj_gridlist_from_nadgrids(srs::detail::nadgrids const& nadgrids, std::string name(it->begin() + (required ? 0 : 1), it->end()); - if ( ! pj_gridlist_merge_gridfile(name, stream_policy, grids, gridindexes) + if ( ! pj_gridlist_merge_gridfile(name, stream_policy, grids, gridindexes, + typename Grids::tag()) && required ) { BOOST_THROW_EXCEPTION( projection_exception(error_failed_to_load_grid) ); @@ -155,15 +212,13 @@ inline void pj_gridlist_from_nadgrids(srs::detail::nadgrids const& nadgrids, } } -template -inline void pj_gridlist_from_nadgrids(Par const& defn, srs::projection_grids & grids) +template +inline void pj_gridlist_from_nadgrids(Par const& defn, ProjectionGrids & proj_grids) { - BOOST_GEOMETRY_ASSERT(grids.storage_ptr != NULL); - pj_gridlist_from_nadgrids(defn.nadgrids, - grids.storage_ptr->stream_policy, - grids.storage_ptr->hgrids, - grids.hindexes); + proj_grids.grids_storage().stream_policy, + proj_grids.grids_storage().hgrids, + proj_grids.hindexes); } diff --git a/include/boost/geometry/srs/projections/impl/pj_gridlist_shared.hpp b/include/boost/geometry/srs/projections/impl/pj_gridlist_shared.hpp deleted file mode 100644 index de8640a01..000000000 --- a/include/boost/geometry/srs/projections/impl/pj_gridlist_shared.hpp +++ /dev/null @@ -1,122 +0,0 @@ -// Boost.Geometry -// This file is manually converted from PROJ4 - -// This file was modified by Oracle on 2018, 2019. -// Modifications copyright (c) 2018-2019, Oracle and/or its affiliates. -// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle - -// Use, modification and distribution is subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// This file is converted from PROJ4, http://trac.osgeo.org/proj -// PROJ4 is originally written by Gerald Evenden (then of the USGS) -// PROJ4 is maintained by Frank Warmerdam -// This file was converted to Geometry Library by Adam Wulkiewicz - -// Original copyright notice: -// Author: Frank Warmerdam, warmerdam@pobox.com - -// Copyright (c) 2000, Frank Warmerdam - -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -#ifndef BOOST_GEOMETRY_SRS_PROJECTIONS_IMPL_PJ_GRIDLIST_SHARED_HPP -#define BOOST_GEOMETRY_SRS_PROJECTIONS_IMPL_PJ_GRIDLIST_SHARED_HPP - - -#include -#include -#include - - -namespace boost { namespace geometry { namespace projections -{ - -namespace detail -{ - - -/************************************************************************/ -/* pj_gridlist_merge_grid() */ -/* */ -/* Find/load the named gridfile and merge it into the */ -/* last_nadgrids_list. */ -/************************************************************************/ - -// Generic stream policy and shared grids -template -inline bool pj_gridlist_merge_gridfile(std::string const& gridname, - StreamPolicy const& stream_policy, - shared_grids & grids, - std::vector & gridindexes) -{ - // Try to find in the existing list of loaded grids. Add all - // matching grids as with NTv2 we can get many grids from one - // file (one shared gridname). - { - boost::shared_lock lock(grids.mutex); - - if (pj_gridlist_find_all(gridname, grids.gridinfo, gridindexes)) - return true; - } - - // Try to load the named grid. - typename StreamPolicy::stream_type is; - stream_policy.open(is, gridname); - - pj_gridinfo new_grids; - - if (! pj_gridinfo_init(gridname, is, new_grids)) - { - return false; - } - - // Add the grid now that it is loaded. - - std::size_t orig_size = 0; - std::size_t new_size = 0; - - { - boost::unique_lock lock(grids.mutex); - - // Try to find in the existing list of loaded grids again - // in case other thread already added it. - if (pj_gridlist_find_all(gridname, grids.gridinfo, gridindexes)) - return true; - - orig_size = grids.gridinfo.size(); - new_size = orig_size + new_grids.size(); - - grids.gridinfo.resize(new_size); - for (std::size_t i = 0 ; i < new_grids.size() ; ++ i) - new_grids[i].swap(grids.gridinfo[i + orig_size]); - } - - pj_gridlist_add_seq_inc(gridindexes, orig_size, new_size); - - return true; -} - - -} // namespace detail - -}}} // namespace boost::geometry::projections - -#endif // BOOST_GEOMETRY_SRS_PROJECTIONS_IMPL_PJ_GRIDLIST_SHARED_HPP diff --git a/include/boost/geometry/srs/projections/impl/pj_inv.hpp b/include/boost/geometry/srs/projections/impl/pj_inv.hpp index 91cf4c50f..aa65af974 100644 --- a/include/boost/geometry/srs/projections/impl/pj_inv.hpp +++ b/include/boost/geometry/srs/projections/impl/pj_inv.hpp @@ -3,8 +3,8 @@ // Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017. -// Modifications copyright (c) 2017, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, @@ -65,7 +65,9 @@ inline void pj_inv(PRJ const& prj, PAR const& par, XY const& xy, LL& ll) calc_t xy_x = (geometry::get<0>(xy) * par.to_meter - par.x0) * par.ra; calc_t xy_y = (geometry::get<1>(xy) * par.to_meter - par.y0) * par.ra; calc_t lon = 0, lat = 0; - prj.inv(xy_x, xy_y, lon, lat); /* inverse project */ + + prj.inv(par, xy_x, xy_y, lon, lat); /* inverse project */ + lon += par.lam0; /* reduce from del lp.lam */ if (!par.over) lon = adjlon(lon); /* adjust longitude to CM */ diff --git a/include/boost/geometry/srs/projections/impl/proj_mdist.hpp b/include/boost/geometry/srs/projections/impl/proj_mdist.hpp index 65fc41a4c..9e8f0cfbe 100644 --- a/include/boost/geometry/srs/projections/impl/proj_mdist.hpp +++ b/include/boost/geometry/srs/projections/impl/proj_mdist.hpp @@ -54,10 +54,10 @@ namespace detail { static const int static_size = 20; - int nb; T es; T E; T b[static_size]; + int nb; }; template diff --git a/include/boost/geometry/srs/projections/impl/projects.hpp b/include/boost/geometry/srs/projections/impl/projects.hpp index ecb1eeea8..e32272f6d 100644 --- a/include/boost/geometry/srs/projections/impl/projects.hpp +++ b/include/boost/geometry/srs/projections/impl/projects.hpp @@ -97,17 +97,6 @@ struct pj_consts T es_orig, a_orig; /* es and a before any +proj related adjustment */ - // C O O R D I N A T E H A N D L I N G - - int over; /* over-range flag */ - int geoc; /* geocentric latitude flag */ - int is_latlong; /* proj=latlong ... not really a projection at all */ - int is_geocent; /* proj=geocent ... not really a projection at all */ - //int need_ellps; /* 0 for operations that are purely cartesian */ - - //enum pj_io_units left; /* Flags for input/output coordinate types */ - //enum pj_io_units right; - // C A R T O G R A P H I C O F F S E T S T lam0, phi0; /* central longitude, latitude */ @@ -121,27 +110,40 @@ struct pj_consts // D A T U M S A N D H E I G H T S Y S T E M S - detail::datum_type datum_type; /* PJD_UNKNOWN/3PARAM/7PARAM/GRIDSHIFT/WGS84 */ - srs::detail::towgs84 datum_params; /* Parameters for 3PARAM and 7PARAM */ - srs::detail::nadgrids nadgrids; /* Names of horozontal grid files. */ - T from_greenwich; /* prime meridian offset (in radians) */ T long_wrap_center; /* 0.0 for -180 to 180, actually in radians*/ + + srs::detail::towgs84 datum_params; /* Parameters for 3PARAM and 7PARAM */ + srs::detail::nadgrids nadgrids; /* Names of horozontal grid files. */ + detail::datum_type datum_type; /* PJD_UNKNOWN/3PARAM/7PARAM/GRIDSHIFT/WGS84 */ + bool is_long_wrap_set; + // C O O R D I N A T E H A N D L I N G + + bool over; /* over-range flag */ + bool geoc; /* geocentric latitude flag */ + bool is_latlong; /* proj=latlong ... not really a projection at all */ + bool is_geocent; /* proj=geocent ... not really a projection at all */ + //bool need_ellps; /* 0 for operations that are purely cartesian */ + + //enum pj_io_units left; /* Flags for input/output coordinate types */ + //enum pj_io_units right; + // Initialize all variables pj_consts() : a(0), ra(0) , e(0), es(0), one_es(0), rone_es(0) , es_orig(0), a_orig(0) - , over(0), geoc(0), is_latlong(0), is_geocent(0) - //, need_ellps(1) - //, left(PJ_IO_UNITS_ANGULAR), right(PJ_IO_UNITS_CLASSIC) , lam0(0), phi0(0) , x0(0), y0(0)/*, z0(0), t0(0)*/ , k0(0) , to_meter(0), fr_meter(0), vto_meter(0), vfr_meter(0) + , from_greenwich(0), long_wrap_center(0) , datum_type(datum_unknown) - , from_greenwich(0), long_wrap_center(0), is_long_wrap_set(false) + , is_long_wrap_set(false) + , over(false), geoc(false), is_latlong(false), is_geocent(false) + //, need_ellps(true) + //, left(PJ_IO_UNITS_ANGULAR), right(PJ_IO_UNITS_CLASSIC) {} }; diff --git a/include/boost/geometry/srs/projections/proj/aea.hpp b/include/boost/geometry/srs/projections/proj/aea.hpp index 42c2cc9af..00f56316b 100644 --- a/include/boost/geometry/srs/projections/proj/aea.hpp +++ b/include/boost/geometry/srs/projections/proj/aea.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -88,7 +88,7 @@ namespace projections T phi1; T phi2; detail::en en; - int ellips; + bool ellips; }; /* determine latitude angle phi-1 */ @@ -115,23 +115,17 @@ namespace projections return( i ? Phi : HUGE_VAL ); } - // template class, using CRTP to implement forward/inverse template struct base_aea_ellipsoid - : public base_t_fi, T, Parameters> { par_aea m_proj_parm; - inline base_aea_ellipsoid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(e_forward) ellipsoid & spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& par, T lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { T rho = this->m_proj_parm.c - (this->m_proj_parm.ellips - ? this->m_proj_parm.n * pj_qsfn(sin(lp_lat), this->m_par.e, this->m_par.one_es) + ? this->m_proj_parm.n * pj_qsfn(sin(lp_lat), par.e, par.one_es) : this->m_proj_parm.n2 * sin(lp_lat)); if (rho < 0.) BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); @@ -142,7 +136,7 @@ namespace projections // INVERSE(e_inverse) ellipsoid & spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T xy_x, T xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T xy_x, T xy_y, T& lp_lon, T& lp_lat) const { static const T half_pi = detail::half_pi(); @@ -157,7 +151,7 @@ namespace projections if (this->m_proj_parm.ellips) { lp_lat = (this->m_proj_parm.c - lp_lat * lp_lat) / this->m_proj_parm.n; if (fabs(this->m_proj_parm.ec - fabs(lp_lat)) > tolerance7) { - if ((lp_lat = phi1_(lp_lat, this->m_par.e, this->m_par.one_es)) == HUGE_VAL) + if ((lp_lat = phi1_(lp_lat, par.e, par.one_es)) == HUGE_VAL) BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); } else lp_lat = lp_lat < 0. ? -half_pi : half_pi; @@ -282,9 +276,8 @@ namespace projections { template inline aea_ellipsoid(Params const& params, Parameters const& par) - : detail::aea::base_aea_ellipsoid(par) { - detail::aea::setup_aea(params, this->m_par, this->m_proj_parm); + detail::aea::setup_aea(params, par, this->m_proj_parm); } }; @@ -309,9 +302,8 @@ namespace projections { template inline leac_ellipsoid(Params const& params, Parameters const& par) - : detail::aea::base_aea_ellipsoid(par) { - detail::aea::setup_leac(params, this->m_par, this->m_proj_parm); + detail::aea::setup_leac(params, par, this->m_proj_parm); } }; @@ -320,8 +312,8 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_aea, aea_ellipsoid, aea_ellipsoid) - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_leac, leac_ellipsoid, leac_ellipsoid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_aea, aea_ellipsoid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_leac, leac_ellipsoid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(aea_entry, aea_ellipsoid) diff --git a/include/boost/geometry/srs/projections/proj/aeqd.hpp b/include/boost/geometry/srs/projections/proj/aeqd.hpp index 73ce9aac4..0254abeb1 100644 --- a/include/boost/geometry/srs/projections/proj/aeqd.hpp +++ b/include/boost/geometry/srs/projections/proj/aeqd.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -88,12 +88,12 @@ namespace projections T cosph0; detail::en en; T M1; - T N1; + //T N1; T Mp; - T He; - T G; + //T He; + //T G; + T b; mode_type mode; - srs::spheroid spheroid; }; template @@ -129,7 +129,7 @@ namespace projections formula::vincenty_inverse < T, true, true - >::apply(par.lam0, par.phi0, lp_lon + par.lam0, lp_lat, proj_parm.spheroid); + >::apply(par.lam0, par.phi0, lp_lon + par.lam0, lp_lat, srs::spheroid(par.a, proj_parm.b)); //azi1 = inv.azimuth; s12 = inv.distance; xy_x = inv.distance * sin(inv.azimuth) / par.a; xy_y = inv.distance * cos(inv.azimuth) / par.a; @@ -158,7 +158,7 @@ namespace projections formula::vincenty_direct < T, true - >::apply(par.lam0, par.phi0, s12, azi1, proj_parm.spheroid); + >::apply(par.lam0, par.phi0, s12, azi1, srs::spheroid(par.a, proj_parm.b)); lp_lat = dir.lat2; lp_lon = dir.lon2; lp_lon -= par.lam0; @@ -317,41 +317,34 @@ namespace projections break; case equit: case obliq: - proj_parm.N1 = 1. / sqrt(1. - par.es * proj_parm.sinph0 * proj_parm.sinph0); - proj_parm.G = proj_parm.sinph0 * (proj_parm.He = par.e / sqrt(par.one_es)); - proj_parm.He *= proj_parm.cosph0; + //proj_parm.N1 = 1. / sqrt(1. - par.es * proj_parm.sinph0 * proj_parm.sinph0); + //proj_parm.G = proj_parm.sinph0 * (proj_parm.He = par.e / sqrt(par.one_es)); + //proj_parm.He *= proj_parm.cosph0; break; } // Boost.Geometry specific, in proj4 geodesic is initialized at the beginning - T const b = math::sqrt(math::sqr(par.a) * (1. - par.es)); - proj_parm.spheroid = srs::spheroid(par.a, b); + proj_parm.b = math::sqrt(math::sqr(par.a) * (1. - par.es)); } } } - // template class, using CRTP to implement forward/inverse template struct base_aeqd_e - : public base_t_fi, T, Parameters> { par_aeqd m_proj_parm; - inline base_aeqd_e(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(e_forward) elliptical // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { - e_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_par, this->m_proj_parm); + e_forward(lp_lon, lp_lat, xy_x, xy_y, par, this->m_proj_parm); } // INVERSE(e_inverse) elliptical // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { - e_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_par, this->m_proj_parm); + e_inverse(xy_x, xy_y, lp_lon, lp_lat, par, this->m_proj_parm); } static inline std::string get_name() @@ -361,29 +354,23 @@ namespace projections }; - // template class, using CRTP to implement forward/inverse template struct base_aeqd_e_guam - : public base_t_fi, T, Parameters> { par_aeqd m_proj_parm; - inline base_aeqd_e_guam(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(e_guam_fwd) Guam elliptical // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { - e_guam_fwd(lp_lon, lp_lat, xy_x, xy_y, this->m_par, this->m_proj_parm); + e_guam_fwd(lp_lon, lp_lat, xy_x, xy_y, par, this->m_proj_parm); } // INVERSE(e_guam_inv) Guam elliptical // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { - e_guam_inv(xy_x, xy_y, lp_lon, lp_lat, this->m_par, this->m_proj_parm); + e_guam_inv(xy_x, xy_y, lp_lon, lp_lat, par, this->m_proj_parm); } static inline std::string get_name() @@ -393,78 +380,23 @@ namespace projections }; - // template class, using CRTP to implement forward/inverse - template - struct base_aeqd_e_static - : public base_t_fi, T, Parameters> - { - par_aeqd m_proj_parm; - - static const bool is_guam = ! boost::is_same - < - typename srs::spar::detail::tuples_find_if - < - BGParameters, - //srs::par4::detail::is_guam - srs::spar::detail::is_param::pred - >::type, - void - >::value; - - inline base_aeqd_e_static(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - - // FORWARD(e_forward or e_guam_fwd) elliptical - // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const - { - if (is_guam) - e_guam_fwd(lp_lon, lp_lat, xy_x, xy_y, this->m_par, this->m_proj_parm); - else - e_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_par, this->m_proj_parm); - } - - // INVERSE(e_inverse or e_guam_inv) elliptical - // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const - { - if (is_guam) - e_guam_inv(xy_x, xy_y, lp_lon, lp_lat, this->m_par, this->m_proj_parm); - else - e_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_par, this->m_proj_parm); - } - - static inline std::string get_name() - { - return "aeqd_e_static"; - } - - }; - - // template class, using CRTP to implement forward/inverse template struct base_aeqd_s - : public base_t_fi, T, Parameters> { par_aeqd m_proj_parm; - inline base_aeqd_s(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spherical // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { - s_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_par, this->m_proj_parm); + s_forward(lp_lon, lp_lat, xy_x, xy_y, par, this->m_proj_parm); } // INVERSE(s_inverse) spherical // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { - s_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_par, this->m_proj_parm); + s_inverse(xy_x, xy_y, lp_lon, lp_lat, par, this->m_proj_parm); } static inline std::string get_name() @@ -497,10 +429,9 @@ namespace projections struct aeqd_e : public detail::aeqd::base_aeqd_e { template - inline aeqd_e(Params const& params, Parameters const& par) - : detail::aeqd::base_aeqd_e(par) + inline aeqd_e(Params const& params, Parameters & par) { - detail::aeqd::setup_aeqd(params, this->m_par, this->m_proj_parm, false, false); + detail::aeqd::setup_aeqd(params, par, this->m_proj_parm, false, false); } }; @@ -524,38 +455,9 @@ namespace projections struct aeqd_e_guam : public detail::aeqd::base_aeqd_e_guam { template - inline aeqd_e_guam(Params const& params, Parameters const& par) - : detail::aeqd::base_aeqd_e_guam(par) + inline aeqd_e_guam(Params const& params, Parameters & par) { - detail::aeqd::setup_aeqd(params, this->m_par, this->m_proj_parm, false, true); - } - }; - - /*! - \brief Azimuthal Equidistant projection - \ingroup projections - \tparam Geographic latlong point type - \tparam Cartesian xy point type - \tparam Parameters parameter type - \par Projection characteristics - - Azimuthal - - Spheroid - - Ellipsoid - \par Projection parameters - - lat_0: Latitude of origin (degrees) - - guam (boolean) - \par Example - \image html ex_aeqd.gif - */ - template - struct aeqd_e_static : public detail::aeqd::base_aeqd_e_static - { - inline aeqd_e_static(SParams const& params, Parameters const& par) - : detail::aeqd::base_aeqd_e_static(par) - { - detail::aeqd::setup_aeqd(params, this->m_par, this->m_proj_parm, - false, - detail::aeqd::base_aeqd_e_static::is_guam); + detail::aeqd::setup_aeqd(params, par, this->m_proj_parm, false, true); } }; @@ -579,10 +481,9 @@ namespace projections struct aeqd_s : public detail::aeqd::base_aeqd_s { template - inline aeqd_s(Params const& params, Parameters const& par) - : detail::aeqd::base_aeqd_s(par) + inline aeqd_s(Params const& params, Parameters & par) { - detail::aeqd::setup_aeqd(params, this->m_par, this->m_proj_parm, true, false); + detail::aeqd::setup_aeqd(params, par, this->m_proj_parm, true, false); } }; @@ -594,12 +495,30 @@ namespace projections template struct static_projection_type { - typedef aeqd_s type; + typedef static_wrapper_fi, P> type; }; template struct static_projection_type { - typedef aeqd_e_static type; + typedef static_wrapper_fi + < + typename boost::mpl::if_c + < + boost::is_same + < + typename srs::spar::detail::tuples_find_if + < + BGP, + //srs::par4::detail::is_guam + srs::spar::detail::is_param::pred + >::type, + void + >::value, + aeqd_e, + aeqd_e_guam + >::type + , P + > type; }; BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_BEGIN(aeqd_entry) @@ -607,11 +526,11 @@ namespace projections bool const guam = pj_get_param_b(params, "guam", srs::dpar::guam); if (parameters.es && ! guam) - return new base_v_fi, T, Parameters>(params, parameters); + return new dynamic_wrapper_fi, T, Parameters>(params, parameters); else if (parameters.es && guam) - return new base_v_fi, T, Parameters>(params, parameters); + return new dynamic_wrapper_fi, T, Parameters>(params, parameters); else - return new base_v_fi, T, Parameters>(params, parameters); + return new dynamic_wrapper_fi, T, Parameters>(params, parameters); } BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_END diff --git a/include/boost/geometry/srs/projections/proj/airy.hpp b/include/boost/geometry/srs/projections/proj/airy.hpp index fc2ea57de..00931ae82 100644 --- a/include/boost/geometry/srs/projections/proj/airy.hpp +++ b/include/boost/geometry/srs/projections/proj/airy.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -78,23 +78,17 @@ namespace projections T cosph0; T Cb; mode_type mode; - int no_cut; /* do not cut at hemisphere limit */ + bool no_cut; /* do not cut at hemisphere limit */ }; - // template class, using CRTP to implement forward/inverse template struct base_airy_spheroid - : public base_t_f, T, Parameters> { par_airy m_proj_parm; - inline base_airy_spheroid(const Parameters& par) - : base_t_f, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const { static const T half_pi = detail::half_pi(); @@ -209,10 +203,9 @@ namespace projections struct airy_spheroid : public detail::airy::base_airy_spheroid { template - inline airy_spheroid(Params const& params, Parameters const& par) - : detail::airy::base_airy_spheroid(par) + inline airy_spheroid(Params const& params, Parameters & par) { - detail::airy::setup_airy(params, this->m_par, this->m_proj_parm); + detail::airy::setup_airy(params, par, this->m_proj_parm); } }; @@ -221,7 +214,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_airy, airy_spheroid, airy_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_F(srs::spar::proj_airy, airy_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(airy_entry, airy_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/aitoff.hpp b/include/boost/geometry/srs/projections/proj/aitoff.hpp index a7ad3b086..f11a46e9d 100644 --- a/include/boost/geometry/srs/projections/proj/aitoff.hpp +++ b/include/boost/geometry/srs/projections/proj/aitoff.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -77,20 +77,14 @@ namespace projections mode_type mode; }; - // template class, using CRTP to implement forward/inverse template struct base_aitoff_spheroid - : public base_t_fi, T, Parameters> { par_aitoff m_proj_parm; - inline base_aitoff_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { T c, d; @@ -127,7 +121,7 @@ namespace projections // INVERSE(s_inverse) sphere // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { static const T pi = detail::pi(); static const T two_pi = detail::two_pi(); @@ -253,10 +247,9 @@ namespace projections struct aitoff_spheroid : public detail::aitoff::base_aitoff_spheroid { template - inline aitoff_spheroid(Params const& , Parameters const& par) - : detail::aitoff::base_aitoff_spheroid(par) + inline aitoff_spheroid(Params const& , Parameters & par) { - detail::aitoff::setup_aitoff(this->m_par, this->m_proj_parm); + detail::aitoff::setup_aitoff(par, this->m_proj_parm); } }; @@ -278,10 +271,9 @@ namespace projections struct wintri_spheroid : public detail::aitoff::base_aitoff_spheroid { template - inline wintri_spheroid(Params const& params, Parameters const& par) - : detail::aitoff::base_aitoff_spheroid(par) + inline wintri_spheroid(Params const& params, Parameters & par) { - detail::aitoff::setup_wintri(params, this->m_par, this->m_proj_parm); + detail::aitoff::setup_wintri(params, par, this->m_proj_parm); } }; @@ -290,8 +282,8 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_aitoff, aitoff_spheroid, aitoff_spheroid) - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_wintri, wintri_spheroid, wintri_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_aitoff, aitoff_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_wintri, wintri_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(aitoff_entry, aitoff_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/august.hpp b/include/boost/geometry/srs/projections/proj/august.hpp index fb55dcb9e..4db65c5a2 100644 --- a/include/boost/geometry/srs/projections/proj/august.hpp +++ b/include/boost/geometry/srs/projections/proj/august.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -56,18 +56,12 @@ namespace projections //static const double M = 1.333333333333333; - // template class, using CRTP to implement forward/inverse template struct base_august_spheroid - : public base_t_f, T, Parameters> { - inline base_august_spheroid(const Parameters& par) - : base_t_f, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { static const T M = 1.333333333333333333333333333333333333; @@ -116,10 +110,9 @@ namespace projections struct august_spheroid : public detail::august::base_august_spheroid { template - inline august_spheroid(Params const& , Parameters const& par) - : detail::august::base_august_spheroid(par) + inline august_spheroid(Params const& , Parameters & par) { - detail::august::setup_august(this->m_par); + detail::august::setup_august(par); } }; @@ -128,7 +121,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_august, august_spheroid, august_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_F(srs::spar::proj_august, august_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(august_entry, august_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/bacon.hpp b/include/boost/geometry/srs/projections/proj/bacon.hpp index 17b3c36e0..8cdf23a51 100644 --- a/include/boost/geometry/srs/projections/proj/bacon.hpp +++ b/include/boost/geometry/srs/projections/proj/bacon.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -61,24 +61,18 @@ namespace projections struct par_bacon { - int bacn; - int ortl; + bool bacn; + bool ortl; }; - // template class, using CRTP to implement forward/inverse template struct base_bacon_spheroid - : public base_t_f, T, Parameters> { par_bacon m_proj_parm; - inline base_bacon_spheroid(const Parameters& par) - : base_t_f, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { static const T half_pi = detail::half_pi(); static const T half_pi_sqr = detail::half_pi_sqr(); @@ -109,7 +103,7 @@ namespace projections template inline void setup_apian(Parameters& par, par_bacon& proj_parm) { - proj_parm.bacn = proj_parm.ortl = 0; + proj_parm.bacn = proj_parm.ortl = false; par.es = 0.; } @@ -117,8 +111,8 @@ namespace projections template inline void setup_ortel(Parameters& par, par_bacon& proj_parm) { - proj_parm.bacn = 0; - proj_parm.ortl = 1; + proj_parm.bacn = false; + proj_parm.ortl = true; par.es = 0.; } @@ -126,8 +120,8 @@ namespace projections template inline void setup_bacon(Parameters& par, par_bacon& proj_parm) { - proj_parm.bacn = 1; - proj_parm.ortl = 0; + proj_parm.bacn = true; + proj_parm.ortl = false; par.es = 0.; } @@ -151,10 +145,9 @@ namespace projections struct apian_spheroid : public detail::bacon::base_bacon_spheroid { template - inline apian_spheroid(Params const& , Parameters const& par) - : detail::bacon::base_bacon_spheroid(par) + inline apian_spheroid(Params const& , Parameters & par) { - detail::bacon::setup_apian(this->m_par, this->m_proj_parm); + detail::bacon::setup_apian(par, this->m_proj_parm); } }; @@ -175,10 +168,9 @@ namespace projections struct ortel_spheroid : public detail::bacon::base_bacon_spheroid { template - inline ortel_spheroid(Params const& , Parameters const& par) - : detail::bacon::base_bacon_spheroid(par) + inline ortel_spheroid(Params const& , Parameters & par) { - detail::bacon::setup_ortel(this->m_par, this->m_proj_parm); + detail::bacon::setup_ortel(par, this->m_proj_parm); } }; @@ -199,10 +191,9 @@ namespace projections struct bacon_spheroid : public detail::bacon::base_bacon_spheroid { template - inline bacon_spheroid(Params const& , Parameters const& par) - : detail::bacon::base_bacon_spheroid(par) + inline bacon_spheroid(Params const& , Parameters & par) { - detail::bacon::setup_bacon(this->m_par, this->m_proj_parm); + detail::bacon::setup_bacon(par, this->m_proj_parm); } }; @@ -211,9 +202,9 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_apian, apian_spheroid, apian_spheroid) - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_bacon, bacon_spheroid, bacon_spheroid) - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_ortel, ortel_spheroid, ortel_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_F(srs::spar::proj_apian, apian_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_F(srs::spar::proj_bacon, bacon_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_F(srs::spar::proj_ortel, ortel_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(apian_entry, apian_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/bipc.hpp b/include/boost/geometry/srs/projections/proj/bipc.hpp index 9d531f87a..6eb57e839 100644 --- a/include/boost/geometry/srs/projections/proj/bipc.hpp +++ b/include/boost/geometry/srs/projections/proj/bipc.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -81,23 +81,17 @@ namespace projections struct par_bipc { - int noskew; + bool noskew; }; - // template class, using CRTP to implement forward/inverse template struct base_bipc_spheroid - : public base_t_fi, T, Parameters> { par_bipc m_proj_parm; - inline base_bipc_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { static const T half_pi = detail::half_pi(); static const T pi = detail::pi(); @@ -171,7 +165,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T xy_x, T xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T xy_x, T xy_y, T& lp_lon, T& lp_lat) const { T t, r, rp, rl, al, z, fAz, Az, s, c, Av; int neg, i; @@ -251,10 +245,9 @@ namespace projections struct bipc_spheroid : public detail::bipc::base_bipc_spheroid { template - inline bipc_spheroid(Params const& params, Parameters const& par) - : detail::bipc::base_bipc_spheroid(par) + inline bipc_spheroid(Params const& params, Parameters & par) { - detail::bipc::setup_bipc(params, this->m_par, this->m_proj_parm); + detail::bipc::setup_bipc(params, par, this->m_proj_parm); } }; @@ -263,7 +256,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_bipc, bipc_spheroid, bipc_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_bipc, bipc_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(bipc_entry, bipc_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/boggs.hpp b/include/boost/geometry/srs/projections/proj/boggs.hpp index a9bf51716..a7d12509e 100644 --- a/include/boost/geometry/srs/projections/proj/boggs.hpp +++ b/include/boost/geometry/srs/projections/proj/boggs.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -62,18 +62,12 @@ namespace projections static const double FXC2 = 1.11072; static const double FYC = 0.49931; - // template class, using CRTP to implement forward/inverse template struct base_boggs_spheroid - : public base_t_f, T, Parameters> { - inline base_boggs_spheroid(const Parameters& par) - : base_t_f, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { static const T half_pi = detail::half_pi(); static const T pi = detail::pi(); @@ -132,10 +126,9 @@ namespace projections struct boggs_spheroid : public detail::boggs::base_boggs_spheroid { template - inline boggs_spheroid(Params const& , Parameters const& par) - : detail::boggs::base_boggs_spheroid(par) + inline boggs_spheroid(Params const& , Parameters & par) { - detail::boggs::setup_boggs(this->m_par); + detail::boggs::setup_boggs(par); } }; @@ -144,7 +137,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_boggs, boggs_spheroid, boggs_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_F(srs::spar::proj_boggs, boggs_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(boggs_entry, boggs_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/bonne.hpp b/include/boost/geometry/srs/projections/proj/bonne.hpp index 70bdc87fd..dcbf0e001 100644 --- a/include/boost/geometry/srs/projections/proj/bonne.hpp +++ b/include/boost/geometry/srs/projections/proj/bonne.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -72,43 +72,37 @@ namespace projections detail::en en; }; - // template class, using CRTP to implement forward/inverse template struct base_bonne_ellipsoid - : public base_t_fi, T, Parameters> { par_bonne m_proj_parm; - inline base_bonne_ellipsoid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(e_forward) ellipsoid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { T rh, E, c; rh = this->m_proj_parm.am1 + this->m_proj_parm.m1 - pj_mlfn(lp_lat, E = sin(lp_lat), c = cos(lp_lat), this->m_proj_parm.en); - E = c * lp_lon / (rh * sqrt(1. - this->m_par.es * E * E)); + E = c * lp_lon / (rh * sqrt(1. - par.es * E * E)); xy_x = rh * sin(E); xy_y = this->m_proj_parm.am1 - rh * cos(E); } // INVERSE(e_inverse) ellipsoid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T const& xy_x, T xy_y, T& lp_lon, T& lp_lat) const { static const T half_pi = detail::half_pi(); T s, rh; rh = boost::math::hypot(xy_x, xy_y = this->m_proj_parm.am1 - xy_y); - lp_lat = pj_inv_mlfn(this->m_proj_parm.am1 + this->m_proj_parm.m1 - rh, this->m_par.es, this->m_proj_parm.en); + lp_lat = pj_inv_mlfn(this->m_proj_parm.am1 + this->m_proj_parm.m1 - rh, par.es, this->m_proj_parm.en); if ((s = fabs(lp_lat)) < half_pi) { s = sin(lp_lat); lp_lon = rh * atan2(xy_x, xy_y) * - sqrt(1. - this->m_par.es * s * s) / cos(lp_lat); + sqrt(1. - par.es * s * s) / cos(lp_lat); } else if (fabs(s - half_pi) <= epsilon10) lp_lon = 0.; else @@ -122,20 +116,14 @@ namespace projections }; - // template class, using CRTP to implement forward/inverse template struct base_bonne_spheroid - : public base_t_fi, T, Parameters> { par_bonne m_proj_parm; - inline base_bonne_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { T E, rh; @@ -149,7 +137,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T xy_y, T& lp_lon, T& lp_lat) const { static const T half_pi = detail::half_pi(); @@ -175,7 +163,7 @@ namespace projections // Bonne (Werner lat_1=90) template - inline void setup_bonne(Params const& params, Parameters& par, par_bonne& proj_parm) + inline void setup_bonne(Params const& params, Parameters const& par, par_bonne& proj_parm) { static const T half_pi = detail::half_pi(); @@ -221,9 +209,8 @@ namespace projections { template inline bonne_ellipsoid(Params const& params, Parameters const& par) - : detail::bonne::base_bonne_ellipsoid(par) { - detail::bonne::setup_bonne(params, this->m_par, this->m_proj_parm); + detail::bonne::setup_bonne(params, par, this->m_proj_parm); } }; @@ -247,9 +234,8 @@ namespace projections { template inline bonne_spheroid(Params const& params, Parameters const& par) - : detail::bonne::base_bonne_spheroid(par) { - detail::bonne::setup_bonne(params, this->m_par, this->m_proj_parm); + detail::bonne::setup_bonne(params, par, this->m_proj_parm); } }; @@ -258,7 +244,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_bonne, bonne_spheroid, bonne_ellipsoid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(srs::spar::proj_bonne, bonne_spheroid, bonne_ellipsoid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(bonne_entry, bonne_spheroid, bonne_ellipsoid) diff --git a/include/boost/geometry/srs/projections/proj/cass.hpp b/include/boost/geometry/srs/projections/proj/cass.hpp index 4f68cd01b..f87ed312d 100644 --- a/include/boost/geometry/srs/projections/proj/cass.hpp +++ b/include/boost/geometry/srs/projections/proj/cass.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -81,20 +81,14 @@ namespace projections detail::en en; }; - // template class, using CRTP to implement forward/inverse template struct base_cass_ellipsoid - : public base_t_fi, T, Parameters> { par_cass m_proj_parm; - inline base_cass_ellipsoid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(e_forward) ellipsoid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { static const T C1 = cass::C1(); static const T C2 = cass::C2(); @@ -103,11 +97,11 @@ namespace projections T n = sin(lp_lat); T c = cos(lp_lat); xy_y = pj_mlfn(lp_lat, n, c, this->m_proj_parm.en); - n = 1./sqrt(1. - this->m_par.es * n * n); + n = 1./sqrt(1. - par.es * n * n); T tn = tan(lp_lat); T t = tn * tn; T a1 = lp_lon * c; - c *= this->m_par.es * c / (1 - this->m_par.es); + c *= par.es * c / (1 - par.es); T a2 = a1 * a1; xy_x = n * a1 * (1. - a2 * t * (C1 - (8. - t + 8. * c) * a2 * C2)); @@ -117,7 +111,7 @@ namespace projections // INVERSE(e_inverse) ellipsoid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { static const T C3 = cass::C3(); static const T C4 = cass::C4(); @@ -125,12 +119,12 @@ namespace projections T ph1; - ph1 = pj_inv_mlfn(this->m_proj_parm.m0 + xy_y, this->m_par.es, this->m_proj_parm.en); + ph1 = pj_inv_mlfn(this->m_proj_parm.m0 + xy_y, par.es, this->m_proj_parm.en); T tn = tan(ph1); T t = tn * tn; T n = sin(ph1); - T r = 1. / (1. - this->m_par.es * n * n); + T r = 1. / (1. - par.es * n * n); n = sqrt(r); - r *= (1. - this->m_par.es) * n; + r *= (1. - par.es) * n; T dd = xy_x / n; T d2 = dd * dd; lp_lat = ph1 - (n * tn / r) * d2 * @@ -146,30 +140,24 @@ namespace projections }; - // template class, using CRTP to implement forward/inverse template struct base_cass_spheroid - : public base_t_fi, T, Parameters> { par_cass m_proj_parm; - inline base_cass_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { xy_x = asin(cos(lp_lat) * sin(lp_lon)); - xy_y = atan2(tan(lp_lat) , cos(lp_lon)) - this->m_par.phi0; + xy_y = atan2(tan(lp_lat) , cos(lp_lon)) - par.phi0; } // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { - T dd = xy_y + this->m_par.phi0; + T dd = xy_y + par.phi0; lp_lat = asin(sin(dd) * cos(xy_x)); lp_lon = atan2(tan(xy_x), cos(dd)); } @@ -213,9 +201,8 @@ namespace projections { template inline cass_ellipsoid(Params const& , Parameters const& par) - : detail::cass::base_cass_ellipsoid(par) { - detail::cass::setup_cass(this->m_par, this->m_proj_parm); + detail::cass::setup_cass(par, this->m_proj_parm); } }; @@ -237,9 +224,8 @@ namespace projections { template inline cass_spheroid(Params const& , Parameters const& par) - : detail::cass::base_cass_spheroid(par) { - detail::cass::setup_cass(this->m_par, this->m_proj_parm); + detail::cass::setup_cass(par, this->m_proj_parm); } }; @@ -248,7 +234,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_cass, cass_spheroid, cass_ellipsoid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(srs::spar::proj_cass, cass_spheroid, cass_ellipsoid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(cass_entry, cass_spheroid, cass_ellipsoid) diff --git a/include/boost/geometry/srs/projections/proj/cc.hpp b/include/boost/geometry/srs/projections/proj/cc.hpp index fbc97c7bd..0684efc6b 100644 --- a/include/boost/geometry/srs/projections/proj/cc.hpp +++ b/include/boost/geometry/srs/projections/proj/cc.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -58,18 +58,12 @@ namespace projections static const double epsilon10 = 1.e-10; - // template class, using CRTP to implement forward/inverse template struct base_cc_spheroid - : public base_t_fi, T, Parameters> { - inline base_cc_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { static const T half_pi = detail::half_pi(); @@ -82,7 +76,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { lp_lat = atan(xy_y); lp_lon = xy_x; @@ -121,10 +115,9 @@ namespace projections struct cc_spheroid : public detail::cc::base_cc_spheroid { template - inline cc_spheroid(Params const& , Parameters const& par) - : detail::cc::base_cc_spheroid(par) + inline cc_spheroid(Params const& , Parameters & par) { - detail::cc::setup_cc(this->m_par); + detail::cc::setup_cc(par); } }; @@ -133,7 +126,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_cc, cc_spheroid, cc_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_cc, cc_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(cc_entry, cc_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/cea.hpp b/include/boost/geometry/srs/projections/proj/cea.hpp index 14d7ea9a3..53f253aeb 100644 --- a/include/boost/geometry/srs/projections/proj/cea.hpp +++ b/include/boost/geometry/srs/projections/proj/cea.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -68,31 +68,25 @@ namespace projections detail::apa apa; }; - // template class, using CRTP to implement forward/inverse template struct base_cea_ellipsoid - : public base_t_fi, T, Parameters> { par_cea m_proj_parm; - inline base_cea_ellipsoid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(e_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { - xy_x = this->m_par.k0 * lp_lon; - xy_y = .5 * pj_qsfn(sin(lp_lat), this->m_par.e, this->m_par.one_es) / this->m_par.k0; + xy_x = par.k0 * lp_lon; + xy_y = .5 * pj_qsfn(sin(lp_lat), par.e, par.one_es) / par.k0; } // INVERSE(e_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { - lp_lat = pj_authlat(asin( 2. * xy_y * this->m_par.k0 / this->m_proj_parm.qp), this->m_proj_parm.apa); - lp_lon = xy_x / this->m_par.k0; + lp_lat = pj_authlat(asin( 2. * xy_y * par.k0 / this->m_proj_parm.qp), this->m_proj_parm.apa); + lp_lon = xy_x / par.k0; } static inline std::string get_name() @@ -102,39 +96,33 @@ namespace projections }; - // template class, using CRTP to implement forward/inverse template struct base_cea_spheroid - : public base_t_fi, T, Parameters> { par_cea m_proj_parm; - inline base_cea_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { - xy_x = this->m_par.k0 * lp_lon; - xy_y = sin(lp_lat) / this->m_par.k0; + xy_x = par.k0 * lp_lon; + xy_y = sin(lp_lat) / par.k0; } // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T const& xy_x, T xy_y, T& lp_lon, T& lp_lat) const { static const T half_pi = detail::half_pi(); T t; - if ((t = fabs(xy_y *= this->m_par.k0)) - epsilon <= 1.) { + if ((t = fabs(xy_y *= par.k0)) - epsilon <= 1.) { if (t >= 1.) lp_lat = xy_y < 0. ? -half_pi : half_pi; else lp_lat = asin(xy_y); - lp_lon = xy_x / this->m_par.k0; + lp_lon = xy_x / par.k0; } else BOOST_THROW_EXCEPTION( projection_exception(error_tolerance_condition) ); } @@ -190,10 +178,9 @@ namespace projections struct cea_ellipsoid : public detail::cea::base_cea_ellipsoid { template - inline cea_ellipsoid(Params const& params, Parameters const& par) - : detail::cea::base_cea_ellipsoid(par) + inline cea_ellipsoid(Params const& params, Parameters & par) { - detail::cea::setup_cea(params, this->m_par, this->m_proj_parm); + detail::cea::setup_cea(params, par, this->m_proj_parm); } }; @@ -216,10 +203,9 @@ namespace projections struct cea_spheroid : public detail::cea::base_cea_spheroid { template - inline cea_spheroid(Params const& params, Parameters const& par) - : detail::cea::base_cea_spheroid(par) + inline cea_spheroid(Params const& params, Parameters & par) { - detail::cea::setup_cea(params, this->m_par, this->m_proj_parm); + detail::cea::setup_cea(params, par, this->m_proj_parm); } }; @@ -228,7 +214,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_cea, cea_spheroid, cea_ellipsoid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(srs::spar::proj_cea, cea_spheroid, cea_ellipsoid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(cea_entry, cea_spheroid, cea_ellipsoid) diff --git a/include/boost/geometry/srs/projections/proj/chamb.hpp b/include/boost/geometry/srs/projections/proj/chamb.hpp index 0200a565c..d0e33fde1 100644 --- a/include/boost/geometry/srs/projections/proj/chamb.hpp +++ b/include/boost/geometry/srs/projections/proj/chamb.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -112,20 +112,14 @@ namespace projections return aacos(.5 * (b * b + c * c - a * a) / (b * c)); } - // template class, using CRTP to implement forward/inverse template struct base_chamb_spheroid - : public base_t_f, T, Parameters> { par_chamb m_proj_parm; - inline base_chamb_spheroid(const Parameters& par) - : base_t_f, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { static const T third = detail::third(); @@ -263,10 +257,9 @@ namespace projections struct chamb_spheroid : public detail::chamb::base_chamb_spheroid { template - inline chamb_spheroid(Params const& params, Parameters const& par) - : detail::chamb::base_chamb_spheroid(par) + inline chamb_spheroid(Params const& params, Parameters & par) { - detail::chamb::setup_chamb(params, this->m_par, this->m_proj_parm); + detail::chamb::setup_chamb(params, par, this->m_proj_parm); } }; @@ -275,7 +268,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_chamb, chamb_spheroid, chamb_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_F(srs::spar::proj_chamb, chamb_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(chamb_entry, chamb_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/collg.hpp b/include/boost/geometry/srs/projections/proj/collg.hpp index 8cddbf803..06d08a92a 100644 --- a/include/boost/geometry/srs/projections/proj/collg.hpp +++ b/include/boost/geometry/srs/projections/proj/collg.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -60,18 +60,12 @@ namespace projections static const double FYC = 1.77245385090551602729; static const double one_plus_eps = 1.0000001; - // template class, using CRTP to implement forward/inverse template struct base_collg_spheroid - : public base_t_fi, T, Parameters> { - inline base_collg_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { if ((xy_y = 1. - sin(lp_lat)) <= 0.) xy_y = 0.; @@ -83,7 +77,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { static T const half_pi = detail::half_pi(); @@ -135,10 +129,9 @@ namespace projections struct collg_spheroid : public detail::collg::base_collg_spheroid { template - inline collg_spheroid(Params const& , Parameters const& par) - : detail::collg::base_collg_spheroid(par) + inline collg_spheroid(Params const& , Parameters & par) { - detail::collg::setup_collg(this->m_par); + detail::collg::setup_collg(par); } }; @@ -147,7 +140,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_collg, collg_spheroid, collg_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_collg, collg_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(collg_entry, collg_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/crast.hpp b/include/boost/geometry/srs/projections/proj/crast.hpp index fa6fb98a7..ee8887ba9 100644 --- a/include/boost/geometry/srs/projections/proj/crast.hpp +++ b/include/boost/geometry/srs/projections/proj/crast.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -60,18 +60,12 @@ namespace projections static const double RYM = 0.32573500793527994772; //static const double third = 0.333333333333333333; - // template class, using CRTP to implement forward/inverse template struct base_crast_spheroid - : public base_t_fi, T, Parameters> { - inline base_crast_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const { static const T third = detail::third(); @@ -82,7 +76,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { static const T third = detail::third(); @@ -123,10 +117,9 @@ namespace projections struct crast_spheroid : public detail::crast::base_crast_spheroid { template - inline crast_spheroid(Params const& , Parameters const& par) - : detail::crast::base_crast_spheroid(par) + inline crast_spheroid(Params const& , Parameters & par) { - detail::crast::setup_crast(this->m_par); + detail::crast::setup_crast(par); } }; @@ -135,7 +128,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_crast, crast_spheroid, crast_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_crast, crast_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(crast_entry, crast_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/denoy.hpp b/include/boost/geometry/srs/projections/proj/denoy.hpp index 0f344751d..cb5ca2931 100644 --- a/include/boost/geometry/srs/projections/proj/denoy.hpp +++ b/include/boost/geometry/srs/projections/proj/denoy.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -65,18 +65,12 @@ namespace projections template inline T C3() { return 0.0016666666666666666666666666666; } - // template class, using CRTP to implement forward/inverse template struct base_denoy_spheroid - : public base_t_f, T, Parameters> { - inline base_denoy_spheroid(const Parameters& par) - : base_t_f, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { static const T C1 = denoy::C1(); static const T C3 = denoy::C3(); @@ -122,10 +116,9 @@ namespace projections struct denoy_spheroid : public detail::denoy::base_denoy_spheroid { template - inline denoy_spheroid(Params const& , Parameters const& par) - : detail::denoy::base_denoy_spheroid(par) + inline denoy_spheroid(Params const& , Parameters & par) { - detail::denoy::setup_denoy(this->m_par); + detail::denoy::setup_denoy(par); } }; @@ -134,7 +127,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_denoy, denoy_spheroid, denoy_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_F(srs::spar::proj_denoy, denoy_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(denoy_entry, denoy_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/eck1.hpp b/include/boost/geometry/srs/projections/proj/eck1.hpp index a551c0421..4320176f9 100644 --- a/include/boost/geometry/srs/projections/proj/eck1.hpp +++ b/include/boost/geometry/srs/projections/proj/eck1.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -57,18 +57,12 @@ namespace projections static const double FC = .92131773192356127802; static const double RP = .31830988618379067154; - // template class, using CRTP to implement forward/inverse template struct base_eck1_spheroid - : public base_t_fi, T, Parameters> { - inline base_eck1_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { xy_x = FC * lp_lon * (1. - RP * fabs(lp_lat)); xy_y = FC * lp_lat; @@ -76,7 +70,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { lp_lat = xy_y / FC; lp_lon = xy_x / (FC * (1. - RP * fabs(lp_lat))); @@ -115,10 +109,9 @@ namespace projections struct eck1_spheroid : public detail::eck1::base_eck1_spheroid { template - inline eck1_spheroid(Params const& , Parameters const& par) - : detail::eck1::base_eck1_spheroid(par) + inline eck1_spheroid(Params const& , Parameters & par) { - detail::eck1::setup_eck1(this->m_par); + detail::eck1::setup_eck1(par); } }; @@ -127,7 +120,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_eck1, eck1_spheroid, eck1_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_eck1, eck1_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(eck1_entry, eck1_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/eck2.hpp b/include/boost/geometry/srs/projections/proj/eck2.hpp index c9f8f8d41..b09979668 100644 --- a/include/boost/geometry/srs/projections/proj/eck2.hpp +++ b/include/boost/geometry/srs/projections/proj/eck2.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -61,18 +61,12 @@ namespace projections //static const double C13 = 0.33333333333333333333; static const double one_plus_eps = 1.0000001; - // template class, using CRTP to implement forward/inverse template struct base_eck2_spheroid - : public base_t_fi, T, Parameters> { - inline base_eck2_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { xy_x = FXC * lp_lon * (xy_y = sqrt(4. - 3. * sin(fabs(lp_lat)))); xy_y = FYC * (2. - xy_y); @@ -81,7 +75,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { static const T half_pi = detail::half_pi(); static const T C13 = detail::third(); @@ -132,10 +126,9 @@ namespace projections struct eck2_spheroid : public detail::eck2::base_eck2_spheroid { template - inline eck2_spheroid(Params const& , Parameters const& par) - : detail::eck2::base_eck2_spheroid(par) + inline eck2_spheroid(Params const& , Parameters & par) { - detail::eck2::setup_eck2(this->m_par); + detail::eck2::setup_eck2(par); } }; @@ -144,7 +137,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_eck2, eck2_spheroid, eck2_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_eck2, eck2_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(eck2_entry, eck2_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/eck3.hpp b/include/boost/geometry/srs/projections/proj/eck3.hpp index 65ff88429..85d13ed2d 100644 --- a/include/boost/geometry/srs/projections/proj/eck3.hpp +++ b/include/boost/geometry/srs/projections/proj/eck3.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -63,20 +63,14 @@ namespace projections T C_x, C_y, A, B; }; - // template class, using CRTP to implement forward/inverse template struct base_eck3_spheroid - : public base_t_fi, T, Parameters> { par_eck3 m_proj_parm; - inline base_eck3_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { xy_y = this->m_proj_parm.C_y * lp_lat; xy_x = this->m_proj_parm.C_x * lp_lon * (this->m_proj_parm.A + asqrt(1. - this->m_proj_parm.B * lp_lat * lp_lat)); @@ -84,7 +78,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { T denominator; lp_lat = xy_y / this->m_proj_parm.C_y; @@ -179,10 +173,9 @@ namespace projections struct eck3_spheroid : public detail::eck3::base_eck3_spheroid { template - inline eck3_spheroid(Params const& , Parameters const& par) - : detail::eck3::base_eck3_spheroid(par) + inline eck3_spheroid(Params const& , Parameters & par) { - detail::eck3::setup_eck3(this->m_par, this->m_proj_parm); + detail::eck3::setup_eck3(par, this->m_proj_parm); } }; @@ -202,10 +195,9 @@ namespace projections struct putp1_spheroid : public detail::eck3::base_eck3_spheroid { template - inline putp1_spheroid(Params const& , Parameters const& par) - : detail::eck3::base_eck3_spheroid(par) + inline putp1_spheroid(Params const& , Parameters & par) { - detail::eck3::setup_putp1(this->m_par, this->m_proj_parm); + detail::eck3::setup_putp1(par, this->m_proj_parm); } }; @@ -225,10 +217,9 @@ namespace projections struct wag6_spheroid : public detail::eck3::base_eck3_spheroid { template - inline wag6_spheroid(Params const& , Parameters const& par) - : detail::eck3::base_eck3_spheroid(par) + inline wag6_spheroid(Params const& , Parameters & par) { - detail::eck3::setup_wag6(this->m_par, this->m_proj_parm); + detail::eck3::setup_wag6(par, this->m_proj_parm); } }; @@ -248,10 +239,9 @@ namespace projections struct kav7_spheroid : public detail::eck3::base_eck3_spheroid { template - inline kav7_spheroid(Params const& , Parameters const& par) - : detail::eck3::base_eck3_spheroid(par) + inline kav7_spheroid(Params const& , Parameters & par) { - detail::eck3::setup_kav7(this->m_par, this->m_proj_parm); + detail::eck3::setup_kav7(par, this->m_proj_parm); } }; @@ -260,10 +250,10 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_eck3, eck3_spheroid, eck3_spheroid) - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_putp1, putp1_spheroid, putp1_spheroid) - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_wag6, wag6_spheroid, wag6_spheroid) - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_kav7, kav7_spheroid, kav7_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_eck3, eck3_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_putp1, putp1_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_wag6, wag6_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_kav7, kav7_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(eck3_entry, eck3_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/eck4.hpp b/include/boost/geometry/srs/projections/proj/eck4.hpp index 0a8a2bcd9..bdc4311e9 100644 --- a/include/boost/geometry/srs/projections/proj/eck4.hpp +++ b/include/boost/geometry/srs/projections/proj/eck4.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -63,18 +63,12 @@ namespace projections static const double epsilon = 1e-7; static const int n_iter = 6; - // template class, using CRTP to implement forward/inverse template struct base_eck4_spheroid - : public base_t_fi, T, Parameters> { - inline base_eck4_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const { T p, V, s, c; int i; @@ -101,7 +95,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { T c; @@ -143,10 +137,9 @@ namespace projections struct eck4_spheroid : public detail::eck4::base_eck4_spheroid { template - inline eck4_spheroid(Params const& , Parameters const& par) - : detail::eck4::base_eck4_spheroid(par) + inline eck4_spheroid(Params const& , Parameters & par) { - detail::eck4::setup_eck4(this->m_par); + detail::eck4::setup_eck4(par); } }; @@ -155,7 +148,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_eck4, eck4_spheroid, eck4_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_eck4, eck4_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(eck4_entry, eck4_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/eck5.hpp b/include/boost/geometry/srs/projections/proj/eck5.hpp index 23901b71a..ae658ea61 100644 --- a/include/boost/geometry/srs/projections/proj/eck5.hpp +++ b/include/boost/geometry/srs/projections/proj/eck5.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -59,18 +59,12 @@ namespace projections static const double YF = 0.88202554344910296438; static const double RYF = 1.13375401361911319568; - // template class, using CRTP to implement forward/inverse template struct base_eck5_spheroid - : public base_t_fi, T, Parameters> { - inline base_eck5_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { xy_x = XF * (1. + cos(lp_lat)) * lp_lon; xy_y = YF * lp_lat; @@ -78,7 +72,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { lp_lon = RXF * xy_x / (1. + cos( lp_lat = RYF * xy_y)); } @@ -116,10 +110,9 @@ namespace projections struct eck5_spheroid : public detail::eck5::base_eck5_spheroid { template - inline eck5_spheroid(Params const& , Parameters const& par) - : detail::eck5::base_eck5_spheroid(par) + inline eck5_spheroid(Params const& , Parameters & par) { - detail::eck5::setup_eck5(this->m_par); + detail::eck5::setup_eck5(par); } }; @@ -128,7 +121,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_eck5, eck5_spheroid, eck5_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_eck5, eck5_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(eck5_entry, eck5_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/eqc.hpp b/include/boost/geometry/srs/projections/proj/eqc.hpp index 5a19f39ec..93a90dca3 100644 --- a/include/boost/geometry/srs/projections/proj/eqc.hpp +++ b/include/boost/geometry/srs/projections/proj/eqc.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -60,31 +60,25 @@ namespace projections T rc; }; - // template class, using CRTP to implement forward/inverse template struct base_eqc_spheroid - : public base_t_fi, T, Parameters> { par_eqc m_proj_parm; - inline base_eqc_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { xy_x = this->m_proj_parm.rc * lp_lon; - xy_y = lp_lat - this->m_par.phi0; + xy_y = lp_lat - par.phi0; } // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { lp_lon = xy_x / this->m_proj_parm.rc; - lp_lat = xy_y + this->m_par.phi0; + lp_lat = xy_y + par.phi0; } static inline std::string get_name() @@ -126,10 +120,9 @@ namespace projections struct eqc_spheroid : public detail::eqc::base_eqc_spheroid { template - inline eqc_spheroid(Params const& params, Parameters const& par) - : detail::eqc::base_eqc_spheroid(par) + inline eqc_spheroid(Params const& params, Parameters & par) { - detail::eqc::setup_eqc(params, this->m_par, this->m_proj_parm); + detail::eqc::setup_eqc(params, par, this->m_proj_parm); } }; @@ -138,7 +131,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_eqc, eqc_spheroid, eqc_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_eqc, eqc_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(eqc_entry, eqc_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/eqdc.hpp b/include/boost/geometry/srs/projections/proj/eqdc.hpp index 986e258e2..2919c5d7f 100644 --- a/include/boost/geometry/srs/projections/proj/eqdc.hpp +++ b/include/boost/geometry/srs/projections/proj/eqdc.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -75,20 +75,14 @@ namespace projections bool ellips; }; - // template class, using CRTP to implement forward/inverse template struct base_eqdc_ellipsoid - : public base_t_fi, T, Parameters> { par_eqdc m_proj_parm; - inline base_eqdc_ellipsoid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(e_forward) sphere & ellipsoid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { T rho = 0.0; @@ -100,7 +94,7 @@ namespace projections // INVERSE(e_inverse) sphere & ellipsoid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T xy_x, T xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T xy_x, T xy_y, T& lp_lon, T& lp_lat) const { static T const half_pi = detail::half_pi(); @@ -114,7 +108,7 @@ namespace projections } lp_lat = this->m_proj_parm.c - rho; if (this->m_proj_parm.ellips) - lp_lat = pj_inv_mlfn(lp_lat, this->m_par.es, this->m_proj_parm.en); + lp_lat = pj_inv_mlfn(lp_lat, par.es, this->m_proj_parm.en); lp_lon = atan2(xy_x, xy_y) / this->m_proj_parm.n; } else { lp_lon = 0.; @@ -193,9 +187,8 @@ namespace projections { template inline eqdc_ellipsoid(Params const& params, Parameters const& par) - : detail::eqdc::base_eqdc_ellipsoid(par) { - detail::eqdc::setup_eqdc(params, this->m_par, this->m_proj_parm); + detail::eqdc::setup_eqdc(params, par, this->m_proj_parm); } }; @@ -204,7 +197,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_eqdc, eqdc_ellipsoid, eqdc_ellipsoid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_eqdc, eqdc_ellipsoid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(eqdc_entry, eqdc_ellipsoid) diff --git a/include/boost/geometry/srs/projections/proj/etmerc.hpp b/include/boost/geometry/srs/projections/proj/etmerc.hpp index 86e2a506f..946ad2813 100644 --- a/include/boost/geometry/srs/projections/proj/etmerc.hpp +++ b/include/boost/geometry/srs/projections/proj/etmerc.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -163,20 +163,14 @@ namespace projections return(sin(arg_r)*hr); } - // template class, using CRTP to implement forward/inverse template struct base_etmerc_ellipsoid - : public base_t_fi, T, Parameters> { par_etmerc m_proj_parm; - inline base_etmerc_ellipsoid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(e_forward) ellipsoid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { T sin_Cn, cos_Cn, cos_Ce, sin_Ce, dCn, dCe; T Cn = lp_lat, Ce = lp_lon; @@ -205,7 +199,7 @@ namespace projections // INVERSE(e_inverse) ellipsoid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { T sin_Cn, cos_Cn, cos_Ce, sin_Ce, dCn, dCe; T Cn = xy_y, Ce = xy_x; @@ -391,10 +385,9 @@ namespace projections struct etmerc_ellipsoid : public detail::etmerc::base_etmerc_ellipsoid { template - inline etmerc_ellipsoid(Params const& , Parameters const& par) - : detail::etmerc::base_etmerc_ellipsoid(par) + inline etmerc_ellipsoid(Params const& , Parameters & par) { - detail::etmerc::setup_etmerc(this->m_par, this->m_proj_parm); + detail::etmerc::setup_etmerc(par, this->m_proj_parm); } }; @@ -417,10 +410,9 @@ namespace projections struct utm_ellipsoid : public detail::etmerc::base_etmerc_ellipsoid { template - inline utm_ellipsoid(Params const& params, Parameters const& par) - : detail::etmerc::base_etmerc_ellipsoid(par) + inline utm_ellipsoid(Params const& params, Parameters & par) { - detail::etmerc::setup_utm(params, this->m_par, this->m_proj_parm); + detail::etmerc::setup_utm(params, par, this->m_proj_parm); } }; @@ -429,8 +421,8 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_etmerc, etmerc_ellipsoid, etmerc_ellipsoid) - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_utm, utm_ellipsoid, utm_ellipsoid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_etmerc, etmerc_ellipsoid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_utm, utm_ellipsoid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(etmerc_entry, etmerc_ellipsoid) diff --git a/include/boost/geometry/srs/projections/proj/fahey.hpp b/include/boost/geometry/srs/projections/proj/fahey.hpp index 85cc05c93..e143436f9 100644 --- a/include/boost/geometry/srs/projections/proj/fahey.hpp +++ b/include/boost/geometry/srs/projections/proj/fahey.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -57,18 +57,12 @@ namespace projections static const double tolerance = 1e-6; - // template class, using CRTP to implement forward/inverse template struct base_fahey_spheroid - : public base_t_fi, T, Parameters> { - inline base_fahey_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { xy_x = tan(0.5 * lp_lat); xy_y = 1.819152 * xy_x; @@ -77,7 +71,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T xy_y, T& lp_lon, T& lp_lat) const { xy_y /= 1.819152; lp_lat = 2. * atan(xy_y); @@ -118,10 +112,9 @@ namespace projections struct fahey_spheroid : public detail::fahey::base_fahey_spheroid { template - inline fahey_spheroid(Params const& , Parameters const& par) - : detail::fahey::base_fahey_spheroid(par) + inline fahey_spheroid(Params const& , Parameters & par) { - detail::fahey::setup_fahey(this->m_par); + detail::fahey::setup_fahey(par); } }; @@ -130,7 +123,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_fahey, fahey_spheroid, fahey_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_fahey, fahey_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(fahey_entry, fahey_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/fouc_s.hpp b/include/boost/geometry/srs/projections/proj/fouc_s.hpp index f6a8c5ed4..ec1cd3483 100644 --- a/include/boost/geometry/srs/projections/proj/fouc_s.hpp +++ b/include/boost/geometry/srs/projections/proj/fouc_s.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -67,20 +67,14 @@ namespace projections T n, n1; }; - // template class, using CRTP to implement forward/inverse template struct base_fouc_s_spheroid - : public base_t_fi, T, Parameters> { par_fouc_s m_proj_parm; - inline base_fouc_s_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { T t; @@ -91,7 +85,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { static T const half_pi = detail::half_pi(); @@ -154,10 +148,9 @@ namespace projections struct fouc_s_spheroid : public detail::fouc_s::base_fouc_s_spheroid { template - inline fouc_s_spheroid(Params const& params, Parameters const& par) - : detail::fouc_s::base_fouc_s_spheroid(par) + inline fouc_s_spheroid(Params const& params, Parameters & par) { - detail::fouc_s::setup_fouc_s(params, this->m_par, this->m_proj_parm); + detail::fouc_s::setup_fouc_s(params, par, this->m_proj_parm); } }; @@ -166,7 +159,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_fouc_s, fouc_s_spheroid, fouc_s_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_fouc_s, fouc_s_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(fouc_s_entry, fouc_s_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/gall.hpp b/include/boost/geometry/srs/projections/proj/gall.hpp index 5d2779945..61967ce81 100644 --- a/include/boost/geometry/srs/projections/proj/gall.hpp +++ b/include/boost/geometry/srs/projections/proj/gall.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -59,18 +59,12 @@ namespace projections static const double RYF = 0.58578643762690495119; static const double RXF = 1.41421356237309504880; - // template class, using CRTP to implement forward/inverse template struct base_gall_spheroid - : public base_t_fi, T, Parameters> { - inline base_gall_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { xy_x = XF * lp_lon; xy_y = YF * tan(.5 * lp_lat); @@ -78,7 +72,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { lp_lon = RXF * xy_x; lp_lat = 2. * atan(xy_y * RYF); @@ -117,10 +111,9 @@ namespace projections struct gall_spheroid : public detail::gall::base_gall_spheroid { template - inline gall_spheroid(Params const& , Parameters const& par) - : detail::gall::base_gall_spheroid(par) + inline gall_spheroid(Params const& , Parameters & par) { - detail::gall::setup_gall(this->m_par); + detail::gall::setup_gall(par); } }; @@ -129,7 +122,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_gall, gall_spheroid, gall_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_gall, gall_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(gall_entry, gall_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/geocent.hpp b/include/boost/geometry/srs/projections/proj/geocent.hpp index 094feca58..ebb5350dc 100644 --- a/include/boost/geometry/srs/projections/proj/geocent.hpp +++ b/include/boost/geometry/srs/projections/proj/geocent.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -60,18 +60,12 @@ namespace projections namespace detail { namespace geocent { - // template class, using CRTP to implement forward/inverse template struct base_geocent_other - : public base_t_fi, T, Parameters> { - inline base_geocent_other(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(forward) // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { xy_x = lp_lon; xy_y = lp_lat; @@ -79,7 +73,7 @@ namespace projections // INVERSE(inverse) // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { lp_lat = xy_y; lp_lon = xy_x; @@ -96,7 +90,7 @@ namespace projections template inline void setup_geocent(Parameters& par) { - par.is_geocent = 1; + par.is_geocent = true; par.x0 = 0.0; par.y0 = 0.0; } @@ -117,10 +111,9 @@ namespace projections struct geocent_other : public detail::geocent::base_geocent_other { template - inline geocent_other(Params const& , Parameters const& par) - : detail::geocent::base_geocent_other(par) + inline geocent_other(Params const& , Parameters & par) { - detail::geocent::setup_geocent(this->m_par); + detail::geocent::setup_geocent(par); } }; @@ -129,7 +122,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_geocent, geocent_other, geocent_other) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_geocent, geocent_other) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(geocent_entry, geocent_other) diff --git a/include/boost/geometry/srs/projections/proj/geos.hpp b/include/boost/geometry/srs/projections/proj/geos.hpp index f9f290124..e27786ee1 100644 --- a/include/boost/geometry/srs/projections/proj/geos.hpp +++ b/include/boost/geometry/srs/projections/proj/geos.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -75,20 +75,14 @@ namespace projections bool flip_axis; }; - // template class, using CRTP to implement forward/inverse template struct base_geos_ellipsoid - : public base_t_fi, T, Parameters> { par_geos m_proj_parm; - inline base_geos_ellipsoid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(e_forward) ellipsoid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const { T r, Vx, Vy, Vz, tmp; @@ -121,7 +115,7 @@ namespace projections // INVERSE(e_inverse) ellipsoid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { T Vx, Vy, Vz, a, b, det, k; @@ -163,20 +157,14 @@ namespace projections }; - // template class, using CRTP to implement forward/inverse template struct base_geos_spheroid - : public base_t_fi, T, Parameters> { par_geos m_proj_parm; - inline base_geos_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { T Vx, Vy, Vz, tmp; @@ -206,7 +194,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { T Vx, Vy, Vz, a, b, det, k; @@ -325,9 +313,8 @@ namespace projections { template inline geos_ellipsoid(Params const& params, Parameters const& par) - : detail::geos::base_geos_ellipsoid(par) { - detail::geos::setup_geos(params, this->m_par, this->m_proj_parm); + detail::geos::setup_geos(params, par, this->m_proj_parm); } }; @@ -352,9 +339,8 @@ namespace projections { template inline geos_spheroid(Params const& params, Parameters const& par) - : detail::geos::base_geos_spheroid(par) { - detail::geos::setup_geos(params, this->m_par, this->m_proj_parm); + detail::geos::setup_geos(params, par, this->m_proj_parm); } }; @@ -363,7 +349,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_geos, geos_spheroid, geos_ellipsoid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(srs::spar::proj_geos, geos_spheroid, geos_ellipsoid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(geos_entry, geos_spheroid, geos_ellipsoid) diff --git a/include/boost/geometry/srs/projections/proj/gins8.hpp b/include/boost/geometry/srs/projections/proj/gins8.hpp index 2e9088a2a..b1bb4a74c 100644 --- a/include/boost/geometry/srs/projections/proj/gins8.hpp +++ b/include/boost/geometry/srs/projections/proj/gins8.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -61,18 +61,12 @@ namespace projections template inline T C12() { return 0.083333333333333333333333333333333333; } - // template class, using CRTP to implement forward/inverse template struct base_gins8_spheroid - : public base_t_f, T, Parameters> { - inline base_gins8_spheroid(const Parameters& par) - : base_t_f, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { static const T C12 = gins8::C12(); @@ -118,10 +112,9 @@ namespace projections struct gins8_spheroid : public detail::gins8::base_gins8_spheroid { template - inline gins8_spheroid(Params const& , Parameters const& par) - : detail::gins8::base_gins8_spheroid(par) + inline gins8_spheroid(Params const& , Parameters & par) { - detail::gins8::setup_gins8(this->m_par); + detail::gins8::setup_gins8(par); } }; @@ -130,7 +123,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_gins8, gins8_spheroid, gins8_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_F(srs::spar::proj_gins8, gins8_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_F(gins8_entry, gins8_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/gn_sinu.hpp b/include/boost/geometry/srs/projections/proj/gn_sinu.hpp index 2ef7df509..7e6903f9b 100644 --- a/include/boost/geometry/srs/projections/proj/gn_sinu.hpp +++ b/include/boost/geometry/srs/projections/proj/gn_sinu.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -64,46 +64,45 @@ namespace projections static const double loop_tol = 1e-7; template - struct par_gn_sinu + struct par_gn_sinu_e { detail::en en; - T m, n, C_x, C_y; + }; + + template + struct par_gn_sinu_s + { + T m, n, C_x, C_y; }; /* Ellipsoidal Sinusoidal only */ - // template class, using CRTP to implement forward/inverse template struct base_gn_sinu_ellipsoid - : public base_t_fi, T, Parameters> { - par_gn_sinu m_proj_parm; - - inline base_gn_sinu_ellipsoid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} + par_gn_sinu_e m_proj_parm; // FORWARD(e_forward) ellipsoid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { T s, c; xy_y = pj_mlfn(lp_lat, s = sin(lp_lat), c = cos(lp_lat), this->m_proj_parm.en); - xy_x = lp_lon * c / sqrt(1. - this->m_par.es * s * s); + xy_x = lp_lon * c / sqrt(1. - par.es * s * s); } // INVERSE(e_inverse) ellipsoid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { static const T half_pi = detail::half_pi(); T s; - if ((s = fabs(lp_lat = pj_inv_mlfn(xy_y, this->m_par.es, this->m_proj_parm.en))) < half_pi) { + if ((s = fabs(lp_lat = pj_inv_mlfn(xy_y, par.es, this->m_proj_parm.en))) < half_pi) { s = sin(lp_lat); - lp_lon = xy_x * sqrt(1. - this->m_par.es * s * s) / cos(lp_lat); + lp_lon = xy_x * sqrt(1. - par.es * s * s) / cos(lp_lat); } else if ((s - epsilon10) < half_pi) lp_lon = 0.; else @@ -118,20 +117,14 @@ namespace projections }; - // template class, using CRTP to implement forward/inverse template struct base_gn_sinu_spheroid - : public base_t_fi, T, Parameters> { - par_gn_sinu m_proj_parm; - - inline base_gn_sinu_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} + par_gn_sinu_s m_proj_parm; // FORWARD(s_forward) sphere // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const { if (this->m_proj_parm.m == 0.0) lp_lat = this->m_proj_parm.n != 1. ? aasin(this->m_proj_parm.n * sin(lp_lat)): lp_lat; @@ -156,7 +149,7 @@ namespace projections // INVERSE(s_inverse) sphere // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T xy_y, T& lp_lon, T& lp_lat) const { xy_y /= this->m_proj_parm.C_y; lp_lat = (this->m_proj_parm.m != 0.0) ? aasin((this->m_proj_parm.m * xy_y + sin(xy_y)) / this->m_proj_parm.n) : @@ -172,7 +165,7 @@ namespace projections }; template - inline void setup(Parameters& par, par_gn_sinu& proj_parm) + inline void setup(Parameters& par, par_gn_sinu_s& proj_parm) { par.es = 0; @@ -182,7 +175,7 @@ namespace projections // General Sinusoidal Series template - inline void setup_gn_sinu(Params const& params, Parameters& par, par_gn_sinu& proj_parm) + inline void setup_gn_sinu(Params const& params, Parameters& par, par_gn_sinu_s& proj_parm) { if (pj_param_f(params, "n", srs::dpar::n, proj_parm.n) && pj_param_f(params, "m", srs::dpar::m, proj_parm.m)) { @@ -196,22 +189,23 @@ namespace projections // Sinusoidal (Sanson-Flamsteed) template - inline void setup_sinu(Parameters& par, par_gn_sinu& proj_parm) + inline void setup_sinu(Parameters const& par, par_gn_sinu_e& proj_parm) { proj_parm.en = pj_enfn(par.es); + } - if (par.es != 0.0) { - /* empty */ - } else { - proj_parm.n = 1.; - proj_parm.m = 0.; - setup(par, proj_parm); - } + // Sinusoidal (Sanson-Flamsteed) + template + inline void setup_sinu(Parameters& par, par_gn_sinu_s& proj_parm) + { + proj_parm.n = 1.; + proj_parm.m = 0.; + setup(par, proj_parm); } // Eckert VI template - inline void setup_eck6(Parameters& par, par_gn_sinu& proj_parm) + inline void setup_eck6(Parameters& par, par_gn_sinu_s& proj_parm) { proj_parm.m = 1.; proj_parm.n = 2.570796326794896619231321691; @@ -220,7 +214,7 @@ namespace projections // McBryde-Thomas Flat-Polar Sinusoidal template - inline void setup_mbtfps(Parameters& par, par_gn_sinu& proj_parm) + inline void setup_mbtfps(Parameters& par, par_gn_sinu_s& proj_parm) { proj_parm.m = 0.5; proj_parm.n = 1.785398163397448309615660845; @@ -249,10 +243,9 @@ namespace projections struct gn_sinu_spheroid : public detail::gn_sinu::base_gn_sinu_spheroid { template - inline gn_sinu_spheroid(Params const& params, Parameters const& par) - : detail::gn_sinu::base_gn_sinu_spheroid(par) + inline gn_sinu_spheroid(Params const& params, Parameters & par) { - detail::gn_sinu::setup_gn_sinu(params, this->m_par, this->m_proj_parm); + detail::gn_sinu::setup_gn_sinu(params, par, this->m_proj_parm); } }; @@ -273,10 +266,9 @@ namespace projections struct sinu_ellipsoid : public detail::gn_sinu::base_gn_sinu_ellipsoid { template - inline sinu_ellipsoid(Params const& , Parameters const& par) - : detail::gn_sinu::base_gn_sinu_ellipsoid(par) + inline sinu_ellipsoid(Params const& , Parameters & par) { - detail::gn_sinu::setup_sinu(this->m_par, this->m_proj_parm); + detail::gn_sinu::setup_sinu(par, this->m_proj_parm); } }; @@ -297,10 +289,9 @@ namespace projections struct sinu_spheroid : public detail::gn_sinu::base_gn_sinu_spheroid { template - inline sinu_spheroid(Params const& , Parameters const& par) - : detail::gn_sinu::base_gn_sinu_spheroid(par) + inline sinu_spheroid(Params const& , Parameters & par) { - detail::gn_sinu::setup_sinu(this->m_par, this->m_proj_parm); + detail::gn_sinu::setup_sinu(par, this->m_proj_parm); } }; @@ -320,10 +311,9 @@ namespace projections struct eck6_spheroid : public detail::gn_sinu::base_gn_sinu_spheroid { template - inline eck6_spheroid(Params const& , Parameters const& par) - : detail::gn_sinu::base_gn_sinu_spheroid(par) + inline eck6_spheroid(Params const& , Parameters & par) { - detail::gn_sinu::setup_eck6(this->m_par, this->m_proj_parm); + detail::gn_sinu::setup_eck6(par, this->m_proj_parm); } }; @@ -343,10 +333,9 @@ namespace projections struct mbtfps_spheroid : public detail::gn_sinu::base_gn_sinu_spheroid { template - inline mbtfps_spheroid(Params const& , Parameters const& par) - : detail::gn_sinu::base_gn_sinu_spheroid(par) + inline mbtfps_spheroid(Params const& , Parameters & par) { - detail::gn_sinu::setup_mbtfps(this->m_par, this->m_proj_parm); + detail::gn_sinu::setup_mbtfps(par, this->m_proj_parm); } }; @@ -355,10 +344,10 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_gn_sinu, gn_sinu_spheroid, gn_sinu_spheroid) - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_sinu, sinu_spheroid, sinu_ellipsoid) - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_eck6, eck6_spheroid, eck6_spheroid) - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_mbtfps, mbtfps_spheroid, mbtfps_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_gn_sinu, gn_sinu_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(srs::spar::proj_sinu, sinu_spheroid, sinu_ellipsoid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_eck6, eck6_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_mbtfps, mbtfps_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(gn_sinu_entry, gn_sinu_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/gnom.hpp b/include/boost/geometry/srs/projections/proj/gnom.hpp index 6c9ca3a02..bde8e1906 100644 --- a/include/boost/geometry/srs/projections/proj/gnom.hpp +++ b/include/boost/geometry/srs/projections/proj/gnom.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -74,20 +74,14 @@ namespace projections mode_type mode; }; - // template class, using CRTP to implement forward/inverse template struct base_gnom_spheroid - : public base_t_fi, T, Parameters> { par_gnom m_proj_parm; - inline base_gnom_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { T coslam, cosphi, sinphi; @@ -133,7 +127,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T xy_x, T xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T xy_x, T xy_y, T& lp_lon, T& lp_lat) const { static const T half_pi = detail::half_pi(); @@ -144,7 +138,7 @@ namespace projections cosz = sqrt(1. - sinz * sinz); if (fabs(rh) <= epsilon10) { - lp_lat = this->m_par.phi0; + lp_lat = par.phi0; lp_lon = 0.; } else { switch (this->m_proj_parm.mode) { @@ -223,10 +217,9 @@ namespace projections struct gnom_spheroid : public detail::gnom::base_gnom_spheroid { template - inline gnom_spheroid(Params const& , Parameters const& par) - : detail::gnom::base_gnom_spheroid(par) + inline gnom_spheroid(Params const& , Parameters & par) { - detail::gnom::setup_gnom(this->m_par, this->m_proj_parm); + detail::gnom::setup_gnom(par, this->m_proj_parm); } }; @@ -235,7 +228,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_gnom, gnom_spheroid, gnom_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_gnom, gnom_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(gnom_entry, gnom_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/goode.hpp b/include/boost/geometry/srs/projections/proj/goode.hpp index b9cc03460..f8dd87c37 100644 --- a/include/boost/geometry/srs/projections/proj/goode.hpp +++ b/include/boost/geometry/srs/projections/proj/goode.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -59,46 +59,56 @@ namespace projections static const double Y_COR = 0.05280; static const double PHI_LIM = .71093078197902358062; - // TODO: consider storing references to Parameters instead of copies + // TODO: It would be possible to further decrease the size of par_goode + // because spherical sinu and moll has constant parameters. + template struct par_goode { sinu_spheroid sinu; moll_spheroid moll; + // NOTE: It is ok to share parameters between projections because + // the only member that is modified in the constructors of + // spherical sinu and moll projections is es = 0 which is set + // below in setup_goode() anyway. + // Moreover in these projections parameters are not used + // in fwd() nor inv(). + template - par_goode(Params const& params, Par const& par) - : sinu(params, par), moll(params, par) + par_goode(Params const& params, Par & par) + : sinu(params, par) + , moll(params, par) {} }; template inline void s_forward(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y, - par_goode const& proj_par) + Par const& par, par_goode const& proj_par) { if (fabs(lp_lat) <= PHI_LIM) - proj_par.sinu.fwd(lp_lon, lp_lat, xy_x, xy_y); + proj_par.sinu.fwd(par, lp_lon, lp_lat, xy_x, xy_y); else { - proj_par.moll.fwd(lp_lon, lp_lat, xy_x, xy_y); + proj_par.moll.fwd(par, lp_lon, lp_lat, xy_x, xy_y); xy_y -= lp_lat >= 0.0 ? Y_COR : -Y_COR; } } template inline void s_inverse(T const& xy_x, T xy_y, T& lp_lon, T& lp_lat, - par_goode const& proj_par) + Par const& par, par_goode const& proj_par) { if (fabs(xy_y) <= PHI_LIM) - proj_par.sinu.inv(xy_x, xy_y, lp_lon, lp_lat); + proj_par.sinu.inv(par, xy_x, xy_y, lp_lon, lp_lat); else { xy_y += xy_y >= 0.0 ? Y_COR : -Y_COR; - proj_par.moll.inv(xy_x, xy_y, lp_lon, lp_lat); + proj_par.moll.inv(par, xy_x, xy_y, lp_lon, lp_lat); } } // Goode Homolosine template - inline void setup_goode(Par& par) + inline Par& setup_goode(Par& par) { par.es = 0.; @@ -108,6 +118,8 @@ namespace projections //proj_par.sinu.m_par.es = 0.; //detail::gn_sinu::setup_sinu(proj_par.sinu.m_par, proj_par.sinu.m_proj_parm); + + return par; } }} // namespace detail::goode @@ -126,42 +138,33 @@ namespace projections \image html ex_goode.gif */ template - struct goode_spheroid : public detail::base_t_fi, T, Parameters> + struct goode_spheroid { detail::goode::par_goode m_proj_parm; template - inline goode_spheroid(Params const& params, Parameters const& par) - : detail::base_t_fi, T, Parameters>(*this, par) - , m_proj_parm(params, setup(this->m_par)) + inline goode_spheroid(Params const& params, Parameters & par) + : m_proj_parm(params, detail::goode::setup_goode(par)) {} // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { - detail::goode::s_forward(lp_lon, lp_lat, xy_x, xy_y, this->m_proj_parm); + detail::goode::s_forward(lp_lon, lp_lat, xy_x, xy_y, par, this->m_proj_parm); } // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { - detail::goode::s_inverse(xy_x, xy_y, lp_lon, lp_lat, this->m_proj_parm); + detail::goode::s_inverse(xy_x, xy_y, lp_lon, lp_lat, par, this->m_proj_parm); } static inline std::string get_name() { return "goode_spheroid"; } - - private: - static Parameters& setup(Parameters& par) - { - detail::goode::setup_goode(par); - return par; - } - }; #ifndef DOXYGEN_NO_DETAIL @@ -169,7 +172,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_goode, goode_spheroid, goode_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_goode, goode_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(goode_entry, goode_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/gstmerc.hpp b/include/boost/geometry/srs/projections/proj/gstmerc.hpp index b53cb9d73..a39db181a 100644 --- a/include/boost/geometry/srs/projections/proj/gstmerc.hpp +++ b/include/boost/geometry/srs/projections/proj/gstmerc.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -67,42 +67,36 @@ namespace projections T YS; }; - // template class, using CRTP to implement forward/inverse template struct base_gstmerc_spheroid - : public base_t_fi, T, Parameters> { par_gstmerc m_proj_parm; - inline base_gstmerc_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& par, T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { T L, Ls, sinLs1, Ls1; L= this->m_proj_parm.n1*lp_lon; - Ls= this->m_proj_parm.c+this->m_proj_parm.n1*log(pj_tsfn(-1.0*lp_lat,-1.0*sin(lp_lat),this->m_par.e)); + Ls= this->m_proj_parm.c+this->m_proj_parm.n1*log(pj_tsfn(-1.0*lp_lat,-1.0*sin(lp_lat), par.e)); sinLs1= sin(L)/cosh(Ls); Ls1= log(pj_tsfn(-1.0*asin(sinLs1),0.0,0.0)); - xy_x= (this->m_proj_parm.XS + this->m_proj_parm.n2*Ls1)*this->m_par.ra; - xy_y= (this->m_proj_parm.YS + this->m_proj_parm.n2*atan(sinh(Ls)/cos(L)))*this->m_par.ra; + xy_x= (this->m_proj_parm.XS + this->m_proj_parm.n2*Ls1) * par.ra; + xy_y= (this->m_proj_parm.YS + this->m_proj_parm.n2*atan(sinh(Ls)/cos(L))) * par.ra; } // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { T L, LC, sinC; - L= atan(sinh((xy_x*this->m_par.a - this->m_proj_parm.XS)/this->m_proj_parm.n2)/cos((xy_y*this->m_par.a - this->m_proj_parm.YS)/this->m_proj_parm.n2)); - sinC= sin((xy_y*this->m_par.a - this->m_proj_parm.YS)/this->m_proj_parm.n2)/cosh((xy_x*this->m_par.a - this->m_proj_parm.XS)/this->m_proj_parm.n2); + L= atan(sinh((xy_x * par.a - this->m_proj_parm.XS)/this->m_proj_parm.n2)/cos((xy_y * par.a - this->m_proj_parm.YS)/this->m_proj_parm.n2)); + sinC= sin((xy_y * par.a - this->m_proj_parm.YS)/this->m_proj_parm.n2)/cosh((xy_x * par.a - this->m_proj_parm.XS)/this->m_proj_parm.n2); LC= log(pj_tsfn(-1.0*asin(sinC),0.0,0.0)); lp_lon= L/this->m_proj_parm.n1; - lp_lat= -1.0*pj_phi2(exp((LC-this->m_proj_parm.c)/this->m_proj_parm.n1),this->m_par.e); + lp_lat= -1.0*pj_phi2(exp((LC-this->m_proj_parm.c)/this->m_proj_parm.n1), par.e); } static inline std::string get_name() @@ -114,7 +108,7 @@ namespace projections // Gauss-Schreiber Transverse Mercator (aka Gauss-Laborde Reunion) template - inline void setup_gstmerc(Parameters& par, par_gstmerc& proj_parm) + inline void setup_gstmerc(Parameters const& par, par_gstmerc& proj_parm) { proj_parm.lamc= par.lam0; proj_parm.n1= sqrt(T(1)+par.es*math::pow(cos(par.phi0),4)/(T(1)-par.es)); @@ -151,9 +145,8 @@ namespace projections { template inline gstmerc_spheroid(Params const& , Parameters const& par) - : detail::gstmerc::base_gstmerc_spheroid(par) { - detail::gstmerc::setup_gstmerc(this->m_par, this->m_proj_parm); + detail::gstmerc::setup_gstmerc(par, this->m_proj_parm); } }; @@ -162,7 +155,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_gstmerc, gstmerc_spheroid, gstmerc_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_gstmerc, gstmerc_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(gstmerc_entry, gstmerc_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/hammer.hpp b/include/boost/geometry/srs/projections/proj/hammer.hpp index f9e1ae4e7..de2afa55e 100644 --- a/include/boost/geometry/srs/projections/proj/hammer.hpp +++ b/include/boost/geometry/srs/projections/proj/hammer.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -63,20 +63,14 @@ namespace projections T m, rm; }; - // template class, using CRTP to implement forward/inverse template struct base_hammer_spheroid - : public base_t_fi, T, Parameters> { par_hammer m_proj_parm; - inline base_hammer_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { T cosphi, d; @@ -87,7 +81,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { T z; @@ -155,10 +149,9 @@ namespace projections struct hammer_spheroid : public detail::hammer::base_hammer_spheroid { template - inline hammer_spheroid(Params const& params, Parameters const& par) - : detail::hammer::base_hammer_spheroid(par) + inline hammer_spheroid(Params const& params, Parameters & par) { - detail::hammer::setup_hammer(params, this->m_par, this->m_proj_parm); + detail::hammer::setup_hammer(params, par, this->m_proj_parm); } }; @@ -167,7 +160,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_hammer, hammer_spheroid, hammer_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_hammer, hammer_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(hammer_entry, hammer_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/hatano.hpp b/include/boost/geometry/srs/projections/proj/hatano.hpp index f3ae7d07d..4d444f87e 100644 --- a/include/boost/geometry/srs/projections/proj/hatano.hpp +++ b/include/boost/geometry/srs/projections/proj/hatano.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -70,18 +70,12 @@ namespace projections static const double FXC = 0.85; static const double RXC = 1.17647058823529411764; - // template class, using CRTP to implement forward/inverse template struct base_hatano_spheroid - : public base_t_fi, T, Parameters> { - inline base_hatano_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_forward) spheroid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const { T th1, c; int i; @@ -97,7 +91,7 @@ namespace projections // INVERSE(s_inverse) spheroid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { static T const half_pi = detail::half_pi(); @@ -161,10 +155,9 @@ namespace projections struct hatano_spheroid : public detail::hatano::base_hatano_spheroid { template - inline hatano_spheroid(Params const& , Parameters const& par) - : detail::hatano::base_hatano_spheroid(par) + inline hatano_spheroid(Params const& , Parameters & par) { - detail::hatano::setup_hatano(this->m_par); + detail::hatano::setup_hatano(par); } }; @@ -173,7 +166,7 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_hatano, hatano_spheroid, hatano_spheroid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI(srs::spar::proj_hatano, hatano_spheroid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI(hatano_entry, hatano_spheroid) diff --git a/include/boost/geometry/srs/projections/proj/healpix.hpp b/include/boost/geometry/srs/projections/proj/healpix.hpp index 2084ae82f..670b8b9af 100644 --- a/include/boost/geometry/srs/projections/proj/healpix.hpp +++ b/include/boost/geometry/srs/projections/proj/healpix.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -74,17 +74,17 @@ namespace projections template struct par_healpix { - int north_square; - int south_square; T qp; detail::apa apa; + int north_square; + int south_square; }; template struct cap_map { - int cn; /* An integer 0--3 indicating the position of the polar cap. */ T x, y; /* Coordinates of the pole point (point of most extreme latitude on the polar caps). */ + int cn; /* An integer 0--3 indicating the position of the polar cap. */ enum region_type {north, south, equatorial} region; }; template @@ -546,28 +546,22 @@ namespace projections xy_y = vector[1]; } - // template class, using CRTP to implement forward/inverse template struct base_healpix_ellipsoid - : public base_t_fi, T, Parameters> { par_healpix m_proj_parm; - inline base_healpix_ellipsoid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(e_healpix_forward) ellipsoid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& par, T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const { - lp_lat = auth_lat(this->params(), m_proj_parm, lp_lat, 0); + lp_lat = auth_lat(par, m_proj_parm, lp_lat, 0); return healpix_sphere(lp_lon, lp_lat, xy_x, xy_y); } // INVERSE(e_healpix_inverse) ellipsoid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { /* Check whether (x, y) lies in the HEALPix image. */ if (in_image(xy_x, xy_y, 0, 0, 0) == 0) { @@ -576,7 +570,7 @@ namespace projections BOOST_THROW_EXCEPTION( projection_exception(error_invalid_x_or_y) ); } healpix_sphere_inverse(xy_x, xy_y, lp_lon, lp_lat); - lp_lat = auth_lat(this->params(), m_proj_parm, lp_lat, 1); + lp_lat = auth_lat(par, m_proj_parm, lp_lat, 1); } static inline std::string get_name() @@ -586,27 +580,21 @@ namespace projections }; - // template class, using CRTP to implement forward/inverse template struct base_healpix_spheroid - : public base_t_fi, T, Parameters> { par_healpix m_proj_parm; - inline base_healpix_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_healpix_forward) sphere // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { return healpix_sphere(lp_lon, lp_lat, xy_x, xy_y); } // INVERSE(s_healpix_inverse) sphere // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T const& xy_x, T const& xy_y, T& lp_lon, T& lp_lat) const { /* Check whether (x, y) lies in the HEALPix image */ if (in_image(xy_x, xy_y, 0, 0, 0) == 0) { @@ -624,29 +612,23 @@ namespace projections }; - // template class, using CRTP to implement forward/inverse template struct base_rhealpix_ellipsoid - : public base_t_fi, T, Parameters> { par_healpix m_proj_parm; - inline base_rhealpix_ellipsoid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(e_rhealpix_forward) ellipsoid // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& par, T const& lp_lon, T lp_lat, T& xy_x, T& xy_y) const { - lp_lat = auth_lat(this->params(), m_proj_parm, lp_lat, 0); + lp_lat = auth_lat(par, m_proj_parm, lp_lat, 0); healpix_sphere(lp_lon, lp_lat, xy_x, xy_y); combine_caps(xy_x, xy_y, this->m_proj_parm.north_square, this->m_proj_parm.south_square, 0); } // INVERSE(e_rhealpix_inverse) ellipsoid // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T xy_x, T xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& par, T xy_x, T xy_y, T& lp_lon, T& lp_lat) const { /* Check whether (x, y) lies in the rHEALPix image. */ if (in_image(xy_x, xy_y, 1, this->m_proj_parm.north_square, this->m_proj_parm.south_square) == 0) { @@ -656,7 +638,7 @@ namespace projections } combine_caps(xy_x, xy_y, this->m_proj_parm.north_square, this->m_proj_parm.south_square, 1); healpix_sphere_inverse(xy_x, xy_y, lp_lon, lp_lat); - lp_lat = auth_lat(this->params(), m_proj_parm, lp_lat, 1); + lp_lat = auth_lat(par, m_proj_parm, lp_lat, 1); } static inline std::string get_name() @@ -666,20 +648,14 @@ namespace projections }; - // template class, using CRTP to implement forward/inverse template struct base_rhealpix_spheroid - : public base_t_fi, T, Parameters> { par_healpix m_proj_parm; - inline base_rhealpix_spheroid(const Parameters& par) - : base_t_fi, T, Parameters>(*this, par) - {} - // FORWARD(s_rhealpix_forward) sphere // Project coordinates from geographic (lon, lat) to cartesian (x, y) - inline void fwd(T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const + inline void fwd(Parameters const& , T const& lp_lon, T const& lp_lat, T& xy_x, T& xy_y) const { healpix_sphere(lp_lon, lp_lat, xy_x, xy_y); combine_caps(xy_x, xy_y, this->m_proj_parm.north_square, this->m_proj_parm.south_square, 0); @@ -687,7 +663,7 @@ namespace projections // INVERSE(s_rhealpix_inverse) sphere // Project coordinates from cartesian (x, y) to geographic (lon, lat) - inline void inv(T xy_x, T xy_y, T& lp_lon, T& lp_lat) const + inline void inv(Parameters const& , T xy_x, T xy_y, T& lp_lon, T& lp_lat) const { /* Check whether (x, y) lies in the rHEALPix image. */ if (in_image(xy_x, xy_y, 1, this->m_proj_parm.north_square, this->m_proj_parm.south_square) == 0) { @@ -762,10 +738,9 @@ namespace projections struct healpix_ellipsoid : public detail::healpix::base_healpix_ellipsoid { template - inline healpix_ellipsoid(Params const& , Parameters const& par) - : detail::healpix::base_healpix_ellipsoid(par) + inline healpix_ellipsoid(Params const& , Parameters & par) { - detail::healpix::setup_healpix(this->m_par, this->m_proj_parm); + detail::healpix::setup_healpix(par, this->m_proj_parm); } }; @@ -785,10 +760,9 @@ namespace projections struct healpix_spheroid : public detail::healpix::base_healpix_spheroid { template - inline healpix_spheroid(Params const& , Parameters const& par) - : detail::healpix::base_healpix_spheroid(par) + inline healpix_spheroid(Params const& , Parameters & par) { - detail::healpix::setup_healpix(this->m_par, this->m_proj_parm); + detail::healpix::setup_healpix(par, this->m_proj_parm); } }; @@ -811,10 +785,9 @@ namespace projections struct rhealpix_ellipsoid : public detail::healpix::base_rhealpix_ellipsoid { template - inline rhealpix_ellipsoid(Params const& params, Parameters const& par) - : detail::healpix::base_rhealpix_ellipsoid(par) + inline rhealpix_ellipsoid(Params const& params, Parameters & par) { - detail::healpix::setup_rhealpix(params, this->m_par, this->m_proj_parm); + detail::healpix::setup_rhealpix(params, par, this->m_proj_parm); } }; @@ -837,10 +810,9 @@ namespace projections struct rhealpix_spheroid : public detail::healpix::base_rhealpix_spheroid { template - inline rhealpix_spheroid(Params const& params, Parameters const& par) - : detail::healpix::base_rhealpix_spheroid(par) + inline rhealpix_spheroid(Params const& params, Parameters & par) { - detail::healpix::setup_rhealpix(params, this->m_par, this->m_proj_parm); + detail::healpix::setup_rhealpix(params, par, this->m_proj_parm); } }; @@ -849,8 +821,8 @@ namespace projections { // Static projection - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_healpix, healpix_spheroid, healpix_ellipsoid) - BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION(srs::spar::proj_rhealpix, rhealpix_spheroid, rhealpix_ellipsoid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(srs::spar::proj_healpix, healpix_spheroid, healpix_ellipsoid) + BOOST_GEOMETRY_PROJECTIONS_DETAIL_STATIC_PROJECTION_FI2(srs::spar::proj_rhealpix, rhealpix_spheroid, rhealpix_ellipsoid) // Factory entry(s) BOOST_GEOMETRY_PROJECTIONS_DETAIL_FACTORY_ENTRY_FI2(healpix_entry, healpix_spheroid, healpix_ellipsoid) diff --git a/include/boost/geometry/srs/projections/proj/igh.hpp b/include/boost/geometry/srs/projections/proj/igh.hpp index 6403d7412..385ac3031 100644 --- a/include/boost/geometry/srs/projections/proj/igh.hpp +++ b/include/boost/geometry/srs/projections/proj/igh.hpp @@ -2,8 +2,8 @@ // Copyright (c) 2008-2015 Barend Gehrels, Amsterdam, the Netherlands. -// This file was modified by Oracle on 2017, 2018. -// Modifications copyright (c) 2017-2018, Oracle and/or its affiliates. +// This file was modified by Oracle on 2017, 2018, 2019. +// Modifications copyright (c) 2017-2019, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle. // Use, modification and distribution is subject to the Boost Software License, @@ -40,9 +40,6 @@ #ifndef BOOST_GEOMETRY_PROJECTIONS_IGH_HPP #define BOOST_GEOMETRY_PROJECTIONS_IGH_HPP -#include -#include - #include #include #include @@ -50,6 +47,10 @@ #include #include +#include + +#include + namespace boost { namespace geometry { @@ -58,13 +59,69 @@ namespace projections #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace igh { - // TODO: consider replacing dynamically created projections - // with member objects + template + struct par_igh_zone + { + T x0; + T y0; + T lam0; + }; + + // NOTE: x0, y0, lam0 are not used in moll nor sinu projections + // so it is a waste of memory to keep 12 copies of projections + // with parameters as in the original Proj4. + + // TODO: It would be possible to further decrease the size of par_igh + // because spherical sinu and moll has constant parameters. + // TODO: Furthermore there is no need to store par_igh_zone parameters + // since they are constant for zones. In both fwd() and inv() there are + // parts of code dependent on specific zones (if statements) anyway + // so these parameters could be hardcoded there instead of stored. + template struct par_igh { - boost::shared_ptr > pj[12]; + moll_spheroid moll; + sinu_spheroid sinu; + par_igh_zone zones[12]; T dy0; + + // NOTE: The constructors of moll and sinu projections sets + // par.es = 0 + + template + inline par_igh(Params const& params, Parameters & par) + : moll(params, par) + , sinu(params, par) + {} + + inline void fwd(int zone, Parameters const& par, T const& lp_lon, T const& lp_lat, T & xy_x, T & xy_y) const + { + if (zone <= 2 || zone >= 9) // 1, 2, 9, 10, 11, 12 + moll.fwd(par, lp_lon, lp_lat, xy_x, xy_y); + else // 3, 4, 5, 6, 7, 8 + sinu.fwd(par, lp_lon, lp_lat, xy_x, xy_y); + } + + inline void inv(int zone, Parameters const& par, T const& xy_x, T const& xy_y, T & lp_lon, T & lp_lat) const + { + if (zone <= 2 || zone >= 9) // 1, 2, 9, 10, 11, 12 + moll.inv(par, xy_x, xy_y, lp_lon, lp_lat); + else // 3, 4, 5, 6, 7, 8 + sinu.inv(par, xy_x, xy_y, lp_lon, lp_lat); + } + + inline void set_zone(int zone, T const& x_0, T const& y_0, T const& lon_0) + { + zones[zone - 1].x0 = x_0; + zones[zone - 1].y0 = y_0; + zones[zone - 1].lam0 = lon_0; + } + + inline par_igh_zone const& get_zone(int zone) const + { + return zones[zone - 1]; + } }; /* 40d 44' 11.8" [degrees] */ @@ -98,36 +155,19 @@ namespace projections static const double epsilon = 1.e-10; // allow a little 'slack' on zone edge positions - // Converted from #define SETUP(n, proj, x_0, y_0, lon_0) - template