From 9b5189abf04e3af8b3e3f914e3a70ae314ace3d0 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 14 Sep 2012 16:10:51 -0700 Subject: [PATCH 1/4] sqlite: improve the error when no key_field is set and the primary key cannot be autodetected --- plugins/input/sqlite/sqlite_datasource.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/input/sqlite/sqlite_datasource.cpp b/plugins/input/sqlite/sqlite_datasource.cpp index 89653bdf9..1b769af53 100644 --- a/plugins/input/sqlite/sqlite_datasource.cpp +++ b/plugins/input/sqlite/sqlite_datasource.cpp @@ -339,10 +339,12 @@ void sqlite_datasource::bind() const else { std::ostringstream s; - s << "Sqlite Plugin: key_field is empty for " - << geometry_field_ - << " and " - << geometry_table_; + s << "Sqlite Plugin: could not generate spatial index" + << " for table '" << geometry_table_ << "'" + << " as no primary key can be detected." + << " You should either declare an INTEGER PRIMARY KEY" + << " or set the 'key_field' option to force a" + << " given field to be used as the primary key"; throw datasource_exception(s.str()); } } From 1b3dcda87d8408c4351cfa32e605f0b4b207051f Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 14 Sep 2012 16:11:37 -0700 Subject: [PATCH 2/4] add method off style to check for active rules --- include/mapnik/feature_type_style.hpp | 6 +++--- src/feature_type_style.cpp | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/include/mapnik/feature_type_style.hpp b/include/mapnik/feature_type_style.hpp index 45707fbdc..a623849f4 100644 --- a/include/mapnik/feature_type_style.hpp +++ b/include/mapnik/feature_type_style.hpp @@ -72,17 +72,17 @@ public: 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); + bool active(double scale_denom) const; + void set_filter_mode(filter_mode_e mode); filter_mode_e get_filter_mode() const; + // filters std::vector const& image_filters() const; std::vector & image_filters(); diff --git a/src/feature_type_style.cpp b/src/feature_type_style.cpp index 2dc820895..ff588af7f 100644 --- a/src/feature_type_style.cpp +++ b/src/feature_type_style.cpp @@ -22,6 +22,9 @@ #include +// boost +#include + namespace mapnik { @@ -89,6 +92,18 @@ rules& feature_type_style::get_rules_nonconst() return rules_; } +bool feature_type_style::active(double scale_denom) const +{ + BOOST_FOREACH(rule const& r, rules_) + { + if (r.active(scale_denom)) + { + return true; + } + } + return false; +} + void feature_type_style::set_filter_mode(filter_mode_e mode) { filter_mode_ = mode; From 56585d11d953b857e1f7aa5fabc06b68e123e073 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 14 Sep 2012 16:13:37 -0700 Subject: [PATCH 3/4] when using style level compositing or image filters still trigger style processing callbacks even if we return without querying the data if there are active rules - closes #1477 --- CHANGELOG.md | 2 + .../mapnik/feature_style_processor_impl.hpp | 64 +++++++++++++------ 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e650903f1..ba5601776 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ For a complete change history, see the git log. ## Future +- Allow style level compositing operations to work outside of featureset extents across tiled requests (#1477) + - Support for encoding `literal` postgres types as strings 69fb17cd3/#1466 - Fixed zoom_all behavior when Map maximum-extent is provided. Previously maximum-extent was used outright but diff --git a/include/mapnik/feature_style_processor_impl.hpp b/include/mapnik/feature_style_processor_impl.hpp index cb4479e47..1514087ca 100644 --- a/include/mapnik/feature_style_processor_impl.hpp +++ b/include/mapnik/feature_style_processor_impl.hpp @@ -256,6 +256,7 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces box2d layer_ext = lay.envelope(); bool fw_success = false; + bool early_return = false; // first, try intersection of map extent forward projected into layer srs if (prj_trans.forward(buffered_query_ext, PROJ_ENVELOPE_POINTS) && buffered_query_ext.intersects(layer_ext)) @@ -266,10 +267,7 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces // if no intersection and projections are also equal, early return else if (prj_trans.equal()) { -#if defined(RENDERING_STATS) - layer_timer.discard(); -#endif - return; + early_return = true; } // next try intersection of layer extent back projected into map srs else if (prj_trans.backward(layer_ext, PROJ_ENVELOPE_POINTS) && buffered_query_ext.intersects(layer_ext)) @@ -278,7 +276,7 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces // forward project layer extent back into native projection if (! prj_trans.forward(layer_ext, PROJ_ENVELOPE_POINTS)) { - MAPNIK_LOG_DEBUG(feature_style_processor) + MAPNIK_LOG_ERROR(feature_style_processor) << "feature_style_processor: Layer=" << lay.name() << " extent=" << layer_ext << " in map projection " << " did not reproject properly back to layer projection"; @@ -287,6 +285,31 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces else { // if no intersection then nothing to do for layer + early_return = true; + } + + if (early_return) + { + // check for styles needing compositing operations applied + // https://github.com/mapnik/mapnik/issues/1477 + BOOST_FOREACH(std::string const& style_name, style_names) + { + boost::optional style=m_.find_style(style_name); + if (!style) + { + continue; + } + if (style->comp_op() || style->image_filters().size() > 0) + { + if (style->active(scale_denom)) + { + std::clog << "triggering\n"; + // trigger any needed compositing ops + p.start_style_processing(*style); + p.end_style_processing(*style); + } + } + } #if defined(RENDERING_STATS) layer_timer.discard(); #endif @@ -344,9 +367,8 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces continue; } - const std::vector& rules=(*style).get_rules(); + std::vector const& rules=(*style).get_rules(); bool active_rules=false; - BOOST_FOREACH(rule const& r, rules) { if (r.active(scale_denom)) @@ -444,22 +466,21 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces } else if (cache_features) { + memory_datasource cache; 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); } - - 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); - } + } + 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); } } // We only have a single style and no grouping. @@ -468,11 +489,8 @@ void feature_style_processor::apply_to_layer(layer const& lay, Proces 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); - } + render_style(lay, p, style, style_names[i++], + ds->features(q), prj_trans, scale_denom); } } } @@ -495,8 +513,12 @@ void feature_style_processor::render_style( proj_transform const& prj_trans, double scale_denom) { - p.start_style_processing(*style); + if (!features) + { + p.end_style_processing(*style); + return; + } #if defined(RENDERING_STATS) std::ostringstream s1; From e629cbb1c3e75649a157a172567d913bf65ac2fd Mon Sep 17 00:00:00 2001 From: Hermann Kraus Date: Sat, 15 Sep 2012 02:06:08 +0200 Subject: [PATCH 4/4] Raise Exception instead of returning None. --- bindings/python/mapnik/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/python/mapnik/__init__.py b/bindings/python/mapnik/__init__.py index dc1ed15cf..484a16db3 100644 --- a/bindings/python/mapnik/__init__.py +++ b/bindings/python/mapnik/__init__.py @@ -703,8 +703,8 @@ class _TextSymbolizer(TextSymbolizer,_injector): if isinstance(self.properties.format_tree, FormattingText): return self.properties.format_tree.text else: - return None # This text symbolizer is using complex formatting features. - # There is no single expression which could be returned as name + # There is no single expression which could be returned as name + raise RuntimeError("TextSymbolizer uses complex formatting features, but old compatibility interface is used to access it. Use self.properties.format_tree instead.") @name.setter def name(self, name):