From 763ece8db6c21b703bfd63b323ef959c37d847d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Thu, 13 Oct 2011 01:30:18 +0200 Subject: [PATCH 01/99] group-by attribute for Layer --- include/mapnik/feature_style_processor.hpp | 22 +- include/mapnik/feature_type_style.hpp | 27 +- include/mapnik/layer.hpp | 11 + include/mapnik/memory_datasource.hpp | 1 + src/feature_style_processor.cpp | 413 +++++++++++---------- src/feature_type_style.cpp | 64 +++- src/layer.cpp | 13 + src/load_map.cpp | 9 +- src/memory_datasource.cpp | 5 + src/save_map.cpp | 5 + 10 files changed, 366 insertions(+), 204 deletions(-) diff --git a/include/mapnik/feature_style_processor.hpp b/include/mapnik/feature_style_processor.hpp index 6c944d979..185b7075f 100644 --- a/include/mapnik/feature_style_processor.hpp +++ b/include/mapnik/feature_style_processor.hpp @@ -25,8 +25,16 @@ #ifndef FEATURE_STYLE_PROCESSOR_HPP #define FEATURE_STYLE_PROCESSOR_HPP +// mapnik +#include +#include +#include + + +// stl #include #include +#include namespace mapnik { @@ -64,11 +72,23 @@ private: /*! * @return render a layer given a projection and scale. */ - void apply_to_layer(layer const& lay, Processor & p, + void apply_to_layer(layer const& lay, + Processor & p, projection const& proj0, double scale_denom, std::set& names); + /*! + * @return renders a featureset with the given styles. + */ + void render_style(layer const& lay, + Processor & p, + feature_type_style* style, + std::string const& style_name, + featureset_ptr features, + proj_transform const& prj_trans, + double scale_denom); + Map const& m_; double scale_factor_; }; diff --git a/include/mapnik/feature_type_style.hpp b/include/mapnik/feature_type_style.hpp index d4a428778..9a73346b3 100644 --- a/include/mapnik/feature_type_style.hpp +++ b/include/mapnik/feature_type_style.hpp @@ -1,5 +1,5 @@ /***************************************************************************** - * + * * This file is part of Mapnik (c++ mapping toolkit) * * Copyright (C) 2006 Artem Pavlenko @@ -24,7 +24,7 @@ #ifndef FEATURE_TYPE_STYLE_HPP #define FEATURE_TYPE_STYLE_HPP -// mapnik +// mapnik #include #include #include @@ -43,29 +43,42 @@ enum filter_mode_enum { DEFINE_ENUM( filter_mode_e, filter_mode_enum ); typedef std::vector rules; +typedef std::vector rule_ptrs; class feature_type_style { private: rules rules_; filter_mode_e filter_mode_; + + // The rule_ptrs vectors are only valid for the scale_denom_validity_. + double scale_denom_validity_; + rule_ptrs if_rules_; + rule_ptrs else_rules_; + rule_ptrs also_rules_; public: feature_type_style(); feature_type_style(feature_type_style const& rhs); - + feature_type_style& operator=(feature_type_style const& rhs); - + void add_rule(rule const& rule); - + rules const& get_rules() const; + rule_ptrs const& get_if_rules(double scale_denom); + rule_ptrs const& get_else_rules(double scale_denom); + rule_ptrs const& get_also_rules(double scale_denom); rules &get_rules_nonconst(); - + void set_filter_mode(filter_mode_e mode); filter_mode_e get_filter_mode() const; - + ~feature_type_style() {} + +private: + void update_rule_cache(double scale_denom); }; } diff --git a/include/mapnik/layer.hpp b/include/mapnik/layer.hpp index d4d4c7ea4..7019f50d6 100644 --- a/include/mapnik/layer.hpp +++ b/include/mapnik/layer.hpp @@ -180,6 +180,16 @@ public: */ bool cache_features() const; + /*! + * @param group_by Set the field rendering of this layer is grouped by. + */ + void set_group_by(std::string column); + + /*! + * @return The field rendering of this layer is grouped by. + */ + std::string group_by() const; + /*! * @brief Attach a datasource for this layer. * @@ -212,6 +222,7 @@ private: bool queryable_; bool clear_label_cache_; bool cache_features_; + std::string group_by_; std::vector styles_; datasource_ptr ds_; }; diff --git a/include/mapnik/memory_datasource.hpp b/include/mapnik/memory_datasource.hpp index f344ff1d7..c7fb14a84 100644 --- a/include/mapnik/memory_datasource.hpp +++ b/include/mapnik/memory_datasource.hpp @@ -44,6 +44,7 @@ public: box2d envelope() const; layer_descriptor get_descriptor() const; size_t size() const; + void clear(); private: std::vector features_; mapnik::layer_descriptor desc_; diff --git a/src/feature_style_processor.cpp b/src/feature_style_processor.cpp index 01fba989b..53ce6ce6e 100644 --- a/src/feature_style_processor.cpp +++ b/src/feature_style_processor.cpp @@ -25,13 +25,10 @@ #include #include #include -#include #include #include #include -#include #include -#include #include #include @@ -308,65 +305,23 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces } } - // push all property names - BOOST_FOREACH(std::string const& name, names) + // Don't even try to do more work if there are no active styles. + if (active_styles.size() > 0) { - q.add_property_name(name); - } - - memory_datasource cache; - bool cache_features = lay.cache_features() && num_styles>1?true:false; - bool first = true; - - #if defined(RENDERING_STATS) - int style_index = 0; - if (!active_styles.size() > 0) { - layer_timer.discard(); - } - #endif - BOOST_FOREACH (feature_type_style * style, active_styles) - { - #if defined(RENDERING_STATS) - std::string s_name = style_names[style_index]; - std::ostringstream s1; - s1 << "rendering style #" << style_index+1 - << " for layer: '" << lay.name() << "' and style '" << s_name << "'"; - mapnik::progress_timer style_timer(std::clog, s1.str()); - if (!num_styles>1) - style_timer.discard(); - style_index++; - #endif - - std::vector if_rules; - std::vector else_rules; - std::vector also_rules; - - std::vector const& rules=style->get_rules(); - - #if defined(RENDERING_STATS) - int feature_count = 0; - int feature_processed_count = 0; - #endif - - BOOST_FOREACH(rule const& r, rules) + // push all property names + BOOST_FOREACH(std::string const& name, names) { - if (r.active(scale_denom)) - { - if (r.has_else_filter()) - { - else_rules.push_back(const_cast(&r)); - } - else if (r.has_also_filter()) - { - also_rules.push_back(const_cast(&r)); - } - else - { - if_rules.push_back(const_cast(&r)); - } + q.add_property_name(name); + } - if ( (ds->type() == datasource::Raster) && - (ds->params().get("filter_factor",0.0) == 0.0) ) + // Update filter_factor for all enabled raster layers. + BOOST_FOREACH (feature_type_style * style, active_styles) + { + BOOST_FOREACH(rule const& r, style->get_rules()) + { + if (r.active(scale_denom) && + ds->type() == datasource::Raster && + ds->params().get("filter_factor",0.0) == 0.0) { rule::symbolizers const& symbols = r.get_symbolizers(); rule::symbolizers::const_iterator symIter = symbols.begin(); @@ -382,163 +337,235 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces } } - // process features - featureset_ptr fs; - if (first) + // Also query the group by attribute + std::string group_by = lay.group_by(); + if (group_by != "") { - if (cache_features) - first = false; - fs = ds->features(q); - } - else - { - fs = cache.features(q); + q.add_property_name(group_by); } - if (fs) + bool cache_features = lay.cache_features() && active_styles.size() > 1; + + // Render incrementally when the column that we group by + // changes value. + if (group_by != "") { - feature_ptr feature; - while ((feature = fs->next())) - { + featureset_ptr features = ds->features(q); + if (features) { + // Cache all features into the memory_datasource before rendering. + memory_datasource cache; + feature_ptr feature, prev; - #if defined(RENDERING_STATS) - feature_count++; - bool feat_processed = false; - #endif + while ((feature = features->next())) + { + if (prev && prev->props()[group_by] != feature->props()[group_by]) + { + // We're at a value boundary, so render what we have + // up to this point. + int i = 0; + BOOST_FOREACH (feature_type_style * style, active_styles) + { + render_style(lay, p, style, style_names[i++], + cache.features(q), prj_trans, scale_denom); + } + cache.clear(); + } + cache.push(feature); + prev = feature; + } - bool do_else=true; - bool do_also=false; - - if (cache_features) + int i = 0; + BOOST_FOREACH (feature_type_style * style, active_styles) + { + render_style(lay, p, style, style_names[i++], + cache.features(q), prj_trans, scale_denom); + } + } + } + else if (cache_features) + { + featureset_ptr features = ds->features(q); + if (features) { + // Cache all features into the memory_datasource before rendering. + memory_datasource cache; + feature_ptr feature; + while ((feature = features->next())) { cache.push(feature); } - BOOST_FOREACH(rule * r, if_rules ) + int i = 0; + BOOST_FOREACH (feature_type_style * style, active_styles) { - expression_ptr const& expr=r->get_filter(); - value_type result = boost::apply_visitor(evaluate(*feature),*expr); - if (result.to_bool()) - { - #if defined(RENDERING_STATS) - feat_processed = true; - #endif - - p.painted(true); - - do_else=false; - do_also=true; - rule::symbolizers const& symbols = r->get_symbolizers(); - - // if the underlying renderer is not able to process the complete set of symbolizers, - // process one by one. -#if defined(SVG_RENDERER) - if(!p.process(symbols,*feature,prj_trans)) -#endif - { - - BOOST_FOREACH (symbolizer const& sym, symbols) - { - boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym); - } - } - if (style->get_filter_mode() == FILTER_FIRST) - { - // Stop iterating over rules and proceed with next feature. - break; - } - } + render_style(lay, p, style, style_names[i++], + cache.features(q), prj_trans, scale_denom); } - if (do_else) - { - BOOST_FOREACH( rule * r, else_rules ) - { - #if defined(RENDERING_STATS) - feat_processed = true; - #endif - - p.painted(true); - - rule::symbolizers const& symbols = r->get_symbolizers(); - // if the underlying renderer is not able to process the complete set of symbolizers, - // process one by one. -#if defined(SVG_RENDERER) - if(!p.process(symbols,*feature,prj_trans)) -#endif - { - BOOST_FOREACH (symbolizer const& sym, symbols) - { - boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym); - } - } - } - } - if (do_also) - { - BOOST_FOREACH( rule * r, also_rules ) - { - #if defined(RENDERING_STATS) - feat_processed = true; - #endif - - p.painted(true); - - rule::symbolizers const& symbols = r->get_symbolizers(); - // if the underlying renderer is not able to process the complete set of symbolizers, - // process one by one. -#if defined(SVG_RENDERER) - if(!p.process(symbols,*feature,prj_trans)) -#endif - { - BOOST_FOREACH (symbolizer const& sym, symbols) - { - boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym); - } - } - } - } - #if defined(RENDERING_STATS) - if (feat_processed) - feature_processed_count++; - #endif } - - #if defined(RENDERING_STATS) - style_timer.stop(); - - // done with style - std::ostringstream s; - if (feature_count > 0) { - double perc_processed = ((double)feature_processed_count/(double)feature_count)*100.0; - - s << "percent rendered: " << perc_processed << "% - " << feature_processed_count - << " rendered for " << feature_count << " queried for "; - s << std::setw(15 - (int)s.tellp()) << " layer '" << lay.name() << "' and style '" << s_name << "'\n"; - - } else { - s << "" << std::setw(15) << "- no features returned from query for layer '" << lay.name() << "' and style '" << s_name << "'\n"; + } + // We only have a single style and no grouping. + else + { + int i = 0; + BOOST_FOREACH (feature_type_style * style, active_styles) + { + featureset_ptr features = ds->features(q); + if (features) { + render_style(lay, p, style, style_names[i++], + features, prj_trans, scale_denom); + } } - std::clog << s.str(); - #endif - } - #if defined(RENDERING_STATS) - else { - style_timer.discard(); - layer_timer.discard(); - } - #endif - cache_features = false; } - + #if defined(RENDERING_STATS) layer_timer.stop(); #endif - p.end_layer_processing(lay); } + +template +void feature_style_processor::render_style( + layer const& lay, + Processor & p, + feature_type_style* style, + std::string const& style_name, + featureset_ptr features, + proj_transform const& prj_trans, + double scale_denom) +{ + #if defined(RENDERING_STATS) + std::ostringstream s1; + s1 << "rendering style for layer: '" << lay.name() + << "' and style '" << style_name << "'"; + mapnik::progress_timer style_timer(std::clog, s1.str()); + + int feature_processed_count = 0; + int feature_count = 0; + #endif + + feature_ptr feature; + while ((feature = features->next())) + { + #if defined(RENDERING_STATS) + feature_count++; + bool feat_processed = false; + #endif + + bool do_else = true; + bool do_also = false; + + BOOST_FOREACH(rule * r, style->get_if_rules(scale_denom) ) + { + expression_ptr const& expr=r->get_filter(); + value_type result = boost::apply_visitor(evaluate(*feature),*expr); + if (result.to_bool()) + { + #if defined(RENDERING_STATS) + feat_processed = true; + #endif + + p.painted(true); + + do_else=false; + do_also=true; + rule::symbolizers const& symbols = r->get_symbolizers(); + + // if the underlying renderer is not able to process the complete set of symbolizers, + // process one by one. +#if defined(SVG_RENDERER) + if(!p.process(symbols,*feature,prj_trans)) +#endif + { + + BOOST_FOREACH (symbolizer const& sym, symbols) + { + boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym); + } + } + if (style->get_filter_mode() == FILTER_FIRST) + { + // Stop iterating over rules and proceed with next feature. + break; + } + } + } + if (do_else) + { + BOOST_FOREACH( rule * r, style->get_else_rules(scale_denom) ) + { + #if defined(RENDERING_STATS) + feat_processed = true; + #endif + + p.painted(true); + + rule::symbolizers const& symbols = r->get_symbolizers(); + // if the underlying renderer is not able to process the complete set of symbolizers, + // process one by one. +#if defined(SVG_RENDERER) + if(!p.process(symbols,*feature,prj_trans)) +#endif + { + BOOST_FOREACH (symbolizer const& sym, symbols) + { + boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym); + } + } + } + } + if (do_also) + { + BOOST_FOREACH( rule * r, style->get_also_rules(scale_denom) ) + { + #if defined(RENDERING_STATS) + feat_processed = true; + #endif + + p.painted(true); + + rule::symbolizers const& symbols = r->get_symbolizers(); + // if the underlying renderer is not able to process the complete set of symbolizers, + // process one by one. +#if defined(SVG_RENDERER) + if(!p.process(symbols,*feature,prj_trans)) +#endif + { + BOOST_FOREACH (symbolizer const& sym, symbols) + { + boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym); + } + } + } + } + #if defined(RENDERING_STATS) + if (feat_processed) + feature_processed_count++; + #endif + } + + #if defined(RENDERING_STATS) + style_timer.stop(); + + // done with style + std::ostringstream s; + if (feature_count > 0) { + double perc_processed = ((double)feature_processed_count/(double)feature_count)*100.0; + + s << "percent rendered: " << perc_processed << "% - " << feature_processed_count + << " rendered for " << feature_count << " queried for "; + s << std::setw(15 - (int)s.tellp()) << " layer '" << lay.name() << "' and style '" << s_name << "'\n"; + + } else { + s << "" << std::setw(15) << "- no features returned from query for layer '" << lay.name() << "' and style '" << s_name << "'\n"; + } + std::clog << s.str(); + style_timer.discard(); + #endif +} + + #if defined(HAVE_CAIRO) template class feature_style_processor >; template class feature_style_processor >; diff --git a/src/feature_type_style.cpp b/src/feature_type_style.cpp index f9047f595..4c37ba12b 100644 --- a/src/feature_type_style.cpp +++ b/src/feature_type_style.cpp @@ -35,22 +35,26 @@ IMPLEMENT_ENUM( filter_mode_e, filter_mode_strings ) feature_type_style::feature_type_style() - : filter_mode_(FILTER_ALL) {} + : filter_mode_(FILTER_ALL), + scale_denom_validity_(-1) {} feature_type_style::feature_type_style(feature_type_style const& rhs) : rules_(rhs.rules_), - filter_mode_(rhs.filter_mode_) {} + filter_mode_(rhs.filter_mode_), + scale_denom_validity_(-1) {} feature_type_style& feature_type_style::operator=(feature_type_style const& rhs) { if (this == &rhs) return *this; rules_=rhs.rules_; + scale_denom_validity_ = -1; return *this; } void feature_type_style::add_rule(rule const& rule) { rules_.push_back(rule); + scale_denom_validity_ = -1; } rules const& feature_type_style::get_rules() const @@ -73,4 +77,60 @@ filter_mode_e feature_type_style::get_filter_mode() const return filter_mode_; } + +void feature_type_style::update_rule_cache(double scale_denom) +{ + if_rules_.clear(); + else_rules_.clear(); + also_rules_.clear(); + + BOOST_FOREACH(rule const& r, rules_) + { + if (r.active(scale_denom)) + { + if (r.has_else_filter()) + { + else_rules_.push_back(const_cast(&r)); + } + else if (r.has_also_filter()) + { + also_rules_.push_back(const_cast(&r)); + } + else + { + if_rules_.push_back(const_cast(&r)); + } + } + } + + scale_denom_validity_ = scale_denom; +} + +rule_ptrs const& feature_type_style::get_if_rules(double scale_denom) +{ + if (scale_denom_validity_ != scale_denom) + { + update_rule_cache(scale_denom); + } + return if_rules_; +} + +rule_ptrs const& feature_type_style::get_else_rules(double scale_denom) +{ + if (scale_denom_validity_ != scale_denom) + { + update_rule_cache(scale_denom); + } + return else_rules_; +} + +rule_ptrs const& feature_type_style::get_also_rules(double scale_denom) +{ + if (scale_denom_validity_ != scale_denom) + { + update_rule_cache(scale_denom); + } + return also_rules_; +} + } diff --git a/src/layer.cpp b/src/layer.cpp index ba40a85f6..f4c2a4d99 100644 --- a/src/layer.cpp +++ b/src/layer.cpp @@ -46,6 +46,7 @@ layer::layer(std::string const& name, std::string const& srs) queryable_(false), clear_label_cache_(false), cache_features_(false), + group_by_(""), ds_() {} layer::layer(const layer& rhs) @@ -59,6 +60,7 @@ layer::layer(const layer& rhs) queryable_(rhs.queryable_), clear_label_cache_(rhs.clear_label_cache_), cache_features_(rhs.cache_features_), + group_by_(rhs.group_by_), styles_(rhs.styles_), ds_(rhs.ds_) {} @@ -86,6 +88,7 @@ void layer::swap(const layer& rhs) queryable_=rhs.queryable_; clear_label_cache_ = rhs.clear_label_cache_; cache_features_ = rhs.cache_features_; + group_by_ = rhs.group_by_; styles_=rhs.styles_; ds_=rhs.ds_; } @@ -228,4 +231,14 @@ bool layer::cache_features() const return cache_features_; } +void layer::set_group_by(std::string column) +{ + group_by_ = column; +} + +std::string layer::group_by() const +{ + return group_by_; +} + } diff --git a/src/load_map.cpp b/src/load_map.cpp index d89110563..333516822 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -535,7 +535,8 @@ void map_parser::parse_layer( Map & map, ptree const & lay ) << "maxzoom," << "queryable," << "clear-label-cache," - << "cache-features"; + << "cache-features," + << "group-by"; ensure_attrs(lay, "Layer", s.str()); try { @@ -596,6 +597,12 @@ void map_parser::parse_layer( Map & map, ptree const & lay ) lyr.set_cache_features( * cache_features ); } + optional group_by = + get_opt_attr(lay, "group-by"); + if (group_by) + { + lyr.set_group_by( * group_by ); + } ptree::const_iterator itr2 = lay.begin(); ptree::const_iterator end2 = lay.end(); diff --git a/src/memory_datasource.cpp b/src/memory_datasource.cpp index d22bcbd8a..7a89e031f 100644 --- a/src/memory_datasource.cpp +++ b/src/memory_datasource.cpp @@ -107,6 +107,11 @@ size_t memory_datasource::size() const return features_.size(); } +void memory_datasource::clear() +{ + features_.clear(); +} + // point_datasource void point_datasource::add_point(double x, double y, const char* key, const char* value) diff --git a/src/save_map.cpp b/src/save_map.cpp index 0e885c9ce..5e99617d9 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -815,6 +815,11 @@ void serialize_layer( ptree & map_node, const layer & layer, bool explicit_defau set_attr/**/( layer_node, "cache-features", layer.cache_features() ); } + if ( layer.group_by() != "" || explicit_defaults ) + { + set_attr( layer_node, "group-by", layer.group_by() ); + } + std::vector const& style_names = layer.styles(); for (unsigned i = 0; i < style_names.size(); ++i) { From 7209988fb042330ee509a48203d3e2675105892e Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Tue, 6 Dec 2011 12:53:16 +0000 Subject: [PATCH 02/99] Simplify geometry model to support: Point/LineString/Polygon Multi geometries are collections of single geometries Remove multiple_geometries parameter --- bindings/python/mapnik_feature.cpp | 2 +- bindings/python/mapnik_geometry.cpp | 9 +- include/mapnik/geometry.hpp | 14 +- include/mapnik/util/geometry_to_wkb.hpp | 4 - include/mapnik/wkb.hpp | 9 +- plugins/input/geos/geos_datasource.cpp | 10 +- plugins/input/geos/geos_datasource.hpp | 1 - plugins/input/geos/geos_featureset.cpp | 10 +- plugins/input/geos/geos_featureset.hpp | 3 +- plugins/input/kismet/kismet_featureset.hpp | 1 - plugins/input/occi/occi_datasource.cpp | 5 +- plugins/input/occi/occi_datasource.hpp | 1 - plugins/input/occi/occi_featureset.cpp | 51 ++--- plugins/input/occi/occi_featureset.hpp | 7 +- plugins/input/postgis/postgis_datasource.cpp | 6 +- plugins/input/postgis/postgis_datasource.hpp | 1 - plugins/input/postgis/postgis_featureset.cpp | 4 +- plugins/input/postgis/postgis_featureset.hpp | 2 - plugins/input/sqlite/sqlite_datasource.cpp | 5 +- plugins/input/sqlite/sqlite_datasource.hpp | 6 +- plugins/input/sqlite/sqlite_featureset.cpp | 6 +- plugins/input/sqlite/sqlite_featureset.hpp | 2 - plugins/input/sqlite/sqlite_utils.hpp | 14 +- src/agg/process_text_symbolizer.cpp | 2 +- src/wkb.cpp | 222 +------------------ 25 files changed, 63 insertions(+), 334 deletions(-) diff --git a/bindings/python/mapnik_feature.cpp b/bindings/python/mapnik_feature.cpp index 57cdec88c..4bc392af4 100644 --- a/bindings/python/mapnik_feature.cpp +++ b/bindings/python/mapnik_feature.cpp @@ -45,7 +45,7 @@ using mapnik::from_wkt; void feature_add_geometries_from_wkb(Feature &feature, std::string wkb) { - geometry_utils::from_wkb(feature.paths(), wkb.c_str(), wkb.size(), true); + geometry_utils::from_wkb(feature.paths(), wkb.c_str(), wkb.size()); } void feature_add_geometries_from_wkt(Feature &feature, std::string wkt) diff --git a/bindings/python/mapnik_geometry.cpp b/bindings/python/mapnik_geometry.cpp index 30f2876df..ee827974d 100644 --- a/bindings/python/mapnik_geometry.cpp +++ b/bindings/python/mapnik_geometry.cpp @@ -56,7 +56,7 @@ void add_wkt_impl(path_type& p, std::string const& wkt) void add_wkb_impl(path_type& p, std::string const& wkb) { - mapnik::geometry_utils::from_wkb(p, wkb.c_str(), wkb.size(), true); + mapnik::geometry_utils::from_wkb(p, wkb.c_str(), wkb.size()); } boost::shared_ptr from_wkt_impl(std::string const& wkt) @@ -70,7 +70,7 @@ boost::shared_ptr from_wkt_impl(std::string const& wkt) boost::shared_ptr from_wkb_impl(std::string const& wkb) { boost::shared_ptr paths = boost::make_shared(); - mapnik::geometry_utils::from_wkb(*paths, wkb.c_str(), wkb.size(), true); + mapnik::geometry_utils::from_wkb(*paths, wkb.c_str(), wkb.size()); return paths; } @@ -97,11 +97,8 @@ void export_geometry() .value("Point",mapnik::Point) .value("LineString",mapnik::LineString) .value("Polygon",mapnik::Polygon) - .value("MultiPoint",mapnik::MultiPoint) - .value("MultiLineString",mapnik::MultiLineString) - .value("MultiPolygon",mapnik::MultiPolygon) ; - + using mapnik::geometry_type; class_, boost::noncopyable>("Geometry2d",no_init) .def("envelope",&geometry_type::envelope) diff --git a/include/mapnik/geometry.hpp b/include/mapnik/geometry.hpp index 965bc4ee8..b2583abe1 100644 --- a/include/mapnik/geometry.hpp +++ b/include/mapnik/geometry.hpp @@ -36,14 +36,10 @@ namespace mapnik { enum eGeomType { Point = 1, - LineString, - Polygon, - MultiPoint, - MultiLineString, - MultiPolygon + LineString = 2, + Polygon = 3 }; - template class Container=vertex_vector> class geometry { @@ -168,12 +164,12 @@ public: */ void label_position(double *x, double *y) const { - if (type_ == LineString || type_ == MultiLineString) + if (type_ == LineString) { middle_point(x,y); return; } - + unsigned size = cont_.size(); if (size < 3) { @@ -232,7 +228,7 @@ public: /* summarized distance centroid */ void label_position3(double *x, double *y) const { - if (type_ == LineString || type_ == MultiLineString) + if (type_ == LineString) { middle_point(x,y); return; diff --git a/include/mapnik/util/geometry_to_wkb.hpp b/include/mapnik/util/geometry_to_wkb.hpp index aa226ce96..ffcdf9ef7 100644 --- a/include/mapnik/util/geometry_to_wkb.hpp +++ b/include/mapnik/util/geometry_to_wkb.hpp @@ -219,10 +219,6 @@ wkb_buffer_ptr to_wkb(geometry_type const& g, wkbByteOrder byte_order ) case mapnik::Polygon: wkb = to_polygon_wkb(g, byte_order); break; - case mapnik::MultiPoint: - case mapnik::MultiLineString: - case mapnik::MultiPolygon: - break; default: break; } diff --git a/include/mapnik/wkb.hpp b/include/mapnik/wkb.hpp index 77c7c04c6..55df4d102 100644 --- a/include/mapnik/wkb.hpp +++ b/include/mapnik/wkb.hpp @@ -27,6 +27,8 @@ #include #include #include +// boost +#include namespace mapnik { @@ -49,19 +51,14 @@ enum wkbFormat wkbSpatiaLite=3 }; -class MAPNIK_DECL geometry_utils +class MAPNIK_DECL geometry_utils : private boost::noncopyable { public: static void from_wkb (boost::ptr_vector& paths, const char* wkb, unsigned size, - bool multiple_geometries = false, wkbFormat format = wkbGeneric); -private: - geometry_utils(); - geometry_utils(geometry_utils const&); - geometry_utils& operator=(const geometry_utils&); }; } diff --git a/plugins/input/geos/geos_datasource.cpp b/plugins/input/geos/geos_datasource.cpp index cfa4e1cf4..f09670a46 100644 --- a/plugins/input/geos/geos_datasource.cpp +++ b/plugins/input/geos/geos_datasource.cpp @@ -97,9 +97,7 @@ geos_datasource::geos_datasource(parameters const& params, bool bind) boost::optional geometry = params.get("wkt"); if (! geometry) throw datasource_exception("missing parameter"); geometry_string_ = *geometry; - - multiple_geometries_ = *params_.get("multiple_geometries",false); - + boost::optional ext = params_.get("extent"); if (ext) extent_initialized_ = extent_.from_string(*ext); @@ -270,8 +268,7 @@ featureset_ptr geos_datasource::features(query const& q) const geometry_id_, geometry_data_, geometry_data_name_, - desc_.get_encoding(), - multiple_geometries_); + desc_.get_encoding()); } featureset_ptr geos_datasource::features_at_point(coord2d const& pt) const @@ -290,6 +287,5 @@ featureset_ptr geos_datasource::features_at_point(coord2d const& pt) const geometry_id_, geometry_data_, geometry_data_name_, - desc_.get_encoding(), - multiple_geometries_); + desc_.get_encoding()); } diff --git a/plugins/input/geos/geos_datasource.hpp b/plugins/input/geos/geos_datasource.hpp index 3d2385776..79e846c41 100644 --- a/plugins/input/geos/geos_datasource.hpp +++ b/plugins/input/geos/geos_datasource.hpp @@ -56,7 +56,6 @@ private: mutable std::string geometry_data_name_; mutable int geometry_id_; std::string geometry_string_; - bool multiple_geometries_; }; #endif // GEOS_DATASOURCE_HPP diff --git a/plugins/input/geos/geos_featureset.cpp b/plugins/input/geos/geos_featureset.cpp index bbcbb832d..afd2d71af 100644 --- a/plugins/input/geos/geos_featureset.cpp +++ b/plugins/input/geos/geos_featureset.cpp @@ -53,15 +53,13 @@ geos_featureset::geos_featureset(GEOSGeometry* geometry, int identifier, const std::string& field, const std::string& field_name, - const std::string& encoding, - bool multiple_geometries) + const std::string& encoding) : geometry_(geometry), tr_(new transcoder(encoding)), extent_(extent), identifier_(identifier), field_(field), field_name_(field_name), - multiple_geometries_(multiple_geometries), already_rendered_(false) { } @@ -120,14 +118,12 @@ feature_ptr geos_featureset::next() geometry_utils::from_wkb(feature->paths(), wkb.data(), - wkb.size(), - multiple_geometries_); - + wkb.size()); if (field_ != "") { boost::put(*feature, field_name_, tr_->transcode(field_.c_str())); } - + return feature; } } diff --git a/plugins/input/geos/geos_featureset.hpp b/plugins/input/geos/geos_featureset.hpp index 2b777efaa..d68352329 100644 --- a/plugins/input/geos/geos_featureset.hpp +++ b/plugins/input/geos/geos_featureset.hpp @@ -44,8 +44,7 @@ public: int identifier, const std::string& field, const std::string& field_name, - const std::string& encoding, - bool multiple_geometries); + const std::string& encoding); virtual ~geos_featureset(); mapnik::feature_ptr next(); diff --git a/plugins/input/kismet/kismet_featureset.hpp b/plugins/input/kismet/kismet_featureset.hpp index 424d39fd0..363f3425a 100644 --- a/plugins/input/kismet/kismet_featureset.hpp +++ b/plugins/input/kismet/kismet_featureset.hpp @@ -50,7 +50,6 @@ private: const std::list& knd_list_; boost::scoped_ptr tr_; mapnik::wkbFormat format_; - bool multiple_geometries_; int feature_id_; std::list::const_iterator knd_list_it; mapnik::projection source_; diff --git a/plugins/input/occi/occi_datasource.cpp b/plugins/input/occi/occi_datasource.cpp index f1fd158ca..335146174 100644 --- a/plugins/input/occi/occi_datasource.cpp +++ b/plugins/input/occi/occi_datasource.cpp @@ -94,7 +94,6 @@ occi_datasource::occi_datasource(parameters const& params, bool bind) table_ = *table; } - multiple_geometries_ = *params_.get("multiple_geometries",false); use_spatial_index_ = *params_.get("use_spatial_index",true); use_connection_pool_ = *params_.get("use_connection_pool",true); @@ -559,8 +558,7 @@ featureset_ptr occi_datasource::features(query const& q) const return boost::make_shared(pool_, conn_, s.str(), - desc_.get_encoding(), - multiple_geometries_, + desc_.get_encoding(), use_connection_pool_, row_prefetch_, props.size()); @@ -642,7 +640,6 @@ featureset_ptr occi_datasource::features_at_point(coord2d const& pt) const conn_, s.str(), desc_.get_encoding(), - multiple_geometries_, use_connection_pool_, row_prefetch_, size); diff --git a/plugins/input/occi/occi_datasource.hpp b/plugins/input/occi/occi_datasource.hpp index 4e751eb60..72096ae9e 100644 --- a/plugins/input/occi/occi_datasource.hpp +++ b/plugins/input/occi/occi_datasource.hpp @@ -64,7 +64,6 @@ private: mutable oracle::occi::StatelessConnectionPool* pool_; mutable oracle::occi::Connection* conn_; bool use_connection_pool_; - bool multiple_geometries_; bool use_spatial_index_; static const std::string METADATA_TABLE; }; diff --git a/plugins/input/occi/occi_featureset.cpp b/plugins/input/occi/occi_featureset.cpp index 76e092bc2..b4ea397ad 100644 --- a/plugins/input/occi/occi_featureset.cpp +++ b/plugins/input/occi/occi_featureset.cpp @@ -59,12 +59,10 @@ occi_featureset::occi_featureset(StatelessConnectionPool* pool, Connection* conn, std::string const& sqlstring, std::string const& encoding, - bool multiple_geometries, bool use_connection_pool, unsigned prefetch_rows, unsigned num_attrs) : tr_(new transcoder(encoding)), - multiple_geometries_(multiple_geometries), num_attrs_(num_attrs), feature_id_(1) { @@ -101,7 +99,7 @@ feature_ptr occi_featureset::next() boost::scoped_ptr geom(dynamic_cast(rs_->getObject(1))); if (geom.get()) { - convert_geometry(geom.get(), feature, multiple_geometries_); + convert_geometry(geom.get(), feature); } std::vector listOfColumns = rs_->getColumnListMetaData(); @@ -204,7 +202,7 @@ feature_ptr occi_featureset::next() } -void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature, bool multiple_geometries) +void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature) { int gtype = (int)geom->getSdo_gtype(); int dimensions = gtype / 1000; @@ -248,16 +246,13 @@ void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature, b { const bool is_single_geom = true; const bool is_point_type = false; - const bool multiple_geoms = false; - convert_ordinates(feature, mapnik::LineString, elem_info, ordinates, dimensions, is_single_geom, - is_point_type, - multiple_geoms); + is_point_type); } } break; @@ -267,16 +262,13 @@ void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature, b { const bool is_single_geom = true; const bool is_point_type = false; - const bool multiple_geoms = false; - convert_ordinates(feature, mapnik::Polygon, elem_info, ordinates, dimensions, is_single_geom, - is_point_type, - multiple_geoms); + is_point_type); } } break; @@ -286,19 +278,15 @@ void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature, b { const bool is_single_geom = false; const bool is_point_type = true; - const bool multiple_geoms = true; - - // Todo - force using true as multiple_geometries until we have proper multipoint handling - // http://trac.mapnik.org/ticket/458 + // FIXME :http://trac.mapnik.org/ticket/458 convert_ordinates(feature, mapnik::Point, elem_info, ordinates, dimensions, is_single_geom, - is_point_type, - multiple_geoms); + is_point_type); } } break; @@ -315,8 +303,7 @@ void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature, b ordinates, dimensions, is_single_geom, - is_point_type, - multiple_geometries); + is_point_type); } } break; @@ -333,8 +320,7 @@ void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature, b ordinates, dimensions, is_single_geom, - is_point_type, - multiple_geometries); + is_point_type); } } @@ -352,8 +338,7 @@ void occi_featureset::convert_geometry(SDOGeometry* geom, feature_ptr feature, b ordinates, dimensions, is_single_geom, - is_point_type, - multiple_geometries); + is_point_type); } } break; @@ -374,8 +359,7 @@ void occi_featureset::convert_ordinates(mapnik::feature_ptr feature, const std::vector& ordinates, const int dimensions, const bool is_single_geom, - const bool is_point_geom, - const bool multiple_geometries) + const bool is_point_geom) { const int elem_size = elem_info.size(); const int ord_size = ordinates.size(); @@ -388,7 +372,7 @@ void occi_featureset::convert_ordinates(mapnik::feature_ptr feature, if (! is_single_geom && elem_size > SDO_ELEM_INFO_SIZE) { - geometry_type* geom = multiple_geometries ? 0 : new geometry_type(geom_type); + geometry_type* geom = new geometry_type(geom_type); if (geom) geom->set_capacity(ord_size); for (int i = SDO_ELEM_INFO_SIZE; i < elem_size; i+=3) @@ -444,16 +428,13 @@ void occi_featureset::convert_ordinates(mapnik::feature_ptr feature, if (is_linear_element) { - if (multiple_geometries) + if (geom) { - if (geom) - { - feature->add_geometry(geom); - } - - geom = new geometry_type(gtype); - geom->set_capacity((next_offset - 1) - (offset - 1 - dimensions)); + feature->add_geometry(geom); } + + geom = new geometry_type(gtype); + geom->set_capacity((next_offset - 1) - (offset - 1 - dimensions)); fill_geometry_type(geom, offset - 1, diff --git a/plugins/input/occi/occi_featureset.hpp b/plugins/input/occi/occi_featureset.hpp index 88977d678..4c2a0db67 100644 --- a/plugins/input/occi/occi_featureset.hpp +++ b/plugins/input/occi/occi_featureset.hpp @@ -42,7 +42,6 @@ public: oracle::occi::Connection* conn, std::string const& sqlstring, std::string const& encoding, - bool multiple_geometries, bool use_connection_pool, unsigned prefetch_rows, unsigned num_attrs); @@ -50,15 +49,14 @@ public: mapnik::feature_ptr next(); private: - void convert_geometry (SDOGeometry* geom, mapnik::feature_ptr feature, bool multiple_geometries); + void convert_geometry (SDOGeometry* geom, mapnik::feature_ptr feature); void convert_ordinates (mapnik::feature_ptr feature, const mapnik::eGeomType& geom_type, const std::vector& elem_info, const std::vector& ordinates, const int dimensions, const bool is_single_geom, - const bool is_point_geom, - const bool multiple_geometries); + const bool is_point_geom); void fill_geometry_type (mapnik::geometry_type* geom, const int real_offset, const int next_offset, @@ -70,7 +68,6 @@ private: oracle::occi::ResultSet* rs_; boost::scoped_ptr tr_; const char* fidcolumn_; - bool multiple_geometries_; unsigned num_attrs_; mutable int feature_id_; }; diff --git a/plugins/input/postgis/postgis_datasource.cpp b/plugins/input/postgis/postgis_datasource.cpp index 9b2c641c1..2d0d642f9 100644 --- a/plugins/input/postgis/postgis_datasource.cpp +++ b/plugins/input/postgis/postgis_datasource.cpp @@ -87,8 +87,6 @@ postgis_datasource::postgis_datasource(parameters const& params, bool bind) { if (table_.empty()) throw mapnik::datasource_exception("Postgis Plugin: missing parameter"); - multiple_geometries_ = *params_.get("multiple_geometries",false); - boost::optional ext = params_.get("extent"); if (ext) extent_initialized_ = extent_.from_string(*ext); @@ -517,7 +515,7 @@ featureset_ptr postgis_datasource::features(const query& q) const unsigned num_attr = props.size(); if (!key_field_.empty()) ++num_attr; - return boost::make_shared(rs,desc_.get_encoding(),multiple_geometries_,!key_field_.empty(),num_attr); + return boost::make_shared(rs,desc_.get_encoding(), !key_field_.empty(),num_attr); } else { @@ -585,7 +583,7 @@ featureset_ptr postgis_datasource::features_at_point(coord2d const& pt) const } boost::shared_ptr rs = get_resultset(conn, s.str()); - return boost::make_shared(rs,desc_.get_encoding(),multiple_geometries_,!key_field_.empty(),size); + return boost::make_shared(rs,desc_.get_encoding(), !key_field_.empty(),size); } } return featureset_ptr(); diff --git a/plugins/input/postgis/postgis_datasource.hpp b/plugins/input/postgis/postgis_datasource.hpp index 8ad42e4f9..0ad00df9c 100644 --- a/plugins/input/postgis/postgis_datasource.hpp +++ b/plugins/input/postgis/postgis_datasource.hpp @@ -69,7 +69,6 @@ class postgis_datasource : public datasource mutable mapnik::box2d extent_; mutable layer_descriptor desc_; ConnectionCreator creator_; - bool multiple_geometries_; const std::string bbox_token_; const std::string scale_denom_token_; bool persist_connection_; diff --git a/plugins/input/postgis/postgis_featureset.cpp b/plugins/input/postgis/postgis_featureset.cpp index 84a877248..087047ce5 100644 --- a/plugins/input/postgis/postgis_featureset.cpp +++ b/plugins/input/postgis/postgis_featureset.cpp @@ -49,11 +49,9 @@ using mapnik::feature_factory; postgis_featureset::postgis_featureset(boost::shared_ptr const& rs, std::string const& encoding, - bool multiple_geometries, bool key_field=false, unsigned num_attrs=0) : rs_(rs), - multiple_geometries_(multiple_geometries), num_attrs_(num_attrs), tr_(new transcoder(encoding)), totalGeomSize_(0), @@ -103,7 +101,7 @@ feature_ptr postgis_featureset::next() // parse geometry int size = rs_->getFieldLength(0); const char *data = rs_->getValue(0); - geometry_utils::from_wkb(feature->paths(),data,size,multiple_geometries_); + geometry_utils::from_wkb(feature->paths(), data, size); totalGeomSize_+=size; for ( ;pos rs_; - bool multiple_geometries_; unsigned num_attrs_; boost::scoped_ptr tr_; int totalGeomSize_; @@ -53,7 +52,6 @@ private: public: postgis_featureset(boost::shared_ptr const& rs, std::string const& encoding, - bool multiple_geometries, bool key_field, unsigned num_attrs); mapnik::feature_ptr next(); diff --git a/plugins/input/sqlite/sqlite_datasource.cpp b/plugins/input/sqlite/sqlite_datasource.cpp index 7946dfead..477208aca 100644 --- a/plugins/input/sqlite/sqlite_datasource.cpp +++ b/plugins/input/sqlite/sqlite_datasource.cpp @@ -102,7 +102,6 @@ void sqlite_datasource::bind() const throw datasource_exception("Sqlite Plugin: " + dataset_name_ + " does not exist"); } - multiple_geometries_ = *params_.get("multiple_geometries", false); use_spatial_index_ = *params_.get("use_spatial_index", true); // TODO - remove this option once all datasources have an indexing api @@ -502,7 +501,6 @@ featureset_ptr sqlite_datasource::features(query const& q) const return boost::make_shared(rs, desc_.get_encoding(), format_, - multiple_geometries_, using_subquery_); } @@ -577,9 +575,8 @@ featureset_ptr sqlite_datasource::features_at_point(coord2d const& pt) const return boost::make_shared(rs, desc_.get_encoding(), format_, - multiple_geometries_, using_subquery_); } - + return featureset_ptr(); } diff --git a/plugins/input/sqlite/sqlite_datasource.hpp b/plugins/input/sqlite/sqlite_datasource.hpp index afecfcb89..85c67fdba 100644 --- a/plugins/input/sqlite/sqlite_datasource.hpp +++ b/plugins/input/sqlite/sqlite_datasource.hpp @@ -51,6 +51,11 @@ public: void bind() const; private: + + // FIXME: remove mutable qualifier from data members + // by factoring out bind() logic out from + // datasource impl !!! + mutable mapnik::box2d extent_; mutable bool extent_initialized_; int type_; @@ -67,7 +72,6 @@ private: mutable int row_limit_; mutable mapnik::layer_descriptor desc_; mutable mapnik::wkbFormat format_; - mutable bool multiple_geometries_; mutable bool use_spatial_index_; mutable bool has_spatial_index_; mutable bool using_subquery_; diff --git a/plugins/input/sqlite/sqlite_featureset.cpp b/plugins/input/sqlite/sqlite_featureset.cpp index 1cf0d8110..f92a8ba46 100644 --- a/plugins/input/sqlite/sqlite_featureset.cpp +++ b/plugins/input/sqlite/sqlite_featureset.cpp @@ -47,12 +47,10 @@ using mapnik::feature_factory; sqlite_featureset::sqlite_featureset(boost::shared_ptr rs, std::string const& encoding, mapnik::wkbFormat format, - bool multiple_geometries, bool using_subquery) : rs_(rs), tr_(new transcoder(encoding)), format_(format), - multiple_geometries_(multiple_geometries), using_subquery_(using_subquery) { } @@ -75,8 +73,8 @@ feature_ptr sqlite_featureset::next() int feature_id = rs_->column_integer(1); feature_ptr feature(feature_factory::create(feature_id)); - geometry_utils::from_wkb(feature->paths(), data, size, multiple_geometries_, format_); - + geometry_utils::from_wkb(feature->paths(), data, size, format_); + for (int i = 2; i < rs_->column_count(); ++i) { const int type_oid = rs_->column_type(i); diff --git a/plugins/input/sqlite/sqlite_featureset.hpp b/plugins/input/sqlite/sqlite_featureset.hpp index 313cadb38..4ec7472ba 100644 --- a/plugins/input/sqlite/sqlite_featureset.hpp +++ b/plugins/input/sqlite/sqlite_featureset.hpp @@ -42,7 +42,6 @@ public: sqlite_featureset(boost::shared_ptr rs, std::string const& encoding, mapnik::wkbFormat format, - bool multiple_geometries, bool using_subquery); virtual ~sqlite_featureset(); mapnik::feature_ptr next(); @@ -51,7 +50,6 @@ private: boost::shared_ptr rs_; boost::scoped_ptr tr_; mapnik::wkbFormat format_; - bool multiple_geometries_; bool using_subquery_; }; diff --git a/plugins/input/sqlite/sqlite_utils.hpp b/plugins/input/sqlite/sqlite_utils.hpp index 1e3ede064..3bd8a753e 100644 --- a/plugins/input/sqlite/sqlite_utils.hpp +++ b/plugins/input/sqlite/sqlite_utils.hpp @@ -151,11 +151,11 @@ public: while (rs->is_valid() && rs->step_next()) { int size; - const char* data = (const char*) rs->column_blob(0, size); + const char* data = static_cast(rs->column_blob(0, size)); if (data) { boost::ptr_vector paths; - mapnik::geometry_utils::from_wkb(paths, data, size, false, mapnik::wkbAuto); + mapnik::geometry_utils::from_wkb(paths, data, size, mapnik::wkbAuto); for (unsigned i=0; i const& bbox = paths[i].envelope(); @@ -241,9 +241,7 @@ public: if (data) { boost::ptr_vector paths; - // TODO - contraint fails if multiple_geometries = true - bool multiple_geometries = false; - mapnik::geometry_utils::from_wkb(paths, data, size, multiple_geometries, mapnik::wkbAuto); + mapnik::geometry_utils::from_wkb(paths, data, size, mapnik::wkbAuto); for (unsigned i=0; i const& bbox = paths[i].envelope(); @@ -320,13 +318,11 @@ public: while (rs->is_valid() && rs->step_next()) { int size; - const char* data = (const char*) rs->column_blob(0, size); + const char* data = static_cast(rs->column_blob(0, size)); if (data) { boost::ptr_vector paths; - // TODO - contraint fails if multiple_geometries = true - bool multiple_geometries = false; - mapnik::geometry_utils::from_wkb(paths, data, size, multiple_geometries, mapnik::wkbAuto); + mapnik::geometry_utils::from_wkb(paths, data, size, mapnik::wkbAuto); for (unsigned i=0; i const& bbox = paths[i].envelope(); diff --git a/src/agg/process_text_symbolizer.cpp b/src/agg/process_text_symbolizer.cpp index a127a19ee..e460fa322 100644 --- a/src/agg/process_text_symbolizer.cpp +++ b/src/agg/process_text_symbolizer.cpp @@ -44,7 +44,7 @@ void agg_renderer::process(text_symbolizer const& sym, if (geom.num_points() == 0) continue; // don't bother with empty geometries - if ((geom.type() == Polygon || geom.type() == MultiPolygon) && sym.get_minimum_path_length() > 0) + if ((geom.type() == Polygon) && sym.get_minimum_path_length() > 0) { // TODO - find less costly method than fetching full envelope box2d gbox = t_.forward(geom.envelope(),prj_trans); diff --git a/src/wkb.cpp b/src/wkb.cpp index f704971b7..158311cc4 100644 --- a/src/wkb.cpp +++ b/src/wkb.cpp @@ -114,16 +114,13 @@ public: needSwap_ = byteOrder_ ? wkbNDR : wkbXDR; #endif } - - ~wkb_reader() {} - - void read_multi(boost::ptr_vector & paths) + + void read(boost::ptr_vector & paths) { int type = read_integer(); #ifdef MAPNIK_DEBUG_WKB - std::clog << "wkb_reader: read_multi " - << wkb_geometry_type_string(type) << " " << type << std::endl; + std::clog << "wkb_reader: read " << wkb_geometry_type_string(type) << " " << type << std::endl; #endif switch (type) @@ -174,63 +171,6 @@ public: break; } } - - void read(boost::ptr_vector & paths) - { - int type = read_integer(); - -#ifdef MAPNIK_DEBUG_WKB - std::clog << "wkb_reader: read " << wkb_geometry_type_string(type) << " " << type << std::endl; -#endif - - switch (type) - { - case wkbPoint: - read_point(paths); - break; - case wkbLineString: - read_linestring(paths); - break; - case wkbPolygon: - read_polygon(paths); - break; - case wkbMultiPoint: - read_multipoint_2(paths); - break; - case wkbMultiLineString: - read_multilinestring_2(paths); - break; - case wkbMultiPolygon: - read_multipolygon_2(paths); - break; - case wkbGeometryCollection: - read_collection_2(paths); - break; - case wkbPointZ: - read_point_xyz(paths); - break; - case wkbLineStringZ: - read_linestring_xyz(paths); - break; - case wkbPolygonZ: - read_polygon_xyz(paths); - break; - case wkbMultiPointZ: - read_multipoint_xyz_2(paths); - break; - case wkbMultiLineStringZ: - read_multilinestring_xyz_2(paths); - break; - case wkbMultiPolygonZ: - read_multipolygon_xyz_2(paths); - break; - case wkbGeometryCollectionZ: - read_collection_2(paths); - break; - default: - break; - } - } private: @@ -329,21 +269,7 @@ private: read_point(paths); } } - - void read_multipoint_2(boost::ptr_vector & paths) - { - geometry_type* pt = new geometry_type(MultiPoint); - int num_points = read_integer(); - for (int i = 0; i < num_points; ++i) - { - pos_ += 5; - double x = read_double(); - double y = read_double(); - pt->move_to(x, y); - } - paths.push_back(pt); - } - + void read_point_xyz(boost::ptr_vector & paths) { geometry_type* pt = new geometry_type(Point); @@ -364,22 +290,6 @@ private: } } - void read_multipoint_xyz_2(boost::ptr_vector & paths) - { - geometry_type* pt = new geometry_type(MultiPoint); - int num_points = read_integer(); - for (int i = 0; i < num_points; ++i) - { - pos_ += 5; - double x = read_double(); - double y = read_double(); - pos_ += 8; // double z = read_double(); - pt->move_to(x, y); - } - paths.push_back(pt); - } - - void read_linestring(boost::ptr_vector & paths) { geometry_type* line = new geometry_type(LineString); @@ -404,29 +314,7 @@ private: read_linestring(paths); } } - - void read_multilinestring_2(boost::ptr_vector & paths) - { - geometry_type* line = new geometry_type(MultiLineString); - int num_lines = read_integer(); - unsigned capacity = 0; - for (int i = 0; i < num_lines; ++i) - { - pos_ += 5; - int num_points = read_integer(); - capacity += num_points; - CoordinateArray ar(num_points); - read_coords(ar); - line->set_capacity(capacity); - line->move_to(ar[0].x, ar[0].y); - for (int j = 1; j < num_points; ++j) - { - line->line_to(ar[j].x, ar[j].y); - } - } - paths.push_back(line); - } - + void read_linestring_xyz(boost::ptr_vector & paths) { geometry_type* line = new geometry_type(LineString); @@ -452,29 +340,7 @@ private: } } - void read_multilinestring_xyz_2(boost::ptr_vector & paths) - { - geometry_type* line = new geometry_type(MultiLineString); - int num_lines = read_integer(); - unsigned capacity = 0; - for (int i = 0; i < num_lines; ++i) - { - pos_ += 5; - int num_points = read_integer(); - capacity += num_points; - CoordinateArray ar(num_points); - read_coords_xyz(ar); - line->set_capacity(capacity); - line->move_to(ar[0].x, ar[0].y); - for (int j = 1; j < num_points; ++j) - { - line->line_to(ar[j].x, ar[j].y); - } - } - paths.push_back(line); - } - - + void read_polygon(boost::ptr_vector & paths) { geometry_type* poly = new geometry_type(Polygon); @@ -506,33 +372,6 @@ private: } } - void read_multipolygon_2(boost::ptr_vector & paths) - { - geometry_type* poly = new geometry_type(MultiPolygon); - int num_polys = read_integer(); - unsigned capacity = 0; - for (int i = 0; i < num_polys; ++i) - { - pos_ += 5; - int num_rings = read_integer(); - for (int r = 0; r < num_rings; ++r) - { - int num_points = read_integer(); - capacity += num_points; - CoordinateArray ar(num_points); - read_coords(ar); - poly->set_capacity(capacity); - poly->move_to(ar[0].x, ar[0].y); - for (int j = 1; j < num_points; ++j) - { - poly->line_to(ar[j].x, ar[j].y); - } - poly->line_to(ar[0].x, ar[0].y); - } - } - paths.push_back(poly); - } - void read_polygon_xyz(boost::ptr_vector & paths) { geometry_type* poly = new geometry_type(Polygon); @@ -564,34 +403,6 @@ private: } } - void read_multipolygon_xyz_2(boost::ptr_vector & paths) - { - geometry_type* poly = new geometry_type(MultiPolygon); - int num_polys = read_integer(); - unsigned capacity = 0; - for (int i = 0; i < num_polys; ++i) - { - pos_ += 5; - int num_rings = read_integer(); - for (int r = 0; r < num_rings; ++r) - { - int num_points = read_integer(); - capacity += num_points; - CoordinateArray ar(num_points); - read_coords_xyz(ar); - poly->set_capacity(capacity); - poly->move_to(ar[0].x, ar[0].y); - for (int j = 1; j < num_points; ++j) - { - poly->line_to(ar[j].x, ar[j].y); - } - poly->line_to(ar[0].x, ar[0].y); - } - } - paths.push_back(poly); - } - - void read_collection(boost::ptr_vector & paths) { int num_geometries = read_integer(); @@ -602,16 +413,6 @@ private: } } - void read_collection_2(boost::ptr_vector & paths) - { - int num_geometries = read_integer(); - for (int i = 0; i < num_geometries; ++i) - { - pos_ += 1; // skip byte order - read_multi(paths); - } - } - #ifdef MAPNIK_DEBUG_WKB std::string wkb_geometry_type_string(int type) { @@ -645,17 +446,10 @@ private: void geometry_utils::from_wkb (boost::ptr_vector& paths, const char* wkb, unsigned size, - bool multiple_geometries, wkbFormat format) { wkb_reader reader(wkb, size, format); - if (multiple_geometries) - { - return reader.read_multi(paths); - } - else - { - return reader.read(paths); - } + return reader.read(paths); } + } From 77adf6cec6f2fb078d0d95ad25e8f479856df091 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Tue, 6 Dec 2011 16:25:30 +0000 Subject: [PATCH 03/99] + make geometry noncopyable + make ctor explicit --- include/mapnik/geometry.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mapnik/geometry.hpp b/include/mapnik/geometry.hpp index b2583abe1..c07378cd5 100644 --- a/include/mapnik/geometry.hpp +++ b/include/mapnik/geometry.hpp @@ -41,7 +41,7 @@ enum eGeomType { }; template class Container=vertex_vector> -class geometry +class geometry : private::noncopyable { public: typedef T coord_type; @@ -54,7 +54,7 @@ private: mutable unsigned itr_; public: - geometry(eGeomType type) + explicit geometry(eGeomType type) : type_(type), itr_(0) {} From 283e2066e93011ceea162fad24c74df50c411005 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Wed, 7 Dec 2011 09:16:24 +0000 Subject: [PATCH 04/99] fix missing qualifier --- include/mapnik/geometry.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/mapnik/geometry.hpp b/include/mapnik/geometry.hpp index c07378cd5..a936a0b9f 100644 --- a/include/mapnik/geometry.hpp +++ b/include/mapnik/geometry.hpp @@ -41,13 +41,12 @@ enum eGeomType { }; template class Container=vertex_vector> -class geometry : private::noncopyable +class geometry : private::boost::noncopyable { public: typedef T coord_type; typedef Container container_type; typedef typename container_type::value_type value_type; - private: container_type cont_; eGeomType type_; From bd564449d77bb908b72409d9680cb12c9b8647f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Wed, 7 Dec 2011 23:03:14 +0100 Subject: [PATCH 05/99] fix typo --- src/feature_type_style.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/feature_type_style.cpp b/src/feature_type_style.cpp index 6e5a04924..6dc0fe86b 100644 --- a/src/feature_type_style.cpp +++ b/src/feature_type_style.cpp @@ -40,7 +40,7 @@ feature_type_style::feature_type_style() feature_type_style::feature_type_style(feature_type_style const& rhs, bool deep_copy) : filter_mode_(rhs.filter_mode_), - scale_denom_valicity_(-1) + scale_denom_validity_(-1) { if (!deep_copy) { rules_ = rhs.rules_; From 525998279224a0c952321fe6272cb15b103c23aa Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 8 Dec 2011 18:16:15 +0000 Subject: [PATCH 06/99] update to_wkb params --- utils/pgsql2sqlite/pgsql2sqlite.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/pgsql2sqlite/pgsql2sqlite.hpp b/utils/pgsql2sqlite/pgsql2sqlite.hpp index 818ec9d88..3e6caeeae 100644 --- a/utils/pgsql2sqlite/pgsql2sqlite.hpp +++ b/utils/pgsql2sqlite/pgsql2sqlite.hpp @@ -297,7 +297,7 @@ void pgsql2sqlite(Connection conn, if (oid == geometry_oid) { mapnik::Feature feat(pkid); - geometry_utils::from_wkb(feat.paths(),buf,size,false,wkbGeneric); + geometry_utils::from_wkb(feat.paths(),buf,size,wkbGeneric); if (feat.num_geometries() > 0) { geometry_type const& geom=feat.get_geometry(0); From 20478770acf30c24cb61f16c24919f1d4b33509f Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Thu, 8 Dec 2011 19:46:07 +0000 Subject: [PATCH 07/99] cleanup unused code --- utils/pgsql2sqlite/pgsql2sqlite.hpp | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/utils/pgsql2sqlite/pgsql2sqlite.hpp b/utils/pgsql2sqlite/pgsql2sqlite.hpp index 3e6caeeae..1de81ae8c 100644 --- a/utils/pgsql2sqlite/pgsql2sqlite.hpp +++ b/utils/pgsql2sqlite/pgsql2sqlite.hpp @@ -47,27 +47,6 @@ namespace mapnik { -/* -struct blob_to_hex -{ - std::string operator() (const char* blob, unsigned size) - { - std::string buf; - buf.reserve(size*2); - std::ostringstream s(buf); - s.seekp(0); - char hex[3]; - std::memset(hex,0,3); - for ( unsigned pos=0; pos < size; ++pos) - { - std::sprintf (hex, "%02X", int(blob[pos]) & 0xff); - s << hex; - } - return s.str(); - } -}; -*/ - template void pgsql2sqlite(Connection conn, std::string const& query, @@ -316,8 +295,6 @@ void pgsql2sqlite(Connection conn, empty_geom = false; } } - - //output_rec.push_back(sqlite::value_type("X'" + hex(buf,size) + "'")); output_rec.push_back(sqlite::blob(buf,size)); } else From 3ed2133e39926eccaedb70da80f4790ed3afdbd9 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 8 Dec 2011 17:13:41 -0800 Subject: [PATCH 08/99] maintain boost 1.42 compatibility (fixes nighly debian builds on lucid,maverick,and natty --- bindings/python/mapnik_geometry.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/bindings/python/mapnik_geometry.cpp b/bindings/python/mapnik_geometry.cpp index 516c5fc90..c30005438 100644 --- a/bindings/python/mapnik_geometry.cpp +++ b/bindings/python/mapnik_geometry.cpp @@ -26,13 +26,18 @@ #include #include #include +#include // mapnik #include #include #include + +#include +#if BOOST_VERSION >= 104700 #include #include +#endif namespace { @@ -79,6 +84,7 @@ boost::shared_ptr from_wkb_impl(std::string const& wkb) PyObject* to_wkb( geometry_type const& geom) { +#if BOOST_VERSION >= 104700 mapnik::util::wkb_buffer_ptr wkb = mapnik::util::to_wkb(geom,mapnik::util::wkbXDR); return #if PY_VERSION_HEX >= 0x03000000 @@ -87,10 +93,16 @@ PyObject* to_wkb( geometry_type const& geom) ::PyString_FromStringAndSize #endif ((const char*)wkb->buffer(),wkb->size()); +#else + std::ostringstream s; + s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100; + throw std::runtime_error("mapnik::to_wkb() requires at least boost 1.47 while your build was compiled against boost " + s.str()); +#endif } std::string to_wkt( geometry_type const& geom) { +#if BOOST_VERSION >= 104700 std::string wkt; // Use Python String directly ? bool result = mapnik::util::to_wkt(wkt,geom); if (!result) @@ -98,6 +110,11 @@ std::string to_wkt( geometry_type const& geom) throw std::runtime_error("Generate WKT failed"); } return wkt; +#else + std::ostringstream s; + s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100; + throw std::runtime_error("mapnik::to_wkt() requires at least boost 1.47 while your build was compiled against boost " + s.str()); +#endif } void export_geometry() From 8bf359451dc4ac03ef21b6053d860e293b14e1aa Mon Sep 17 00:00:00 2001 From: Cezary Tarnowski Date: Fri, 9 Dec 2011 12:08:50 +0100 Subject: [PATCH 09/99] Adding support for height as expression for building symbolizer --- include/mapnik/attribute_collector.hpp | 6 ++++++ include/mapnik/polygon_symbolizer.hpp | 10 +++++----- src/agg/process_building_symbolizer.cpp | 9 ++++++++- src/cairo_renderer.cpp | 8 +++++++- src/grid/process_building_symbolizer.cpp | 9 ++++++++- src/load_map.cpp | 5 ++--- 6 files changed, 36 insertions(+), 11 deletions(-) diff --git a/include/mapnik/attribute_collector.hpp b/include/mapnik/attribute_collector.hpp index b9b62a89c..70e1a5e8d 100644 --- a/include/mapnik/attribute_collector.hpp +++ b/include/mapnik/attribute_collector.hpp @@ -213,6 +213,12 @@ struct symbolizer_attributes : public boost::static_visitor<> void operator () (building_symbolizer const& sym) { + expression_ptr const& height_expr = sym.height(); + if (height_expr) + { + expression_attributes f_attr(names_); + boost::apply_visitor(f_attr,*height_expr); + } collect_metawriter(sym); } // TODO - support remaining syms diff --git a/include/mapnik/polygon_symbolizer.hpp b/include/mapnik/polygon_symbolizer.hpp index 809ceced3..a4791eed3 100644 --- a/include/mapnik/polygon_symbolizer.hpp +++ b/include/mapnik/polygon_symbolizer.hpp @@ -26,6 +26,7 @@ // mapnik #include #include +#include namespace mapnik { @@ -79,11 +80,10 @@ struct MAPNIK_DECL building_symbolizer : public symbolizer_base explicit building_symbolizer() : symbolizer_base(), fill_(color(128,128,128)), - height_(0.0), opacity_(1.0) {} - building_symbolizer(color const& fill,double height) + building_symbolizer(color const& fill, expression_ptr height) : symbolizer_base(), fill_(fill), height_(height), @@ -97,11 +97,11 @@ struct MAPNIK_DECL building_symbolizer : public symbolizer_base { fill_ = fill; } - double height() const + expression_ptr height() const { return height_; } - void set_height(double height) + void set_height(expression_ptr height) { height_=height; } @@ -115,7 +115,7 @@ struct MAPNIK_DECL building_symbolizer : public symbolizer_base } private: color fill_; - double height_; + expression_ptr height_; double opacity_; }; } diff --git a/src/agg/process_building_symbolizer.cpp b/src/agg/process_building_symbolizer.cpp index a9b8b0dbd..4546b0d7d 100644 --- a/src/agg/process_building_symbolizer.cpp +++ b/src/agg/process_building_symbolizer.cpp @@ -25,6 +25,7 @@ #include #include #include +#include // boost #include @@ -66,7 +67,13 @@ void agg_renderer::process(building_symbolizer const& sym, ras_ptr->reset(); ras_ptr->gamma(agg::gamma_linear()); - double height = sym.height() * scale_factor_; + double height = 0.0; + expression_ptr height_expr = sym.height(); + if (height_expr) + { + value_type result = boost::apply_visitor(evaluate(feature), *height_expr); + height = result.to_double() * scale_factor_; + } for (unsigned i=0;i(feature), *height_expr); + height = 0.7071 * result.to_double(); + } for (unsigned i = 0; i < feature.num_geometries(); ++i) { diff --git a/src/grid/process_building_symbolizer.cpp b/src/grid/process_building_symbolizer.cpp index 27c156a27..dcbb3665e 100644 --- a/src/grid/process_building_symbolizer.cpp +++ b/src/grid/process_building_symbolizer.cpp @@ -28,6 +28,7 @@ #include #include #include +#include // boost #include @@ -59,7 +60,13 @@ void grid_renderer::process(building_symbolizer const& sym, ras_ptr->reset(); - double height = sym.height() * scale_factor_; + double height = 0.0; + expression_ptr height_expr = sym.height(); + if (height_expr) + { + value_type result = boost::apply_visitor(evaluate(feature), *height_expr); + height = result.to_double() * scale_factor_; + } for (unsigned i=0;i opacity = get_opt_attr(sym, "fill-opacity"); if (opacity) building_sym.set_opacity(*opacity); // height - // TODO - expression - optional height = get_opt_attr(sym, "height"); - if (height) building_sym.set_height(*height); + optional height = get_opt_attr(sym, "height"); + if (height) building_sym.set_height(parse_expression(*height, "utf8")); parse_metawriter_in_symbolizer(building_sym, sym); rule.append(building_sym); From d700162834ccfa80ac80658e709206c43840e51e Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Fri, 9 Dec 2011 11:28:41 +0000 Subject: [PATCH 10/99] + increase coordinates precision --- include/mapnik/util/geometry_wkt_generator.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/mapnik/util/geometry_wkt_generator.hpp b/include/mapnik/util/geometry_wkt_generator.hpp index 38ce28a02..7ff923ce0 100644 --- a/include/mapnik/util/geometry_wkt_generator.hpp +++ b/include/mapnik/util/geometry_wkt_generator.hpp @@ -78,6 +78,7 @@ struct coordinate_policy : karma::real_policies { typedef boost::spirit::karma::real_policies base_type; static int floatfield(T n) { return base_type::fmtflags::fixed; } + static unsigned precision(T n) { return 6u ;} }; From 0d0f9fa0ba1a1310c4b7dda0048107733cf7fef2 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Fri, 9 Dec 2011 11:29:34 +0000 Subject: [PATCH 11/99] SVG generator impl --- .../mapnik/util/geometry_svg_generator.hpp | 105 ++++++++++++++++-- 1 file changed, 93 insertions(+), 12 deletions(-) diff --git a/include/mapnik/util/geometry_svg_generator.hpp b/include/mapnik/util/geometry_svg_generator.hpp index e69070148..22337ed1c 100644 --- a/include/mapnik/util/geometry_svg_generator.hpp +++ b/include/mapnik/util/geometry_svg_generator.hpp @@ -30,7 +30,6 @@ #include #include #include - // boost #include #include @@ -38,6 +37,8 @@ #include #include #include +#include +#include //#define BOOST_SPIRIT_USE_PHOENIX_V3 1 @@ -46,20 +47,100 @@ namespace mapnik { namespace util { namespace karma = boost::spirit::karma; namespace phoenix = boost::phoenix; -template -bool generate_svg (OutputIterator sink, mapnik::geometry_type const& geom) +namespace detail { +struct get_type { - using boost::spirit::karma::double_; - using boost::spirit::karma::uint_; - using boost::spirit::karma::generate; - return generate (sink, - // begin grammar - ((&uint_(mapnik::SEG_MOVETO) << 'M' | 'L') - << " " << double_ << " " << double_) % ' ' - // end grammar - , geom); + template + struct result { typedef int type; }; + + int operator() (geometry_type const& geom) const + { + return (int)geom.type(); + } +}; + +struct get_first +{ + template + struct result { typedef geometry_type::value_type const type; }; + + geometry_type::value_type const operator() (geometry_type const& geom) const + { + geometry_type::value_type coord; + boost::get<0>(coord) = geom.get_vertex(0,&boost::get<1>(coord),&boost::get<2>(coord)); + return coord; + } +}; + +template +struct coordinate_policy : karma::real_policies +{ + typedef boost::spirit::karma::real_policies base_type; + static int floatfield(T n) { return base_type::fmtflags::fixed; } + static unsigned precision(T n) { return 6u ;} +}; } +template +struct svg_generator : + karma::grammar +{ + + svg_generator() + : svg_generator::base_type(svg) + { + using boost::spirit::karma::uint_; + using boost::spirit::karma::_val; + using boost::spirit::karma::_1; + using boost::spirit::karma::lit; + using boost::spirit::karma::_a; + + svg = point | linestring | polygon + ; + + point = &uint_(mapnik::Point)[_1 = _type(_val)] + << svg_point [_1 = _first(_val)] + ; + + svg_point = &uint_ + << lit("cx=\"") << coord_type + << lit("\" cy=\"") << coord_type + << lit('\"') + ; + + linestring = &uint_(mapnik::LineString)[_1 = _type(_val)] + << svg_path + ; + + polygon = &uint_(mapnik::Polygon)[_1 = _type(_val)] + << svg_path + ; + + svg_path %= ((&uint_(mapnik::SEG_MOVETO) << lit('M') + | &uint_(mapnik::SEG_LINETO) [_a +=1] << karma::string [if_(_a == 1) [_1 = "L" ] ]) + << lit(' ') << coord_type << lit(' ') << coord_type) % lit(' ') + ; + + + + } + // rules + karma::rule svg; + karma::rule point; + karma::rule linestring; + karma::rule polygon; + + karma::rule svg_point; + karma::rule, geometry_type const& ()> svg_path; + + // phoenix functions + phoenix::function _type; + phoenix::function _first; + // + karma::real_generator > coord_type; + +}; + }} #endif // MAPNIK_GEOMETRY_SVG_GENERATOR_HPP From 14c3102c313d0ab11780dfe62a89d445c4d0f86c Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Fri, 9 Dec 2011 12:24:51 +0000 Subject: [PATCH 12/99] fix typo --- include/mapnik/geometry.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mapnik/geometry.hpp b/include/mapnik/geometry.hpp index a936a0b9f..6ae01d179 100644 --- a/include/mapnik/geometry.hpp +++ b/include/mapnik/geometry.hpp @@ -387,7 +387,7 @@ public: typedef geometry geometry_type; typedef boost::shared_ptr geometry_ptr; -typedef boost::ptr_vector geometry_containter; +typedef boost::ptr_vector geometry_container; } From bf2c8c4e9fe9490bbae931bc6e172c543e8cb35c Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Fri, 9 Dec 2011 12:25:13 +0000 Subject: [PATCH 13/99] make shape_io work with geometry_container concept --- plugins/input/shape/shape_featureset.cpp | 38 +-- .../input/shape/shape_index_featureset.cpp | 35 +-- plugins/input/shape/shape_io.cpp | 246 +----------------- plugins/input/shape/shape_io.hpp | 16 +- 4 files changed, 24 insertions(+), 311 deletions(-) diff --git a/plugins/input/shape/shape_featureset.cpp b/plugins/input/shape/shape_featureset.cpp index 9a6753b52..779c3869d 100644 --- a/plugins/input/shape/shape_featureset.cpp +++ b/plugins/input/shape/shape_featureset.cpp @@ -248,55 +248,25 @@ feature_ptr shape_featureset::next() } case shape_io::shape_polyline: - { - geometry_type* line = shape_.read_polyline(); - feature->add_geometry(line); - ++count_; - break; - } - case shape_io::shape_polylinem: - { - geometry_type* line = shape_.read_polylinem(); - feature->add_geometry(line); - ++count_; - break; - } - case shape_io::shape_polylinez: { - geometry_type* line = shape_.read_polylinez(); - feature->add_geometry(line); + shape_.read_polyline(feature->paths()); ++count_; break; } - + case shape_io::shape_polygon: - { - geometry_type* poly = shape_.read_polygon(); - feature->add_geometry(poly); - ++count_; - break; - } - case shape_io::shape_polygonm: - { - geometry_type* poly = shape_.read_polygonm(); - feature->add_geometry(poly); - ++count_; - break; - } - case shape_io::shape_polygonz: { - geometry_type* poly = shape_.read_polygonz(); - feature->add_geometry(poly); + shape_.read_polygon(feature->paths()); ++count_; break; } } } - + feature->set_id(shape_.id_); if (attr_ids_.size()) { diff --git a/plugins/input/shape/shape_index_featureset.cpp b/plugins/input/shape/shape_index_featureset.cpp index b25e8c644..0c0fcadc5 100644 --- a/plugins/input/shape/shape_index_featureset.cpp +++ b/plugins/input/shape/shape_index_featureset.cpp @@ -193,49 +193,18 @@ feature_ptr shape_index_featureset::next() } case shape_io::shape_polyline: - { - geometry_type* line = shape_.read_polyline(); - feature->add_geometry(line); - ++count_; - break; - } - case shape_io::shape_polylinem: - { - geometry_type* line = shape_.read_polylinem(); - feature->add_geometry(line); - ++count_; - break; - } - case shape_io::shape_polylinez: { - geometry_type* line = shape_.read_polylinez(); - feature->add_geometry(line); + shape_.read_polyline(feature->paths()); ++count_; break; } - case shape_io::shape_polygon: - { - geometry_type* poly = shape_.read_polygon(); - feature->add_geometry(poly); - ++count_; - break; - } - case shape_io::shape_polygonm: - { - geometry_type* poly = shape_.read_polygonm(); - feature->add_geometry(poly); - ++count_; - break; - } - case shape_io::shape_polygonz: { - geometry_type* poly = shape_.read_polygonz(); - feature->add_geometry(poly); + shape_.read_polygon(feature->paths()); ++count_; break; } diff --git a/plugins/input/shape/shape_io.cpp b/plugins/input/shape/shape_io.cpp index 04aa48814..54b7f32fc 100644 --- a/plugins/input/shape/shape_io.cpp +++ b/plugins/input/shape/shape_io.cpp @@ -106,18 +106,16 @@ dbf_file& shape_io::dbf() return dbf_; } -geometry_type* shape_io::read_polyline() +void shape_io::read_polyline(mapnik::geometry_container & geom) { shape_file::record_type record(reclength_ * 2 - 36); shp_.read_record(record); - + int num_parts = record.read_ndr_integer(); int num_points = record.read_ndr_integer(); - geometry_type* line = new geometry_type(mapnik::LineString); - line->set_capacity(num_points + num_parts); if (num_parts == 1) { - line->set_capacity(num_points + 1); + geometry_type* line = new geometry_type(mapnik::LineString); record.skip(4); double x = record.read_double(); double y = record.read_double(); @@ -128,6 +126,7 @@ geometry_type* shape_io::read_polyline() y = record.read_double(); line->line_to(x, y); } + geom.push_back(line); } else { @@ -140,6 +139,7 @@ geometry_type* shape_io::read_polyline() int start, end; for (int k = 0; k < num_parts; ++k) { + geometry_type* line = new geometry_type(mapnik::LineString); start = parts[k]; if (k == num_parts - 1) { @@ -160,135 +160,9 @@ geometry_type* shape_io::read_polyline() y = record.read_double(); line->line_to(x, y); } + geom.push_back(line); } } - return line; -} - -geometry_type* shape_io::read_polylinem() -{ - shape_file::record_type record(reclength_ * 2 - 36); - shp_.read_record(record); - - int num_parts = record.read_ndr_integer(); - int num_points = record.read_ndr_integer(); - geometry_type* line = new geometry_type(mapnik::LineString); - line->set_capacity(num_points + num_parts); - if (num_parts == 1) - { - record.skip(4); - double x = record.read_double(); - double y = record.read_double(); - line->move_to(x, y); - for (int i = 1; i < num_points; ++i) - { - x = record.read_double(); - y = record.read_double(); - line->line_to(x, y); - } - } - else - { - std::vector parts(num_parts); - for (int i = 0; i < num_parts; ++i) - { - parts[i] = record.read_ndr_integer(); - } - - int start, end; - for (int k = 0; k < num_parts; ++k) - { - start = parts[k]; - if (k == num_parts - 1) - { - end = num_points; - } - else - { - end = parts[k + 1]; - } - - double x = record.read_double(); - double y = record.read_double(); - line->move_to(x, y); - - for (int j = start + 1; j < end; ++j) - { - x = record.read_double(); - y = record.read_double(); - line->line_to(x, y); - } - } - } - - // m-range - //double m0=record.read_double(); - //double m1=record.read_double(); - - //for (int i=0;iset_capacity(num_points + num_parts); - if (num_parts == 1) - { - record.skip(4); - double x = record.read_double(); - double y = record.read_double(); - line->move_to(x, y); - for (int i = 1; i < num_points; ++i) - { - x = record.read_double(); - y = record.read_double(); - line->line_to(x, y); - } - } - else - { - std::vector parts(num_parts); - for (int i = 0; i < num_parts; ++i) - { - parts[i] = record.read_ndr_integer(); - } - - int start, end; - for (int k = 0; k < num_parts; ++k) - { - start = parts[k]; - if (k == num_parts - 1) - { - end = num_points; - } - else - { - end = parts[k + 1]; - } - - double x = record.read_double(); - double y = record.read_double(); - line->move_to(x, y); - - for (int j = start + 1; j < end; ++j) - { - x = record.read_double(); - y = record.read_double(); - line->line_to(x, y); - } - } - } - // z-range //double z0=record.read_double(); //double z1=record.read_double(); @@ -306,19 +180,17 @@ geometry_type* shape_io::read_polylinez() // double m=record.read_double(); //} - return line; } -geometry_type* shape_io::read_polygon() +void shape_io::read_polygon(mapnik::geometry_container & geom) { shape_file::record_type record(reclength_ * 2 - 36); shp_.read_record(record); - + int num_parts = record.read_ndr_integer(); int num_points = record.read_ndr_integer(); std::vector parts(num_parts); - geometry_type* poly = new geometry_type(mapnik::Polygon); - poly->set_capacity(num_points + num_parts); + for (int i = 0; i < num_parts; ++i) { parts[i] = record.read_ndr_integer(); @@ -326,6 +198,7 @@ geometry_type* shape_io::read_polygon() for (int k = 0; k < num_parts; k++) { + geometry_type* poly = new geometry_type(mapnik::Polygon); int start = parts[k]; int end; if (k == num_parts - 1) @@ -347,101 +220,8 @@ geometry_type* shape_io::read_polygon() y = record.read_double(); poly->line_to(x, y); } + geom.push_back(poly); } - return poly; -} - -geometry_type* shape_io::read_polygonm() -{ - shape_file::record_type record(reclength_ * 2 - 36); - shp_.read_record(record); - - int num_parts = record.read_ndr_integer(); - int num_points = record.read_ndr_integer(); - std::vector parts(num_parts); - geometry_type* poly = new geometry_type(mapnik::Polygon); - poly->set_capacity(num_points + num_parts); - for (int i = 0; i < num_parts; ++i) - { - parts[i] = record.read_ndr_integer(); - } - - for (int k = 0; k < num_parts; k++) - { - int start = parts[k]; - int end; - if (k == num_parts - 1) - { - end = num_points; - } - else - { - end = parts[k + 1]; - } - - double x = record.read_double(); - double y = record.read_double(); - poly->move_to(x, y); - - for (int j = start + 1; j < end; j++) - { - x = record.read_double(); - y = record.read_double(); - poly->line_to(x, y); - } - } - - // m-range - //double m0=record.read_double(); - //double m1=record.read_double(); - - //for (int i=0;i parts(num_parts); - geometry_type* poly = new geometry_type(mapnik::Polygon); - poly->set_capacity(num_points + num_parts); - for (int i = 0; i < num_parts; ++i) - { - parts[i] = record.read_ndr_integer(); - } - - for (int k = 0; k < num_parts; k++) - { - int start = parts[k]; - int end; - if (k == num_parts - 1) - { - end = num_points; - } - else - { - end = parts[k + 1]; - } - - double x = record.read_double(); - double y = record.read_double(); - poly->move_to(x, y); - - for (int j = start + 1; j < end; j++) - { - x = record.read_double(); - y = record.read_double(); - poly->line_to(x, y); - } - } - // z-range //double z0=record.read_double(); //double z1=record.read_double(); @@ -458,6 +238,6 @@ geometry_type* shape_io::read_polygonz() //{ // double m=record.read_double(); //} - - return poly; } + + diff --git a/plugins/input/shape/shape_io.hpp b/plugins/input/shape/shape_io.hpp index 1623402df..1421ec0ab 100644 --- a/plugins/input/shape/shape_io.hpp +++ b/plugins/input/shape/shape_io.hpp @@ -23,6 +23,8 @@ #ifndef SHAPE_IO_HPP #define SHAPE_IO_HPP +// mapnik +#include // boost #include #include @@ -56,9 +58,8 @@ public: ~shape_io(); shape_file& shp(); - //shape_file& shx(); dbf_file& dbf(); - + inline boost::shared_ptr& index() { return index_; @@ -72,16 +73,10 @@ public: void move_to(int id); int type() const; const box2d& current_extent() const; - mapnik::geometry_type* read_polyline(); - mapnik::geometry_type* read_polylinem(); - mapnik::geometry_type* read_polylinez(); - mapnik::geometry_type* read_polygon(); - mapnik::geometry_type* read_polygonm(); - mapnik::geometry_type* read_polygonz(); - + void read_polyline(mapnik::geometry_container & geom); + void read_polygon(mapnik::geometry_container & geom); unsigned type_; shape_file shp_; - //shape_file shx_; dbf_file dbf_; boost::shared_ptr index_; unsigned reclength_; @@ -89,7 +84,6 @@ public: box2d cur_extent_; static const std::string SHP; - //static const std::string SHX; static const std::string DBF; static const std::string INDEX; }; From b4c3c26b79ad2546c2a606f858d633da27ac11d2 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Mon, 12 Dec 2011 10:16:39 +0000 Subject: [PATCH 14/99] copy fontsets --- src/map.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/map.cpp b/src/map.cpp index ec974fb49..4b7af5513 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -87,6 +87,7 @@ Map::Map(const Map& rhs) background_image_(rhs.background_image_), styles_(rhs.styles_), metawriters_(rhs.metawriters_), + fontsets_(rhs.fontsets_), layers_(rhs.layers_), aspectFixMode_(rhs.aspectFixMode_), current_extent_(rhs.current_extent_), @@ -106,6 +107,7 @@ Map& Map::operator=(const Map& rhs) background_image_=rhs.background_image_; styles_=rhs.styles_; metawriters_ = rhs.metawriters_; + fontsets_ = rhs.fontsets_; layers_=rhs.layers_; aspectFixMode_=rhs.aspectFixMode_; maximum_extent_=rhs.maximum_extent_; From c0f918114e180a9e73c2729a2e57c4b186d11c46 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 12 Dec 2011 08:30:46 -0800 Subject: [PATCH 15/99] sqlite: fixup rtree bbox entries to use cumulative extent of multipolygons to avoid contraint errors --- plugins/input/sqlite/sqlite_utils.hpp | 50 ++++++++++++++++----------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/plugins/input/sqlite/sqlite_utils.hpp b/plugins/input/sqlite/sqlite_utils.hpp index 3bd8a753e..878669e34 100644 --- a/plugins/input/sqlite/sqlite_utils.hpp +++ b/plugins/input/sqlite/sqlite_utils.hpp @@ -242,38 +242,46 @@ public: { boost::ptr_vector paths; mapnik::geometry_utils::from_wkb(paths, data, size, mapnik::wkbAuto); + mapnik::box2d bbox; for (unsigned i=0; i const& bbox = paths[i].envelope(); - if (bbox.valid()) + if (i==0) { - - ps.bind(bbox); - - const int type_oid = rs->column_type(1); - if (type_oid != SQLITE_INTEGER) - { - std::ostringstream error_msg; - error_msg << "Sqlite Plugin: invalid type for key field '" - << rs->column_name(1) << "' when creating index '" << index_table - << "' type was: " << type_oid << ""; - throw mapnik::datasource_exception(error_msg.str()); - } - - const sqlite_int64 pkid = rs->column_integer64(1); - ps.bind(pkid); + bbox = paths[i].envelope(); } else + { + bbox.expand_to_include(paths[i].envelope()); + } + } + if (bbox.valid()) + { + + ps.bind(bbox); + + const int type_oid = rs->column_type(1); + if (type_oid != SQLITE_INTEGER) { std::ostringstream error_msg; - error_msg << "SQLite Plugin: encountered invalid bbox at '" - << rs->column_name(1) << "' == " << rs->column_integer64(1); + error_msg << "Sqlite Plugin: invalid type for key field '" + << rs->column_name(1) << "' when creating index '" << index_table + << "' type was: " << type_oid << ""; throw mapnik::datasource_exception(error_msg.str()); } - ps.step_next(); - one_success = true; + const sqlite_int64 pkid = rs->column_integer64(1); + ps.bind(pkid); } + else + { + std::ostringstream error_msg; + error_msg << "SQLite Plugin: encountered invalid bbox at '" + << rs->column_name(1) << "' == " << rs->column_integer64(1); + throw mapnik::datasource_exception(error_msg.str()); + } + + ps.step_next(); + one_success = true; } } } From 7e8e6007908edb2729e0ac0ec2f874ccf2d1f748 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Mon, 12 Dec 2011 18:19:52 +0000 Subject: [PATCH 16/99] + WKT generator for mapnik::geometry_container --- bindings/python/mapnik_geometry.cpp | 19 ++++ include/mapnik/util/geometry_to_wkt.hpp | 11 ++- .../mapnik/util/geometry_wkt_generator.hpp | 99 +++++++++++++++++-- 3 files changed, 119 insertions(+), 10 deletions(-) diff --git a/bindings/python/mapnik_geometry.cpp b/bindings/python/mapnik_geometry.cpp index 929b7fdec..22a68eba5 100644 --- a/bindings/python/mapnik_geometry.cpp +++ b/bindings/python/mapnik_geometry.cpp @@ -117,6 +117,24 @@ std::string to_wkt( geometry_type const& geom) #endif } +std::string to_wkt2( path_type const& geom) +{ +#if BOOST_VERSION >= 104700 + std::string wkt; // Use Python String directly ? + bool result = mapnik::util::to_wkt(wkt,geom); + if (!result) + { + throw std::runtime_error("Generate WKT failed"); + } + return wkt; +#else + std::ostringstream s; + s << BOOST_VERSION/100000 << "." << BOOST_VERSION/100 % 1000 << "." << BOOST_VERSION % 100; + throw std::runtime_error("mapnik::to_wkt() requires at least boost 1.47 while your build was compiled against boost " + s.str()); +#endif +} + + void export_geometry() { using namespace boost::python; @@ -142,6 +160,7 @@ void export_geometry() .def("__len__", &path_type::size) .def("add_wkt",add_wkt_impl) .def("add_wkb",add_wkb_impl) + .def("to_wkt",&to_wkt2) .def("from_wkt",from_wkt_impl) .def("from_wkb",from_wkb_impl) .staticmethod("from_wkt") diff --git a/include/mapnik/util/geometry_to_wkt.hpp b/include/mapnik/util/geometry_to_wkt.hpp index 962909f00..42735c3a2 100644 --- a/include/mapnik/util/geometry_to_wkt.hpp +++ b/include/mapnik/util/geometry_to_wkt.hpp @@ -42,7 +42,16 @@ bool to_wkt(std::string & wkt, mapnik::geometry_type const& geom) { typedef std::back_insert_iterator sink_type; sink_type sink(wkt); - wkt_generator generator; + wkt_generator generator(true); + bool result = karma::generate(sink, generator, geom); + return result; +} + +bool to_wkt(std::string & wkt, mapnik::geometry_container const& geom) +{ + typedef std::back_insert_iterator sink_type; + sink_type sink(wkt); + wkt_multi_generator generator; bool result = karma::generate(sink, generator, geom); return result; } diff --git a/include/mapnik/util/geometry_wkt_generator.hpp b/include/mapnik/util/geometry_wkt_generator.hpp index 7ff923ce0..df7bab059 100644 --- a/include/mapnik/util/geometry_wkt_generator.hpp +++ b/include/mapnik/util/geometry_wkt_generator.hpp @@ -30,7 +30,6 @@ #include #include #include - // boost #include #include @@ -49,6 +48,8 @@ namespace mapnik { namespace util { namespace karma = boost::spirit::karma; namespace phoenix = boost::phoenix; +namespace { + struct get_type { template @@ -73,21 +74,52 @@ struct get_first } }; + +struct multi_geometry_ +{ + template + struct result { typedef bool type; }; + + bool operator() (geometry_container const& geom) const + { + return geom.size() > 1 ? true : false; + } +}; + +struct multi_geometry_type +{ + template + struct result { typedef unsigned type; }; + + unsigned operator() (geometry_container const& geom) const + { + unsigned type = 0u; + geometry_container::const_iterator itr = geom.begin(); + geometry_container::const_iterator end = geom.end(); + for ( ; itr != end; ++itr) + { + type = itr->type(); + } + return type; + } +}; + template struct coordinate_policy : karma::real_policies { typedef boost::spirit::karma::real_policies base_type; static int floatfield(T n) { return base_type::fmtflags::fixed; } - static unsigned precision(T n) { return 6u ;} + static unsigned precision(T n) { return 6 ;} }; +} template struct wkt_generator : karma::grammar { - wkt_generator() + wkt_generator(bool single = false) : wkt_generator::base_type(wkt) { using boost::spirit::karma::uint_; @@ -97,22 +129,27 @@ struct wkt_generator : using boost::spirit::karma::_a; using boost::spirit::karma::_r1; using boost::spirit::karma::eps; + using boost::spirit::karma::string; wkt = point | linestring | polygon ; point = &uint_(mapnik::Point)[_1 = _type(_val)] - << lit("Point(") << point_coord [_1 = _first(_val)] << lit(')') + << string[ phoenix::if_ (single) [_1 = "Point("] + .else_[_1 = "("]] + << point_coord [_1 = _first(_val)] << lit(')') ; linestring = &uint_(mapnik::LineString)[_1 = _type(_val)] - << lit("LineString(") + << string[ phoenix::if_ (single) [_1 = "LineString("] + .else_[_1 = "("]] << coords << lit(')') ; polygon = &uint_(mapnik::Polygon)[_1 = _type(_val)] - << lit("Polygon(") + << string[ phoenix::if_ (single) [_1 = "Polygon("] + .else_[_1 = "("]] << coords2 << lit("))") ; @@ -121,8 +158,8 @@ struct wkt_generator : ; polygon_coord %= ( &uint_(mapnik::SEG_MOVETO) << eps[_r1 += 1] - << karma::string[ if_ (_r1 > 1) [_1 = "),("] - .else_[_1 = "("] ] | &uint_ << ",") + << string[ if_ (_r1 > 1) [_1 = "),("] + .else_[_1 = "("] ] | &uint_ << ",") << coord_type << lit(' ') << coord_type @@ -144,7 +181,7 @@ struct wkt_generator : karma::rule coords; karma::rule, geometry_type const& ()> coords2; karma::rule point_coord; - karma::rule polygon_coord; + karma::rule polygon_coord; // phoenix functions phoenix::function _type; @@ -154,6 +191,50 @@ struct wkt_generator : }; + +template +struct wkt_multi_generator : + karma::grammar +{ + + wkt_multi_generator() + : wkt_multi_generator::base_type(wkt) + { + using boost::spirit::karma::lit; + using boost::spirit::karma::eps; + using boost::spirit::karma::_val; + using boost::spirit::karma::_1; + + geometry_types.add + (mapnik::Point,"Point") + (mapnik::LineString,"LineString") + (mapnik::Polygon,"Polygon") + ; + + wkt = eps(_multi(_val)) << "Multi" << geometry_types[_1 = _type(_val)] + << "(" << multi_geometry << ")" | geometry_types[_1 = _type(_val)] + << geometry + ; + + geometry = *path + ; + + multi_geometry = -(path % lit(',')) + ; + + } + // rules + karma::rule wkt; + karma::rule geometry; + karma::rule multi_geometry; + wkt_generator path; + // phoenix + phoenix::function _multi; + phoenix::function _type; + // + karma::symbols geometry_types; +}; + }} From 0bb1073b3fd9af456489dc9ab07f651d5bd6e5f4 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 12 Dec 2011 15:55:33 -0800 Subject: [PATCH 17/99] csv plugin: allow values with leading zeros to stay as strings - closes #993 - refs https://github.com/mapbox/tilemill/issues/1007 --- plugins/input/csv/csv_datasource.cpp | 69 ++++++++++++++++------------ tests/python_tests/csv_test.py | 19 ++++++++ 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/plugins/input/csv/csv_datasource.cpp b/plugins/input/csv/csv_datasource.cpp index 6280d16f4..1d44b90c2 100644 --- a/plugins/input/csv/csv_datasource.cpp +++ b/plugins/input/csv/csv_datasource.cpp @@ -489,10 +489,12 @@ void csv_datasource::parse_csv(T& stream, std::string::const_iterator str_beg = value.begin(); std::string::const_iterator str_end = value.end(); bool r = qi::phrase_parse(str_beg,str_end, - ( - qi::lit("POINT") >> '(' >> double_[ref(x) = _1] >> double_[ref(y) = _1] >> ')' - ), - ascii::space); + ( + qi::lit("POINT") >> '(' + >> double_[ref(x) = _1] + >> double_[ref(y) = _1] >> ')' + ), + ascii::space); if (r && (str_beg == str_end)) { @@ -615,28 +617,27 @@ void csv_datasource::parse_csv(T& stream, } } - // add all values as attributes - // here we detect numbers and treat everything else as pure strings - // this is intentional since boolean and null types are not common in csv editors - if (value.empty()) - { - UnicodeString ustr = tr.transcode(value.c_str()); - boost::put(*feature,fld_name,ustr); - if (feature_count == 1) - { - desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String)); - } - } - // only true strings are this long - else if (value_length > 20) - { - UnicodeString ustr = tr.transcode(value.c_str()); - boost::put(*feature,fld_name,ustr); - if (feature_count == 1) - { - desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String)); - } + // now, add all values as attributes + /* First we detect likely strings, then try parsing likely numbers, + finally falling back to string type + * We intentionally do not try to detect boolean or null types + since they are not common in csv + * Likely strings are either empty values, very long values + or value with leading zeros like 001 (which are not safe + to assume are numbers) + */ + bool has_dot = value.find(".") != std::string::npos; + if (value.empty() || + (value_length > 20) || + (value_length > 1 && !has_dot && value[0] == '0')) + { + UnicodeString ustr = tr.transcode(value.c_str()); + boost::put(*feature,fld_name,ustr); + if (feature_count == 1) + { + desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String)); + } } else if ((value[0] >= '0' && value[0] <= '9') || value[0] == '-') { @@ -646,12 +647,14 @@ void csv_datasource::parse_csv(T& stream, bool r = qi::phrase_parse(str_beg,str_end,qi::double_,ascii::space,float_val); if (r && (str_beg == str_end)) { - if (value.find(".") != std::string::npos) + if (has_dot) { boost::put(*feature,fld_name,float_val); if (feature_count == 1) { - desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::Double)); + desc_.add_descriptor( + mapnik::attribute_descriptor( + fld_name,mapnik::Double)); } } else @@ -660,7 +663,9 @@ void csv_datasource::parse_csv(T& stream, boost::put(*feature,fld_name,val); if (feature_count == 1) { - desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::Integer)); + desc_.add_descriptor( + mapnik::attribute_descriptor( + fld_name,mapnik::Integer)); } } } @@ -671,7 +676,9 @@ void csv_datasource::parse_csv(T& stream, boost::put(*feature,fld_name,ustr); if (feature_count == 1) { - desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String)); + desc_.add_descriptor( + mapnik::attribute_descriptor( + fld_name,mapnik::String)); } } } @@ -682,7 +689,9 @@ void csv_datasource::parse_csv(T& stream, boost::put(*feature,fld_name,ustr); if (feature_count == 1) { - desc_.add_descriptor(mapnik::attribute_descriptor(fld_name,mapnik::String)); + desc_.add_descriptor( + mapnik::attribute_descriptor( + fld_name,mapnik::String)); } } } diff --git a/tests/python_tests/csv_test.py b/tests/python_tests/csv_test.py index f84442ebb..66df0564e 100644 --- a/tests/python_tests/csv_test.py +++ b/tests/python_tests/csv_test.py @@ -227,6 +227,25 @@ if 'csv' in mapnik.DatasourceCache.instance().plugin_names(): query.add_property_name('bogus') fs = ds.features(query) + def test_that_leading_zeros_mean_strings(**kwargs): + ds = get_csv_ds('leading_zeros.csv') + eq_(len(ds.fields()),3) + eq_(ds.fields(),['x','y','fips']) + eq_(ds.field_types(),['int','int','str']) + fs = ds.featureset() + feat = fs.next() + eq_(feat['x'],0) + eq_(feat['y'],0) + eq_(feat['fips'],'001') + feat = fs.next() + eq_(feat['x'],0) + eq_(feat['y'],0) + eq_(feat['fips'],'003') + feat = fs.next() + eq_(feat['x'],0) + eq_(feat['y'],0) + eq_(feat['fips'],'005') + if __name__ == "__main__": setup() [eval(run)(visual=True) for run in dir() if 'test_' in run] From 077eb4c865133819e79408f7f37b6af897ed6b27 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 12 Dec 2011 16:00:53 -0800 Subject: [PATCH 18/99] add new csv test --- tests/data/csv/leading_zeros.csv | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 tests/data/csv/leading_zeros.csv diff --git a/tests/data/csv/leading_zeros.csv b/tests/data/csv/leading_zeros.csv new file mode 100644 index 000000000..f0d8615dc --- /dev/null +++ b/tests/data/csv/leading_zeros.csv @@ -0,0 +1,4 @@ +x,y,fips +0,0,001 +0,0,003 +0,0,005 From d0cbb77864ebfa40da34b5cc8fc0d2ae79f985d2 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 12 Dec 2011 16:02:12 -0800 Subject: [PATCH 19/99] add readme to svg test dir --- tests/data/svg/README.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 tests/data/svg/README.md diff --git a/tests/data/svg/README.md b/tests/data/svg/README.md new file mode 100644 index 000000000..328d72ae9 --- /dev/null +++ b/tests/data/svg/README.md @@ -0,0 +1,6 @@ +Other good sources of svg for tests include: + + * http://intertwingly.net/svg/ + * http://www.w3.org/Graphics/SVG/Test/20110816/ + * http://croczilla.com/bits_and_pieces/svg/samples/ + * http://www.w3schools.com/svg/svg_examples.asp \ No newline at end of file From b438a56ada4b976178d1e2c9421344d0ecdc3ada Mon Sep 17 00:00:00 2001 From: Cezary Tarnowski Date: Tue, 13 Dec 2011 15:28:18 +0100 Subject: [PATCH 20/99] refactoring following comment on pull request --- include/mapnik/attribute_collector.hpp | 12 ++++++------ src/agg/process_building_symbolizer.cpp | 4 ++-- src/cairo_renderer.cpp | 12 ++++++------ src/save_map.cpp | 7 +++---- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/include/mapnik/attribute_collector.hpp b/include/mapnik/attribute_collector.hpp index 70e1a5e8d..e256a6c9e 100644 --- a/include/mapnik/attribute_collector.hpp +++ b/include/mapnik/attribute_collector.hpp @@ -213,12 +213,12 @@ struct symbolizer_attributes : public boost::static_visitor<> void operator () (building_symbolizer const& sym) { - expression_ptr const& height_expr = sym.height(); - if (height_expr) - { - expression_attributes f_attr(names_); - boost::apply_visitor(f_attr,*height_expr); - } + expression_ptr const& height_expr = sym.height(); + if (height_expr) + { + expression_attributes f_attr(names_); + boost::apply_visitor(f_attr,*height_expr); + } collect_metawriter(sym); } // TODO - support remaining syms diff --git a/src/agg/process_building_symbolizer.cpp b/src/agg/process_building_symbolizer.cpp index 4546b0d7d..0a5b573a7 100644 --- a/src/agg/process_building_symbolizer.cpp +++ b/src/agg/process_building_symbolizer.cpp @@ -71,8 +71,8 @@ void agg_renderer::process(building_symbolizer const& sym, expression_ptr height_expr = sym.height(); if (height_expr) { - value_type result = boost::apply_visitor(evaluate(feature), *height_expr); - height = result.to_double() * scale_factor_; + value_type result = boost::apply_visitor(evaluate(feature), *height_expr); + height = result.to_double() * scale_factor_; } for (unsigned i=0;i(feature), *height_expr); - height = 0.7071 * result.to_double(); - } + expression_ptr height_expr = sym.height(); + if (height_expr) + { + value_type result = boost::apply_visitor(evaluate(feature), *height_expr); + height = 0.7071 * result.to_double(); + } for (unsigned i = 0; i < feature.num_geometries(); ++i) { diff --git a/src/save_map.cpp b/src/save_map.cpp index 63edbfce8..63f1b84ff 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -241,10 +241,9 @@ public: { set_attr( sym_node, "fill-opacity", sym.get_opacity() ); } - if ( sym.height() != dfl.height() || explicit_defaults_ ) - { - set_attr( sym_node, "height", sym.height() ); - } + + set_attr( sym_node, "height", to_expression_string(*sym.height()) ); + add_metawriter_attributes(sym_node, sym); } From 4250e5de584efa7072b4a657e416aa1f5ecc078b Mon Sep 17 00:00:00 2001 From: Cezary Tarnowski Date: Tue, 13 Dec 2011 15:40:47 +0100 Subject: [PATCH 21/99] Changing the gamma for better visual effect --- src/agg/process_polygon_symbolizer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/agg/process_polygon_symbolizer.cpp b/src/agg/process_polygon_symbolizer.cpp index c376d9544..a3c3f9d1d 100644 --- a/src/agg/process_polygon_symbolizer.cpp +++ b/src/agg/process_polygon_symbolizer.cpp @@ -62,7 +62,7 @@ void agg_renderer::process(polygon_symbolizer const& sym, renderer ren(renb); ras_ptr->reset(); - ras_ptr->gamma(agg::gamma_linear(0.0, sym.get_gamma())); + ras_ptr->gamma(agg::gamma_power(sym.get_gamma())); metawriter_with_properties writer = sym.get_metawriter(); for (unsigned i=0;i Date: Tue, 13 Dec 2011 16:33:27 +0000 Subject: [PATCH 22/99] + support GEOMETRYCOLLECTION in WKT generator --- .../mapnik/util/geometry_wkt_generator.hpp | 50 +++++++++++++------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/include/mapnik/util/geometry_wkt_generator.hpp b/include/mapnik/util/geometry_wkt_generator.hpp index df7bab059..6c2df624b 100644 --- a/include/mapnik/util/geometry_wkt_generator.hpp +++ b/include/mapnik/util/geometry_wkt_generator.hpp @@ -89,23 +89,32 @@ struct multi_geometry_ struct multi_geometry_type { template - struct result { typedef unsigned type; }; + struct result { typedef boost::tuple type; }; - unsigned operator() (geometry_container const& geom) const + boost::tuple operator() (geometry_container const& geom) const { unsigned type = 0u; + bool collection = false; + geometry_container::const_iterator itr = geom.begin(); geometry_container::const_iterator end = geom.end(); + for ( ; itr != end; ++itr) - { + { + if (type != 0 && itr->type() != type) + { + collection = true; + break; + } type = itr->type(); } - return type; + return boost::tuple(type, collection); } }; + template -struct coordinate_policy : karma::real_policies +struct wkt_coordinate_policy : karma::real_policies { typedef boost::spirit::karma::real_policies base_type; static int floatfield(T n) { return base_type::fmtflags::fixed; } @@ -187,14 +196,15 @@ struct wkt_generator : phoenix::function _type; phoenix::function _first; // - karma::real_generator > coord_type; + karma::real_generator > coord_type; }; + template struct wkt_multi_generator : - karma::grammar + karma::grammar >, geometry_container const& ()> { wkt_multi_generator() @@ -204,6 +214,7 @@ struct wkt_multi_generator : using boost::spirit::karma::eps; using boost::spirit::karma::_val; using boost::spirit::karma::_1; + using boost::spirit::karma::_a; geometry_types.add (mapnik::Point,"Point") @@ -211,27 +222,34 @@ struct wkt_multi_generator : (mapnik::Polygon,"Polygon") ; - wkt = eps(_multi(_val)) << "Multi" << geometry_types[_1 = _type(_val)] - << "(" << multi_geometry << ")" | geometry_types[_1 = _type(_val)] - << geometry + wkt = eps(phoenix::at_c<1>(_a))[_a = _multi_type(_val)] + << lit("GeometryCollection(") << geometry << lit(")") + | eps(is_multi(_val)) << lit("Multi") << geometry_types[_1 = phoenix::at_c<0>(_a)] + << "(" << multi_geometry << ")" + | geometry ; - - geometry = *path + + geometry = -(single_geometry % lit(',')) ; + single_geometry = geometry_types[_1 = _type(_val)] << path + ; + multi_geometry = -(path % lit(',')) ; } // rules - karma::rule wkt; + karma::rule >, geometry_container const& ()> wkt; karma::rule geometry; + karma::rule single_geometry; karma::rule multi_geometry; wkt_generator path; // phoenix - phoenix::function _multi; - phoenix::function _type; - // + phoenix::function is_multi; + phoenix::function _multi_type; + phoenix::function _type; + // karma::symbols geometry_types; }; From bf9dd32e2c1097515b992206a2fc112a0973f28a Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Tue, 13 Dec 2011 16:34:10 +0000 Subject: [PATCH 23/99] remove title,abstract members from layer class --- bindings/python/mapnik_layer.cpp | 50 +++++--------------------------- include/mapnik/layer.hpp | 29 +++--------------- src/layer.cpp | 26 ----------------- src/load_map.cpp | 14 +-------- src/save_map.cpp | 13 ++------- 5 files changed, 15 insertions(+), 117 deletions(-) diff --git a/bindings/python/mapnik_layer.cpp b/bindings/python/mapnik_layer.cpp index 916f8f602..a37843b7f 100644 --- a/bindings/python/mapnik_layer.cpp +++ b/bindings/python/mapnik_layer.cpp @@ -54,7 +54,7 @@ struct layer_pickle_suite : boost::python::pickle_suite { s.append(style_names[i]); } - return boost::python::make_tuple(l.abstract(),l.title(),l.clear_label_cache(),l.getMinZoom(),l.getMaxZoom(),l.isQueryable(),l.datasource()->params(),l.cache_features(),s); + return boost::python::make_tuple(l.clear_label_cache(),l.getMinZoom(),l.getMaxZoom(),l.isQueryable(),l.datasource()->params(),l.cache_features(),s); } static void @@ -70,28 +70,24 @@ struct layer_pickle_suite : boost::python::pickle_suite throw_error_already_set(); } - l.set_abstract(extract(state[0])); + l.set_clear_label_cache(extract(state[0])); - l.set_title(extract(state[1])); + l.setMinZoom(extract(state[1])); - l.set_clear_label_cache(extract(state[2])); + l.setMaxZoom(extract(state[2])); - l.setMinZoom(extract(state[3])); + l.setQueryable(extract(state[3])); - l.setMaxZoom(extract(state[4])); - - l.setQueryable(extract(state[5])); - - mapnik::parameters params = extract(state[6]); + mapnik::parameters params = extract(state[4]); l.set_datasource(datasource_cache::instance()->create(params)); - boost::python::list s = extract(state[7]); + boost::python::list s = extract(state[5]); for (int i=0;i(s[i])); } - l.set_cache_features(extract(state[8])); + l.set_cache_features(extract(state[6])); } }; @@ -152,21 +148,6 @@ void export_layer() "False\n" ) - .add_property("abstract", - make_function(&layer::abstract,return_value_policy()), - &layer::set_abstract, - "Get/Set the abstract of the layer.\n" - "\n" - "Usage:\n" - ">>> from mapnik import Layer\n" - ">>> lyr = Layer('My Layer','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')\n" - ">>> lyr.abstract\n" - "'' # default is en empty string\n" - ">>> lyr.abstract = 'My Shapefile rendered with Mapnik'\n" - ">>> lyr.abstract\n" - "'My Shapefile rendered with Mapnik'\n" - ) - .add_property("active", &layer::isActive, &layer::setActive, @@ -310,20 +291,5 @@ void export_layer() "'My Style'\n" ) - .add_property("title", - make_function(&layer::title, return_value_policy()), - &layer::set_title, - "Get/Set the title of the layer.\n" - "\n" - "Usage:\n" - ">>> from mapnik import layer\n" - ">>> lyr = layer('My layer','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')\n" - ">>> lyr.title\n" - "''\n" - ">>> lyr.title = 'My first layer'\n" - ">>> lyr.title\n" - "'My first layer'\n" - ) - ; } diff --git a/include/mapnik/layer.hpp b/include/mapnik/layer.hpp index 4ed7e477e..98d3b6fd9 100644 --- a/include/mapnik/layer.hpp +++ b/include/mapnik/layer.hpp @@ -52,32 +52,13 @@ public: * @brief Set the name of the layer. */ void set_name(std::string const& name); - + /*! * @return the name of the layer. */ + const std::string& name() const; - - /*! - * @brief Set the title of the layer. - */ - void set_title(std::string const& title); - - /*! - * @return the title of the layer. - */ - const std::string& title() const; - - /*! - * @brief Set the abstract of the layer. - */ - void set_abstract(std::string const& abstract); - - /*! - * @return the abstract of the layer. - */ - const std::string& abstract() const; - + /*! * @brief Set the SRS of the layer. */ @@ -212,10 +193,8 @@ private: void swap(const layer& other); std::string name_; - std::string title_; - std::string abstract_; std::string srs_; - + double minZoom_; double maxZoom_; bool active_; diff --git a/src/layer.cpp b/src/layer.cpp index a185cac7f..3d88e17e6 100644 --- a/src/layer.cpp +++ b/src/layer.cpp @@ -37,8 +37,6 @@ namespace mapnik { layer::layer(std::string const& name, std::string const& srs) : name_(name), - title_(""), - abstract_(""), srs_(srs), minZoom_(0), maxZoom_(std::numeric_limits::max()), @@ -51,8 +49,6 @@ layer::layer(std::string const& name, std::string const& srs) layer::layer(const layer& rhs) : name_(rhs.name_), - title_(rhs.title_), - abstract_(rhs.abstract_), srs_(rhs.srs_), minZoom_(rhs.minZoom_), maxZoom_(rhs.maxZoom_), @@ -79,8 +75,6 @@ bool layer::operator==(layer const& other) const void layer::swap(const layer& rhs) { name_=rhs.name_; - title_=rhs.title_; - abstract_=rhs.abstract_; srs_ = rhs.srs_; minZoom_=rhs.minZoom_; maxZoom_=rhs.maxZoom_; @@ -105,26 +99,6 @@ std::string const& layer::name() const return name_; } -void layer::set_title( std::string const& title) -{ - title_ = title; -} - -std::string const& layer::title() const -{ - return title_; -} - -void layer::set_abstract( std::string const& abstract) -{ - abstract_ = abstract; -} - -std::string const& layer::abstract() const -{ - return abstract_; -} - void layer::set_srs(std::string const& srs) { srs_ = srs; diff --git a/src/load_map.cpp b/src/load_map.cpp index b3089ab2b..37231b790 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -600,19 +600,7 @@ void map_parser::parse_layer( Map & map, ptree const & lay ) { lyr.setActive( * status ); } - - optional title = get_opt_attr(lay, "title"); - if (title) - { - lyr.set_title( * title ); - } - - optional abstract = get_opt_attr(lay, "abstract"); - if (abstract) - { - lyr.set_abstract( * abstract ); - } - + optional minZoom = get_opt_attr(lay, "minzoom"); if (minZoom) { diff --git a/src/save_map.cpp b/src/save_map.cpp index 63edbfce8..862925fb1 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -815,21 +815,12 @@ void serialize_layer( ptree & map_node, const layer & layer, bool explicit_defau { ptree & layer_node = map_node.push_back( ptree::value_type("Layer", ptree()))->second; + if ( layer.name() != "" ) { set_attr( layer_node, "name", layer.name() ); } - - if ( layer.abstract() != "" ) - { - set_attr( layer_node, "abstract", layer.abstract() ); - } - - if ( layer.title() != "" ) - { - set_attr( layer_node, "title", layer.title() ); - } - + if ( layer.srs() != "" ) { set_attr( layer_node, "srs", layer.srs() ); From fad6c614e86e656f42daa6ecb5d38ed6485473b3 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Tue, 13 Dec 2011 16:47:45 +0000 Subject: [PATCH 24/99] remove title, abstract data members from mapnik::rule --- bindings/python/mapnik_rule.cpp | 21 +++++---------------- include/mapnik/rule.hpp | 32 +------------------------------- src/load_map.cpp | 8 ++------ src/save_map.cpp | 6 +----- 4 files changed, 9 insertions(+), 58 deletions(-) diff --git a/bindings/python/mapnik_rule.cpp b/bindings/python/mapnik_rule.cpp index b226dc865..b6f3e4bc8 100644 --- a/bindings/python/mapnik_rule.cpp +++ b/bindings/python/mapnik_rule.cpp @@ -86,7 +86,7 @@ struct rule_pickle_suite : boost::python::pickle_suite static boost::python::tuple getinitargs(const rule& r) { - return boost::python::make_tuple(r.get_name(),r.get_title(),r.get_min_scale(),r.get_max_scale()); + return boost::python::make_tuple(r.get_name(),r.get_min_scale(),r.get_max_scale()); } static boost::python::tuple @@ -102,7 +102,7 @@ struct rule_pickle_suite : boost::python::pickle_suite // We serialize filter expressions AST as strings std::string filter_expr = to_expression_string(*r.get_filter()); - return boost::python::make_tuple(r.get_abstract(),filter_expr,r.has_else_filter(),r.has_also_filter(),syms); + return boost::python::make_tuple(filter_expr,r.has_else_filter(),r.has_also_filter(),syms); } static void @@ -119,11 +119,6 @@ struct rule_pickle_suite : boost::python::pickle_suite } if (state[0]) - { - r.set_title(extract(state[0])); - } - - if (state[1]) { rule dfl; std::string filter = extract(state[1]); @@ -134,12 +129,12 @@ struct rule_pickle_suite : boost::python::pickle_suite } } - if (state[2]) + if (state[1]) { r.set_else(true); } - if (state[3]) + if (state[2]) { r.set_also(true); } @@ -176,18 +171,12 @@ void export_rule() class_("Rule",init<>("default constructor")) .def(init >()) + boost::python::optional >()) .def_pickle(rule_pickle_suite()) .add_property("name",make_function (&rule::get_name, return_value_policy()), &rule::set_name) - .add_property("title",make_function - (&rule::get_title,return_value_policy()), - &rule::set_title) - .add_property("abstract",make_function - (&rule::get_abstract,return_value_policy()), - &rule::set_abstract) .add_property("filter",make_function (&rule::get_filter,return_value_policy()), &rule::set_filter) diff --git a/include/mapnik/rule.hpp b/include/mapnik/rule.hpp index 9664d1173..eb5a02c7e 100644 --- a/include/mapnik/rule.hpp +++ b/include/mapnik/rule.hpp @@ -132,8 +132,6 @@ public: private: std::string name_; - std::string title_; - std::string abstract_; double min_scale_; double max_scale_; symbolizers syms_; @@ -143,8 +141,6 @@ private: public: rule() : name_(), - title_(), - abstract_(), min_scale_(0), max_scale_(std::numeric_limits::infinity()), syms_(), @@ -153,11 +149,9 @@ public: also_filter_(false) {} rule(const std::string& name, - const std::string& title="", double min_scale_denominator=0, double max_scale_denominator=std::numeric_limits::infinity()) : name_(name), - title_(title), min_scale_(min_scale_denominator), max_scale_(max_scale_denominator), syms_(), @@ -167,8 +161,6 @@ public: rule(const rule& rhs, bool deep_copy = false) : name_(rhs.name_), - title_(rhs.title_), - abstract_(rhs.abstract_), min_scale_(rhs.min_scale_), max_scale_(rhs.max_scale_), syms_(rhs.syms_), @@ -263,27 +255,7 @@ public: { return name_; } - - std::string const& get_title() const - { - return title_; - } - - void set_title(std::string const& title) - { - title_=title; - } - - void set_abstract(std::string const& abstract) - { - abstract_=abstract; - } - - std::string const& get_abstract() const - { - return abstract_; - } - + void append(const symbolizer& sym) { syms_.push_back(sym); @@ -362,8 +334,6 @@ private: void swap(rule& rhs) throw() { name_=rhs.name_; - title_=rhs.title_; - abstract_=rhs.abstract_; min_scale_=rhs.min_scale_; max_scale_=rhs.max_scale_; syms_=rhs.syms_; diff --git a/src/load_map.cpp b/src/load_map.cpp index 37231b790..bbb2ee641 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -577,8 +577,6 @@ void map_parser::parse_layer( Map & map, ptree const & lay ) s << "name," << "srs," << "status," - << "title," - << "abstract," << "minzoom," << "maxzoom," << "queryable," @@ -753,14 +751,12 @@ void map_parser::parse_layer( Map & map, ptree const & lay ) void map_parser::parse_rule( feature_type_style & style, ptree const & r ) { - ensure_attrs(r, "Rule", "name,title"); + ensure_attrs(r, "Rule", "name"); std::string name; try { name = get_attr( r, "name", std::string()); - std::string title = get_attr( r, "title", std::string()); - - rule rule(name,title); + rule rule(name); optional filter_expr = get_opt_child( r, "Filter"); diff --git a/src/save_map.cpp b/src/save_map.cpp index 862925fb1..ae237a1c9 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -647,11 +647,7 @@ void serialize_rule( ptree & style_node, const rule & r, bool explicit_defaults) { set_attr(rule_node, "name", r.get_name()); } - if ( r.get_title() != dfl.get_title() ) - { - set_attr(rule_node, "title", r.get_title()); - } - + if ( r.has_else_filter() ) { rule_node.push_back( ptree::value_type( From 382a04f33f73049adada8bd9b0ca7efead802e79 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 13 Dec 2011 11:17:44 -0800 Subject: [PATCH 25/99] python: also include uninstall target for deprecated module name --- bindings/python/build.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bindings/python/build.py b/bindings/python/build.py index 5a3c4af98..2c4846cc3 100644 --- a/bindings/python/build.py +++ b/bindings/python/build.py @@ -41,6 +41,7 @@ def is_py3(): prefix = env['PREFIX'] target_path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik') +target_path_deprecated = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2') libraries = ['mapnik','png'] @@ -152,8 +153,7 @@ if 'install' in COMMAND_LINE_TARGETS: init_module = env.Install(target_path, init_files) env.Alias(target='install', source=init_module) # install mapnik2 module which redirects to mapnik and issues DeprecatedWarning - path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2') - init_mapnik2 = env.Install(path, 'mapnik2/__init__.py') + init_mapnik2 = env.Install(target_path_deprecated, 'mapnik2/__init__.py') env.Alias(target='install', source=init_mapnik2) # fix perms and install the custom generated 'paths.py' @@ -204,4 +204,5 @@ if 'uninstall' not in COMMAND_LINE_TARGETS: env['create_uninstall_target'](env, target_path) +env['create_uninstall_target'](env, target_path_deprecated) From 754581f278f3f8903625bd05b4d8351a2a5bbc32 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 13 Dec 2011 13:52:11 -0800 Subject: [PATCH 26/99] tests: no need to test sqlite through ogr anymore - native impl is robust and has its own tests now --- tests/data/good_maps/sqlite.xml | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/tests/data/good_maps/sqlite.xml b/tests/data/good_maps/sqlite.xml index dac315cc0..a8270c32e 100644 --- a/tests/data/good_maps/sqlite.xml +++ b/tests/data/good_maps/sqlite.xml @@ -7,25 +7,15 @@ - - - - world_borders_style1 - - ogr - ../sqlite/world.sqlite - world_merc - - - - + + world_borders_style1 world_borders_style2 sqlite From 5f84df96d46ffd2384525031b16bd434d432ea3f Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 13 Dec 2011 17:02:00 -0800 Subject: [PATCH 27/99] python 2.5 compatibility --- tests/run_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/run_tests.py b/tests/run_tests.py index f1f9c222d..a4be7190d 100755 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -12,7 +12,7 @@ def usage(): def main(): try: opts, args = getopt.getopt(sys.argv[1:], "hvqp:", ["help", "prefix="]) - except getopt.GetoptError as err: + except getopt.GetoptError,err: print(str(err)) usage() sys.exit(2) From 5a2da87aa897f0d277b921efc3288a34216613a0 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 13 Dec 2011 17:51:40 -0800 Subject: [PATCH 28/99] removed unused file remaining from old automake system --- bindings/python/mapnik/paths.py.in | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 bindings/python/mapnik/paths.py.in diff --git a/bindings/python/mapnik/paths.py.in b/bindings/python/mapnik/paths.py.in deleted file mode 100644 index 0100d6a83..000000000 --- a/bindings/python/mapnik/paths.py.in +++ /dev/null @@ -1,3 +0,0 @@ -mapniklibpath = '@PACKAGE_LIB_DIR@' -inputpluginspath = mapniklibpath + '/input' -fontscollectionpath = '@SYSTEM_FONTS_DIR@/truetype/ttf-dejavu' From acb726ce639b50ad00d9fc233889d0cad9de1304 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 13 Dec 2011 17:53:31 -0800 Subject: [PATCH 29/99] serialize relative path to fonts/plugins in python paths.py and re-assemble absolute path dynamically at load time to provide greatest portability --- bindings/python/build.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/bindings/python/build.py b/bindings/python/build.py index 2c4846cc3..f65ff69f1 100644 --- a/bindings/python/build.py +++ b/bindings/python/build.py @@ -43,7 +43,8 @@ prefix = env['PREFIX'] target_path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik') target_path_deprecated = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2') -libraries = ['mapnik','png'] +libraries = ['mapnik'] +libraries.append('png') if env['JPEG']: libraries.append('jpeg') @@ -122,22 +123,24 @@ else: paths = ''' """Configuration paths of Mapnik fonts and input plugins (auto-generated by SCons).""" -import os +from os.path import normpath,join,dirname mapniklibpath = '%s' +mapniklibpath = normpath(join(dirname(__file__),mapniklibpath)) ''' -paths += "inputpluginspath = os.path.normpath(mapniklibpath + '/input')\n" +paths += "inputpluginspath = join(mapniklibpath,'input')\n" if env['SYSTEM_FONTS']: - paths += "fontscollectionpath = os.path.normpath('%s')" % env['SYSTEM_FONTS'] + paths += "fontscollectionpath = normpath('%s')\n" % env['SYSTEM_FONTS'] else: - paths += "fontscollectionpath = os.path.normpath(mapniklibpath + '/fonts')" + paths += "fontscollectionpath = join(mapniklibpath,'fonts')\n" +paths += "__all__ = [mapniklibpath,inputpluginspath,fontscollectionpath]\n" if not os.path.exists('mapnik'): os.mkdir('mapnik') -file('mapnik/paths.py','w').write(paths % (env['MAPNIK_LIB_DIR'])) +file('mapnik/paths.py','w').write(paths % (os.path.relpath(env['MAPNIK_LIB_DIR'],target_path))) # force open perms temporarily so that `sudo scons install` # does not later break simple non-install non-sudo rebuild From 56cd9c4d6aa96eb757b33bae4fb39e4f27cf0145 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 14 Dec 2011 11:18:31 -0800 Subject: [PATCH 30/99] python bindings: limit uncessary linking on linux and on osx if '-undefined dynamic_lookup' is used (which is now default) --- bindings/python/build.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/bindings/python/build.py b/bindings/python/build.py index f65ff69f1..caea79ce0 100644 --- a/bindings/python/build.py +++ b/bindings/python/build.py @@ -44,10 +44,6 @@ target_path = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'm target_path_deprecated = os.path.normpath(env['PYTHON_INSTALL_LOCATION'] + os.path.sep + 'mapnik2') libraries = ['mapnik'] -libraries.append('png') - -if env['JPEG']: - libraries.append('jpeg') if env['BOOST_PYTHON_LIB']: libraries.append(env['BOOST_PYTHON_LIB']) @@ -57,11 +53,16 @@ else: else: libraries.append('boost_python%s' % env['BOOST_APPEND']) +# TODO - do solaris/fedora need direct linking too? if env['PLATFORM'] == 'Darwin': - libraries.append(env['ICU_LIB_NAME']) - libraries.append('boost_regex%s' % env['BOOST_APPEND']) - if env['THREADING'] == 'multi': - libraries.append('boost_thread%s' % env['BOOST_APPEND']) + if not env['PYTHON_DYNAMIC_LOOKUP']: + libraries.append('png') + if env['JPEG']: + libraries.append('jpeg') + libraries.append(env['ICU_LIB_NAME']) + libraries.append('boost_regex%s' % env['BOOST_APPEND']) + if env['THREADING'] == 'multi': + libraries.append('boost_thread%s' % env['BOOST_APPEND']) ##### Python linking on OS X is tricky ### # Confounding problems are: @@ -107,6 +108,7 @@ if env['PLATFORM'] == 'Darwin': else: # TODO - do we need to pass -L/? python_link_flag = '-lpython%s' % env['PYTHON_VERSION'] + elif env['PLATFORM'] == 'SunOS': # make sure to explicitly link mapnik.so against # libmapnik in its installed location From 6330978ccef6b0376fb115fa380654aba787d509 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 14 Dec 2011 15:51:57 -0800 Subject: [PATCH 31/99] move the json config into the main script --- utils/mapnik-config/build.py | 14 -------------- utils/mapnik-config/mapnik-config.template.sh | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/utils/mapnik-config/build.py b/utils/mapnik-config/build.py index c86d3b5e7..8519051e0 100644 --- a/utils/mapnik-config/build.py +++ b/utils/mapnik-config/build.py @@ -28,20 +28,6 @@ CONFIG_FONTS='%(fonts)s' CONFIG_INPUT_PLUGINS='%(input_plugins)s' CONFIG_GIT_REVISION='%(git_revision)s' -CONFIG_JSON="{ - \\"prefix\\": \\"${CONFIG_PREFIX}\\", - \\"mapnik_libname\\": \\"${CONFIG_MAPNIK_LIBNAME}\\", - \\"mapnik_include\\": \\"${CONFIG_MAPNIK_INCLUDE}\\", - \\"mapnik_lib\\": \\"${CONFIG_MAPNIK_LIB}\\", - \\"version\\": \\"${CONFIG_MAPNIK_VERSION}\\", - \\"ldflags\\": \\"${CONFIG_MAPNIK_LDFLAGS}\\", - \\"dep_libs\\": \\"${CONFIG_DEP_LIBS}\\", - \\"other_includes\\": \\"${CONFIG_OTHER_INCLUDES}\\", - \\"fonts\\": \\"${CONFIG_FONTS}\\", - \\"input_plugins\\": \\"${CONFIG_INPUT_PLUGINS}\\", - \\"git_revision\\": \\"${CONFIG_GIT_REVISION}\\", -}" - ''' def write_config(configuration,template,config_file): diff --git a/utils/mapnik-config/mapnik-config.template.sh b/utils/mapnik-config/mapnik-config.template.sh index ef62cdb86..c89bb3ef1 100755 --- a/utils/mapnik-config/mapnik-config.template.sh +++ b/utils/mapnik-config/mapnik-config.template.sh @@ -1,6 +1,20 @@ ## program below +CONFIG_JSON="{ + \"prefix\": \"${CONFIG_PREFIX}\", + \"mapnik_libname\": \"${CONFIG_MAPNIK_LIBNAME}\", + \"mapnik_include\": \"${CONFIG_MAPNIK_INCLUDE}\", + \"mapnik_lib\": \"${CONFIG_MAPNIK_LIB}\", + \"version\": \"${CONFIG_MAPNIK_VERSION}\", + \"ldflags\": \"${CONFIG_MAPNIK_LDFLAGS}\", + \"dep_libs\": \"${CONFIG_DEP_LIBS}\", + \"other_includes\": \"${CONFIG_OTHER_INCLUDES}\", + \"fonts\": \"${CONFIG_FONTS}\", + \"input_plugins\": \"${CONFIG_INPUT_PLUGINS}\", + \"git_revision\": \"${CONFIG_GIT_REVISION}\" +}" + usage() { cat < Date: Thu, 15 Dec 2011 14:57:57 +0000 Subject: [PATCH 32/99] untabify --- src/placement_finder.cpp | 56 ++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/placement_finder.cpp b/src/placement_finder.cpp index b0dafd56b..c965d03cf 100644 --- a/src/placement_finder.cpp +++ b/src/placement_finder.cpp @@ -293,7 +293,7 @@ void placement_finder::find_point_placement(placement & p, // wrap text at first wrap_char after (default) the wrap width or immediately before the current word if ((c == '\n') || (line_width > 0 && (((line_width - character_spacing) > wrap_at && !p.wrap_before) || - ((line_width + word_width - character_spacing) > wrap_at && p.wrap_before)) )) + ((line_width + word_width - character_spacing) > wrap_at && p.wrap_before)) )) { // Remove width of breaking space character since it is not rendered and the character_spacing for the last character on the line line_width -= (last_wrap_char_width + character_spacing); @@ -381,12 +381,12 @@ void placement_finder::find_point_placement(placement & p, x = -(line_width / 2.0); if (p.info.get_rtl()==false) { - y = (0.5 * (string_height + (line_spacing * (total_lines-1)))) - max_character_height; - } - else - { - y = -(0.5 * (string_height + (line_spacing * (total_lines-1)))) + max_character_height; - } + y = (0.5 * (string_height + (line_spacing * (total_lines-1)))) - max_character_height; + } + else + { + y = -(0.5 * (string_height + (line_spacing * (total_lines-1)))) + max_character_height; + } // if needed, adjust for desired justification (J_MIDDLE is the default) if( po->jalign == J_LEFT ) @@ -411,14 +411,14 @@ void placement_finder::find_point_placement(placement & p, index_to_wrap_at = line_breaks[++line_number]; line_width = line_widths[line_number]; - if (p.info.get_rtl()==false) - { - y -= (max_character_height + line_spacing); // move position down to line start - } - else - { - y += (max_character_height + line_spacing); // move position up to line start - } + if (p.info.get_rtl()==false) + { + y -= (max_character_height + line_spacing); // move position down to line start + } + else + { + y += (max_character_height + line_spacing); // move position up to line start + } // reset to begining of line position x = ((po->jalign == J_LEFT)? -(string_width / 2.0): ((po->jalign == J_RIGHT)? ((string_width /2.0) - line_width): -(line_width / 2.0))); @@ -467,9 +467,9 @@ void placement_finder::find_point_placement(placement & p, if (p.minimum_padding > 0) { box2d epad(e.minx()-p.minimum_padding, - e.miny()-p.minimum_padding, - e.maxx()+p.minimum_padding, - e.maxy()+p.minimum_padding); + e.miny()-p.minimum_padding, + e.maxx()+p.minimum_padding, + e.maxy()+p.minimum_padding); if (!dimensions_.contains(epad)) { return; @@ -485,18 +485,18 @@ void placement_finder::find_point_placement(placement & p, // check the placement of any additional envelopes if (!p.allow_overlap && !p.additional_boxes.empty()) { - BOOST_FOREACH(box2d box, p.additional_boxes) - { - box2d pt(box.minx() + current_placement->starting_x, - box.miny() + current_placement->starting_y, - box.maxx() + current_placement->starting_x, - box.maxy() + current_placement->starting_y); + BOOST_FOREACH(box2d box, p.additional_boxes) + { + box2d pt(box.minx() + current_placement->starting_x, + box.miny() + current_placement->starting_y, + box.maxx() + current_placement->starting_x, + box.maxy() + current_placement->starting_y); - // abort the whole placement if the additional envelopes can't be placed. - if (!detector_.has_point_placement(pt, p.minimum_distance)) return; + // abort the whole placement if the additional envelopes can't be placed. + if (!detector_.has_point_placement(pt, p.minimum_distance)) return; - c_envelopes.push(pt); - } + c_envelopes.push(pt); + } } // since there was no early exit, add the character envelopes to the placements' envelopes From 6e18e307eece86ca999fc15c4d7e3deb588d69f5 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 15 Dec 2011 17:18:22 -0800 Subject: [PATCH 33/99] Add missing break --- plugins/input/sqlite/sqlite_utils.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/input/sqlite/sqlite_utils.hpp b/plugins/input/sqlite/sqlite_utils.hpp index 1e3ede064..6fbe32b31 100644 --- a/plugins/input/sqlite/sqlite_utils.hpp +++ b/plugins/input/sqlite/sqlite_utils.hpp @@ -568,6 +568,7 @@ public: // PRAGMA table_info is used so here we assume the column is a string // which is a lesser evil than altogether dropping the column desc.add_descriptor(mapnik::attribute_descriptor(fld_name, mapnik::String)); + break; case SQLITE_BLOB: if (geometry_field.empty() From 90b5cf69cc9ebcf54bbf95bb9f1daa5927b4d3fa Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 16 Dec 2011 07:22:52 -0800 Subject: [PATCH 34/99] update tests as per #992 --- bindings/python/mapnik/printing.py | 8 ++++---- tests/data/good_maps/markers_symbolizer_lines.xml | 2 +- tests/data/good_maps/markers_symbolizer_points.xml | 14 +++++++------- tests/data/good_maps/point_csv.xml | 6 +++--- tests/data/good_maps/point_json.xml | 6 +++--- tests/data/good_maps/point_json_inline.xml | 6 +++--- tests/data/good_maps/point_symbolizer.xml | 14 +++++++------- .../point_symbolizer_ignore_placements.xml | 4 ++-- .../good_maps/point_symbolizer_on_polygon_map.xml | 10 +++++----- tests/data/good_maps/text_rotation.xml | 14 +++++++------- tests/python_tests/object_test.py | 13 +++---------- 11 files changed, 45 insertions(+), 52 deletions(-) diff --git a/bindings/python/mapnik/printing.py b/bindings/python/mapnik/printing.py index 58f18b653..5e6456bd9 100644 --- a/bindings/python/mapnik/printing.py +++ b/bindings/python/mapnik/printing.py @@ -593,7 +593,7 @@ class PDFPrinter: for l in m.layers: # extract the layer names for naming layers if we use OCG - self._layer_names.append(l.title or l.name) + self._layer_names.append(l.name) layer_map = Map(m.width,m.height,m.srs) layer_map.layers.append(l) @@ -884,7 +884,7 @@ class PDFPrinter: for l in reversed(m.layers): have_layer_header = False added_styles={} - layer_title = l.title or l.name + layer_title = l.name if layer_title in processed_layers: continue processed_layers.append(layer_title) @@ -906,8 +906,8 @@ class PDFPrinter: if r.filter and str(r.filter) != "true": if len(rule_text) > 0: rule_text += " AND " - if r.title: - rule_text += r.title + if r.name: + rule_text += r.name else: rule_text += str(r.filter) active_rules = tuple(active_rules) diff --git a/tests/data/good_maps/markers_symbolizer_lines.xml b/tests/data/good_maps/markers_symbolizer_lines.xml index d3adaefb6..1336f56bc 100644 --- a/tests/data/good_maps/markers_symbolizer_lines.xml +++ b/tests/data/good_maps/markers_symbolizer_lines.xml @@ -1,7 +1,7 @@