From ec4ef1bb34f056a4e0381bb2d847ca4056f73cf0 Mon Sep 17 00:00:00 2001 From: Artem Pavlenko Date: Wed, 16 Mar 2011 16:50:02 +0000 Subject: [PATCH] + add missing files from 735_metawriter_inmem.patch --- include/mapnik/metawriter_factory.hpp | 55 +++++++++ include/mapnik/metawriter_inmem.hpp | 118 ++++++++++++++++++ src/metawriter_factory.cpp | 88 +++++++++++++ src/metawriter_inmem.cpp | 170 ++++++++++++++++++++++++++ 4 files changed, 431 insertions(+) create mode 100644 include/mapnik/metawriter_factory.hpp create mode 100644 include/mapnik/metawriter_inmem.hpp create mode 100644 src/metawriter_factory.cpp create mode 100644 src/metawriter_inmem.cpp diff --git a/include/mapnik/metawriter_factory.hpp b/include/mapnik/metawriter_factory.hpp new file mode 100644 index 000000000..2cd49226e --- /dev/null +++ b/include/mapnik/metawriter_factory.hpp @@ -0,0 +1,55 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2011 MapQuest + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + + +#ifndef METAWRITER_FACTORY_HPP +#define METAWRITER_FACTORY_HPP + +// mapnik +#include + +// boost +#include + +namespace mapnik { + +/** + * Creates a metawriter with the properties specified in the property + * tree argument. Currently, this is hard-coded to the JSON and inmem + * metawriters, but should provide an easy point to make them a + * proper factory method if this is wanted in the future. + */ +metawriter_ptr metawriter_create(const boost::property_tree::ptree &pt); + +/** + * Writes properties into the given property tree representing the + * metawriter argument, and which can be used to reconstruct it. + */ +void metawriter_save( + const metawriter_ptr &m, + boost::property_tree::ptree &pt, + bool explicit_defaults); + +}; + +#endif /* METAWRITER_FACTORY_HPP */ + diff --git a/include/mapnik/metawriter_inmem.hpp b/include/mapnik/metawriter_inmem.hpp new file mode 100644 index 000000000..98781aad2 --- /dev/null +++ b/include/mapnik/metawriter_inmem.hpp @@ -0,0 +1,118 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2011 MapQuest + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + + +#ifndef METAWRITER_INMEM_HPP +#define METAWRITER_INMEM_HPP + +// Mapnik +#include + +// STL +#include + +namespace mapnik { + +/** + * Keeps metadata information in-memory, where it can be retrieved by whatever's + * calling Mapnik and custom output provided. + * + * Stored data is all in image coordinates in the current implementation. + * + * This is most useful when Mapnik is being called from Python, and the result + * of the metawriter can be queried and injected into the (meta)tile or whatever + * in a very flexible way. E.g: for a GUI app the metawriter can be used to + * create hit areas, for a web app it could be used to create an HTML image map. + * + * Because this is kept in-memory, applying this metawriter to features which are + * very common in the rendered image will increase memory usage, especially if + * many attributes are also kept. + */ +class metawriter_inmem + : public metawriter, private boost::noncopyable { +public: + /** + * Construct an in-memory writer which keeps properties specified by the + * dflt_properties argument. For example: if dflt_properties contains "name", + * then the name attribute of rendered features referencing this metawriter + * will be kept in memory. + */ + metawriter_inmem(metawriter_properties dflt_properties); + ~metawriter_inmem(); + + virtual void add_box(box2d const& box, Feature const& feature, + CoordTransform const& t, + metawriter_properties const& properties); + virtual void add_text(placement const& p, + face_set_ptr face, + Feature const& feature, + CoordTransform const& t, + metawriter_properties const& properties); + virtual void add_polygon(path_type & path, + Feature const& feature, + CoordTransform const& t, + metawriter_properties const& properties); + virtual void add_line(path_type & path, + Feature const& feature, + CoordTransform const& t, + metawriter_properties const& properties); + + virtual void start(metawriter_property_map const& properties); + virtual void stop(); + virtual void set_map_srs(projection const& proj); + + /** + * An instance of a rendered feature. The box represents the image + * coordinates of a bounding box around the feature. The properties + * are the intersection of the features' properties and the "kept" + * properties of the metawriter. + */ + struct meta_instance { + box2d box; + std::map properties; + }; + + typedef std::list meta_instance_list; + + // const-only access to the instances. + const meta_instance_list &instances() const; + + // utility iterators for use in the python bindings. + meta_instance_list::const_iterator inst_begin() const; + meta_instance_list::const_iterator inst_end() const; + +private: + + std::list instances_; + + void add_vertices(path_type & path, + Feature const& feature, + CoordTransform const& t, + metawriter_properties const& properties); +}; + +/** Shared pointer to metawriter_inmem object. */ +typedef boost::shared_ptr metawriter_inmem_ptr; + +} + +#endif /* METAWRITER_INMEM_HPP */ diff --git a/src/metawriter_factory.cpp b/src/metawriter_factory.cpp new file mode 100644 index 000000000..6d6d3e7f4 --- /dev/null +++ b/src/metawriter_factory.cpp @@ -0,0 +1,88 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2011 MapQuest + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ +//$Id$ + +#include +#include + +#include +#include + +#include + +using boost::property_tree::ptree; +using boost::optional; +using std::string; + +namespace mapnik +{ + +metawriter_ptr +metawriter_create(const boost::property_tree::ptree &pt) { + metawriter_ptr writer; + string type = get_attr(pt, "type"); + + if (type == "json") { + string file = get_attr(pt, "file"); + optional properties = get_opt_attr(pt, "default-output"); + metawriter_json_ptr json = metawriter_json_ptr(new metawriter_json(properties, parse_path(file))); + optional output_empty = get_opt_attr(pt, "output-empty"); + if (output_empty) { + json->set_output_empty(*output_empty); + } + writer = json; + + } else if (type == "inmem") { + optional properties = get_opt_attr(pt, "default-output"); + metawriter_inmem_ptr inmem = metawriter_inmem_ptr(new metawriter_inmem(properties)); + writer = inmem; + + } else { + throw config_error(string("Unknown type '") + type + "'"); + } + + return writer; +} + +void +metawriter_save(const metawriter_ptr &metawriter, ptree &metawriter_node, bool explicit_defaults) { + + metawriter_json *json = dynamic_cast(metawriter.get()); + if (json) { + set_attr(metawriter_node, "type", "json"); + std::string const& filename = path_processor_type::to_string(*(json->get_filename())); + if (!filename.empty() || explicit_defaults) { + set_attr(metawriter_node, "file", filename); + } + } + + metawriter_inmem *inmem = dynamic_cast(metawriter.get()); + if (inmem) { + set_attr(metawriter_node, "type", "inmem"); + } + + if (!metawriter->get_default_properties().empty() || explicit_defaults) { + set_attr(metawriter_node, "default-output", metawriter->get_default_properties().to_string()); + } +} + +} // namespace mapnik diff --git a/src/metawriter_inmem.cpp b/src/metawriter_inmem.cpp new file mode 100644 index 000000000..3f34e08fa --- /dev/null +++ b/src/metawriter_inmem.cpp @@ -0,0 +1,170 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2011 MapQuest + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// Mapnik +#include +#include +#include + +// Boost +#include + +using std::map; +using std::string; + +namespace { + +using mapnik::value; +using mapnik::Feature; +using mapnik::metawriter_properties; + +// intersect a set of properties with those in the feature descriptor +map intersect_properties(const Feature &feature, const metawriter_properties &properties) { + const map &fprops = feature.props(); + map nprops; + + BOOST_FOREACH(string p, properties) { + map::const_iterator itr = fprops.find(p); + if (itr != fprops.end()) { + nprops.insert(*itr); + } + } + + return nprops; +} +} // end anonymous namespace + +namespace mapnik { + +metawriter_inmem::metawriter_inmem(metawriter_properties dflt_properties) + : metawriter(dflt_properties) { + // ??? +} + +metawriter_inmem::~metawriter_inmem() { +} + +void +metawriter_inmem::add_box(box2d const& box, Feature const& feature, + CoordTransform const& t, + metawriter_properties const& properties) { + meta_instance inst; + inst.box = box; + inst.properties = intersect_properties(feature, properties); + instances_.push_back(inst); +} + +void +metawriter_inmem::add_text(placement const& p, + face_set_ptr face, + Feature const& feature, + CoordTransform const& t, + metawriter_properties const& properties) { + // there's more than one bbox for the text (one for each char), so keeping it + // simple for the moment and merging them all together... + if (p.envelopes.size() > 0) { + // stupid queue - doesn't expose begin() and end(), so forced to iterate by + // taking a copy... + std::queue > env_copy = p.envelopes; + meta_instance inst; + box2d box = env_copy.front(); + while (env_copy.size() > 1) { + env_copy.pop(); + box.expand_to_include(env_copy.front()); + } + inst.properties = intersect_properties(feature, properties); + inst.box = box; + instances_.push_back(inst); + } +} + +void +metawriter_inmem::add_polygon(path_type & path, + Feature const& feature, + CoordTransform const& t, + metawriter_properties const& properties) { + add_vertices(path, feature, t, properties); +} + +void +metawriter_inmem::add_line(path_type & path, + Feature const& feature, + CoordTransform const& t, + metawriter_properties const& properties) { + add_vertices(path, feature, t, properties); +} + +void +metawriter_inmem::add_vertices(path_type & path, + Feature const& feature, + CoordTransform const& t, + metawriter_properties const& properties) { + box2d box; + unsigned cmd; + double x = 0.0, y = 0.0; + + path.rewind(0); + while ((cmd = path.vertex(&x, &y)) != SEG_END) { + box.expand_to_include(x, y); + } + + if ((box.width() >= 0.0) && (box.height() >= 0.0)) { + meta_instance inst; + inst.properties = intersect_properties(feature, properties); + inst.box = box; + instances_.push_back(inst); + } +} + +void +metawriter_inmem::start(metawriter_property_map const& properties) { + instances_.clear(); +} + +void +metawriter_inmem::stop() { +} + +void +metawriter_inmem::set_map_srs(projection const& proj) { + // currently unused, since the inmem metawriter keeps everything in + // image coordinates. +} + +const std::list & +metawriter_inmem::instances() const { + return instances_; +} + +metawriter_inmem::meta_instance_list::const_iterator +metawriter_inmem::inst_begin() const { + return instances_.begin(); +} + +metawriter_inmem::meta_instance_list::const_iterator +metawriter_inmem::inst_end() const { + return instances_.end(); +} + + +} +