/usr/include/boost/geometry/srs
Edit: /usr/include/boost/geometry/srs/transformation.hpp (22411B)
// Boost.Geometry (aka GGL, Generic Geometry Library)
// 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)
#ifndef BOOST_GEOMETRY_SRS_TRANSFORMATION_HPP
#define BOOST_GEOMETRY_SRS_TRANSFORMATION_HPP
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace boost { namespace geometry
{
namespace projections { namespace detail
{
template
inline bool same_object(T1 const& , T2 const& )
{
return false;
}
template
inline bool same_object(T const& o1, T const& o2)
{
return boost::addressof(o1) == boost::addressof(o2);
}
template
<
typename PtIn,
typename PtOut,
bool SameUnits = boost::is_same
<
typename geometry::detail::cs_angular_units::type,
typename geometry::detail::cs_angular_units::type
>::value
>
struct transform_geometry_point_coordinates
{
static inline void apply(PtIn const& in, PtOut & out, bool /*enable_angles*/)
{
geometry::set<0>(out, geometry::get<0>(in));
geometry::set<1>(out, geometry::get<1>(in));
}
};
template
struct transform_geometry_point_coordinates
{
static inline void apply(PtIn const& in, PtOut & out, bool enable_angles)
{
if (enable_angles)
{
geometry::set_from_radian<0>(out, geometry::get_as_radian<0>(in));
geometry::set_from_radian<1>(out, geometry::get_as_radian<1>(in));
}
else
{
geometry::set<0>(out, geometry::get<0>(in));
geometry::set<1>(out, geometry::get<1>(in));
}
}
};
template
struct transform_geometry_point
{
typedef typename geometry::point_type::type point_type;
typedef geometry::model::point
<
typename select_most_precise
<
typename geometry::coordinate_type::type,
CT
>::type,
geometry::dimension::type::value,
typename geometry::coordinate_system::type
> type;
template
static inline void apply(PtIn const& in, PtOut & out, bool enable_angles)
{
transform_geometry_point_coordinates::apply(in, out, enable_angles);
projections::detail::copy_higher_dimensions<2>(in, out);
}
};
template
struct transform_geometry_range_base
{
struct convert_strategy
{
convert_strategy(bool enable_angles)
: m_enable_angles(enable_angles)
{}
template
void apply(PtIn const& in, PtOut & out)
{
transform_geometry_point::apply(in, out, m_enable_angles);
}
bool m_enable_angles;
};
template
static inline void apply(In const& in, Out & out, bool enable_angles)
{
// Change the order and/or closure if needed
// In - arbitrary geometry
// Out - either Geometry or std::vector
// So the order and closure of In and Geometry shoudl be compared
// std::vector's order is assumed to be the same as of Geometry
geometry::detail::conversion::range_to_range
<
In,
Out,
geometry::point_order::value != geometry::point_order::value
>::apply(in, out, convert_strategy(enable_angles));
}
};
template
<
typename Geometry,
typename CT,
typename Tag = typename geometry::tag::type
>
struct transform_geometry
{};
template
struct transform_geometry
: transform_geometry_point
{};
template
struct transform_geometry
{
typedef geometry::model::segment
<
typename transform_geometry_point::type
> type;
template
static inline void apply(In const& in, Out & out, bool enable_angles)
{
apply<0>(in, out, enable_angles);
apply<1>(in, out, enable_angles);
}
private:
template
static inline void apply(In const& in, Out & out, bool enable_angles)
{
geometry::detail::indexed_point_view in_pt(in);
geometry::detail::indexed_point_view out_pt(out);
transform_geometry_point::apply(in_pt, out_pt, enable_angles);
}
};
template
struct transform_geometry
: transform_geometry_range_base
{
typedef model::multi_point
<
typename transform_geometry_point::type
> type;
};
template
struct transform_geometry
: transform_geometry_range_base
{
typedef model::linestring
<
typename transform_geometry_point::type
> type;
};
template
struct transform_geometry
: transform_geometry_range_base
{
typedef model::ring
<
typename transform_geometry_point::type,
geometry::point_order::value == clockwise,
geometry::closure::value == closed
> type;
};
template
<
typename OutGeometry,
typename CT,
bool EnableTemporary = ! boost::is_same
<
typename select_most_precise
<
typename geometry::coordinate_type::type,
CT
>::type,
typename geometry::coordinate_type::type
>::type::value
>
struct transform_geometry_wrapper
{
typedef transform_geometry transform;
typedef typename transform::type type;
template
transform_geometry_wrapper(InGeometry const& in, OutGeometry & out, bool input_angles)
: m_out(out)
{
transform::apply(in, m_temp, input_angles);
}
type & get() { return m_temp; }
void finish() { geometry::convert(m_temp, m_out); } // this is always copy 1:1 without changing the order or closure
private:
type m_temp;
OutGeometry & m_out;
};
template
<
typename OutGeometry,
typename CT
>
struct transform_geometry_wrapper
{
typedef transform_geometry transform;
typedef OutGeometry type;
transform_geometry_wrapper(OutGeometry const& in, OutGeometry & out, bool input_angles)
: m_out(out)
{
if (! same_object(in, out))
transform::apply(in, out, input_angles);
}
template
transform_geometry_wrapper(InGeometry const& in, OutGeometry & out, bool input_angles)
: m_out(out)
{
transform::apply(in, out, input_angles);
}
OutGeometry & get() { return m_out; }
void finish() {}
private:
OutGeometry & m_out;
};
template
struct transform_range
{
template
<
typename Proj1, typename Par1,
typename Proj2, typename Par2,
typename RangeIn, typename RangeOut,
typename Grids
>
static inline bool apply(Proj1 const& proj1, Par1 const& par1,
Proj2 const& proj2, Par2 const& par2,
RangeIn const& in, RangeOut & out,
Grids const& grids1, Grids const& grids2)
{
// NOTE: this has to be consistent with pj_transform()
bool const input_angles = !par1.is_geocent && par1.is_latlong;
transform_geometry_wrapper wrapper(in, out, input_angles);
bool res = true;
try
{
res = pj_transform(proj1, par1, proj2, par2, wrapper.get(), grids1, grids2);
}
catch (projection_exception const&)
{
res = false;
}
catch(...)
{
BOOST_RETHROW
}
wrapper.finish();
return res;
}
};
template
struct transform_multi
{
template
<
typename Proj1, typename Par1,
typename Proj2, typename Par2,
typename MultiIn, typename MultiOut,
typename Grids
>
static inline bool apply(Proj1 const& proj1, Par1 const& par1,
Proj2 const& proj2, Par2 const& par2,
MultiIn const& in, MultiOut & out,
Grids const& grids1, Grids const& grids2)
{
if (! same_object(in, out))
range::resize(out, boost::size(in));
return apply(proj1, par1, proj2, par2,
boost::begin(in), boost::end(in),
boost::begin(out),
grids1, grids2);
}
private:
template
<
typename Proj1, typename Par1,
typename Proj2, typename Par2,
typename InIt, typename OutIt,
typename Grids
>
static inline bool apply(Proj1 const& proj1, Par1 const& par1,
Proj2 const& proj2, Par2 const& par2,
InIt in_first, InIt in_last, OutIt out_first,
Grids const& grids1, Grids const& grids2)
{
bool res = true;
for ( ; in_first != in_last ; ++in_first, ++out_first )
{
if ( ! Policy::apply(proj1, par1, proj2, par2, *in_first, *out_first, grids1, grids2) )
{
res = false;
}
}
return res;
}
};
template
<
typename Geometry,
typename CT,
typename Tag = typename geometry::tag::type
>
struct transform
: not_implemented
{};
template
struct transform
{
template
<
typename Proj1, typename Par1,
typename Proj2, typename Par2,
typename PointIn, typename PointOut,
typename Grids
>
static inline bool apply(Proj1 const& proj1, Par1 const& par1,
Proj2 const& proj2, Par2 const& par2,
PointIn const& in, PointOut & out,
Grids const& grids1, Grids const& grids2)
{
// NOTE: this has to be consistent with pj_transform()
bool const input_angles = !par1.is_geocent && par1.is_latlong;
transform_geometry_wrapper wrapper(in, out, input_angles);
typedef typename transform_geometry_wrapper::type point_type;
point_type * ptr = boost::addressof(wrapper.get());
std::pair range = std::make_pair(ptr, ptr + 1);
bool res = true;
try
{
res = pj_transform(proj1, par1, proj2, par2, range, grids1, grids2);
}
catch (projection_exception const&)
{
res = false;
}
catch(...)
{
BOOST_RETHROW
}
wrapper.finish();
return res;
}
};
template
struct transform
: transform_range
{};
template
struct transform
{
template
<
typename Proj1, typename Par1,
typename Proj2, typename Par2,
typename SegmentIn, typename SegmentOut,
typename Grids
>
static inline bool apply(Proj1 const& proj1, Par1 const& par1,
Proj2 const& proj2, Par2 const& par2,
SegmentIn const& in, SegmentOut & out,
Grids const& grids1, Grids const& grids2)
{
// NOTE: this has to be consistent with pj_transform()
bool const input_angles = !par1.is_geocent && par1.is_latlong;
transform_geometry_wrapper wrapper(in, out, input_angles);
typedef typename geometry::point_type
<
typename transform_geometry_wrapper::type
>::type point_type;
point_type points[2];
geometry::detail::assign_point_from_index<0>(wrapper.get(), points[0]);
geometry::detail::assign_point_from_index<1>(wrapper.get(), points[1]);
std::pair range = std::make_pair(points, points + 2);
bool res = true;
try
{
res = pj_transform(proj1, par1, proj2, par2, range, grids1, grids2);
}
catch (projection_exception const&)
{
res = false;
}
catch(...)
{
BOOST_RETHROW
}
geometry::detail::assign_point_to_index<0>(points[0], wrapper.get());
geometry::detail::assign_point_to_index<1>(points[1], wrapper.get());
wrapper.finish();
return res;
}
};
template
struct transform
: transform_range
{};
template
struct transform
: transform_multi >
{};
template
struct transform
: transform_range
{};
template
struct transform
{
template
<
typename Proj1, typename Par1,
typename Proj2, typename Par2,
typename PolygonIn, typename PolygonOut,
typename Grids
>
static inline bool apply(Proj1 const& proj1, Par1 const& par1,
Proj2 const& proj2, Par2 const& par2,
PolygonIn const& in, PolygonOut & out,
Grids const& grids1, Grids const& grids2)
{
bool r1 = transform_range
<
CT
>::apply(proj1, par1, proj2, par2,
geometry::exterior_ring(in),
geometry::exterior_ring(out),
grids1, grids2);
bool r2 = transform_multi
<
transform_range
>::apply(proj1, par1, proj2, par2,
geometry::interior_rings(in),
geometry::interior_rings(out),
grids1, grids2);
return r1 && r2;
}
};
template
struct transform
: transform_multi
<
transform
<
typename boost::range_value::type,
CT,
polygon_tag
>
>
{};
}} // namespace projections::detail
namespace srs
{
/*!
\brief Representation of projection
\details Either dynamic or static projection representation
\ingroup projection
\tparam Proj1 default_dynamic or static projection parameters
\tparam Proj2 default_dynamic or static projection parameters
\tparam CT calculation type used internally
*/
template
<
typename Proj1 = srs::dynamic,
typename Proj2 = srs::dynamic,
typename CT = double
>
class transformation
{
typedef typename projections::detail::promote_to_double::type calc_t;
public:
// Both static and default constructed
transformation()
{}
// First dynamic, second static and default constructed
template
explicit transformation(Parameters1 const& parameters1,
typename boost::enable_if_c
<
boost::is_same::value
&& projections::dynamic_parameters::is_specialized
>::type * = 0)
: m_proj1(parameters1)
{}
// First static, second static and default constructed
explicit transformation(Proj1 const& parameters1)
: m_proj1(parameters1)
{}
// Both dynamic
template
transformation(Parameters1 const& parameters1,
Parameters2 const& parameters2,
typename boost::enable_if_c
<
boost::is_same::value
&& boost::is_same::value
&& projections::dynamic_parameters::is_specialized
&& projections::dynamic_parameters::is_specialized
> * = 0)
: m_proj1(parameters1)
, m_proj2(parameters2)
{}
// First dynamic, second static
template
transformation(Parameters1 const& parameters1,
Proj2 const& parameters2,
typename boost::enable_if_c
<
boost::is_same::value
&& projections::dynamic_parameters::is_specialized
> * = 0)
: m_proj1(parameters1)
, m_proj2(parameters2)
{}
// First static, second dynamic
template
transformation(Proj1 const& parameters1,
Parameters2 const& parameters2,
typename boost::enable_if_c
<
boost::is_same::value
&& projections::dynamic_parameters::is_specialized
> * = 0)
: m_proj1(parameters1)
, m_proj2(parameters2)
{}
// Both static
transformation(Proj1 const& parameters1,
Proj2 const& parameters2)
: m_proj1(parameters1)
, m_proj2(parameters2)
{}
template
bool forward(GeometryIn const& in, GeometryOut & out) const
{
return forward(in, out, transformation_grids());
}
template
bool inverse(GeometryIn const& in, GeometryOut & out) const
{
return inverse(in, out, transformation_grids());
}
template
bool forward(GeometryIn const& in, GeometryOut & out,
transformation_grids const& grids) const
{
BOOST_MPL_ASSERT_MSG((projections::detail::same_tags::value),
NOT_SUPPORTED_COMBINATION_OF_GEOMETRIES,
(GeometryIn, GeometryOut));
return projections::detail::transform
<
GeometryOut,
calc_t
>::apply(m_proj1.proj(), m_proj1.proj().params(),
m_proj2.proj(), m_proj2.proj().params(),
in, out,
grids.src_grids,
grids.dst_grids);
}
template
bool inverse(GeometryIn const& in, GeometryOut & out,
transformation_grids const& grids) const
{
BOOST_MPL_ASSERT_MSG((projections::detail::same_tags::value),
NOT_SUPPORTED_COMBINATION_OF_GEOMETRIES,
(GeometryIn, GeometryOut));
return projections::detail::transform
<
GeometryOut,
calc_t
>::apply(m_proj2.proj(), m_proj2.proj().params(),
m_proj1.proj(), m_proj1.proj().params(),
in, out,
grids.dst_grids,
grids.src_grids);
}
template
inline transformation_grids initialize_grids(GridsStorage & grids_storage) const
{
transformation_grids result(grids_storage);
using namespace projections::detail;
pj_gridlist_from_nadgrids(m_proj1.proj().params(),
result.src_grids);
pj_gridlist_from_nadgrids(m_proj2.proj().params(),
result.dst_grids);
return result;
}
private:
projections::proj_wrapper m_proj1;
projections::proj_wrapper m_proj2;
};
} // namespace srs
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_SRS_TRANSFORMATION_HPP