summaryrefslogtreecommitdiff
path: root/boost/geometry/srs/projections/impl/pj_init.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/geometry/srs/projections/impl/pj_init.hpp')
-rw-r--r--boost/geometry/srs/projections/impl/pj_init.hpp494
1 files changed, 313 insertions, 181 deletions
diff --git a/boost/geometry/srs/projections/impl/pj_init.hpp b/boost/geometry/srs/projections/impl/pj_init.hpp
index 1d2db1af24..28b2b5850d 100644
--- a/boost/geometry/srs/projections/impl/pj_init.hpp
+++ b/boost/geometry/srs/projections/impl/pj_init.hpp
@@ -44,12 +44,15 @@
#include <vector>
#include <boost/algorithm/string.hpp>
+#include <boost/mpl/find.hpp>
+#include <boost/mpl/if.hpp>
#include <boost/range.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/geometry/util/math.hpp>
#include <boost/geometry/util/condition.hpp>
+#include <boost/geometry/srs/projections/dpar.hpp>
#include <boost/geometry/srs/projections/impl/dms_parser.hpp>
#include <boost/geometry/srs/projections/impl/pj_datum_set.hpp>
#include <boost/geometry/srs/projections/impl/pj_datums.hpp>
@@ -58,6 +61,7 @@
#include <boost/geometry/srs/projections/impl/pj_units.hpp>
#include <boost/geometry/srs/projections/impl/projects.hpp>
#include <boost/geometry/srs/projections/proj4.hpp>
+#include <boost/geometry/srs/projections/spar.hpp>
namespace boost { namespace geometry { namespace projections
@@ -67,70 +71,62 @@ namespace boost { namespace geometry { namespace projections
namespace detail
{
-template <typename BGParams, typename T>
-inline void pj_push_defaults(BGParams const& /*bg_params*/, parameters<T>& pin)
+/************************************************************************/
+/* pj_init_proj() */
+/************************************************************************/
+
+template <typename T>
+inline void pj_init_proj(srs::detail::proj4_parameters const& params,
+ parameters<T> & par)
{
- pin.params.push_back(pj_mkparam<T>("ellps", "WGS84"));
+ par.id = pj_get_param_s(params, "proj");
+}
- if (pin.name == "aea")
- {
- pin.params.push_back(pj_mkparam<T>("lat_1", "29.5"));
- pin.params.push_back(pj_mkparam<T>("lat_2", "45.5 "));
- }
- else if (pin.name == "lcc")
- {
- pin.params.push_back(pj_mkparam<T>("lat_1", "33"));
- pin.params.push_back(pj_mkparam<T>("lat_2", "45"));
- }
- else if (pin.name == "lagrng")
+template <typename T>
+inline void pj_init_proj(srs::dpar::parameters<T> const& params,
+ parameters<T> & par)
+{
+ typename srs::dpar::parameters<T>::const_iterator it = pj_param_find(params, srs::dpar::proj);
+ if (it != params.end())
{
- pin.params.push_back(pj_mkparam<T>("W", "2"));
+ par.id = static_cast<srs::dpar::value_proj>(it->template get_value<int>());
}
}
-template <BOOST_GEOMETRY_PROJECTIONS_DETAIL_TYPENAME_PX, typename T>
-inline void pj_push_defaults(srs::static_proj4<BOOST_GEOMETRY_PROJECTIONS_DETAIL_PX> const& /*bg_params*/,
- parameters<T>& pin)
+template <typename T, BOOST_GEOMETRY_PROJECTIONS_DETAIL_TYPENAME_PX>
+inline void pj_init_proj(srs::spar::parameters<BOOST_GEOMETRY_PROJECTIONS_DETAIL_PX> const& ,
+ parameters<T> & par)
{
- typedef srs::static_proj4<BOOST_GEOMETRY_PROJECTIONS_DETAIL_PX> static_parameters_type;
- typedef typename srs::par4::detail::pick_proj_tag
+ typedef srs::spar::parameters<BOOST_GEOMETRY_PROJECTIONS_DETAIL_PX> params_type;
+ typedef typename srs::spar::detail::tuples_find_if
<
- static_parameters_type
- >::type proj_tag;
+ params_type,
+ srs::spar::detail::is_param_tr<srs::spar::detail::proj_traits>::pred
+ >::type proj_type;
- // statically defaulting to WGS84
- //pin.params.push_back(pj_mkparam("ellps", "WGS84"));
+ static const bool is_found = srs::spar::detail::tuples_is_found<proj_type>::value;
- if (BOOST_GEOMETRY_CONDITION((boost::is_same<proj_tag, srs::par4::aea>::value)))
- {
- pin.params.push_back(pj_mkparam<T>("lat_1", "29.5"));
- pin.params.push_back(pj_mkparam<T>("lat_2", "45.5 "));
- }
- else if (BOOST_GEOMETRY_CONDITION((boost::is_same<proj_tag, srs::par4::lcc>::value)))
- {
- pin.params.push_back(pj_mkparam<T>("lat_1", "33"));
- pin.params.push_back(pj_mkparam<T>("lat_2", "45"));
- }
- else if (BOOST_GEOMETRY_CONDITION((boost::is_same<proj_tag, srs::par4::lagrng>::value)))
- {
- pin.params.push_back(pj_mkparam<T>("W", "2"));
- }
+ BOOST_MPL_ASSERT_MSG((is_found), PROJECTION_NOT_NAMED, (params_type));
+
+ par.id = srs::spar::detail::proj_traits<proj_type>::id;
}
-template <typename T>
-inline void pj_init_units(std::vector<pvalue<T> > const& params,
- std::string const& sunits,
- std::string const& sto_meter,
+/************************************************************************/
+/* pj_init_units() */
+/************************************************************************/
+
+template <typename T, bool Vertical>
+inline void pj_init_units(srs::detail::proj4_parameters const& params,
T & to_meter,
T & fr_meter,
T const& default_to_meter,
T const& default_fr_meter)
{
std::string s;
- std::string units = pj_get_param_s(params, sunits);
+ std::string units = pj_get_param_s(params, Vertical ? "vunits" : "units");
if (! units.empty())
{
- const int n = sizeof(pj_units) / sizeof(pj_units[0]);
+ static const int n = sizeof(pj_units) / sizeof(pj_units[0]);
int index = -1;
for (int i = 0; i < n && index == -1; i++)
{
@@ -148,9 +144,10 @@ inline void pj_init_units(std::vector<pvalue<T> > const& params,
if (s.empty())
{
- s = pj_get_param_s(params, sto_meter);
+ s = pj_get_param_s(params, Vertical ? "vto_meter" : "to_meter");
}
+ // TODO: numerator and denominator could be taken from pj_units
if (! s.empty())
{
std::size_t const pos = s.find('/');
@@ -181,63 +178,283 @@ inline void pj_init_units(std::vector<pvalue<T> > const& params,
}
}
+template <typename T, bool Vertical>
+inline void pj_init_units(srs::dpar::parameters<T> const& params,
+ T & to_meter,
+ T & fr_meter,
+ T const& default_to_meter,
+ T const& default_fr_meter)
+{
+ typename srs::dpar::parameters<T>::const_iterator
+ it = pj_param_find(params, Vertical ? srs::dpar::vunits : srs::dpar::units);
+ if (it != params.end())
+ {
+ static const int n = sizeof(pj_units) / sizeof(pj_units[0]);
+ const int i = it->template get_value<int>();
+ if (i >= 0 && i < n)
+ {
+ T const numerator = pj_units[i].numerator;
+ T const denominator = pj_units[i].denominator;
+ if (numerator == 0.0 || denominator == 0.0)
+ {
+ BOOST_THROW_EXCEPTION( projection_exception(error_unit_factor_less_than_0) );
+ }
+ to_meter = numerator / denominator;
+ fr_meter = 1. / to_meter;
+ }
+ else
+ {
+ BOOST_THROW_EXCEPTION( projection_exception(error_unknow_unit_id) );
+ }
+ }
+ else
+ {
+ it = pj_param_find(params, Vertical ? srs::dpar::vto_meter : srs::dpar::to_meter);
+ if (it != params.end())
+ {
+ to_meter = it->template get_value<T>();
+ fr_meter = 1. / to_meter;
+ }
+ else
+ {
+ to_meter = default_to_meter;
+ fr_meter = default_fr_meter;
+ }
+ }
+}
+
+template
+<
+ typename Params,
+ bool Vertical,
+ int UnitsI = srs::spar::detail::tuples_find_index_if
+ <
+ Params,
+ boost::mpl::if_c
+ <
+ Vertical,
+ srs::spar::detail::is_param_t<srs::spar::vunits>,
+ srs::spar::detail::is_param_tr<srs::spar::detail::units_traits>
+ >::type::template pred
+ >::value,
+ int ToMeterI = srs::spar::detail::tuples_find_index_if
+ <
+ Params,
+ boost::mpl::if_c
+ <
+ Vertical,
+ srs::spar::detail::is_param_t<srs::spar::vto_meter>,
+ srs::spar::detail::is_param_t<srs::spar::to_meter>
+ >::type::template pred
+ >::value,
+ int N = boost::tuples::length<Params>::value
+>
+struct pj_init_units_static
+ : pj_init_units_static<Params, Vertical, UnitsI, N, N>
+{};
+
+template <typename Params, bool Vertical, int UnitsI, int N>
+struct pj_init_units_static<Params, Vertical, UnitsI, N, N>
+{
+ static const int n = sizeof(pj_units) / sizeof(pj_units[0]);
+ static const int i = srs::spar::detail::units_traits
+ <
+ typename boost::tuples::element<UnitsI, Params>::type
+ >::id;
+ static const bool is_valid = i >= 0 && i < n;
+
+ BOOST_MPL_ASSERT_MSG((is_valid), UNKNOWN_UNIT_ID, (Params));
+
+ template <typename T>
+ static void apply(Params const& ,
+ T & to_meter, T & fr_meter,
+ T const& , T const& )
+ {
+ T const numerator = pj_units[i].numerator;
+ T const denominator = pj_units[i].denominator;
+ if (numerator == 0.0 || denominator == 0.0)
+ {
+ BOOST_THROW_EXCEPTION( projection_exception(error_unit_factor_less_than_0) );
+ }
+ to_meter = numerator / denominator;
+ fr_meter = 1. / to_meter;
+ }
+};
+
+template <typename Params, bool Vertical, int ToMeterI, int N>
+struct pj_init_units_static<Params, Vertical, N, ToMeterI, N>
+{
+ template <typename T>
+ static void apply(Params const& params,
+ T & to_meter, T & fr_meter,
+ T const& , T const& )
+ {
+ to_meter = boost::tuples::get<ToMeterI>(params).value;
+ fr_meter = 1. / to_meter;
+ }
+};
+
+template <typename Params, bool Vertical, int N>
+struct pj_init_units_static<Params, Vertical, N, N, N>
+{
+ template <typename T>
+ static void apply(Params const& ,
+ T & to_meter, T & fr_meter,
+ T const& default_to_meter, T const& default_fr_meter)
+ {
+ to_meter = default_to_meter;
+ fr_meter = default_fr_meter;
+ }
+};
+
+template <typename T, bool Vertical, BOOST_GEOMETRY_PROJECTIONS_DETAIL_TYPENAME_PX>
+inline void pj_init_units(srs::spar::parameters<BOOST_GEOMETRY_PROJECTIONS_DETAIL_PX> const& params,
+ T & to_meter,
+ T & fr_meter,
+ T const& default_to_meter,
+ T const& default_fr_meter)
+{
+ pj_init_units_static
+ <
+ srs::spar::parameters<BOOST_GEOMETRY_PROJECTIONS_DETAIL_PX>,
+ Vertical
+ >::apply(params, to_meter, fr_meter, default_to_meter, default_fr_meter);
+}
+
+/************************************************************************/
+/* pj_init_pm() */
+/************************************************************************/
+
+template <typename T>
+inline void pj_init_pm(srs::detail::proj4_parameters const& params, T& val)
+{
+ std::string pm = pj_get_param_s(params, "pm");
+ if (! pm.empty())
+ {
+ int n = sizeof(pj_prime_meridians) / sizeof(pj_prime_meridians[0]);
+ for (int i = 0; i < n ; i++)
+ {
+ if(pj_prime_meridians[i].id == pm)
+ {
+ val = pj_prime_meridians[i].deg * math::d2r<T>();
+ return;
+ }
+ }
+
+ // TODO: Is this try-catch needed?
+ // In other cases the bad_str_cast exception is simply thrown
+ BOOST_TRY
+ {
+ val = dms_parser<T, true>::apply(pm).angle();
+ return;
+ }
+ BOOST_CATCH(geometry::bad_str_cast const&)
+ {
+ BOOST_THROW_EXCEPTION( projection_exception(error_unknown_prime_meridian) );
+ }
+ BOOST_CATCH_END
+ }
+
+ val = 0.0;
+}
+
+template <typename T>
+inline void pj_init_pm(srs::dpar::parameters<T> const& params, T& val)
+{
+ typename srs::dpar::parameters<T>::const_iterator it = pj_param_find(params, srs::dpar::pm);
+ if (it != params.end())
+ {
+ if (it->template is_value_set<int>())
+ {
+ int n = sizeof(pj_prime_meridians) / sizeof(pj_prime_meridians[0]);
+ int i = it->template get_value<int>();
+ if (i >= 0 && i < n)
+ {
+ val = pj_prime_meridians[i].deg * math::d2r<T>();
+ return;
+ }
+ else
+ {
+ BOOST_THROW_EXCEPTION( projection_exception(error_unknown_prime_meridian) );
+ }
+ }
+ else if (it->template is_value_set<T>())
+ {
+ val = it->template get_value<T>() * math::d2r<T>();
+ return;
+ }
+ }
+
+ val = 0.0;
+}
+
+template
+<
+ typename Params,
+ int I = srs::spar::detail::tuples_find_index_if
+ <
+ Params,
+ srs::spar::detail::is_param_tr<srs::spar::detail::pm_traits>::pred
+ >::value,
+ int N = boost::tuples::length<Params>::value
+>
+struct pj_init_pm_static
+{
+ template <typename T>
+ static void apply(Params const& params, T & val)
+ {
+ typedef typename boost::tuples::element<I, Params>::type param_type;
+
+ val = srs::spar::detail::pm_traits<param_type>::value(boost::tuples::get<I>(params));
+ }
+};
+template <typename Params, int N>
+struct pj_init_pm_static<Params, N, N>
+{
+ template <typename T>
+ static void apply(Params const& , T & val)
+ {
+ val = 0;
+ }
+};
+
+template <typename T, BOOST_GEOMETRY_PROJECTIONS_DETAIL_TYPENAME_PX>
+inline void pj_init_pm(srs::spar::parameters<BOOST_GEOMETRY_PROJECTIONS_DETAIL_PX> const& params, T& val)
+{
+ pj_init_pm_static
+ <
+ srs::spar::parameters<BOOST_GEOMETRY_PROJECTIONS_DETAIL_PX>
+ >::apply(params, val);
+}
+
/************************************************************************/
/* pj_init() */
/* */
/* Main entry point for initialing a PJ projections */
-/* definition. Note that the projection specific function is */
-/* called to do the initial allocation so it can be created */
-/* large enough to hold projection specific parameters. */
+/* definition. */
/************************************************************************/
-template <typename T, typename BGParams, typename R>
-inline parameters<T> pj_init(BGParams const& bg_params, R const& arguments, bool use_defaults = true)
+template <typename T, typename Params>
+inline parameters<T> pj_init(Params const& params)
{
parameters<T> pin;
- for (std::vector<std::string>::const_iterator it = boost::begin(arguments);
- it != boost::end(arguments); it++)
- {
- pin.params.push_back(pj_mkparam<T>(*it));
- }
-
- // maybe TODO: handle "init" parameter
- /* check if +init present */
- //std::string sinit;
- //if (pj_param_s(pin.params, "init", sinit))
- //{
- // //if (!(curr = get_init(&arguments, curr, sinit)))
- //}
// find projection -> implemented in projection factory
- pin.name = pj_get_param_s(pin.params, "proj");
+ pj_init_proj(params, pin);
// exception thrown in projection<>
// TODO: consider throwing here both projection_unknown_id_exception and
// projection_not_named_exception in order to throw before other exceptions
//if (pin.name.empty())
//{ BOOST_THROW_EXCEPTION( projection_not_named_exception() ); }
- // set defaults, unless inhibited
- // GL-Addition, if use_defaults is false then defaults are ignored
- if (use_defaults && ! pj_get_param_b(pin.params, "no_defs"))
- {
- // proj4 gets defaults from "proj_def.dat", file of 94/02/23 with a few defaults.
- // Here manually
- pj_push_defaults(bg_params, pin);
- //curr = get_defaults(&arguments, curr, name);
- }
-
- /* allocate projection structure */
- // done by BGParams constructor:
- // pin.is_latlong = 0;
- // pin.is_geocent = 0;
- // pin.long_wrap_center = 0.0;
- // pin.long_wrap_center = 0.0;
- pin.is_long_wrap_set = false;
-
+ // NOTE: proj4 gets defaults from "proj_def.dat".
+ // In Boost.Geometry this is emulated by manually setting them in
+ // pj_ell_init and projections aea, lcc and lagrng
+
/* set datum parameters */
- pj_datum_set(bg_params, pin.params, pin);
+ pj_datum_init(params, pin);
/* set ellipsoid/sphere parameters */
- pj_ell_set(bg_params, pin.params, pin.a, pin.es);
+ pj_ell_init(params, pin.a, pin.es);
pin.a_orig = pin.a;
pin.es_orig = pin.es;
@@ -262,28 +479,28 @@ inline parameters<T> pj_init(BGParams const& bg_params, R const& arguments, bool
}
/* set pin.geoc coordinate system */
- pin.geoc = (pin.es && pj_get_param_b(pin.params, "geoc"));
+ pin.geoc = (pin.es && pj_get_param_b<srs::spar::geoc>(params, "geoc", srs::dpar::geoc));
/* over-ranging flag */
- pin.over = pj_get_param_b(pin.params, "over");
+ pin.over = pj_get_param_b<srs::spar::over>(params, "over", srs::dpar::over);
/* longitude center for wrapping */
- pin.is_long_wrap_set = pj_param_r(pin.params, "lon_wrap", pin.long_wrap_center);
+ pin.is_long_wrap_set = pj_param_r<srs::spar::lon_wrap>(params, "lon_wrap", srs::dpar::lon_wrap, pin.long_wrap_center);
/* central meridian */
- pin.lam0 = pj_get_param_r(pin.params, "lon_0");
+ pin.lam0 = pj_get_param_r<T, srs::spar::lon_0>(params, "lon_0", srs::dpar::lon_0);
/* central latitude */
- pin.phi0 = pj_get_param_r(pin.params, "lat_0");
+ pin.phi0 = pj_get_param_r<T, srs::spar::lat_0>(params, "lat_0", srs::dpar::lat_0);
/* false easting and northing */
- pin.x0 = pj_get_param_f(pin.params, "x_0");
- pin.y0 = pj_get_param_f(pin.params, "y_0");
+ pin.x0 = pj_get_param_f<T, srs::spar::x_0>(params, "x_0", srs::dpar::x_0);
+ pin.y0 = pj_get_param_f<T, srs::spar::y_0>(params, "y_0", srs::dpar::y_0);
/* general scaling factor */
- if (pj_param_f(pin.params, "k_0", pin.k0)) {
+ if (pj_param_f<srs::spar::k_0>(params, "k_0", srs::dpar::k_0, pin.k0)) {
/* empty */
- } else if (pj_param_f(pin.params, "k", pin.k0)) {
+ } else if (pj_param_f<srs::spar::k>(params, "k", srs::dpar::k, pin.k0)) {
/* empty */
} else
pin.k0 = 1.;
@@ -292,100 +509,15 @@ inline parameters<T> pj_init(BGParams const& bg_params, R const& arguments, bool
}
/* set units */
- pj_init_units(pin.params, "units", "to_meter",
- pin.to_meter, pin.fr_meter, 1., 1.);
- pj_init_units(pin.params, "vunits", "vto_meter",
- pin.vto_meter, pin.vfr_meter, pin.to_meter, pin.fr_meter);
+ pj_init_units<T, false>(params, pin.to_meter, pin.fr_meter, 1., 1.);
+ pj_init_units<T, true>(params, pin.vto_meter, pin.vfr_meter, pin.to_meter, pin.fr_meter);
/* prime meridian */
- std::string pm = pj_get_param_s(pin.params, "pm");
- if (! pm.empty())
- {
- std::string value;
-
- int n = sizeof(pj_prime_meridians) / sizeof(pj_prime_meridians[0]);
- for (int i = 0; i < n ; i++)
- {
- if(pj_prime_meridians[i].id == pm)
- {
- value = pj_prime_meridians[i].defn;
- break;
- }
- }
-
- dms_parser<T, true> parser;
-
- // TODO: Is this try-catch needed?
- // In other cases the bad_str_cast exception is simply thrown
- BOOST_TRY
- {
- if (value.empty()) {
- pin.from_greenwich = parser.apply(pm).angle();
- } else {
- pin.from_greenwich = parser.apply(value).angle();
- }
- }
- BOOST_CATCH(geometry::bad_str_cast const&)
- {
- BOOST_THROW_EXCEPTION( projection_exception(error_unknown_prime_meridian) );
- }
- BOOST_CATCH_END
- }
- else
- {
- pin.from_greenwich = 0.0;
- }
+ pj_init_pm(params, pin.from_greenwich);
return pin;
}
-/************************************************************************/
-/* pj_init_plus() */
-/* */
-/* Same as pj_init() except it takes one argument string with */
-/* individual arguments preceeded by '+', such as "+proj=utm */
-/* +zone=11 +ellps=WGS84". */
-/************************************************************************/
-template <typename T, typename BGParams>
-inline parameters<T> pj_init_plus(BGParams const& bg_params, std::string const& definition, bool use_defaults = true)
-{
- const char* sep = " +";
-
- /* split into arguments based on '+' and trim white space */
-
- // boost::split splits on one character, here it should be on " +", so implementation below
- // todo: put in different routine or sort out
- std::vector<std::string> arguments;
- std::string def = boost::trim_copy(definition);
- boost::trim_left_if(def, boost::is_any_of(sep));
-
- std::string::size_type loc = def.find(sep);
- while (loc != std::string::npos)
- {
- std::string par = def.substr(0, loc);
- boost::trim(par);
- if (! par.empty())
- {
- arguments.push_back(par);
- }
-
- def.erase(0, loc);
- boost::trim_left_if(def, boost::is_any_of(sep));
- loc = def.find(sep);
- }
-
- if (! def.empty())
- {
- arguments.push_back(def);
- }
-
- /*boost::split(arguments, definition, boost::is_any_of("+"));
- for (std::vector<std::string>::iterator it = arguments.begin(); it != arguments.end(); it++)
- {
- boost::trim(*it);
- }*/
- return pj_init<T>(bg_params, arguments, use_defaults);
-}
} // namespace detail
}}} // namespace boost::geometry::projections