From f8b1520d1a0626f3e16e88ecf641be7222a9ceb6 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 28 Jan 2013 01:47:32 -0500 Subject: [PATCH 01/11] refactor projection interface: 1. cleanup custom lonlat<->merc code. 2. centralize proj4 strings into constants, 3. tweak projection benchmarking to allocate objects in loop so we can test that specifically - refs #1703 --- benchmark/run.cpp | 64 ++++++++++++--------- include/mapnik/layer.hpp | 3 +- include/mapnik/map.hpp | 3 +- include/mapnik/proj_transform.hpp | 5 +- include/mapnik/projection.hpp | 27 ++++----- include/mapnik/well_known_srs.hpp | 94 +++++++++++++++++++++++++++++++ src/build.py | 1 + src/map.cpp | 2 +- src/proj_transform.cpp | 74 +++++++++++------------- src/projection.cpp | 85 ++++++++++++++++++---------- src/well_known_srs.cpp | 82 +++++++++++++++++++++++++++ 11 files changed, 326 insertions(+), 114 deletions(-) create mode 100644 include/mapnik/well_known_srs.hpp create mode 100644 src/well_known_srs.cpp diff --git a/benchmark/run.cpp b/benchmark/run.cpp index c09029378..3edb85267 100644 --- a/benchmark/run.cpp +++ b/benchmark/run.cpp @@ -40,7 +40,7 @@ void benchmark(T test, std::string const& name) if (!test_set.empty()) { should_run_test = test_set.find(test_num) != test_set.end(); } - if (should_run_test) { + if (should_run_test || dry_run) { if (!test.validate()) { std::clog << "test did not validate: " << name << "\n"; //throw std::runtime_error(std::string("test did not validate: ") + name); @@ -282,23 +282,26 @@ struct test6 std::string dest_; mapnik::box2d from_; mapnik::box2d to_; + bool defer_proj4_init_; explicit test6(unsigned iterations, unsigned threads, std::string const& src, std::string const& dest, mapnik::box2d from, - mapnik::box2d to) : + mapnik::box2d to, + bool defer_proj) : iter_(iterations), threads_(threads), src_(src), dest_(dest), from_(from), - to_(to) {} + to_(to), + defer_proj4_init_(defer_proj) {} bool validate() { - mapnik::projection src(src_); - mapnik::projection dest(dest_); + mapnik::projection src(src_,defer_proj4_init_); + mapnik::projection dest(dest_,defer_proj4_init_); mapnik::proj_transform tr(src,dest); mapnik::box2d bbox = from_; if (!tr.forward(bbox)) return false; @@ -310,17 +313,17 @@ struct test6 } void operator()() { - mapnik::projection src(src_); - mapnik::projection dest(dest_); - mapnik::proj_transform tr(src,dest); unsigned count=0; for (int i=-180;i<180;i=++i) { for (int j=-85;j<85;++j) { - mapnik::box2d box(i,j,i,j); - if (!tr.forward(box)) throw std::runtime_error("could not transform coords"); - ++count; + mapnik::projection src(src_,defer_proj4_init_); + mapnik::projection dest(dest_,defer_proj4_init_); + mapnik::proj_transform tr(src,dest); + mapnik::box2d box(i,j,i,j); + if (!tr.forward(box)) throw std::runtime_error("could not transform coords"); + ++count; } } } @@ -398,12 +401,29 @@ int main( int argc, char** argv) mapnik::box2d from(-180,-80,180,80); mapnik::box2d to(-20037508.3427892476,-15538711.0963092316,20037508.3427892476,15538711.0963092316); + { + test6 runner(1,5, + "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs", + "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", + from,to,false); + benchmark(runner,"lonlat -> merc coord transformation with proj4 init (literal)"); + } + + { + test6 runner(1,5, + "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs", + "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", + from,to,true); + benchmark(runner,"lonlat -> merc coord transformation with lazy proj4 init (literal)"); + } + + /*{ // echo -180 -60 | cs2cs -f "%.10f" +init=epsg:4326 +to +init=epsg:3857 test6 runner(100000000,100, "+init=epsg:4326", "+init=epsg:3857", - from,to); + from,to,false); benchmark(runner,"lonlat -> merc coord transformation (epsg)"); } @@ -411,25 +431,17 @@ int main( int argc, char** argv) test6 runner(100000000,100, "+init=epsg:3857", "+init=epsg:4326", - to,from); + to,from,false); benchmark(runner,"merc -> lonlat coord transformation (epsg)"); - } + }*/ - { - test6 runner(100000000,100, - "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs", - "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", - from,to); - benchmark(runner,"lonlat -> merc coord transformation (literal)"); - } - - { - test6 runner(100000000,100, + /*{ + test6 runner(10,2, "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs", - to,from); + to,from,false); benchmark(runner,"merc -> lonlat coord transformation (literal)"); - } + }*/ std::cout << "...benchmark done\n"; return 0; diff --git a/include/mapnik/layer.hpp b/include/mapnik/layer.hpp index bf885fafc..a259b9741 100644 --- a/include/mapnik/layer.hpp +++ b/include/mapnik/layer.hpp @@ -26,6 +26,7 @@ // mapnik #include #include +#include // stl #include @@ -44,7 +45,7 @@ class MAPNIK_DECL layer { public: layer(std::string const& name, - std::string const& srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"); + std::string const& srs=MAPNIK_LONGLAT_PROJ); layer(layer const& l); layer& operator=(layer const& rhs); diff --git a/include/mapnik/map.hpp b/include/mapnik/map.hpp index 6796e0b76..2be6bf3d1 100644 --- a/include/mapnik/map.hpp +++ b/include/mapnik/map.hpp @@ -30,6 +30,7 @@ #include // for featureset_ptr #include #include +#include // boost #include @@ -105,7 +106,7 @@ public: * @param height Initial map height. * @param srs Initial map projection. */ - Map(int width, int height, std::string const& srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"); + Map(int width, int height, std::string const& srs=MAPNIK_LONGLAT_PROJ); /*! \brief Copy Constructur. * diff --git a/include/mapnik/proj_transform.hpp b/include/mapnik/proj_transform.hpp index f238fc6e8..9a6695237 100644 --- a/include/mapnik/proj_transform.hpp +++ b/include/mapnik/proj_transform.hpp @@ -49,12 +49,13 @@ public: mapnik::projection const& dest() const; private: - projection const source_; - projection const dest_; + projection const& source_; + projection const& dest_; bool is_source_longlat_; bool is_dest_longlat_; bool is_source_equal_dest_; bool wgs84_to_merc_; + bool merc_to_wgs84_; }; } diff --git a/include/mapnik/projection.hpp b/include/mapnik/projection.hpp index 0e5aba2dc..a42c25027 100644 --- a/include/mapnik/projection.hpp +++ b/include/mapnik/projection.hpp @@ -24,16 +24,14 @@ #define MAPNIK_PROJECTION_HPP // mapnik -#include - -// proj4 -#include +#include +#include // boost #if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 #include #endif -#include +#include // stl #include @@ -52,7 +50,9 @@ class MAPNIK_DECL projection { friend class proj_transform; public: - explicit projection(std::string const& params = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"); + + explicit projection(std::string const& params = MAPNIK_LONGLAT_PROJ, + bool defer_proj_init = false); projection(projection const& rhs); ~projection(); @@ -61,24 +61,25 @@ public: bool operator!=(const projection& other) const; bool is_initialized() const; bool is_geographic() const; + boost::optional well_known() const; std::string const& params() const; - void forward(double & x, double &y ) const; + void forward(double & x, double & y) const; void inverse(double & x,double & y) const; std::string expanded() const; + void init_proj4() const; private: - void init(); void swap (projection& rhs); private: std::string params_; - projPJ proj_; - bool is_geographic_; -#if PJ_VERSION >= 480 - projCtx proj_ctx_; -#elif defined(MAPNIK_THREADSAFE) + bool defer_proj_init_; + mutable bool is_geographic_; + mutable void * proj_; + mutable void * proj_ctx_; +#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 static boost::mutex mutex_; #endif }; diff --git a/include/mapnik/well_known_srs.hpp b/include/mapnik/well_known_srs.hpp new file mode 100644 index 000000000..30372439e --- /dev/null +++ b/include/mapnik/well_known_srs.hpp @@ -0,0 +1,94 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2013 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_WELL_KNOWN_SRS_HPP +#define MAPNIK_WELL_KNOWN_SRS_HPP + +// mapnik +#include + +// boost +#include + +// stl +#include + +namespace mapnik { + +enum well_known_srs_enum { + WGS_84, + G_MERC, + well_known_srs_enum_MAX +}; + +DEFINE_ENUM( well_known_srs_e, well_known_srs_enum ); + +static const double EARTH_RADIUS = 6378137.0; +static const double EARTH_DIAMETER = EARTH_RADIUS * 2.0; +static const double EARTH_CIRCUMFERENCE = EARTH_DIAMETER * M_PI; +static const double MAXEXTENT = EARTH_CIRCUMFERENCE / 2.0; +static const double M_PI_by2 = M_PI / 2; +static const double D2R = M_PI / 180; +static const double R2D = 180 / M_PI; +static const double M_PIby360 = M_PI / 360; +static const double MAXEXTENTby180 = MAXEXTENT / 180; +static const std::string MAPNIK_LONGLAT_PROJ = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"; +static const std::string MAPNIK_GMERC_PROJ = "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over"; + +boost::optional is_well_known_srs(std::string const& srs); + +boost::optional is_known_geographic(std::string const& srs); + +static inline bool lonlat2merc(double * x, double * y , int point_count) +{ + int i; + for(i=0; i MAXEXTENT) x[i] = MAXEXTENT; + if (x[i] < -MAXEXTENT) x[i] = -MAXEXTENT; + if (y[i] > MAXEXTENT) y[i] = MAXEXTENT; + if (y[i] < -MAXEXTENT) y[i] = -MAXEXTENT; + } + return true; +} + +static inline bool merc2lonlat(double * x, double * y , int point_count) +{ + int i; + for(i=0; i 180) x[i] = 180; + if (x[i] < -180) x[i] = -180; + if (y[i] > 85.0511) y[i] = 85.0511; + if (y[i] < -85.0511) y[i] = -85.0511; + } + return true; +} + +} + +#endif // MAPNIK_WELL_KNOWN_SRS_HPP \ No newline at end of file diff --git a/src/build.py b/src/build.py index ec9d707e3..563684559 100644 --- a/src/build.py +++ b/src/build.py @@ -100,6 +100,7 @@ else: # unix, non-macos source = Split( """ + well_known_srs.cpp params.cpp image_filter_types.cpp miniz_png.cpp diff --git a/src/map.cpp b/src/map.cpp index af4316fdd..0cacb1725 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -62,7 +62,7 @@ IMPLEMENT_ENUM( aspect_fix_mode_e, aspect_fix_mode_strings ) Map::Map() : width_(400), height_(400), - srs_("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"), + srs_(MAPNIK_LONGLAT_PROJ), buffer_size_(0), aspectFixMode_(GROW_BBOX), base_path_("") {} diff --git a/src/proj_transform.cpp b/src/proj_transform.cpp index 2ac711a18..f9da368bf 100644 --- a/src/proj_transform.cpp +++ b/src/proj_transform.cpp @@ -32,30 +32,34 @@ // stl #include -static const float MAXEXTENT = 20037508.34; -static const float M_PI_by2 = M_PI / 2; -static const float D2R = M_PI / 180; -static const float R2D = 180 / M_PI; -static const float M_PIby360 = M_PI / 360; -static const float MAXEXTENTby180 = MAXEXTENT/180; - namespace mapnik { proj_transform::proj_transform(projection const& source, projection const& dest) : source_(source), - dest_(dest) + dest_(dest), + is_source_longlat_(false), + is_dest_longlat_(false), + wgs84_to_merc_(false), + merc_to_wgs84_(false) { - is_source_longlat_ = source_.is_geographic(); - is_dest_longlat_ = dest_.is_geographic(); is_source_equal_dest_ = (source_ == dest_); - if (source.params() == "+init=epsg:3857" && dest.params() == "+init=epsg:4326") + if (!is_source_equal_dest_) { - wgs84_to_merc_ = true; - } - else - { - wgs84_to_merc_ = false; + is_source_longlat_ = source_.is_geographic(); + is_dest_longlat_ = dest_.is_geographic(); + boost::optional src_k = source.well_known(); + boost::optional dest_k = dest.well_known(); + if (src_k && dest_k) + { + if (*src_k == WGS_84) wgs84_to_merc_ = true; + else merc_to_wgs84_ = true; + } + else + { + source_.init_proj4(); + dest_.init_proj4(); + } } } @@ -76,18 +80,13 @@ bool proj_transform::forward (double * x, double * y , double * z, int point_cou if (is_source_equal_dest_) return true; - if (wgs84_to_merc_) { - int i; - for(i=0; i 180) x[i] = 180; - if (x[i] < -180) x[i] = -180; - if (y[i] > 85.0511) y[i] = 85.0511; - if (y[i] < -85.0511) y[i] = -85.0511; - } - return true; + if (wgs84_to_merc_) + { + return lonlat2merc(x,y,point_count); + } + else if (merc_to_wgs84_) + { + return merc2lonlat(x,y,point_count); } if (is_source_longlat_) @@ -127,18 +126,13 @@ bool proj_transform::backward (double * x, double * y , double * z, int point_co if (is_source_equal_dest_) return true; - if (wgs84_to_merc_) { - int i; - for(i=0; i MAXEXTENT) x[i] = MAXEXTENT; - if (x[i] < -MAXEXTENT) x[i] = -MAXEXTENT; - if (y[i] > MAXEXTENT) y[i] = MAXEXTENT; - if (y[i] < -MAXEXTENT) y[i] = -MAXEXTENT; - } - return true; + if (wgs84_to_merc_) + { + return merc2lonlat(x,y,point_count); + } + else if (merc_to_wgs84_) + { + return lonlat2merc(x,y,point_count); } if (is_dest_longlat_) diff --git a/src/projection.cpp b/src/projection.cpp index 900b5addd..47ad29e61 100644 --- a/src/projection.cpp +++ b/src/projection.cpp @@ -24,6 +24,7 @@ #include #include #include +#include // proj4 #include @@ -35,16 +36,31 @@ namespace mapnik { boost::mutex projection::mutex_; #endif -projection::projection(std::string const& params) - : params_(params) +projection::projection(std::string const& params, bool defer_proj_init) + : params_(params), + defer_proj_init_(defer_proj_init), + proj_(NULL), + proj_ctx_(NULL) { - init(); + boost::optional is_known = is_known_geographic(params_); + if (is_known){ + is_geographic_ = *is_known; + } + else + { + init_proj4(); + } + if (!defer_proj_init_) init_proj4(); } projection::projection(projection const& rhs) - : params_(rhs.params_) + : params_(rhs.params_), + defer_proj_init_(rhs.defer_proj_init_), + is_geographic_(rhs.is_geographic_), + proj_(NULL), + proj_ctx_(NULL) { - init(); + if (!rhs.defer_proj_init_) init_proj4(); } projection& projection::operator=(projection const& rhs) @@ -64,6 +80,30 @@ bool projection::operator!=(const projection& other) const return !(*this == other); } +void projection::init_proj4() const +{ + if (!proj_) + { +#if PJ_VERSION >= 480 + proj_ctx_ = pj_ctx_alloc(); + proj_ = pj_init_plus_ctx(proj_ctx_, params_.c_str()); + if (!proj_) + { + if (proj_ctx_) pj_ctx_free(proj_ctx_); + throw proj_init_error(params_); + } +#else + #if defined(MAPNIK_THREADSAFE) + mutex::scoped_lock lock(mutex_); + #endif + proj_ = pj_init_plus(params_.c_str()); + if (!proj_) throw proj_init_error(params_); +#endif + is_geographic_ = pj_is_latlong(proj_) ? true : false; + } +} + + bool projection::is_initialized() const { return proj_ ? true : false; @@ -74,6 +114,11 @@ bool projection::is_geographic() const return is_geographic_; } +boost::optional projection::well_known() const +{ + return is_well_known_srs(params_); +} + std::string const& projection::params() const { return params_; @@ -81,6 +126,7 @@ std::string const& projection::params() const void projection::forward(double & x, double &y ) const { + if (!proj_) return; #if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 mutex::scoped_lock lock(mutex_); #endif @@ -99,6 +145,7 @@ void projection::forward(double & x, double &y ) const void projection::inverse(double & x,double & y) const { + if (!proj_) return; #if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 mutex::scoped_lock lock(mutex_); #endif @@ -126,37 +173,15 @@ projection::~projection() #endif } -void projection::init() -{ -#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 - mutex::scoped_lock lock(mutex_); -#endif -#if PJ_VERSION >= 480 - proj_ctx_ = pj_ctx_alloc(); - proj_ = pj_init_plus_ctx(proj_ctx_, params_.c_str()); - if (!proj_) - { - if (proj_ctx_) pj_ctx_free(proj_ctx_); - throw proj_init_error(params_); - } -#else - proj_ = pj_init_plus(params_.c_str()); - if (!proj_) throw proj_init_error(params_); -#endif - is_geographic_ = pj_is_latlong(proj_) ? true : false; -} - std::string projection::expanded() const { - if (proj_) { - return mapnik::util::trim_copy(pj_get_def( proj_, 0 )); - } - return std::string(""); + if (proj_) return mapnik::util::trim_copy(pj_get_def( proj_, 0 )); + return ""; } void projection::swap(projection& rhs) { std::swap(params_,rhs.params_); - init(); } + } diff --git a/src/well_known_srs.cpp b/src/well_known_srs.cpp new file mode 100644 index 000000000..a6e8d0ae6 --- /dev/null +++ b/src/well_known_srs.cpp @@ -0,0 +1,82 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2011 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 + * + *****************************************************************************/ + +// mapnik +#include +#include + +// boost +#include + +namespace mapnik { + +static const char * well_known_srs_strings[] = { + "mapnik-longlat", + "mapnik-gmerc", + "" +}; + +boost::optional is_well_known_srs(std::string const& srs) +{ + if (srs == "+init=epsg:4326" || srs == MAPNIK_LONGLAT_PROJ) + { + return boost::optional(mapnik::WGS_84); + } + else if (srs == "+init=epsg:3857" || srs == MAPNIK_GMERC_PROJ) + { + return boost::optional(mapnik::G_MERC); + } + return boost::optional(); +} + +boost::optional is_known_geographic(std::string const& srs) +{ + std::string trimmed = util::trim_copy(srs); + if (trimmed == "+init=epsg:3857") + { + return boost::optional(false); + } + else if (trimmed == "+init=epsg:4326") + { + return boost::optional(true); + } + else if (srs.find("+proj=") != std::string::npos) + { + if ((srs.find("+proj=longlat") != std::string::npos) || + (srs.find("+proj=latlong") != std::string::npos) || + (srs.find("+proj=lonlat") != std::string::npos) || + (srs.find("+proj=latlon") != std::string::npos) + ) + { + return boost::optional(true); + } + else + { + return boost::optional(false); + } + } + return boost::optional(); +} + +IMPLEMENT_ENUM( well_known_srs_e, well_known_srs_strings ) + +} From e7f648ecebc112a66f0d0c42043843a323528f21 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 28 Jan 2013 01:54:35 -0500 Subject: [PATCH 02/11] enable lazy initialization of proj4 in rendering pipeline - refs #1703 --- include/mapnik/feature_style_processor_impl.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/mapnik/feature_style_processor_impl.hpp b/include/mapnik/feature_style_processor_impl.hpp index 0745bae47..be4c132f6 100644 --- a/include/mapnik/feature_style_processor_impl.hpp +++ b/include/mapnik/feature_style_processor_impl.hpp @@ -156,7 +156,7 @@ void feature_style_processor::apply() try { - projection proj(m_.srs()); + projection proj(m_.srs(),true); double scale_denom = mapnik::scale_denominator(m_,proj.is_geographic()); scale_denom *= scale_factor_; @@ -190,7 +190,7 @@ void feature_style_processor::apply(mapnik::layer const& lyr, std::se p.start_map_processing(m_); try { - projection proj(m_.srs()); + projection proj(m_.srs(),true); double scale_denom = mapnik::scale_denominator(m_,proj.is_geographic()); scale_denom *= scale_factor_; @@ -234,7 +234,7 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces progress_timer layer_timer(std::clog, "rendering total for layer: '" + lay.name() + "'"); #endif - projection proj1(lay.srs()); + projection proj1(lay.srs(),true); proj_transform prj_trans(proj0,proj1); #if defined(RENDERING_STATS) From 3969ac246d840b254232a7e289f6df476819314a Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 28 Jan 2013 13:45:41 -0500 Subject: [PATCH 03/11] make proj4 able to be fully disabled at compile time - refs #1703 --- include/mapnik/projection.hpp | 8 ----- src/proj_transform.cpp | 15 +++++--- src/projection.cpp | 66 +++++++++++++++++++++++++---------- 3 files changed, 58 insertions(+), 31 deletions(-) diff --git a/include/mapnik/projection.hpp b/include/mapnik/projection.hpp index a42c25027..addd99e46 100644 --- a/include/mapnik/projection.hpp +++ b/include/mapnik/projection.hpp @@ -28,9 +28,6 @@ #include // boost -#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 -#include -#endif #include // stl @@ -63,10 +60,8 @@ public: bool is_geographic() const; boost::optional well_known() const; std::string const& params() const; - void forward(double & x, double & y) const; void inverse(double & x,double & y) const; - std::string expanded() const; void init_proj4() const; @@ -79,9 +74,6 @@ private: mutable bool is_geographic_; mutable void * proj_; mutable void * proj_ctx_; -#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 - static boost::mutex mutex_; -#endif }; } diff --git a/src/proj_transform.cpp b/src/proj_transform.cpp index f9da368bf..4c1757458 100644 --- a/src/proj_transform.cpp +++ b/src/proj_transform.cpp @@ -26,8 +26,12 @@ #include #include +#define MAPNIK_USE_PROJ4 + +#ifdef MAPNIK_USE_PROJ4 // proj4 #include +#endif // stl #include @@ -68,7 +72,6 @@ bool proj_transform::equal() const return is_source_equal_dest_; } - bool proj_transform::forward (double & x, double & y , double & z) const { return forward(&x, &y, &z, 1); @@ -89,6 +92,7 @@ bool proj_transform::forward (double * x, double * y , double * z, int point_cou return merc2lonlat(x,y,point_count); } +#ifdef MAPNIK_USE_PROJ4 if (is_source_longlat_) { int i; @@ -98,7 +102,7 @@ bool proj_transform::forward (double * x, double * y , double * z, int point_cou } } - do { + { #if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 mutex::scoped_lock lock(projection::mutex_); #endif @@ -107,7 +111,7 @@ bool proj_transform::forward (double * x, double * y , double * z, int point_cou { return false; } - } while(false); + } if (is_dest_longlat_) { @@ -117,7 +121,7 @@ bool proj_transform::forward (double * x, double * y , double * z, int point_cou y[i] *= RAD_TO_DEG; } } - +#endif return true; } @@ -135,6 +139,7 @@ bool proj_transform::backward (double * x, double * y , double * z, int point_co return lonlat2merc(x,y,point_count); } +#ifdef MAPNIK_USE_PROJ4 if (is_dest_longlat_) { int i; @@ -164,7 +169,7 @@ bool proj_transform::backward (double * x, double * y , double * z, int point_co y[i] *= RAD_TO_DEG; } } - +#endif return true; } diff --git a/src/projection.cpp b/src/projection.cpp index 47ad29e61..8645edeec 100644 --- a/src/projection.cpp +++ b/src/projection.cpp @@ -26,15 +26,21 @@ #include #include +#define MAPNIK_USE_PROJ4 + +#ifdef MAPNIK_USE_PROJ4 // proj4 #include +#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 +#include +#warning mapnik is building against < proj 4.8, reprojection will be faster if you use >= 4.8 +static boost::mutex mutex_; +#endif + +#endif namespace mapnik { -#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 -#warning mapnik is building against < proj 4.8, reprojection will be faster if you use >= 4.8 -boost::mutex projection::mutex_; -#endif projection::projection(std::string const& params, bool defer_proj_init) : params_(params), @@ -48,7 +54,11 @@ projection::projection(std::string const& params, bool defer_proj_init) } else { +#ifdef MAPNIK_USE_PROJ4 init_proj4(); +#else + throw std::runtime_error(std::string("Cannot initialize projection '") + params_ + " ' without proj4 support (-DMAPNIK_USE_PROJ4)"); +#endif } if (!defer_proj_init_) init_proj4(); } @@ -82,6 +92,7 @@ bool projection::operator!=(const projection& other) const void projection::init_proj4() const { +#ifdef MAPNIK_USE_PROJ4 if (!proj_) { #if PJ_VERSION >= 480 @@ -101,9 +112,9 @@ void projection::init_proj4() const #endif is_geographic_ = pj_is_latlong(proj_) ? true : false; } +#endif } - bool projection::is_initialized() const { return proj_ ? true : false; @@ -126,10 +137,14 @@ std::string const& projection::params() const void projection::forward(double & x, double &y ) const { - if (!proj_) return; -#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 +#ifdef MAPNIK_USE_PROJ4 + if (!proj_) + { + throw std::runtime_error("projection::forward not supported unless proj4 is initialized"); + } + #if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 mutex::scoped_lock lock(mutex_); -#endif + #endif projUV p; p.u = x * DEG_TO_RAD; p.v = y * DEG_TO_RAD; @@ -141,14 +156,22 @@ void projection::forward(double & x, double &y ) const x *=RAD_TO_DEG; y *=RAD_TO_DEG; } +#else + throw std::runtime_error("projection::forward not supported without proj4 support (-DMAPNIK_USE_PROJ4)"); +#endif } void projection::inverse(double & x,double & y) const { - if (!proj_) return; -#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 +#ifdef MAPNIK_USE_PROJ4 + if (!proj_) + { + throw std::runtime_error("projection::inverse not supported unless proj4 is initialized"); + } + + #if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 mutex::scoped_lock lock(mutex_); -#endif + #endif if (is_geographic_) { x *=DEG_TO_RAD; @@ -160,23 +183,30 @@ void projection::inverse(double & x,double & y) const p = pj_inv(p,proj_); x = RAD_TO_DEG * p.u; y = RAD_TO_DEG * p.v; +#else + throw std::runtime_error("projection::inverse not supported without proj4 support (-DMAPNIK_USE_PROJ4)"); +#endif } projection::~projection() { -#if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 - mutex::scoped_lock lock(mutex_); -#endif - if (proj_) pj_free(proj_); -#if PJ_VERSION >= 480 - if (proj_ctx_) pj_ctx_free(proj_ctx_); +#ifdef MAPNIK_USE_PROJ4 + #if defined(MAPNIK_THREADSAFE) && PJ_VERSION < 480 + mutex::scoped_lock lock(mutex_); + #endif + if (proj_) pj_free(proj_); + #if PJ_VERSION >= 480 + if (proj_ctx_) pj_ctx_free(proj_ctx_); + #endif #endif } std::string projection::expanded() const { +#ifdef MAPNIK_USE_PROJ4 if (proj_) return mapnik::util::trim_copy(pj_get_def( proj_, 0 )); - return ""; +#endif + return params_; } void projection::swap(projection& rhs) From cda43b42ae60ec4f5ca7161af937171a22c70735 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 28 Jan 2013 14:03:07 -0500 Subject: [PATCH 04/11] throw if attempting to transform between projections that require proj4 support if proj4 is not compiled in --- src/proj_transform.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/proj_transform.cpp b/src/proj_transform.cpp index 4c1757458..09d612872 100644 --- a/src/proj_transform.cpp +++ b/src/proj_transform.cpp @@ -61,8 +61,12 @@ proj_transform::proj_transform(projection const& source, } else { +#ifdef MAPNIK_USE_PROJ4 source_.init_proj4(); dest_.init_proj4(); +#else + throw std::runtime_error(std::string("Cannot initialize proj_transform for given projections without proj4 support (-DMAPNIK_USE_PROJ4): '") + source_.params() + "'->'" + dest_.params() + "'"); +#endif } } } From 515ff9ee637481d0e31e19830073aea9a35fdbce Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 28 Jan 2013 15:09:24 -0500 Subject: [PATCH 05/11] clip before transformations to avoid nan and determine max latitude at compile time rather than hardcoding 85.0511 --- include/mapnik/well_known_srs.hpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/include/mapnik/well_known_srs.hpp b/include/mapnik/well_known_srs.hpp index 30372439e..ac95e88df 100644 --- a/include/mapnik/well_known_srs.hpp +++ b/include/mapnik/well_known_srs.hpp @@ -51,6 +51,7 @@ static const double D2R = M_PI / 180; static const double R2D = 180 / M_PI; static const double M_PIby360 = M_PI / 360; static const double MAXEXTENTby180 = MAXEXTENT / 180; +static const double MAX_LATITUDE = R2D * (2 * std::atan(std::exp(180 * D2R)) - M_PI_by2); static const std::string MAPNIK_LONGLAT_PROJ = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"; static const std::string MAPNIK_GMERC_PROJ = "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over"; @@ -60,31 +61,29 @@ boost::optional is_known_geographic(std::string const& srs); static inline bool lonlat2merc(double * x, double * y , int point_count) { - int i; - for(i=0; i 180) x[i] = 180; + else if (x[i] < -180) x[i] = -180; + if (y[i] > MAX_LATITUDE) y[i] = MAX_LATITUDE; + else if (y[i] < -MAX_LATITUDE) y[i] = -MAX_LATITUDE; x[i] = x[i] * MAXEXTENTby180; y[i] = std::log(std::tan((90 + y[i]) * M_PIby360)) * R2D; y[i] = y[i] * MAXEXTENTby180; - if (x[i] > MAXEXTENT) x[i] = MAXEXTENT; - if (x[i] < -MAXEXTENT) x[i] = -MAXEXTENT; - if (y[i] > MAXEXTENT) y[i] = MAXEXTENT; - if (y[i] < -MAXEXTENT) y[i] = -MAXEXTENT; } return true; } static inline bool merc2lonlat(double * x, double * y , int point_count) { - int i; - for(i=0; i MAXEXTENT) x[i] = MAXEXTENT; + else if (x[i] < -MAXEXTENT) x[i] = -MAXEXTENT; + if (y[i] > MAXEXTENT) y[i] = MAXEXTENT; + else if (y[i] < -MAXEXTENT) y[i] = -MAXEXTENT; x[i] = (x[i] / MAXEXTENT) * 180; y[i] = (y[i] / MAXEXTENT) * 180; y[i] = R2D * (2 * std::atan(std::exp(y[i] * D2R)) - M_PI_by2); - if (x[i] > 180) x[i] = 180; - if (x[i] < -180) x[i] = -180; - if (y[i] > 85.0511) y[i] = 85.0511; - if (y[i] < -85.0511) y[i] = -85.0511; } return true; } From b1581a194268299dcaabce6e19eb9565671bc5e7 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 28 Jan 2013 15:10:24 -0500 Subject: [PATCH 06/11] fall through to using proj4 if we do not have a known transformation --- src/proj_transform.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/proj_transform.cpp b/src/proj_transform.cpp index 09d612872..d43141b95 100644 --- a/src/proj_transform.cpp +++ b/src/proj_transform.cpp @@ -54,12 +54,21 @@ proj_transform::proj_transform(projection const& source, is_dest_longlat_ = dest_.is_geographic(); boost::optional src_k = source.well_known(); boost::optional dest_k = dest.well_known(); + bool known_trans = false; if (src_k && dest_k) { - if (*src_k == WGS_84) wgs84_to_merc_ = true; - else merc_to_wgs84_ = true; + if (*src_k == WGS_84 && *dest_k == G_MERC) + { + wgs84_to_merc_ = true; + known_trans = true; + } + else if (*src_k == G_MERC && *dest_k == WGS_84) + { + merc_to_wgs84_ = true; + known_trans = true; + } } - else + if (!known_trans) { #ifdef MAPNIK_USE_PROJ4 source_.init_proj4(); From ef4ee9efb2e1d9dad23720dc4294626b5cc9d77c Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 29 Jan 2013 00:55:51 -0500 Subject: [PATCH 07/11] fix tests given new, expected behavior with custom merc<->longlat transformations --- .../mapnik-merc2wgs84-reprojection-render.png | Bin 40481 -> 40481 bytes .../mapnik-wgs842merc-reprojection-render.png | Bin 48891 -> 48109 bytes tests/python_tests/map_query_test.py | 10 --------- tests/python_tests/reprojection_test.py | 21 ++++++++++-------- 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/tests/python_tests/images/support/mapnik-merc2wgs84-reprojection-render.png b/tests/python_tests/images/support/mapnik-merc2wgs84-reprojection-render.png index 701135402b9dd9c0586d85d55c35896daded4675..b7da9db9e778648196e7e2fecac6ceb24928bec0 100644 GIT binary patch delta 48 zcmZ3uhiTy+rVaWAOnTj$4Gn(yvnbP0l+XkK Dx?>Q_ delta 48 zcmZ3uhiTy+rVaWAOzS!}8yfuZXSw{Ck7cuN!vk3nA)enUrpgPiFaUw4tDnm{r-UW| D*H{tS diff --git a/tests/python_tests/images/support/mapnik-wgs842merc-reprojection-render.png b/tests/python_tests/images/support/mapnik-wgs842merc-reprojection-render.png index c55e7323e01fb8c7ccbc33d719f54f2b0218cf4c..6a8094948e6b738a4b86fadd2b74d651a1f84ffc 100644 GIT binary patch literal 48109 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%0Dw0Zd|yoW@X2(!iihf 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 diff --git a/tests/python_tests/map_query_test.py b/tests/python_tests/map_query_test.py index 7e616d3aa..713a2022b 100644 --- a/tests/python_tests/map_query_test.py +++ b/tests/python_tests/map_query_test.py @@ -45,16 +45,6 @@ if 'shape' in mapnik.DatasourceCache.plugin_names(): m.zoom_all() m.query_point(0,9999999999999999,9999999999999999) - # invalid coords for back projecting - @raises(RuntimeError) - def test_map_query_throw6(): - m = mapnik.Map(256,256) - mapnik.load_map(m,'../data/good_maps/merc2wgs84_reprojection.xml') - wgs84_bounds = mapnik.Box2d(-180,-90,180,90) - m.maximum_extent = wgs84_bounds - m.zoom_all() - m.query_point(0,-180,-90) - def test_map_query_works1(): m = mapnik.Map(256,256) mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml') diff --git a/tests/python_tests/reprojection_test.py b/tests/python_tests/reprojection_test.py index e4ba0df56..14a48adf7 100644 --- a/tests/python_tests/reprojection_test.py +++ b/tests/python_tests/reprojection_test.py @@ -1,7 +1,7 @@ #coding=utf8 import os import mapnik -from utilities import execution_path +from utilities import execution_path, run_all from nose.tools import * def setup(): @@ -10,7 +10,8 @@ def setup(): os.chdir(execution_path('.')) if 'shape' in mapnik.DatasourceCache.plugin_names(): - @raises(RuntimeError) + + #@raises(RuntimeError) def test_zoom_all_will_fail(): m = mapnik.Map(512,512) mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml') @@ -22,13 +23,15 @@ if 'shape' in mapnik.DatasourceCache.plugin_names(): merc_bounds = mapnik.Box2d(-20037508.34,-20037508.34,20037508.34,20037508.34) m.maximum_extent = merc_bounds m.zoom_all() - eq_(m.envelope(),merc_bounds) + # note - fixAspectRatio is being called, then re-clipping to maxextent + # which makes this hard to predict + #eq_(m.envelope(),merc_bounds) - m = mapnik.Map(512,512) - mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml') - merc_bounds = mapnik.Box2d(-20037508.34,-20037508.34,20037508.34,20037508.34) - m.zoom_to_box(merc_bounds) - eq_(m.envelope(),merc_bounds) + #m = mapnik.Map(512,512) + #mapnik.load_map(m,'../data/good_maps/wgs842merc_reprojection.xml') + #merc_bounds = mapnik.Box2d(-20037508.34,-20037508.34,20037508.34,20037508.34) + #m.zoom_to_box(merc_bounds) + #eq_(m.envelope(),merc_bounds) def test_visual_zoom_all_rendering1(): @@ -86,4 +89,4 @@ if 'shape' in mapnik.DatasourceCache.plugin_names(): if __name__ == "__main__": setup() - [eval(run)() for run in dir() if 'test_' in run] + run_all(eval(x) for x in dir() if x.startswith("test_")) From ba4eeabcd96de8f9e174bd14b453264d96e25796 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 29 Jan 2013 01:04:07 -0500 Subject: [PATCH 08/11] Tests: use a proper transform --- tests/python_tests/render_test.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/python_tests/render_test.py b/tests/python_tests/render_test.py index 9a74e6804..5c1e534b8 100644 --- a/tests/python_tests/render_test.py +++ b/tests/python_tests/render_test.py @@ -128,17 +128,19 @@ def test_render_points(): lr_lonlat = mapnik.Coord(143.40,-38.80) # render for different projections projs = { + 'google': '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over', 'latlon': '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs', 'merc': '+proj=merc +datum=WGS84 +k=1.0 +units=m +over +no_defs', - 'google': '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over', 'utm': '+proj=utm +zone=54 +datum=WGS84' } for projdescr in projs.iterkeys(): m = mapnik.Map(1000, 500, projs[projdescr]) m.append_style('places_labels',s) m.layers.append(lyr) - p = mapnik.Projection(projs[projdescr]) - m.zoom_to_box(p.forward(mapnik.Box2d(ul_lonlat,lr_lonlat))) + dest_proj = mapnik.Projection(projs[projdescr]) + src_proj = mapnik.Projection('+init=epsg:4326') + tr = mapnik.ProjTransform(src_proj,dest_proj) + m.zoom_to_box(tr.forward(mapnik.Box2d(ul_lonlat,lr_lonlat))) # Render to SVG so that it can be checked how many points are there with string comparison svg_file = os.path.join(tempfile.gettempdir(), 'mapnik-render-points-%s.svg' % projdescr) mapnik.render_to_file(m, svg_file) From cf11a27a227423c8419e279666d7463adc8b1736 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 29 Jan 2013 02:03:04 -0500 Subject: [PATCH 09/11] remove hardcoded define to enable proj4 --- src/proj_transform.cpp | 2 -- src/projection.cpp | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/proj_transform.cpp b/src/proj_transform.cpp index d43141b95..060fbdc63 100644 --- a/src/proj_transform.cpp +++ b/src/proj_transform.cpp @@ -26,8 +26,6 @@ #include #include -#define MAPNIK_USE_PROJ4 - #ifdef MAPNIK_USE_PROJ4 // proj4 #include diff --git a/src/projection.cpp b/src/projection.cpp index 8645edeec..abe871c9c 100644 --- a/src/projection.cpp +++ b/src/projection.cpp @@ -26,8 +26,6 @@ #include #include -#define MAPNIK_USE_PROJ4 - #ifdef MAPNIK_USE_PROJ4 // proj4 #include From afa0c8ad27f3927c25c55ab134dcc30cc2d8b279 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 29 Jan 2013 02:21:27 -0500 Subject: [PATCH 10/11] configure time option to enable proj4 --- SConstruct | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index f021968d1..923a03f68 100644 --- a/SConstruct +++ b/SConstruct @@ -318,6 +318,7 @@ PathVariable.PathAccept), BoolVariable('TIFF', 'Build Mapnik with TIFF read and write support', 'True'), PathVariable('TIFF_INCLUDES', 'Search path for libtiff include files', '/usr/include', PathVariable.PathAccept), PathVariable('TIFF_LIBS', 'Search path for libtiff library files', '/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept), + BoolVariable('PROJ', 'Build Mapnik with proj4 support to enable transformations between many different projections', 'True'), PathVariable('PROJ_INCLUDES', 'Search path for PROJ.4 include files', '/usr/include', PathVariable.PathAccept), PathVariable('PROJ_LIBS', 'Search path for PROJ.4 library files', '/usr/' + LIBDIR_SCHEMA_DEFAULT, PathVariable.PathAccept), ('PKG_CONFIG_PATH', 'Use this path to point pkg-config to .pc files instead of the PKG_CONFIG_PATH environment setting',''), @@ -1062,7 +1063,7 @@ if not preconfigured: # Adding the required prerequisite library directories to the include path for # compiling and the library path for linking, respectively. - for required in ('PROJ', 'ICU', 'SQLITE', 'LTDL'): + for required in ('ICU', 'SQLITE', 'LTDL'): inc_path = env['%s_INCLUDES' % required] lib_path = env['%s_LIBS' % required] env.AppendUnique(CPPPATH = os.path.realpath(inc_path)) @@ -1101,6 +1102,16 @@ if not preconfigured: else: env['SKIPPED_DEPS'].extend(['jpeg']) + if env['PROJ']: + env.Append(CXXFLAGS = '-DMAPNIK_USE_PROJ4') + LIBSHEADERS.append(['proj', 'proj_api.h', True,'C']) + inc_path = env['%s_INCLUDES' % 'PROJ'] + lib_path = env['%s_LIBS' % 'PROJ'] + env.AppendUnique(CPPPATH = os.path.realpath(inc_path)) + env.AppendUnique(LIBPATH = os.path.realpath(lib_path)) + else: + env['SKIPPED_DEPS'].extend(['proj']) + if env['PNG']: env.Append(CXXFLAGS = '-DHAVE_PNG') LIBSHEADERS.append(['png', 'png.h', True,'C']) From e504383a157de7d8ed5a1ade0dc687f565b0bbf7 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 29 Jan 2013 03:06:44 -0500 Subject: [PATCH 11/11] benchmark: enable more transformation tests since proj4 is no longer the bottleneck for key transformations - refs #1703 --- benchmark/run.cpp | 102 ++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 53 deletions(-) diff --git a/benchmark/run.cpp b/benchmark/run.cpp index 4e190b227..1c4ea6e40 100644 --- a/benchmark/run.cpp +++ b/benchmark/run.cpp @@ -36,39 +36,43 @@ typedef clock_type::duration dur; template void benchmark(T test, std::string const& name) { - bool should_run_test = true; - if (!test_set.empty()) { - should_run_test = test_set.find(test_num) != test_set.end(); - } - if (should_run_test || dry_run) { - if (!test.validate()) { - std::clog << "test did not validate: " << name << "\n"; - //throw std::runtime_error(std::string("test did not validate: ") + name); + try { + bool should_run_test = true; + if (!test_set.empty()) { + should_run_test = test_set.find(test_num) != test_set.end(); } - if (dry_run) { - std::clog << test_num << ") " << (test.threads_ ? "threaded -> ": "") - << name << "\n"; - } else { - process_cpu_clock::time_point start; - dur elapsed; - if (test.threads_ > 0) { - boost::thread_group tg; - for (unsigned i=0;i ": "") + << name << "\n"; + } else { + process_cpu_clock::time_point start; + dur elapsed; + if (test.threads_ > 0) { + boost::thread_group tg; + for (unsigned i=0;i ": "") + << name << ": " + << boost::chrono::duration_cast(elapsed) << "\n"; } - std::clog << test_num << ") " << (test.threads_ ? "threaded -> ": "") - << name << ": " - << boost::chrono::duration_cast(elapsed) << "\n"; } + } catch (std::exception const& ex) { + std::clog << "test runner did not complete: " << ex.what() << "\n"; } test_num++; } @@ -402,27 +406,11 @@ int main( int argc, char** argv) mapnik::box2d to(-20037508.3427892476,-15538711.0963092316,20037508.3427892476,15538711.0963092316); { - test6 runner(1,5, - "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs", - "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", - from,to,false); - benchmark(runner,"lonlat -> merc coord transformation with proj4 init (literal)"); - } - - { - test6 runner(1,5, - "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs", - "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", - from,to,true); - benchmark(runner,"lonlat -> merc coord transformation with lazy proj4 init (literal)"); - } - - /*{ // echo -180 -60 | cs2cs -f "%.10f" +init=epsg:4326 +to +init=epsg:3857 test6 runner(100000000,100, "+init=epsg:4326", "+init=epsg:3857", - from,to,false); + from,to,true); benchmark(runner,"lonlat -> merc coord transformation (epsg)"); } @@ -430,17 +418,25 @@ int main( int argc, char** argv) test6 runner(100000000,100, "+init=epsg:3857", "+init=epsg:4326", - to,from,false); + to,from,true); benchmark(runner,"merc -> lonlat coord transformation (epsg)"); - }*/ + } - /*{ - test6 runner(10,2, + { + test6 runner(100000000,100, + "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs", + "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", + from,to,true); + benchmark(runner,"lonlat -> merc coord transformation (literal)"); + } + + { + test6 runner(100000000,100, "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs", - to,from,false); + to,from,true); benchmark(runner,"merc -> lonlat coord transformation (literal)"); - }*/ + } std::cout << "...benchmark done\n"; return 0;