Added the rounding_cast utility, and added a scale_rounding_strategy to support this new casting type. Added tests for it
This commit is contained in:
parent
1dddfd17ef
commit
39428585f0
3 changed files with 128 additions and 2 deletions
|
@ -24,6 +24,7 @@
|
||||||
#define MAPNIK_GEOMETRY_STRATEGY_HPP
|
#define MAPNIK_GEOMETRY_STRATEGY_HPP
|
||||||
|
|
||||||
#include <mapnik/geometry_adapters.hpp>
|
#include <mapnik/geometry_adapters.hpp>
|
||||||
|
#include <mapnik/util/rounding_cast.hpp>
|
||||||
|
|
||||||
namespace mapnik {
|
namespace mapnik {
|
||||||
namespace geometry {
|
namespace geometry {
|
||||||
|
@ -192,6 +193,57 @@ private:
|
||||||
double offset_;
|
double offset_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct scale_rounding_strategy
|
||||||
|
{
|
||||||
|
scale_rounding_strategy(double scale, double offset = 0)
|
||||||
|
: scale_(scale), offset_(offset) {}
|
||||||
|
|
||||||
|
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) * scale_) + offset_;
|
||||||
|
double y = (boost::geometry::get<1>(p1) * scale_) + offset_;
|
||||||
|
try {
|
||||||
|
boost::geometry::set<0>(p2, util::rounding_cast<p2_type>(x));
|
||||||
|
}
|
||||||
|
catch(boost::numeric::negative_overflow&)
|
||||||
|
{
|
||||||
|
boost::geometry::set<0>(p2, std::numeric_limits<p2_type>::min());
|
||||||
|
}
|
||||||
|
catch(boost::numeric::positive_overflow&)
|
||||||
|
{
|
||||||
|
boost::geometry::set<0>(p2, std::numeric_limits<p2_type>::max());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
boost::geometry::set<1>(p2, util::rounding_cast<p2_type>(y));
|
||||||
|
}
|
||||||
|
catch(boost::numeric::negative_overflow&)
|
||||||
|
{
|
||||||
|
boost::geometry::set<1>(p2, std::numeric_limits<p2_type>::min());
|
||||||
|
}
|
||||||
|
catch(boost::numeric::positive_overflow&)
|
||||||
|
{
|
||||||
|
boost::geometry::set<1>(p2, std::numeric_limits<p2_type>::max());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename P1, typename P2>
|
||||||
|
inline P2 execute(P1 const& p1, bool & status) const
|
||||||
|
{
|
||||||
|
P2 p2;
|
||||||
|
status = apply(p1, p2);
|
||||||
|
return p2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
double scale_;
|
||||||
|
double offset_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} // end geometry ns
|
} // end geometry ns
|
||||||
} // end mapnik ns
|
} // end mapnik ns
|
||||||
|
|
||||||
|
|
48
include/mapnik/util/rounding_cast.hpp
Normal file
48
include/mapnik/util/rounding_cast.hpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* 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_UTIL_ROUNDING_CAST_HPP
|
||||||
|
#define MAPNIK_UTIL_ROUNDING_CAST_HPP
|
||||||
|
|
||||||
|
#include <boost/numeric/conversion/converter.hpp>
|
||||||
|
|
||||||
|
namespace mapnik {
|
||||||
|
namespace util {
|
||||||
|
|
||||||
|
template<typename Target, typename Source>
|
||||||
|
inline
|
||||||
|
Target rounding_cast ( Source arg )
|
||||||
|
{
|
||||||
|
typedef boost::numeric::conversion_traits<Target,Source> Traits ;
|
||||||
|
|
||||||
|
typedef
|
||||||
|
boost::numeric::converter<Target,Source,Traits,boost::numeric::def_overflow_handler,boost::numeric::RoundEven<Source>
|
||||||
|
> Converter ;
|
||||||
|
|
||||||
|
return Converter::convert(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end util ns
|
||||||
|
} // end mapnik ns
|
||||||
|
|
||||||
|
#endif //MAPNIK_UTIL_ROUNDING_CAST_HPP
|
||||||
|
|
|
@ -88,8 +88,8 @@ SECTION("proj and view strategy") {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// Test with scaling as well. This would be like projection from 4326 to a vector tile.
|
// Test with scaling as well. This would be like projection from 4326 to a vector tile.
|
||||||
mapnik::geometry::scale_strategy ss(16, 0.5);
|
mapnik::geometry::scale_rounding_strategy ss(16);
|
||||||
using sg_type = strategy_group<mapnik::proj_strategy, mapnik::view_strategy, mapnik::geometry::scale_strategy >;
|
using sg_type = strategy_group<mapnik::proj_strategy, mapnik::view_strategy, mapnik::geometry::scale_rounding_strategy >;
|
||||||
sg_type sg(ps, vs, ss);
|
sg_type sg(ps, vs, ss);
|
||||||
geometry<double> p1(std::move(point<double>(-97.553098,35.523105)));
|
geometry<double> p1(std::move(point<double>(-97.553098,35.523105)));
|
||||||
point<std::int64_t> r1(938 , 1615);
|
point<std::int64_t> r1(938 , 1615);
|
||||||
|
@ -112,6 +112,32 @@ SECTION("proj and view strategy") {
|
||||||
//std::cout << p3.x << " , " << p3.y << std::endl;
|
//std::cout << p3.x << " , " << p3.y << std::endl;
|
||||||
assert_g_equal(r1, p3);
|
assert_g_equal(r1, p3);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
// Test with scaling + offset as well. This would be like projection from 4326 to a vector tile.
|
||||||
|
mapnik::geometry::scale_rounding_strategy ss(16, 20);
|
||||||
|
using sg_type = strategy_group<mapnik::proj_strategy, mapnik::view_strategy, mapnik::geometry::scale_rounding_strategy >;
|
||||||
|
sg_type sg(ps, vs, ss);
|
||||||
|
geometry<double> p1(std::move(point<double>(-97.553098,35.523105)));
|
||||||
|
point<std::int64_t> r1(958 , 1635);
|
||||||
|
geometry<std::int64_t> p2 = transform<std::int64_t>(p1, sg);
|
||||||
|
REQUIRE(p2.is<point<std::int64_t> >());
|
||||||
|
point<std::int64_t> p3 = mapnik::util::get<point<std::int64_t> >(p2);
|
||||||
|
//std::cout << p3.x << " , " << p3.y << std::endl;
|
||||||
|
assert_g_equal(r1, p3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Test the entire scaling plus offset in reverse process in reverse! This would be like converting a vector tile coordinate to 4326.
|
||||||
|
mapnik::geometry::scale_strategy ss(1.0/16.0, -20.0/16.0);
|
||||||
|
using sg_type = strategy_group_first<mapnik::geometry::scale_strategy, mapnik::unview_strategy, mapnik::proj_strategy >;
|
||||||
|
sg_type sg(ss, uvs, ps_rev);
|
||||||
|
geometry<std::int64_t> p1(std::move(point<std::int64_t>(958 , 1635)));
|
||||||
|
point<double> r1(-97.5586 , 35.5322);
|
||||||
|
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…
Reference in a new issue