Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch '2.1.x' of github.com:mapnik/mapnik into 2.1.x

  • Loading branch information...
commit 66aaa4f70ca61cc3785a1cbdc0b01bd3af81cb75 2 parents 8b649f7 + 9d209cf
@springmeyer springmeyer authored
View
79 include/mapnik/util/conversions.hpp
@@ -38,6 +38,7 @@
#if BOOST_VERSION >= 104500
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/karma.hpp>
+#include <boost/math/special_functions/trunc.hpp> // trunc to avoid needing C++11
#else
#include <boost/lexical_cast.hpp>
#endif
@@ -67,8 +68,80 @@ template <typename T>
struct double_policy : boost::spirit::karma::real_policies<T>
{
typedef boost::spirit::karma::real_policies<T> base_type;
- static int floatfield(T n) { return base_type::fmtflags::fixed; }
- static unsigned precision(T n) { return 16 ;}
+
+ static int floatfield(T n) {
+ using namespace boost::spirit; // for traits
+
+ if (traits::test_zero(n))
+ return base_type::fmtflags::fixed;
+
+ T abs_n = traits::get_absolute_value(n);
+ return (abs_n >= 1e16 || abs_n < 1e-4)
+ ? base_type::fmtflags::scientific : base_type::fmtflags::fixed;
+ }
+
+ static unsigned precision(T n) {
+ if ( n == 0.0 ) return 0;
+ using namespace boost::spirit; // for traits
+ return static_cast<unsigned>(15 - boost::math::trunc(log10(traits::get_absolute_value(n))));
+ }
+
+ template <typename OutputIterator>
+ static bool dot(OutputIterator& sink, T n, unsigned precision) {
+ if (n == 0.0) return true; // avoid trailing zeroes
+ return base_type::dot(sink, n, precision);
+ }
+
+ template <typename OutputIterator>
+ static bool fraction_part (OutputIterator& sink, T n
+ , unsigned precision_, unsigned precision)
+ {
+ // NOTE: copied from karma only to avoid trailing zeroes
+ // (maybe a bug ?)
+
+ // allow for ADL to find the correct overload for floor and log10
+ using namespace std;
+
+ using namespace boost::spirit; // for traits
+ using namespace boost::spirit::karma; // for char_inserter
+ using namespace boost; // for remove_const
+
+ if ( traits::test_zero(n) ) return true; // this part added to karma
+
+ // The following is equivalent to:
+ // generate(sink, right_align(precision, '0')[ulong], n);
+ // but it's spelled out to avoid inter-modular dependencies.
+
+ typename remove_const<T>::type digits =
+ (traits::test_zero(n) ? 0 : floor(log10(n))) + 1;
+ bool r = true;
+ for (/**/; r && digits < precision_; digits = digits + 1)
+ r = char_inserter<>::call(sink, '0');
+ if (precision && r)
+ r = int_inserter<10>::call(sink, n);
+ return r;
+ }
+
+ template <typename CharEncoding, typename Tag, typename OutputIterator>
+ static bool exponent (OutputIterator& sink, long n)
+ {
+ // NOTE: copied from karma to force sign in exponent
+ const bool force_sign = true;
+
+ using namespace boost::spirit; // for traits
+ using namespace boost::spirit::karma; // for char_inserter, sign_inserter
+
+ long abs_n = traits::get_absolute_value(n);
+ bool r = char_inserter<CharEncoding, Tag>::call(sink, 'e') &&
+ sign_inserter::call(sink, traits::test_zero(n)
+ , traits::test_negative(n), force_sign);
+
+ // the C99 Standard requires at least two digits in the exponent
+ if (r && abs_n < 10)
+ r = char_inserter<CharEncoding, Tag>::call(sink, '0');
+ return r && int_inserter<10>::call(sink, abs_n);
+ }
+
};
@@ -77,7 +150,7 @@ template <>
inline bool to_string(std::string & str, double value)
{
namespace karma = boost::spirit::karma;
- typedef boost::spirit::karma::real_generator<double, double_policy<double> > double_type;
+ typedef karma::real_generator<double, double_policy<double> > double_type;
std::back_insert_iterator<std::string> sink(str);
return karma::generate(sink, double_type(), value);
}
View
5 plugins/input/postgis/postgis_datasource.cpp
@@ -655,7 +655,10 @@ featureset_ptr postgis_datasource::features(const query& q) const
s << "\"" << geometryColumn_ << "\"";
if (simplify_geometries_) {
- const double tolerance = std::min(px_gw, px_gh) / 2.0;
+ // 1/20 of pixel seems to be a good compromise to avoid
+ // drop of collapsed polygons.
+ // See https://github.com/mapnik/mapnik/issues/1639
+ const double tolerance = std::min(px_gw, px_gh) / 20.0;
s << ", " << tolerance << ")";
}
View
123 tests/cpp_tests/conversions_test.cpp
@@ -0,0 +1,123 @@
+#include <boost/version.hpp>
+#include <mapnik/util/conversions.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <iostream>
+
+int main( int, char*[] )
+{
+ using mapnik::util::to_string;
+
+ try
+ {
+ std::string out;
+
+ // Test double
+ to_string(out, double(0));
+ BOOST_TEST_EQ( out, "0" );
+ out.clear();
+
+ to_string(out, double(1));
+ BOOST_TEST_EQ( out, "1" );
+ out.clear();
+
+ to_string(out, double(-1));
+ BOOST_TEST_EQ( out, "-1" );
+ out.clear();
+
+ to_string(out, double(0.1));
+ BOOST_TEST_EQ( out, "0.1" );
+ out.clear();
+
+ to_string(out, double(-0.1));
+ BOOST_TEST_EQ( out, "-0.1" );
+ out.clear();
+
+ to_string(out, double(0.123));
+ BOOST_TEST_EQ( out, "0.123" );
+ out.clear();
+
+ to_string(out, double(-0.123));
+ BOOST_TEST_EQ( out, "-0.123" );
+ out.clear();
+
+ to_string(out, double(1e-06));
+ BOOST_TEST_EQ( out, "1e-06" );
+ out.clear();
+
+ to_string(out, double(-1e-06));
+ BOOST_TEST_EQ( out, "-1e-06" );
+ out.clear();
+
+ to_string(out, double(1e-05));
+ BOOST_TEST_EQ( out, "1e-05" );
+ out.clear();
+
+ to_string(out, double(-1e-05));
+ BOOST_TEST_EQ( out, "-1e-05" );
+ out.clear();
+
+ to_string(out, double(0.0001));
+ BOOST_TEST_EQ( out, "0.0001" );
+ out.clear();
+
+ to_string(out, double(-0.0001));
+ BOOST_TEST_EQ( out, "-0.0001" );
+ out.clear();
+
+ to_string(out, double(0.0001234567890123456));
+ BOOST_TEST_EQ( out, "0.0001234567890123456" );
+ out.clear();
+
+ to_string(out, double(-0.0001234567890123456));
+ BOOST_TEST_EQ( out, "-0.0001234567890123456" );
+ out.clear();
+
+ to_string(out, double(1000000000000000));
+ BOOST_TEST_EQ( out, "1000000000000000" );
+ out.clear();
+
+ to_string(out, double(-1000000000000000));
+ BOOST_TEST_EQ( out, "-1000000000000000" );
+ out.clear();
+
+ to_string(out, double(100000000000000.1));
+ BOOST_TEST_EQ( out, "100000000000000.1" );
+ out.clear();
+
+ to_string(out, double(1.00001));
+ BOOST_TEST_EQ( out, "1.00001" );
+ out.clear();
+
+ to_string(out, double(1234000000000000));
+ BOOST_TEST_EQ( out, "1234000000000000" );
+ out.clear();
+
+ to_string(out, double(1.234e+16));
+ BOOST_TEST_EQ( out, "1.234e+16" );
+ out.clear();
+
+ to_string(out, double(-1.234e+16));
+ BOOST_TEST_EQ( out, "-1.234e+16" );
+ out.clear();
+
+ // Test int
+
+ to_string(out, int(2));
+ BOOST_TEST_EQ( out, "2" );
+ out.clear();
+ }
+ catch (std::exception const & ex)
+ {
+ std::clog << "C++ type conversions problem: " << ex.what() << "\n";
+ BOOST_TEST(false);
+ }
+
+ if (!::boost::detail::test_errors()) {
+ std::clog << "C++ type conversions: \x1b[1;32m✓ \x1b[0m\n";
+#if BOOST_VERSION >= 104600
+ ::boost::detail::report_errors_remind().called_report_errors_function = true;
+#endif
+ } else {
+ return ::boost::report_errors();
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.