/usr/include/boost/geometry/strategies/transform
Edit: /usr/include/boost/geometry/strategies/transform/matrix_transformers.hpp (17064B)
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
// This file was modified by Oracle on 2015.
// Modifications copyright (c) 2015 Oracle and/or its affiliates.
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP
#define BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace boost { namespace geometry
{
namespace strategy { namespace transform
{
namespace detail { namespace matrix_transformer
{
template
<
typename Point,
std::size_t Dimension = 0,
std::size_t DimensionCount = geometry::dimension::value
>
struct set_point_from_vec
{
template
static inline void apply(Point & p, Vector const& v)
{
typedef typename geometry::coordinate_type::type coord_t;
set(p, boost::numeric_cast(qvm::A(v)));
set_point_from_vec::apply(p, v);
}
};
template
<
typename Point,
std::size_t DimensionCount
>
struct set_point_from_vec
{
template
static inline void apply(Point &, Vector const&) {}
};
template
<
typename Point,
std::size_t Dimension = 0,
std::size_t DimensionCount = geometry::dimension::value
>
struct set_vec_from_point
{
template
static inline void apply(Point const& p, Vector & v)
{
qvm::A(v) = get(p);
set_vec_from_point::apply(p, v);
}
};
template
<
typename Point,
std::size_t DimensionCount
>
struct set_vec_from_point
{
template
static inline void apply(Point const&, Vector &) {}
};
template
<
typename CalculationType,
std::size_t Dimension1,
std::size_t Dimension2
>
class matrix_transformer
{
protected :
typedef CalculationType ct;
typedef boost::qvm::mat matrix_type;
matrix_type m_matrix;
public :
matrix_type const& matrix() const { return m_matrix; }
template
inline bool apply(P1 const& p1, P2& p2) const
{
assert_dimension_greater_equal();
assert_dimension_greater_equal();
qvm::vec p1temp;
qvm::A(p1temp) = 1;
qvm::vec p2temp;
set_vec_from_point::apply(p1, p1temp);
p2temp = m_matrix * p1temp;
set_point_from_vec::apply(p2, p2temp);
return true;
}
};
}} // namespace detail::matrix_transform
/*!
\brief Affine transformation strategy in Cartesian system.
\details The strategy serves as a generic definition of an affine transformation
matrix and procedure for applying it to a given point.
\see http://en.wikipedia.org/wiki/Affine_transformation
and http://www.devmaster.net/wiki/Transformation_matrices
\ingroup strategies
\tparam Dimension1 number of dimensions to transform from
\tparam Dimension2 number of dimensions to transform to
*/
template
<
typename CalculationType,
std::size_t Dimension1,
std::size_t Dimension2
>
class matrix_transformer : public detail::matrix_transformer::matrix_transformer
{
public:
template
inline matrix_transformer(Matrix const& matrix)
{
qvm::assign(this->m_matrix, matrix);
}
inline matrix_transformer() {}
};
template
class matrix_transformer : public detail::matrix_transformer::matrix_transformer
{
typedef CalculationType ct;
public :
template
inline matrix_transformer(Matrix const& matrix)
{
qvm::assign(this->m_matrix, matrix);
}
inline matrix_transformer() {}
inline matrix_transformer(
ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
{
qvm::A<0,0>(this->m_matrix) = m_0_0; qvm::A<0,1>(this->m_matrix) = m_0_1; qvm::A<0,2>(this->m_matrix) = m_0_2;
qvm::A<1,0>(this->m_matrix) = m_1_0; qvm::A<1,1>(this->m_matrix) = m_1_1; qvm::A<1,2>(this->m_matrix) = m_1_2;
qvm::A<2,0>(this->m_matrix) = m_2_0; qvm::A<2,1>(this->m_matrix) = m_2_1; qvm::A<2,2>(this->m_matrix) = m_2_2;
}
template
inline bool apply(P1 const& p1, P2& p2) const
{
assert_dimension_greater_equal();
assert_dimension_greater_equal();
ct const& c1 = get<0>(p1);
ct const& c2 = get<1>(p1);
typedef typename geometry::coordinate_type::type ct2;
set<0>(p2, boost::numeric_cast(c1 * qvm::A<0,0>(this->m_matrix) + c2 * qvm::A<0,1>(this->m_matrix) + qvm::A<0,2>(this->m_matrix)));
set<1>(p2, boost::numeric_cast(c1 * qvm::A<1,0>(this->m_matrix) + c2 * qvm::A<1,1>(this->m_matrix) + qvm::A<1,2>(this->m_matrix)));
return true;
}
};
// It IS possible to go from 3 to 2 coordinates
template
class matrix_transformer : public detail::matrix_transformer::matrix_transformer
{
typedef CalculationType ct;
public :
template
inline matrix_transformer(Matrix const& matrix)
{
qvm::assign(this->m_matrix, matrix);
}
inline matrix_transformer() {}
inline matrix_transformer(
ct const& m_0_0, ct const& m_0_1, ct const& m_0_2,
ct const& m_1_0, ct const& m_1_1, ct const& m_1_2,
ct const& m_2_0, ct const& m_2_1, ct const& m_2_2)
{
qvm::A<0,0>(this->m_matrix) = m_0_0; qvm::A<0,1>(this->m_matrix) = m_0_1; qvm::A<0,2>(this->m_matrix) = 0; qvm::A<0,3>(this->m_matrix) = m_0_2;
qvm::A<1,0>(this->m_matrix) = m_1_0; qvm::A<1,1>(this->m_matrix) = m_1_1; qvm::A<1,2>(this->m_matrix) = 0; qvm::A<1,3>(this->m_matrix) = m_1_2;
qvm::A<2,0>(this->m_matrix) = m_2_0; qvm::A<2,1>(this->m_matrix) = m_2_1; qvm::A<2,2>(this->m_matrix) = 0; qvm::A<2,3>(this->m_matrix) = m_2_2;
}
template
inline bool apply(P1 const& p1, P2& p2) const
{
assert_dimension_greater_equal();
assert_dimension_greater_equal();
ct const& c1 = get<0>(p1);
ct const& c2 = get<1>(p1);
ct const& c3 = get<2>(p1);
typedef typename geometry::coordinate_type::type ct2;
set<0>(p2, boost::numeric_cast(
c1 * qvm::A<0,0>(this->m_matrix) + c2 * qvm::A<0,1>(this->m_matrix) + c3 * qvm::A<0,2>(this->m_matrix) + qvm::A<0,3>(this->m_matrix)));
set<1>(p2, boost::numeric_cast(
c1 * qvm::A<1,0>(this->m_matrix) + c2 * qvm::A<1,1>(this->m_matrix) + c3 * qvm::A<1,2>(this->m_matrix) + qvm::A<1,3>(this->m_matrix)));
return true;
}
};
template
class matrix_transformer : public detail::matrix_transformer::matrix_transformer
{
typedef CalculationType ct;
public :
template
inline matrix_transformer(Matrix const& matrix)
{
qvm::assign(this->m_matrix, matrix);
}
inline matrix_transformer() {}
inline matrix_transformer(
ct const& m_0_0, ct const& m_0_1, ct const& m_0_2, ct const& m_0_3,
ct const& m_1_0, ct const& m_1_1, ct const& m_1_2, ct const& m_1_3,
ct const& m_2_0, ct const& m_2_1, ct const& m_2_2, ct const& m_2_3,
ct const& m_3_0, ct const& m_3_1, ct const& m_3_2, ct const& m_3_3
)
{
qvm::A<0,0>(this->m_matrix) = m_0_0; qvm::A<0,1>(this->m_matrix) = m_0_1; qvm::A<0,2>(this->m_matrix) = m_0_2; qvm::A<0,3>(this->m_matrix) = m_0_3;
qvm::A<1,0>(this->m_matrix) = m_1_0; qvm::A<1,1>(this->m_matrix) = m_1_1; qvm::A<1,2>(this->m_matrix) = m_1_2; qvm::A<1,3>(this->m_matrix) = m_1_3;
qvm::A<2,0>(this->m_matrix) = m_2_0; qvm::A<2,1>(this->m_matrix) = m_2_1; qvm::A<2,2>(this->m_matrix) = m_2_2; qvm::A<2,3>(this->m_matrix) = m_2_3;
qvm::A<3,0>(this->m_matrix) = m_3_0; qvm::A<3,1>(this->m_matrix) = m_3_1; qvm::A<3,2>(this->m_matrix) = m_3_2; qvm::A<3,3>(this->m_matrix) = m_3_3;
}
template
inline bool apply(P1 const& p1, P2& p2) const
{
assert_dimension_greater_equal();
assert_dimension_greater_equal();
ct const& c1 = get<0>(p1);
ct const& c2 = get<1>(p1);
ct const& c3 = get<2>(p1);
typedef typename geometry::coordinate_type::type ct2;
set<0>(p2, boost::numeric_cast(
c1 * qvm::A<0,0>(this->m_matrix) + c2 * qvm::A<0,1>(this->m_matrix) + c3 * qvm::A<0,2>(this->m_matrix) + qvm::A<0,3>(this->m_matrix)));
set<1>(p2, boost::numeric_cast(
c1 * qvm::A<1,0>(this->m_matrix) + c2 * qvm::A<1,1>(this->m_matrix) + c3 * qvm::A<1,2>(this->m_matrix) + qvm::A<1,3>(this->m_matrix)));
set<2>(p2, boost::numeric_cast(
c1 * qvm::A<2,0>(this->m_matrix) + c2 * qvm::A<2,1>(this->m_matrix) + c3 * qvm::A<2,2>(this->m_matrix) + qvm::A<2,3>(this->m_matrix)));
return true;
}
};
/*!
\brief Strategy of translate transformation in Cartesian system.
\details Translate moves a geometry a fixed distance in 2 or 3 dimensions.
\see http://en.wikipedia.org/wiki/Translation_%28geometry%29
\ingroup strategies
\tparam Dimension1 number of dimensions to transform from
\tparam Dimension2 number of dimensions to transform to
*/
template
<
typename CalculationType,
std::size_t Dimension1,
std::size_t Dimension2
>
class translate_transformer
{
};
template
class translate_transformer : public matrix_transformer
{
public :
// To have translate transformers compatible for 2/3 dimensions, the
// constructor takes an optional third argument doing nothing.
inline translate_transformer(CalculationType const& translate_x,
CalculationType const& translate_y,
CalculationType const& = 0)
: matrix_transformer(
1, 0, translate_x,
0, 1, translate_y,
0, 0, 1)
{}
};
template
class translate_transformer : public matrix_transformer
{
public :
inline translate_transformer(CalculationType const& translate_x,
CalculationType const& translate_y,
CalculationType const& translate_z)
: matrix_transformer(
1, 0, 0, translate_x,
0, 1, 0, translate_y,
0, 0, 1, translate_z,
0, 0, 0, 1)
{}
};
/*!
\brief Strategy of scale transformation in Cartesian system.
\details Scale scales a geometry up or down in all its dimensions.
\see http://en.wikipedia.org/wiki/Scaling_%28geometry%29
\ingroup strategies
\tparam Dimension1 number of dimensions to transform from
\tparam Dimension2 number of dimensions to transform to
*/
template
<
typename CalculationType,
std::size_t Dimension1,
std::size_t Dimension2
>
class scale_transformer
{
};
template
<
typename CalculationType,
std::size_t Dimension1
>
class scale_transformer : public matrix_transformer
{
public:
inline scale_transformer(CalculationType const& scale)
{
boost::qvm::set_identity(this->m_matrix);
this->m_matrix*=scale;
qvm::A(this->m_matrix) = 1;
}
};
template
class scale_transformer : public matrix_transformer
{
public :
inline scale_transformer(CalculationType const& scale_x,
CalculationType const& scale_y,
CalculationType const& = 0)
: matrix_transformer(
scale_x, 0, 0,
0, scale_y, 0,
0, 0, 1)
{}
inline scale_transformer(CalculationType const& scale)
: matrix_transformer(
scale, 0, 0,
0, scale, 0,
0, 0, 1)
{}
};
template
class scale_transformer : public matrix_transformer
{
public :
inline scale_transformer(CalculationType const& scale_x,
CalculationType const& scale_y,
CalculationType const& scale_z)
: matrix_transformer(
scale_x, 0, 0, 0,
0, scale_y, 0, 0,
0, 0, scale_z, 0,
0, 0, 0, 1)
{}
inline scale_transformer(CalculationType const& scale)
: matrix_transformer(
scale, 0, 0, 0,
0, scale, 0, 0,
0, 0, scale, 0,
0, 0, 0, 1)
{}
};
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template
struct as_radian
{};
template <>
struct as_radian
{
template
static inline T get(T const& value)
{
return value;
}
};
template <>
struct as_radian
{
template
static inline T get(T const& value)
{
typedef typename promote_floating_point::type promoted_type;
return value * math::d2r();
}
};
template
<
typename CalculationType,
std::size_t Dimension1,
std::size_t Dimension2
>
class rad_rotate_transformer
: public transform::matrix_transformer
{
public :
inline rad_rotate_transformer(CalculationType const& angle)
: transform::matrix_transformer(
cos(angle), sin(angle), 0,
-sin(angle), cos(angle), 0,
0, 0, 1)
{}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
/*!
\brief Strategy for rotate transformation in Cartesian coordinate system.
\details Rotate rotates a geometry by a specified angle about a fixed point (e.g. origin).
\see http://en.wikipedia.org/wiki/Rotation_%28mathematics%29
\ingroup strategies
\tparam DegreeOrRadian degree/or/radian, type of rotation angle specification
\note A single angle is needed to specify a rotation in 2D.
Not yet in 3D, the 3D version requires special things to allow
for rotation around X, Y, Z or arbitrary axis.
\todo The 3D version will not compile.
*/
template
<
typename DegreeOrRadian,
typename CalculationType,
std::size_t Dimension1,
std::size_t Dimension2
>
class rotate_transformer : public detail::rad_rotate_transformer
{
public :
inline rotate_transformer(CalculationType const& angle)
: detail::rad_rotate_transformer
<
CalculationType, Dimension1, Dimension2
>(detail::as_radian::get(angle))
{}
};
}} // namespace strategy::transform
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGIES_TRANSFORM_MATRIX_TRANSFORMERS_HPP