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.hpp395
1 files changed, 395 insertions, 0 deletions
diff --git a/boost/geometry/srs/projections/impl/pj_init.hpp b/boost/geometry/srs/projections/impl/pj_init.hpp
new file mode 100644
index 0000000000..8b93343bcd
--- /dev/null
+++ b/boost/geometry/srs/projections/impl/pj_init.hpp
@@ -0,0 +1,395 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+// This file is manually converted from PROJ4
+
+// 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.
+// 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
+// PROJ4 is converted to Geometry Library by Barend Gehrels (Geodan, Amsterdam)
+
+// Original copyright notice:
+
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+#ifndef BOOST_GEOMETRY_PROJECTIONS_IMPL_PJ_INIT_HPP
+#define BOOST_GEOMETRY_PROJECTIONS_IMPL_PJ_INIT_HPP
+
+#include <cstdlib>
+#include <string>
+#include <vector>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.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/impl/dms_parser.hpp>
+#include <boost/geometry/srs/projections/impl/pj_datum_set.hpp>
+#include <boost/geometry/srs/projections/impl/pj_datums.hpp>
+#include <boost/geometry/srs/projections/impl/pj_ell_set.hpp>
+#include <boost/geometry/srs/projections/impl/pj_param.hpp>
+#include <boost/geometry/srs/projections/impl/pj_units.hpp>
+#include <boost/geometry/srs/projections/impl/projects.hpp>
+#include <boost/geometry/srs/projections/proj4.hpp>
+
+
+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)
+{
+ pin.params.push_back(pj_mkparam<T>("ellps=WGS84"));
+
+ 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")
+ {
+ pin.params.push_back(pj_mkparam<T>("W=2"));
+ }
+}
+
+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)
+{
+ typedef srs::static_proj4<BOOST_GEOMETRY_PROJECTIONS_DETAIL_PX> static_parameters_type;
+ typedef typename srs::par4::detail::pick_proj_tag
+ <
+ static_parameters_type
+ >::type proj_tag;
+
+ // statically defaulting to WGS84
+ //pin.params.push_back(pj_mkparam("ellps=WGS84"));
+
+ 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"));
+ }
+}
+
+template <typename T>
+inline void pj_init_units(std::vector<pvalue<T> > const& params,
+ std::string const& sunits,
+ std::string const& sto_meter,
+ T & to_meter,
+ T & fr_meter,
+ T const& default_to_meter,
+ T const& default_fr_meter)
+{
+ std::string s;
+ std::string units = pj_param(params, sunits).s;
+ if (! units.empty())
+ {
+ const int n = sizeof(pj_units) / sizeof(pj_units[0]);
+ int index = -1;
+ for (int i = 0; i < n && index == -1; i++)
+ {
+ if(pj_units[i].id == units)
+ {
+ index = i;
+ }
+ }
+
+ if (index == -1) {
+ BOOST_THROW_EXCEPTION( projection_exception(-7) );
+ }
+ s = pj_units[index].to_meter;
+ }
+
+ if (s.empty())
+ {
+ s = pj_param(params, sto_meter).s;
+ }
+
+ if (! s.empty())
+ {
+ std::size_t const pos = s.find('/');
+ if (pos == std::string::npos)
+ {
+ to_meter = lexical_cast<T>(s);
+ }
+ else
+ {
+ T const numerator = lexical_cast<T>(s.substr(0, pos));
+ T const denominator = lexical_cast<T>(s.substr(pos + 1));
+ if (numerator == 0.0 || denominator == 0.0)
+ {
+ BOOST_THROW_EXCEPTION( projection_exception(-99) );
+ }
+ to_meter = numerator / denominator;
+ }
+ if (to_meter == 0.0)
+ {
+ BOOST_THROW_EXCEPTION( projection_exception(-99) );
+ }
+ fr_meter = 1. / to_meter;
+ }
+ else
+ {
+ to_meter = default_to_meter;
+ fr_meter = default_fr_meter;
+ }
+}
+
+/************************************************************************/
+/* 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. */
+/************************************************************************/
+template <typename T, typename BGParams, typename R>
+inline parameters<T> pj_init(BGParams const& bg_params, R const& arguments, bool use_defaults = true)
+{
+ 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));
+ }
+
+ /* check if +init present */
+ if (pj_param(pin.params, "tinit").i)
+ {
+ // maybe TODO: handle "init" parameter
+ //if (!(curr = get_init(&arguments, curr, pj_param(pin.params, "sinit").s)))
+ }
+
+ // find projection -> implemented in projection factory
+ pin.name = pj_param(pin.params, "sproj").s;
+ // 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_param(pin.params, "bno_defs").i)
+ {
+ // 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;
+
+ /* set datum parameters */
+ pj_datum_set(bg_params, pin.params, pin);
+
+ /* set ellipsoid/sphere parameters */
+ pj_ell_set(bg_params, pin.params, pin.a, pin.es);
+
+ pin.a_orig = pin.a;
+ pin.es_orig = pin.es;
+
+ pin.e = sqrt(pin.es);
+ pin.ra = 1. / pin.a;
+ pin.one_es = 1. - pin.es;
+ if (pin.one_es == 0.) {
+ BOOST_THROW_EXCEPTION( projection_exception(-6) );
+ }
+ pin.rone_es = 1./pin.one_es;
+
+ /* Now that we have ellipse information check for WGS84 datum */
+ if( pin.datum_type == PJD_3PARAM
+ && pin.datum_params[0] == 0.0
+ && pin.datum_params[1] == 0.0
+ && pin.datum_params[2] == 0.0
+ && pin.a == 6378137.0
+ && geometry::math::abs(pin.es - 0.006694379990) < 0.000000000050 )/*WGS84/GRS80*/
+ {
+ pin.datum_type = PJD_WGS84;
+ }
+
+ /* set pin.geoc coordinate system */
+ pin.geoc = (pin.es && pj_param(pin.params, "bgeoc").i);
+
+ /* over-ranging flag */
+ pin.over = pj_param(pin.params, "bover").i;
+
+ /* longitude center for wrapping */
+ pin.is_long_wrap_set = pj_param(pin.params, "tlon_wrap").i != 0;
+ if (pin.is_long_wrap_set)
+ pin.long_wrap_center = pj_param(pin.params, "rlon_wrap").f;
+
+ /* central meridian */
+ pin.lam0 = pj_param(pin.params, "rlon_0").f;
+
+ /* central latitude */
+ pin.phi0 = pj_param(pin.params, "rlat_0").f;
+
+ /* false easting and northing */
+ pin.x0 = pj_param(pin.params, "dx_0").f;
+ pin.y0 = pj_param(pin.params, "dy_0").f;
+
+ /* general scaling factor */
+ if (pj_param(pin.params, "tk_0").i)
+ pin.k0 = pj_param(pin.params, "dk_0").f;
+ else if (pj_param(pin.params, "tk").i)
+ pin.k0 = pj_param(pin.params, "dk").f;
+ else
+ pin.k0 = 1.;
+ if (pin.k0 <= 0.) {
+ BOOST_THROW_EXCEPTION( projection_exception(-31) );
+ }
+
+ /* set units */
+ pj_init_units(pin.params, "sunits", "sto_meter",
+ pin.to_meter, pin.fr_meter, 1., 1.);
+ pj_init_units(pin.params, "svunits", "svto_meter",
+ pin.vto_meter, pin.vfr_meter, pin.to_meter, pin.fr_meter);
+
+ /* prime meridian */
+ std::string pm = pj_param(pin.params, "spm").s;
+ 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: Handle case when lexical_cast is not used consistently.
+ // This should probably be done in dms_parser.
+ BOOST_TRY
+ {
+ if (value.empty()) {
+ pin.from_greenwich = parser.apply(pm).angle();
+ } else {
+ pin.from_greenwich = parser.apply(value).angle();
+ }
+ }
+ BOOST_CATCH(boost::bad_lexical_cast const&)
+ {
+ BOOST_THROW_EXCEPTION( projection_exception(-46) );
+ }
+ BOOST_CATCH_END
+ }
+ else
+ {
+ pin.from_greenwich = 0.0;
+ }
+
+ 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
+
+#endif // BOOST_GEOMETRY_PROJECTIONS_IMPL_PJ_INIT_HPP