A venture into variadic templates for strategies and transforms.
This commit is contained in:
parent
a19da799e0
commit
75ccfdf934
5 changed files with 195 additions and 0 deletions
69
include/mapnik/geometry_strategy.hpp
Normal file
69
include/mapnik/geometry_strategy.hpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2015 Artem Pavlenko
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef MAPNIK_GEOMETRY_STRATEGY_HPP
|
||||
#define MAPNIK_GEOMETRY_STRATEGY_HPP
|
||||
|
||||
namespace mapnik {
|
||||
namespace geometry {
|
||||
|
||||
template <typename Strategy, typename... Strategies>
|
||||
struct strategy_group
|
||||
{
|
||||
strategy_group(Strategy const& op, Strategies const& ... ops)
|
||||
: ops_(op, ops ...) {}
|
||||
|
||||
template <typename P1, typename P2>
|
||||
inline bool apply(P1 const& p1, P2 & p2) const
|
||||
{
|
||||
bool status = true;
|
||||
p2 = execute_first<0, P1, P2, Strategy, ...Strategies>(p1, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
template <int c, typename P1, typename P2, typename T, typename ...Args>
|
||||
inline P2 execute_first(P1 const& p, bool & status)
|
||||
{
|
||||
return execute_next<c+1,P1,P2,...Args>(std::get<c>(ops_).template execute<P1,P2>(p, status), status);
|
||||
}
|
||||
|
||||
template <int c, typename P2, typename T, typename ...Args>
|
||||
inline P2 execute_next(P2 const& p, bool & status)
|
||||
{
|
||||
return execute_next<c+1, P2, ...Args>(std::get<c>(ops_).template execute<P2,P2>(p, status), status);
|
||||
}
|
||||
|
||||
template <int c, typename P2, typename T>
|
||||
inline P2 execute_next(P2 const& p, bool & status)
|
||||
{
|
||||
return std::get<c>(ops_).template execute<P2,P2>(p, status);
|
||||
}
|
||||
|
||||
private:
|
||||
std::tuple<Strategy const&, Strategies const& ...> ops_;
|
||||
|
||||
};
|
||||
|
||||
} // end geometry ns
|
||||
} // end mapnik ns
|
||||
|
||||
#endif //MAPNIK_GEOMETRY_STRATEGY_HPP
|
|
@ -70,6 +70,7 @@ struct geometry_transform
|
|||
}
|
||||
Transformer const& transformer_;
|
||||
};
|
||||
|
||||
} // ns detail
|
||||
|
||||
template <typename T0, typename T1, typename T2>
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include <mapnik/config.hpp>
|
||||
#include <mapnik/util/noncopyable.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/geometry.hpp>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
namespace geometry {
|
||||
|
@ -68,6 +71,36 @@ private:
|
|||
bool wgs84_to_merc_;
|
||||
bool merc_to_wgs84_;
|
||||
};
|
||||
|
||||
struct proj_strategy
|
||||
{
|
||||
proj_strategy(proj_transform const& prj_trans)
|
||||
: prj_trans_(prj_trans) {}
|
||||
|
||||
template <typename P1, typename P2>
|
||||
inline bool apply(P1 const& p1, P2 & p2) const
|
||||
{
|
||||
using p2_type = typename boost::geometry::coordinate_type<P2>::type;
|
||||
double x = boost::geometry::get<0>(p1);
|
||||
double y = boost::geometry::get<1>(p1);
|
||||
double z = 0.0;
|
||||
if (!prj_trans_.forward(x, y, z)) return false;
|
||||
boost::geometry::set<0>(p2, boost::numeric_cast<p2_type>(x));
|
||||
boost::geometry::set<1>(p2, boost::numeric_cast<p2_type>(y));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename P1, typename P2>
|
||||
inline P2 execute(P1 const& p1, bool & status) const
|
||||
{
|
||||
P2 p2;
|
||||
status = apply(p1, p2);
|
||||
return p2;
|
||||
}
|
||||
|
||||
proj_transform const& prj_trans_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MAPNIK_PROJ_TRANSFORM_HPP
|
||||
|
|
|
@ -178,6 +178,39 @@ public:
|
|||
return extent_;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename CalculationType>
|
||||
struct view_strategy
|
||||
{
|
||||
using calc_type = CalculationType;
|
||||
|
||||
view_strategy(view_transform const& tr)
|
||||
: tr_(tr) {}
|
||||
|
||||
template <typename P1, typename P2>
|
||||
inline bool apply(P1 const& p1, P2 & p2) const
|
||||
{
|
||||
using coordinate_type = typename boost::geometry::coordinate_type<P2>::type;
|
||||
calc_type x = boost::geometry::get<0>(p1);
|
||||
calc_type y = boost::geometry::get<1>(p1);
|
||||
calc_type z = 0.0;
|
||||
tr_.forward(&x,&y);
|
||||
boost::geometry::set<0>(p2, boost::numeric_cast<coordinate_type>(x));
|
||||
boost::geometry::set<1>(p2, boost::numeric_cast<coordinate_type>(y));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename P1, typename P2>
|
||||
inline P2 execute(P1 const& p1, bool & status) const
|
||||
{
|
||||
P2 p2;
|
||||
status = apply(p1, p2);
|
||||
return p2;
|
||||
}
|
||||
|
||||
view_transform const& tr_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MAPNIK_VIEW_TRANSFORM_HPP
|
||||
|
|
59
tests/cxx/geometry_strategy_test.cpp
Normal file
59
tests/cxx/geometry_strategy_test.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
#include "catch.hpp"
|
||||
#include "geometry_equal.hpp"
|
||||
|
||||
#include <mapnik/geometry.hpp>
|
||||
#include <mapnik/projection.hpp>
|
||||
#include <mapnik/proj_transform.hpp>
|
||||
#include <mapnik/view_transform.hpp>
|
||||
#include <mapnik/geometry_transform.hpp>
|
||||
#include <mapnik/geometry_strategy.hpp>
|
||||
|
||||
TEST_CASE("geometry strategy tests") {
|
||||
|
||||
SECTION("proj and view strategy") {
|
||||
using namespace mapnik::geometry;
|
||||
mapnik::box2d<double> e(-20037508.342789,-20037508.342789,20037508.342789,20037508.342789);
|
||||
mapnik::view_transform vt(256, 256, e);
|
||||
mapnik::view_strategy<double> vs(vt);
|
||||
mapnik::projection source("+init=epsg:4326");
|
||||
mapnik::projection dest("+init=epsg:3857");
|
||||
mapnik::proj_transform proj_trans(source, dest);
|
||||
mapnik::proj_strategy ps(proj_trans);
|
||||
{
|
||||
// Test first that proj strategy works properly
|
||||
point<double> p1(-97.553098,35.523105);
|
||||
point<double> r1(-1.08596e+07, 4.2352e+06);
|
||||
geometry<double> p2 = transform<double>(p1, ps);
|
||||
REQUIRE(p2.is<point<double> >());
|
||||
point<double> p3 = mapnik::util::get<point<double> >(p2);
|
||||
assert_g_equal(r1, p3);
|
||||
}
|
||||
{
|
||||
// Test next that view_strategy works
|
||||
point<double> p1(-1.08596e+07, 4.2352e+06);
|
||||
point<double> r1(58.6287 , 100.945);
|
||||
geometry<double> p2 = transform<double>(p1, vs);
|
||||
REQUIRE(p2.is<point<double> >());
|
||||
point<double> p3 = mapnik::util::get<point<double> >(p2);
|
||||
//std::cout << p3.x << " , " << p3.y << std::endl;
|
||||
assert_g_equal(r1, p3);
|
||||
|
||||
}
|
||||
{
|
||||
// Test that both work streamed together
|
||||
using sg_type = strategy_group<mapnik::proj_strategy, mapnik::view_strategy<double> >;
|
||||
sg_type sg(ps, vs);
|
||||
point<double> p1(-97.553098,35.523105);
|
||||
point<double> r1(58.6287 , 100.945);
|
||||
geometry<double> p2 = transform<double>(p1, sg);
|
||||
REQUIRE(p2.is<point<double> >());
|
||||
point<double> p3 = mapnik::util::get<point<double> >(p2);
|
||||
std::cout << p3.x << " , " << p3.y << std::endl;
|
||||
assert_g_equal(r1, p3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Add table
Reference in a new issue