+ impl metawriter_renderer - initial stub

This commit is contained in:
Artem Pavlenko 2012-06-08 13:24:15 +01:00
parent 03e6f9d023
commit b37212d9a0
25 changed files with 880 additions and 332 deletions

View file

@ -150,16 +150,17 @@ bool has_metawriter(mapnik::Map const& m)
// returns empty shared_ptr when the metawriter isn't found, or is // returns empty shared_ptr when the metawriter isn't found, or is
// of the wrong type. empty pointers make it back to Python as a None. // of the wrong type. empty pointers make it back to Python as a None.
mapnik::metawriter_inmem_ptr find_inmem_metawriter(const mapnik::Map & m, std::string const& name) {
mapnik::metawriter_ptr metawriter = m.find_metawriter(name);
mapnik::metawriter_inmem_ptr inmem;
if (metawriter) { //mapnik::metawriter_inmem_ptr find_inmem_metawriter(const mapnik::Map & m, std::string const& name) {
inmem = boost::dynamic_pointer_cast<mapnik::metawriter_inmem>(metawriter); // mapnik::metawriter_ptr metawriter = m.find_metawriter(name);
} /// mapnik::metawriter_inmem_ptr inmem;
return inmem; // if (metawriter) {
} // inmem = boost::dynamic_pointer_cast<mapnik::metawriter_inmem>(metawriter);
// }
//
// return inmem;
//}
// TODO - we likely should allow indexing by negative number from python // TODO - we likely should allow indexing by negative number from python
// for now, protect against negative values and kindly throw // for now, protect against negative values and kindly throw
@ -482,13 +483,14 @@ void export_map()
"\n" "\n"
"Use a path like \"[z]/[x]/[y].json\" to create filenames.\n" "Use a path like \"[z]/[x]/[y].json\" to create filenames.\n"
) )
.def("find_inmem_metawriter", find_inmem_metawriter,
(arg("name")), // .def("find_inmem_metawriter", find_inmem_metawriter,
"Gets an inmem metawriter, or None if no such metawriter " // (arg("name")),
"exists.\n" // "Gets an inmem metawriter, or None if no such metawriter "
"Use this after the map has been rendered to retrieve information " // "exists.\n"
"about the hit areas rendered on the map.\n" // "Use this after the map has been rendered to retrieve information "
) // "about the hit areas rendered on the map.\n"
// )
.def("__deepcopy__",&map_deepcopy) .def("__deepcopy__",&map_deepcopy)
.add_property("parameters",make_function(params_nonconst,return_value_policy<reference_existing_object>()),"TODO") .add_property("parameters",make_function(params_nonconst,return_value_policy<reference_existing_object>()),"TODO")

View file

@ -39,6 +39,12 @@
#include <mapnik/config_error.hpp> #include <mapnik/config_error.hpp>
#include <mapnik/load_map.hpp> #include <mapnik/load_map.hpp>
#include <mapnik/save_map.hpp> #include <mapnik/save_map.hpp>
#include <mapnik/metawriter_renderer.hpp>
#ifdef HAVE_CAIRO
// cairo
#include <mapnik/cairo_renderer.hpp>
#include <cairomm/surface.h>
#endif
#endif #endif
// qt // qt
@ -49,6 +55,8 @@
#include "layerdelegate.hpp" #include "layerdelegate.hpp"
#include "about_dialog.hpp" #include "about_dialog.hpp"
MainWindow::MainWindow() MainWindow::MainWindow()
: filename_(), : filename_(),
default_extent_(-20037508.3428,-20037508.3428,20037508.3428,20037508.3428) default_extent_(-20037508.3428,-20037508.3428,20037508.3428,20037508.3428)
@ -256,6 +264,56 @@ void MainWindow::export_as()
} }
} }
void MainWindow::export_as_pdf()
{
QAction *action = qobject_cast<QAction *>(sender());
QString initialPath = QDir::currentPath() + "/mapnik-cairo.pdf";
QString fileName = QFileDialog::getSaveFileName(this, tr("Export As PDF"),
initialPath,
tr("%1 Files (*.%2);;All Files (*)")
.arg(QString("PDF"))
.arg(QString("pdf")));
if (!fileName.isEmpty())
{
std::cout << "FILE NAME:" << fileName.toStdString() << std::endl;
#ifdef HAVE_CAIRO
boost::shared_ptr<mapnik::Map> map_ptr = mapWidget_->getMap();
if (map_ptr)
{
Cairo::RefPtr<Cairo::Surface> surface;
surface = Cairo::PdfSurface::create(fileName.toStdString().c_str(), map_ptr->width(),map_ptr->height());
mapnik::cairo_renderer<Cairo::Surface> pdf_render(*map_ptr, surface);
pdf_render.apply();
}
#endif
}
}
void MainWindow::export_as_meta()
{
QAction *action = qobject_cast<QAction *>(sender());
QString initialPath = QDir::currentPath() + "/mapnik-meta.json";
QString fileName = QFileDialog::getSaveFileName(this, tr("Export As Meta JSON"),
initialPath,
tr("%1 Files (*.%2);;All Files (*)")
.arg(QString("META"))
.arg(QString("json")));
if (!fileName.isEmpty())
{
std::cout << "FILE NAME:" << fileName.toStdString() << std::endl;
#ifdef HAVE_CAIRO
boost::shared_ptr<mapnik::Map> map_ptr = mapWidget_->getMap();
if (map_ptr)
{
mapnik::metawriter_renderer ren(*map_ptr);
ren.apply();
}
#endif
}
}
void MainWindow::print() void MainWindow::print()
{ {
@ -328,6 +386,14 @@ void MainWindow::createActions()
exportAsActs.append(action); exportAsActs.append(action);
} }
// export PDF
exportPdfAction = new QAction(QString("PDF (cairo)"), this);
connect(exportPdfAction, SIGNAL(triggered()), this, SLOT(export_as_pdf()));
// export META Json
exportMetaAction = new QAction(QString("META (json)"), this);
connect(exportMetaAction, SIGNAL(triggered()), this, SLOT(export_as_meta()));
printAct = new QAction(QIcon(":/images/print.png"),tr("&Print ..."),this); printAct = new QAction(QIcon(":/images/print.png"),tr("&Print ..."),this);
printAct->setShortcut(tr("Ctrl+E")); printAct->setShortcut(tr("Ctrl+E"));
connect(printAct, SIGNAL(triggered()), this, SLOT(print())); connect(printAct, SIGNAL(triggered()), this, SLOT(print()));
@ -349,6 +415,8 @@ void MainWindow::createMenus()
fileMenu = new QMenu(tr("&File"),this); fileMenu = new QMenu(tr("&File"),this);
fileMenu->addAction(openAct); fileMenu->addAction(openAct);
fileMenu->addAction(saveAct); fileMenu->addAction(saveAct);
fileMenu->addAction(exportPdfAction);
fileMenu->addAction(exportMetaAction);
fileMenu->addMenu(exportMenu); fileMenu->addMenu(exportMenu);
fileMenu->addAction(printAct); fileMenu->addAction(printAct);
fileMenu->addSeparator(); fileMenu->addSeparator();

View file

@ -54,6 +54,8 @@ public slots:
void pan(); void pan();
void info(); void info();
void export_as(); void export_as();
void export_as_pdf();
void export_as_meta();
void open(QString const& path = QString()); void open(QString const& path = QString());
void reload(); void reload();
void save(); void save();
@ -88,6 +90,8 @@ private:
QAction *infoAct; QAction *infoAct;
QAction *openAct; QAction *openAct;
QAction *saveAct; QAction *saveAct;
QAction *exportPdfAction;
QAction *exportMetaAction;
QAction *printAct; QAction *printAct;
QAction *exitAct; QAction *exitAct;
QAction *aboutAct; QAction *aboutAct;

View file

@ -28,7 +28,7 @@
#include <mapnik/feature_type_style.hpp> #include <mapnik/feature_type_style.hpp>
#include <mapnik/datasource.hpp> #include <mapnik/datasource.hpp>
#include <mapnik/layer.hpp> #include <mapnik/layer.hpp>
#include <mapnik/metawriter.hpp> #include <mapnik/metawriter_factory.hpp>
#include <mapnik/params.hpp> #include <mapnik/params.hpp>
// boost // boost
@ -72,7 +72,7 @@ private:
boost::optional<color> background_; boost::optional<color> background_;
boost::optional<std::string> background_image_; boost::optional<std::string> background_image_;
std::map<std::string,feature_type_style> styles_; std::map<std::string,feature_type_style> styles_;
std::map<std::string,metawriter_ptr> metawriters_; std::map<std::string,metawriter> metawriters_;
std::map<std::string,font_set> fontsets_; std::map<std::string,font_set> fontsets_;
std::vector<layer> layers_; std::vector<layer> layers_;
aspect_fix_mode aspectFixMode_; aspect_fix_mode aspectFixMode_;
@ -87,7 +87,7 @@ public:
typedef std::map<std::string,feature_type_style>::iterator style_iterator; typedef std::map<std::string,feature_type_style>::iterator style_iterator;
typedef std::map<std::string,font_set>::const_iterator const_fontset_iterator; typedef std::map<std::string,font_set>::const_iterator const_fontset_iterator;
typedef std::map<std::string,font_set>::iterator fontset_iterator; typedef std::map<std::string,font_set>::iterator fontset_iterator;
typedef std::map<std::string,metawriter_ptr>::const_iterator const_metawriter_iterator; typedef std::map<std::string,metawriter>::const_iterator const_metawriter_iterator;
/*! \brief Default constructor. /*! \brief Default constructor.
* *
@ -173,7 +173,7 @@ public:
* @return true If success. * @return true If success.
* @return false If no success. * @return false If no success.
*/ */
bool insert_metawriter(std::string const& name, metawriter_ptr const& writer); bool insert_metawriter(std::string const& name, metawriter const& writer);
/*! \brief Remove a metawriter from the map. /*! \brief Remove a metawriter from the map.
* @param name The name of the writer. * @param name The name of the writer.
@ -184,12 +184,12 @@ public:
* @param name The name of the writer. * @param name The name of the writer.
* @return The writer if found. If not found return 0. * @return The writer if found. If not found return 0.
*/ */
metawriter_ptr find_metawriter(std::string const& name) const; metawriter find_metawriter(std::string const& name) const;
/*! \brief Get all metawriters. /*! \brief Get all metawriters.
* @return Const reference to metawriters. * @return Const reference to metawriters.
*/ */
std::map<std::string,metawriter_ptr> const& metawriters() const; std::map<std::string,metawriter> const& metawriters() const;
/*! \brief Get first iterator in metawriters. /*! \brief Get first iterator in metawriters.
* @return Constant metawriter iterator. * @return Constant metawriter iterator.

View file

@ -27,13 +27,12 @@
#include <mapnik/feature.hpp> #include <mapnik/feature.hpp>
#include <mapnik/ctrans.hpp> #include <mapnik/ctrans.hpp>
#include <mapnik/projection.hpp> #include <mapnik/projection.hpp>
// boost // boost
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/concept_check.hpp> #include <boost/concept_check.hpp>
#include <boost/variant.hpp>
// stl // stl
#include <set> #include <set>
#include <string> #include <string>
@ -79,7 +78,7 @@ private:
}; };
/** All properties to be output by a metawriter. */ // All properties to be output by a metawriter.
class metawriter_properties : public std::set<std::string> class metawriter_properties : public std::set<std::string>
{ {
public: public:
@ -90,76 +89,23 @@ public:
std::string to_string() const; std::string to_string() const;
}; };
/** Abstract baseclass for all metawriter classes. */ // Abstract baseclass for all metawriter classes.
class metawriter class metawriter_base
{ {
public: public:
typedef coord_transform<CoordTransform,geometry_type> path_type; explicit metawriter_base(metawriter_properties dflt_properties) :
metawriter(metawriter_properties dflt_properties) :
dflt_properties_(dflt_properties), dflt_properties_(dflt_properties),
width_(0), width_(0),
height_(0) {} height_(0) {}
virtual ~metawriter() {}
/** Output a rectangular area. void set_size(int width, int height) { width_ = width; height_ = height; }
* \param box Area (in pixel coordinates)
* \param feature The feature being processed
* \param prj_trans Projection transformation
* \param t Coordinate transformation
* \param properties List of properties to output
*/
virtual void add_box(box2d<double> const& box, Feature const& feature,
CoordTransform const& t,
metawriter_properties const& properties)=0;
virtual void add_text(boost::ptr_vector<text_path> &placements,
box2d<double> const& extents,
Feature const& feature,
CoordTransform const& t,
metawriter_properties const& properties)=0;
virtual void add_polygon(path_type & path,
Feature const& feature,
CoordTransform const& t,
metawriter_properties const& properties)=0;
virtual void add_line(path_type & path,
Feature const& feature,
CoordTransform const& t,
metawriter_properties const& properties)=0;
/** Start processing.
* Write file header, init database connection, ...
*
* \param properties metawriter_property_map object with userdefined values.
* Useful for setting filename etc.
*/
virtual void start(metawriter_property_map const& properties)
{
boost::ignore_unused_variable_warning(properties);
}
/** Stop processing.
* Write file footer, close database connection, ...
*/
virtual void stop() {}
/** Set output size (pixels).
* All features that are completely outside this size are discarded.
*/
void set_size(int width, int height) { width_ = width; height_ = height; }
/** Set Map object's srs. */
virtual void set_map_srs(projection const& proj) { /* Not required when working with image coordinates. */ }
/** Return the list of default properties. */
metawriter_properties const& get_default_properties() const { return dflt_properties_;} metawriter_properties const& get_default_properties() const { return dflt_properties_;}
protected: protected:
metawriter_properties dflt_properties_; metawriter_properties dflt_properties_;
/** Output width (pixels). */
int width_; int width_;
/** Output height (pixels). */
int height_; int height_;
}; };
/** Shared pointer to metawriter object. */
typedef boost::shared_ptr<metawriter> metawriter_ptr;
/** Metawriter object + properties. */
typedef std::pair<metawriter_ptr, metawriter_properties> metawriter_with_properties;
} }
#endif // MAPNIK_METAWRITER_HPP #endif // MAPNIK_METAWRITER_HPP

View file

@ -25,28 +25,198 @@
// mapnik // mapnik
#include <mapnik/metawriter.hpp> #include <mapnik/metawriter.hpp>
#include <mapnik/metawriter_json.hpp>
#include <mapnik/metawriter_inmem.hpp>
// boost // boost
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/ptree.hpp>
namespace mapnik { namespace mapnik {
class xml_node; class xml_node;
struct is_valid : boost::static_visitor<bool>
{
template <typename T>
bool operator() (T const& writer_ptr) const
{
return (writer_ptr.get()!=0) ? true : false;
}
};
struct add_box_ : boost::static_visitor<>
{
add_box_(box2d<double> const& box, Feature const& feature,
CoordTransform const& t,
metawriter_properties const& properties)
: box_(box),
feature_(feature),
t_(t),
properties_(properties)
{}
template <typename T>
void operator() (T const& writer_ptr) const
{
return writer_ptr->add_box(box_,feature_,t_, properties_);
}
box2d<double> const& box_;
Feature const& feature_;
CoordTransform const& t_;
metawriter_properties const& properties_;
};
template <typename T>
struct add_line_ : boost::static_visitor<>
{
typedef T path_type;
add_line_(path_type & path, Feature const& feature,
CoordTransform const& t,
metawriter_properties const& properties)
: path_(path),
feature_(feature),
t_(t),
properties_(properties)
{}
template <typename U>
void operator() (U const& writer_ptr) const
{
return writer_ptr->add_line(path_,feature_,t_, properties_);
}
path_type & path_;
Feature const& feature_;
CoordTransform const& t_;
metawriter_properties const& properties_;
};
struct start_ : boost::static_visitor<>
{
start_(metawriter_property_map const& properties)
: properties_(properties) {}
template <typename U>
void operator() (U const& writer_ptr) const
{
std::cout << typeid(*writer_ptr).name() << std::endl;
return writer_ptr->start(properties_);
}
metawriter_property_map const& properties_;
};
struct set_size_ : boost::static_visitor<>
{
set_size_(unsigned w, unsigned h)
: w_(w), h_(h) {}
template <typename U>
void operator() (U const& writer_ptr) const
{
return writer_ptr->set_size(w_,h_);
}
unsigned w_;
unsigned h_;
};
struct set_map_srs_ : boost::static_visitor<>
{
set_map_srs_(projection const& proj)
: proj_(proj) {}
template <typename U>
void operator() (U const& writer_ptr) const
{
return writer_ptr->set_map_srs(proj_);
}
projection const& proj_;
};
struct stop_ : boost::static_visitor<>
{
template <typename U>
void operator() (U const& writer_ptr) const
{
return writer_ptr->stop();
}
};
typedef boost::variant<metawriter_json_ptr, metawriter_inmem_ptr> metawriter;
inline bool check_metawriter(metawriter const& m)
{
return boost::apply_visitor(is_valid(), m);
}
inline void add_box(metawriter const& m,
box2d<double> const& box, Feature const& feature,
CoordTransform const& t,
metawriter_properties const& properties)
{
add_box_ v(box,feature,t,properties);
boost::apply_visitor(v, m);
}
template <typename T>
void add_line(metawriter const& m,
T & path,
Feature const& feature,
CoordTransform const& t,
metawriter_properties const& properties)
{
add_line_<T> v(path,feature,t,properties);
boost::apply_visitor(v, m);
}
inline void start(metawriter const& m, metawriter_property_map const& properties )
{
start_ v(properties);
boost::apply_visitor(v, m);
}
inline void stop(metawriter const& m)
{
boost::apply_visitor(stop_(), m);
}
inline void set_size(metawriter const& m, unsigned w, unsigned h)
{
set_size_ v(w,h);
boost::apply_visitor(v, m);
}
inline void set_map_srs(metawriter const& m, projection const& proj)
{
set_map_srs_ v(proj);
boost::apply_visitor(v, m);
}
typedef std::pair<metawriter, metawriter_properties> metawriter_with_properties;
/** /**
* Creates a metawriter with the properties specified in the property * Creates a metawriter with the properties specified in the property
* tree argument. Currently, this is hard-coded to the JSON and inmem * tree argument. Currently, this is hard-coded to the JSON and inmem
* metawriters, but should provide an easy point to make them a * metawriters, but should provide an easy point to make them a
* proper factory method if this is wanted in the future. * proper factory method if this is wanted in the future.
*/ */
metawriter_ptr metawriter_create(xml_node const& pt); metawriter metawriter_create(xml_node const& pt);
/** /**
* Writes properties into the given property tree representing the * Writes properties into the given property tree representing the
* metawriter argument, and which can be used to reconstruct it. * metawriter argument, and which can be used to reconstruct it.
*/ */
void metawriter_save( void metawriter_save(
const metawriter_ptr &m, metawriter const& m,
boost::property_tree::ptree &pt, boost::property_tree::ptree & pt,
bool explicit_defaults); bool explicit_defaults);
} }

View file

@ -32,6 +32,8 @@
// stl // stl
#include <list> #include <list>
#include <map>
#include <string>
namespace mapnik { namespace mapnik {
@ -50,37 +52,76 @@ namespace mapnik {
* very common in the rendered image will increase memory usage, especially if * very common in the rendered image will increase memory usage, especially if
* many attributes are also kept. * many attributes are also kept.
*/ */
namespace {
using mapnik::value;
using mapnik::Feature;
using mapnik::metawriter_properties;
// intersect a set of properties with those in the feature descriptor
std::map<std::string,value> intersect_properties(Feature const& feature, metawriter_properties const& properties)
{
std::map<std::string,value> nprops;
BOOST_FOREACH(std::string p, properties)
{
if (feature.has_key(p))
nprops.insert(std::make_pair(p,feature.get(p)));
}
return nprops;
}} // end anonymous namespace
class MAPNIK_DECL metawriter_inmem class MAPNIK_DECL metawriter_inmem
: public metawriter, private boost::noncopyable { : public metawriter_base, private boost::noncopyable
{
public: 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(metawriter_properties dflt_properties);
~metawriter_inmem(); ~metawriter_inmem();
virtual void add_box(box2d<double> const& box, Feature const& feature, void add_box(box2d<double> const& box, Feature const& feature,
CoordTransform const& t, CoordTransform const& t,
metawriter_properties const& properties); metawriter_properties const& properties);
virtual void add_text(boost::ptr_vector<text_path> &placements, void add_text(boost::ptr_vector<text_path> &placements,
box2d<double> const& extents, box2d<double> const& extents,
Feature const& feature, Feature const& feature,
CoordTransform const& t, CoordTransform const& t,
metawriter_properties const& properties); metawriter_properties const& properties);
virtual void add_polygon(path_type & path,
Feature const& feature, template <typename T>
CoordTransform const& t, void add_polygon(T & path,
metawriter_properties const& properties); Feature const& feature,
virtual void add_line(path_type & path, CoordTransform const& t,
Feature const& feature, metawriter_properties const& properties);
CoordTransform const& t,
metawriter_properties const& properties); template <typename T>
void add_line(T & path,
virtual void start(metawriter_property_map const& properties); Feature const& feature,
CoordTransform const& t,
metawriter_properties const& properties)
{
box2d<double> 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 start(metawriter_property_map const& properties);
void stop() {};
void set_map_srs(projection const& proj) {}
/** /**
* An instance of a rendered feature. The box represents the image * An instance of a rendered feature. The box represents the image
* coordinates of a bounding box around the feature. The properties * coordinates of a bounding box around the feature. The properties
@ -105,7 +146,8 @@ private:
std::list<meta_instance> instances_; std::list<meta_instance> instances_;
void add_vertices(path_type & path, template <typename T>
void add_vertices(T & path,
Feature const& feature, Feature const& feature,
CoordTransform const& t, CoordTransform const& t,
metawriter_properties const& properties); metawriter_properties const& properties);

View file

@ -35,44 +35,69 @@
namespace mapnik { namespace mapnik {
class metawriter_json_stream : public metawriter_base,
/** Write JSON data to a stream object. */ private boost::noncopyable
class metawriter_json_stream : public metawriter, private boost::noncopyable
{ {
public: public:
metawriter_json_stream(metawriter_properties dflt_properties); explicit metawriter_json_stream(metawriter_properties dflt_properties);
~metawriter_json_stream(); ~metawriter_json_stream();
virtual void add_box(box2d<double> const& box, Feature const& feature, void add_box(box2d<double> const& box, Feature const& feature,
CoordTransform const& t, CoordTransform const& t,
metawriter_properties const& properties); metawriter_properties const& properties);
virtual void add_text(boost::ptr_vector<text_path> &placements, void add_text(boost::ptr_vector<text_path> &placements,
box2d<double> const& extents, box2d<double> const& extents,
Feature const& feature, Feature const& feature,
CoordTransform const& t, CoordTransform const& t,
metawriter_properties const& properties); metawriter_properties const& properties);
virtual void add_polygon(path_type & path, template <typename T>
Feature const& feature, void add_polygon(T & path,
CoordTransform const& t, Feature const& feature,
metawriter_properties const& properties); CoordTransform const& t,
virtual void add_line(path_type & path, metawriter_properties const& properties);
Feature const& feature,
CoordTransform const& t, template <typename T>
metawriter_properties const& properties); void add_line(T & path,
Feature const& feature,
CoordTransform const& t,
metawriter_properties const& properties)
{
write_feature_header("MultiLineString");
virtual void start(metawriter_property_map const& properties); *f_ << " [";
virtual void stop(); double x, y, last_x=0.0, last_y=0.0;
/** Set output stream. This function has to be called before the first output is made. */ unsigned cmd, last_cmd = SEG_END;
void set_stream(std::ostream *f) { f_ = f; } path.rewind(0);
/** Get output stream. */
std::ostream *get_stream() const { return f_; } int polygon_count = 0;
/** Only write header/footer to file with one or more features. */ while ((cmd = path.vertex(&x, &y)) != SEG_END) {
void set_output_empty(bool output_empty) { output_empty_ = output_empty; } if (cmd == SEG_LINETO) {
/** See set_output_empty(). */ if (last_cmd == SEG_MOVETO) {
//Start new polygon/line
if (polygon_count++) *f_ << "], ";
*f_ << "[";
write_point(t, last_x, last_y, true);
}
*f_ << ",";
write_point(t, x, y, true);
}
last_x = x;
last_y = y;
last_cmd = cmd;
}
*f_ << "]]";
write_properties(feature, properties);
}
void start(metawriter_property_map const& properties);
void stop();
void set_stream(std::ostream *f) { f_ = f; }
std::ostream *get_stream() const { return f_; }
void set_output_empty(bool output_empty) { output_empty_ = output_empty; }
bool get_output_empty() { return output_empty_; } bool get_output_empty() { return output_empty_; }
void set_pixel_coordinates(bool on) { pixel_coordinates_ = on; } void set_pixel_coordinates(bool on) { pixel_coordinates_ = on; }
bool get_pixel_coordinates() { return pixel_coordinates_; } bool get_pixel_coordinates() { return pixel_coordinates_; }
virtual void set_map_srs(projection const& proj); void set_map_srs(projection const& proj);
protected: protected:
enum { enum {
HEADER_NOT_WRITTEN = -1, HEADER_NOT_WRITTEN = -1,
@ -87,10 +112,10 @@ protected:
proj_transform *trans_; proj_transform *trans_;
projection output_srs_; projection output_srs_;
bool pixel_coordinates_; bool pixel_coordinates_;
virtual void write_header(); void write_header();
inline void write_feature_header(std::string type)
inline void write_feature_header(std::string type) { {
if (count_ == STOPPED) if (count_ == STOPPED)
{ {
MAPNIK_LOG_WARN(metawrite_json) << "Metawriter: instance not started before using it."; MAPNIK_LOG_WARN(metawrite_json) << "Metawriter: instance not started before using it.";
@ -116,43 +141,38 @@ protected:
*f_ << ","; *f_ << ",";
} }
} }
template <typename T>
void write_line_polygon(T & path, CoordTransform const& t, bool polygon);
void write_line_polygon(path_type & path, CoordTransform const& t, bool polygon);
private: private:
std::ostream *f_; std::ostream *f_;
}; };
/** Shared pointer to metawriter_json_stream object. */ //typedef boost::shared_ptr<metawriter_json_stream> metawriter_json_stream_ptr;
typedef boost::shared_ptr<metawriter_json_stream> metawriter_json_stream_ptr;
/** JSON writer. */ // JSON writer.
class metawriter_json : public metawriter_json_stream class metawriter_json : public metawriter_json_stream
{ {
public: public:
metawriter_json(metawriter_properties dflt_properties, path_expression_ptr fn); metawriter_json(metawriter_properties dflt_properties, path_expression_ptr fn);
void start(metawriter_property_map const& properties);
virtual void start(metawriter_property_map const& properties); void stop();
virtual void stop();
/** Set filename template.
*
* This template is processed with values from Map's metawriter properties to
* create the actual filename during start() call.
*/
void set_filename(path_expression_ptr fn); void set_filename(path_expression_ptr fn);
/** Get filename template. */
path_expression_ptr get_filename() const; path_expression_ptr get_filename() const;
private: private:
path_expression_ptr fn_; path_expression_ptr fn_;
std::fstream f_; std::fstream f_;
std::string filename_; std::string filename_;
protected: protected:
virtual void write_header(); void write_header();
}; };
/** Shared pointer to metawriter_json object. */
typedef boost::shared_ptr<metawriter_json> metawriter_json_ptr; typedef boost::shared_ptr<metawriter_json> metawriter_json_ptr;
} }

View file

@ -0,0 +1,85 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
#ifndef MAPNIK_METAWRITER_RENDERER_HPP
#define MAPNIK_METAWRITER_RENDERER_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/feature_style_processor.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/label_collision_detector.hpp>
#include <mapnik/map.hpp>
// boost
#include <boost/utility.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>
namespace agg {
struct trans_affine;
}
namespace mapnik {
class MAPNIK_DECL metawriter_renderer : public feature_style_processor<metawriter_renderer>,
private boost::noncopyable
{
public:
typedef metawriter_renderer processor_impl_type;
metawriter_renderer(Map const& m, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
metawriter_renderer(Map const &m, boost::shared_ptr<label_collision_detector4> detector,
double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
~metawriter_renderer();
void start_map_processing(Map const& map);
void end_map_processing(Map const& map);
void start_layer_processing(layer const& lay, box2d<double> const& query_extent);
void end_layer_processing(layer const& lay);
void start_style_processing(feature_type_style const& st);
void end_style_processing(feature_type_style const& st);
/*
void process(point_symbolizer const& sym,
mapnik::feature_ptr const& feature,
proj_transform const& prj_trans);
*/
void process(line_symbolizer const& sym,
mapnik::feature_ptr const& feature,
proj_transform const& prj_trans);
void painted(bool painted);
private:
unsigned width_;
unsigned height_;
double scale_factor_;
CoordTransform t_;
freetype_engine font_engine_;
face_manager<freetype_engine> font_manager_;
boost::shared_ptr<label_collision_detector4> detector_;
box2d<double> query_extent_;
void setup(Map const &m);
};
}
#endif // MAPNIK_METAWRITER_RENDERER_HPP

View file

@ -26,7 +26,7 @@
// mapnik // mapnik
#include <mapnik/config.hpp> #include <mapnik/config.hpp>
#include <mapnik/parse_path.hpp> #include <mapnik/parse_path.hpp>
#include <mapnik/metawriter.hpp> #include <mapnik/metawriter_factory.hpp>
#include <mapnik/image_compositing.hpp> #include <mapnik/image_compositing.hpp>
#include <mapnik/transform_expression.hpp> #include <mapnik/transform_expression.hpp>
@ -52,12 +52,8 @@ public:
/** Add a metawriter to this symbolizer using a name. */ /** Add a metawriter to this symbolizer using a name. */
void add_metawriter(std::string const& name, metawriter_properties const& properties); void add_metawriter(std::string const& name, metawriter_properties const& properties);
/** Add a metawriter to this symbolizer using a pointer.
* The name is only needed if you intend to call save_map() some time. void add_metawriter(metawriter const& writer,
* You don't need to call cache_metawriters() when using this function.
* Call this function with an NULL writer_ptr to remove a metawriter.
*/
void add_metawriter(metawriter_ptr writer_ptr,
metawriter_properties const& properties = metawriter_properties(), metawriter_properties const& properties = metawriter_properties(),
std::string const& name = ""); std::string const& name = "");
/** Cache metawriter objects to avoid repeated lookups while processing. /** Cache metawriter objects to avoid repeated lookups while processing.
@ -96,7 +92,7 @@ private:
metawriter_properties properties_; metawriter_properties properties_;
metawriter_properties properties_complete_; metawriter_properties properties_complete_;
std::string writer_name_; std::string writer_name_;
metawriter_ptr writer_ptr_; metawriter writer_;
composite_mode_e comp_op_; composite_mode_e comp_op_;
transform_type affine_transform_; transform_type affine_transform_;
bool clip_; bool clip_;

View file

@ -135,8 +135,8 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
// TODO - impl this for markers? // TODO - impl this for markers?
//if (!sym.get_ignore_placement()) //if (!sym.get_ignore_placement())
// detector_->insert(label_ext); // detector_->insert(label_ext);
metawriter_with_properties writer = sym.get_metawriter(); //metawriter_with_properties writer = sym.get_metawriter();
if (writer.first) writer.first->add_box(extent, *feature, t_, writer.second); //if (writer.first) writer.first->add_box(extent, *feature, t_, writer.second);
} }
} }
else else
@ -168,12 +168,12 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
// rotated itself // rotated itself
} }
if (writer.first) //if (writer.first)
{ //{
//writer.first->add_box(label_ext, feature, t_, writer.second); //writer.first->add_box(label_ext, feature, t_, writer.second);
MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: metawriter do not yet supported for line placement"; // MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: metawriter do not yet supported for line placement";
} //}
} }
} }
} }
@ -274,7 +274,7 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
} }
if (!sym.get_ignore_placement()) if (!sym.get_ignore_placement())
detector_->insert(label_ext); detector_->insert(label_ext);
if (writer.first) writer.first->add_box(label_ext, *feature, t_, writer.second); //if (writer.first) writer.first->add_box(label_ext, *feature, t_, writer.second);
} }
} }
else else
@ -315,12 +315,12 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
// TODO // TODO
if (writer.first) //if (writer.first)
{ //{
//writer.first->add_box(label_ext, feature, t_, writer.second); //writer.first->add_box(label_ext, feature, t_, writer.second);
MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: metawriter do not yet supported for line placement"; // MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: metawriter do not yet supported for line placement";
} //}
agg::conv_transform<agg::path_storage, agg::trans_affine> trans(marker, matrix); agg::conv_transform<agg::path_storage, agg::trans_affine> trans(marker, matrix);
ras_ptr->add_path(trans); ras_ptr->add_path(trans);

View file

@ -100,8 +100,8 @@ void agg_renderer<T>::process(point_symbolizer const& sym,
if (!sym.get_ignore_placement()) if (!sym.get_ignore_placement())
detector_->insert(label_ext); detector_->insert(label_ext);
metawriter_with_properties writer = sym.get_metawriter(); //metawriter_with_properties writer = sym.get_metawriter();
if (writer.first) writer.first->add_box(label_ext, *feature, t_, writer.second); //if (writer.first) writer.first->add_box(label_ext, *feature, t_, writer.second);
} }
} }
} }

View file

@ -273,6 +273,14 @@ source += Split(
grid/process_text_symbolizer.cpp grid/process_text_symbolizer.cpp
""") """)
# metawriter backend
# grid backend
source += Split(
"""
metawriter/metawriter_renderer.cpp
metawriter/process_line_symbolizer.cpp
""")
if env['SVG_RENDERER']: # svg backend if env['SVG_RENDERER']: # svg backend
source += Split( source += Split(
""" """

View file

@ -1172,9 +1172,10 @@ void cairo_renderer_base::start_map_processing(Map const& map)
if (!sym.get_ignore_placement()) if (!sym.get_ignore_placement())
detector_.insert(label_ext); detector_.insert(label_ext);
metawriter_with_properties writer = sym.get_metawriter(); metawriter_with_properties writer = sym.get_metawriter();
if (writer.first) if (check_metawriter(writer.first))
{ {
writer.first->add_box(label_ext, *feature, t_, writer.second); //writer.first->add_box(label_ext, *feature, t_, writer.second);
add_box(writer.first, label_ext,*feature, t_, writer.second);
} }
} }
} }
@ -1439,7 +1440,11 @@ void cairo_renderer_base::start_map_processing(Map const& map)
//if (!sym.get_ignore_placement()) //if (!sym.get_ignore_placement())
// detector_.insert(label_ext); // detector_.insert(label_ext);
metawriter_with_properties writer = sym.get_metawriter(); metawriter_with_properties writer = sym.get_metawriter();
if (writer.first) writer.first->add_box(extent, *feature, t_, writer.second); if (check_metawriter(writer.first))
{
add_box(writer.first, extent,*feature, t_, writer.second);
// writer.first->add_box(extent, *feature, t_, writer.second);
}
} }
} }
else else
@ -1458,7 +1463,7 @@ void cairo_renderer_base::start_map_processing(Map const& map)
agg::trans_affine matrix = recenter * tr * agg::trans_affine_rotation(angle) * agg::trans_affine_translation(x, y); agg::trans_affine matrix = recenter * tr * agg::trans_affine_rotation(angle) * agg::trans_affine_translation(x, y);
render_marker(pixel_position(x - 0.5 * w, y - 0.5 * h), **mark, matrix, sym.get_opacity(),false); render_marker(pixel_position(x - 0.5 * w, y - 0.5 * h), **mark, matrix, sym.get_opacity(),false);
if (writer.first) if (check_metawriter(writer.first))
{ {
//writer.first->add_box(label_ext, feature, t_, writer.second); //writer.first->add_box(label_ext, feature, t_, writer.second);
MAPNIK_LOG_WARN(cairo_renderer) << "metawriter not yet supported for LINE placement"; MAPNIK_LOG_WARN(cairo_renderer) << "metawriter not yet supported for LINE placement";
@ -1548,7 +1553,11 @@ void cairo_renderer_base::start_map_processing(Map const& map)
} }
if (!sym.get_ignore_placement()) if (!sym.get_ignore_placement())
detector_.insert(label_ext); detector_.insert(label_ext);
if (writer.first) writer.first->add_box(label_ext, *feature, t_, writer.second); if (check_metawriter(writer.first))
{
add_box(writer.first, label_ext,*feature, t_, writer.second);
// writer.first->add_box(label_ext, *feature, t_, writer.second);
}
} }
} }
else else
@ -1585,7 +1594,7 @@ void cairo_renderer_base::start_map_processing(Map const& map)
} }
// TODO // TODO
if (writer.first) if (check_metawriter(writer.first))
{ {
//writer.first->add_box(label_ext, feature, t_, writer.second); //writer.first->add_box(label_ext, feature, t_, writer.second);
MAPNIK_LOG_WARN(cairo_renderer) << "metawriter not yet supported for LINE placement"; MAPNIK_LOG_WARN(cairo_renderer) << "metawriter not yet supported for LINE placement";

View file

@ -32,7 +32,7 @@
#include <mapnik/scale_denominator.hpp> #include <mapnik/scale_denominator.hpp>
#include <mapnik/agg_renderer.hpp> #include <mapnik/agg_renderer.hpp>
#include <mapnik/grid/grid_renderer.hpp> #include <mapnik/grid/grid_renderer.hpp>
#include <mapnik/metawriter_renderer.hpp>
// boost // boost
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/concept_check.hpp> #include <boost/concept_check.hpp>
@ -78,7 +78,7 @@ struct process_impl<false>
boost::ignore_unused_variable_warning(f); boost::ignore_unused_variable_warning(f);
boost::ignore_unused_variable_warning(tr); boost::ignore_unused_variable_warning(tr);
#ifdef MAPNIK_DEBUG #ifdef MAPNIK_DEBUG
std::clog << "NO-OP ...\n"; std::clog << "NO-OP " << typeid(sym).name() << std::endl;
#endif #endif
} }
}; };
@ -150,7 +150,7 @@ void feature_style_processor<Processor>::apply()
{ {
projection proj(m_.srs()); projection proj(m_.srs());
start_metawriters(m_,proj); //start_metawriters(m_,proj);
double scale_denom = mapnik::scale_denominator(m_,proj.is_geographic()); double scale_denom = mapnik::scale_denominator(m_,proj.is_geographic());
scale_denom *= scale_factor_; scale_denom *= scale_factor_;
@ -164,7 +164,7 @@ void feature_style_processor<Processor>::apply()
} }
} }
stop_metawriters(m_); //stop_metawriters(m_);
} }
catch (proj_init_error& ex) catch (proj_init_error& ex)
{ {
@ -203,30 +203,6 @@ void feature_style_processor<Processor>::apply(mapnik::layer const& lyr, std::se
p.end_map_processing(m_); p.end_map_processing(m_);
} }
template <typename Processor>
void feature_style_processor<Processor>::start_metawriters(Map const& m_, projection const& proj)
{
Map::const_metawriter_iterator metaItr = m_.begin_metawriters();
Map::const_metawriter_iterator metaItrEnd = m_.end_metawriters();
for (;metaItr!=metaItrEnd; ++metaItr)
{
metaItr->second->set_size(m_.width(), m_.height());
metaItr->second->set_map_srs(proj);
metaItr->second->start(m_.metawriter_output_properties);
}
}
template <typename Processor>
void feature_style_processor<Processor>::stop_metawriters(Map const& m_)
{
Map::const_metawriter_iterator metaItr = m_.begin_metawriters();
Map::const_metawriter_iterator metaItrEnd = m_.end_metawriters();
for (;metaItr!=metaItrEnd; ++metaItr)
{
metaItr->second->stop();
}
}
template <typename Processor> template <typename Processor>
void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Processor & p, void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Processor & p,
projection const& proj0, projection const& proj0,
@ -556,7 +532,7 @@ void feature_style_processor<Processor>::render_style(
// if the underlying renderer is not able to process the complete set of symbolizers, // if the underlying renderer is not able to process the complete set of symbolizers,
// process one by one. // process one by one.
if(!p.process(symbols,feature,prj_trans)) // if(!p.process(symbols,feature,prj_trans))
{ {
BOOST_FOREACH (symbolizer const& sym, symbols) BOOST_FOREACH (symbolizer const& sym, symbols)
@ -584,7 +560,7 @@ void feature_style_processor<Processor>::render_style(
rule::symbolizers const& symbols = r->get_symbolizers(); rule::symbolizers const& symbols = r->get_symbolizers();
// if the underlying renderer is not able to process the complete set of symbolizers, // if the underlying renderer is not able to process the complete set of symbolizers,
// process one by one. // process one by one.
if(!p.process(symbols,feature,prj_trans)) //if(!p.process(symbols,feature,prj_trans))
{ {
BOOST_FOREACH (symbolizer const& sym, symbols) BOOST_FOREACH (symbolizer const& sym, symbols)
{ {
@ -606,7 +582,7 @@ void feature_style_processor<Processor>::render_style(
rule::symbolizers const& symbols = r->get_symbolizers(); rule::symbolizers const& symbols = r->get_symbolizers();
// if the underlying renderer is not able to process the complete set of symbolizers, // if the underlying renderer is not able to process the complete set of symbolizers,
// process one by one. // process one by one.
if(!p.process(symbols,feature,prj_trans)) //if(!p.process(symbols,feature,prj_trans))
{ {
BOOST_FOREACH (symbolizer const& sym, symbols) BOOST_FOREACH (symbolizer const& sym, symbols)
{ {
@ -656,6 +632,7 @@ template class feature_style_processor<svg_renderer<std::ostream_iterator<char>
template class feature_style_processor<grid_renderer<grid> >; template class feature_style_processor<grid_renderer<grid> >;
template class feature_style_processor<agg_renderer<image_32> >; template class feature_style_processor<agg_renderer<image_32> >;
template class feature_style_processor<metawriter_renderer>;
} }

View file

@ -498,7 +498,7 @@ void map_parser::parse_style(Map & map, xml_node const& sty)
void map_parser::parse_metawriter(Map & map, xml_node const& pt) void map_parser::parse_metawriter(Map & map, xml_node const& pt)
{ {
std::string name("<missing name>"); std::string name("<missing name>");
metawriter_ptr writer; metawriter writer;
try try
{ {
name = pt.get_attr<std::string>("name"); name = pt.get_attr<std::string>("name");

View file

@ -169,7 +169,7 @@ boost::optional<feature_type_style const&> Map::find_style(std::string const& na
return boost::optional<feature_type_style const&>() ; return boost::optional<feature_type_style const&>() ;
} }
bool Map::insert_metawriter(std::string const& name, metawriter_ptr const& writer) bool Map::insert_metawriter(std::string const& name, metawriter const& writer)
{ {
return metawriters_.insert(make_pair(name, writer)).second; return metawriters_.insert(make_pair(name, writer)).second;
} }
@ -179,16 +179,16 @@ void Map::remove_metawriter(std::string const& name)
metawriters_.erase(name); metawriters_.erase(name);
} }
metawriter_ptr Map::find_metawriter(std::string const& name) const metawriter Map::find_metawriter(std::string const& name) const
{ {
std::map<std::string, metawriter_ptr>::const_iterator itr = metawriters_.find(name); std::map<std::string, metawriter>::const_iterator itr = metawriters_.find(name);
if (itr != metawriters_.end()) if (itr != metawriters_.end())
return itr->second; return itr->second;
else else
return metawriter_ptr(); return metawriter();
} }
std::map<std::string,metawriter_ptr> const& Map::metawriters() const std::map<std::string,metawriter> const& Map::metawriters() const
{ {
return metawriters_; return metawriters_;
} }

View file

@ -97,7 +97,7 @@ metawriter_json_stream::~metawriter_json_stream()
metawriter_json_stream::metawriter_json_stream(metawriter_properties dflt_properties) metawriter_json_stream::metawriter_json_stream(metawriter_properties dflt_properties)
: metawriter(dflt_properties), count_(-1), output_empty_(true), : metawriter_base(dflt_properties), count_(-1), output_empty_(true),
trans_(0), output_srs_("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"), trans_(0), output_srs_("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"),
pixel_coordinates_(false), f_(0) pixel_coordinates_(false), f_(0)
{ {
@ -262,7 +262,8 @@ void metawriter_json_stream::add_text(
} }
} }
void metawriter_json_stream::add_polygon(path_type & path, template <typename T>
void metawriter_json_stream::add_polygon(T & path,
Feature const& feature, Feature const& feature,
CoordTransform const& t, CoordTransform const& t,
metawriter_properties const& properties) metawriter_properties const& properties)
@ -272,17 +273,9 @@ void metawriter_json_stream::add_polygon(path_type & path,
write_properties(feature, properties); write_properties(feature, properties);
} }
void metawriter_json_stream::add_line(path_type & path,
Feature const& feature,
CoordTransform const& t,
metawriter_properties const& properties)
{
write_feature_header("MultiLineString");
write_line_polygon(path, t, false);
write_properties(feature, properties);
}
void metawriter_json_stream::write_line_polygon(path_type & path, CoordTransform const& t, bool /*polygon*/){ template <typename T>
void metawriter_json_stream::write_line_polygon(T & path, CoordTransform const& t, bool /*polygon*/){
*f_ << " ["; *f_ << " [";
double x, y, last_x=0.0, last_y=0.0; double x, y, last_x=0.0, last_y=0.0;
unsigned cmd, last_cmd = SEG_END; unsigned cmd, last_cmd = SEG_END;
@ -327,7 +320,15 @@ void metawriter_json::start(metawriter_property_map const& properties)
MAPNIK_LOG_DEBUG(metawriter) << "metawriter_json: Filename=" << filename_; MAPNIK_LOG_DEBUG(metawriter) << "metawriter_json: Filename=" << filename_;
metawriter_json_stream::start(properties);
assert(trans_);
if (output_empty_) {
write_header();
} else {
count_ = HEADER_NOT_WRITTEN;
}
//metawriter_json_stream::start(properties);
} }
void metawriter_json::write_header() void metawriter_json::write_header()
@ -337,7 +338,7 @@ void metawriter_json::write_header()
{ {
MAPNIK_LOG_DEBUG(metawriter) << "metawriter_json: Failed to open file " << filename_; MAPNIK_LOG_DEBUG(metawriter) << "metawriter_json: Failed to open file " << filename_;
} }
set_stream(&f_); metawriter_json_stream::set_stream(&f_);
metawriter_json_stream::write_header(); metawriter_json_stream::write_header();
} }

View file

@ -0,0 +1,138 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// mapnik
#include <mapnik/graphics.hpp>
#include <mapnik/metawriter_renderer.hpp>
#include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/font_set.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/map.hpp>
// boost
#include <boost/utility.hpp>
#include <boost/make_shared.hpp>
#include <boost/math/special_functions/round.hpp>
// stl
#include <cmath>
namespace mapnik
{
metawriter_renderer::metawriter_renderer(Map const& m,double scale_factor, unsigned offset_x, unsigned offset_y)
: feature_style_processor<metawriter_renderer>(m, scale_factor),
width_(m.width()),
height_(m.height()),
scale_factor_(scale_factor),
t_(m.width(),m.height(),m.get_current_extent(),offset_x,offset_y),
font_engine_(),
font_manager_(font_engine_),
detector_(boost::make_shared<label_collision_detector4>(box2d<double>(-m.buffer_size(), -m.buffer_size(), m.width() + m.buffer_size() ,m.height() + m.buffer_size())))
{
setup(m);
}
metawriter_renderer::metawriter_renderer(Map const& m, boost::shared_ptr<label_collision_detector4> detector,
double scale_factor, unsigned offset_x, unsigned offset_y)
: feature_style_processor<metawriter_renderer>(m, scale_factor),
width_(m.width()),
height_(m.height()),
scale_factor_(scale_factor),
t_(m.width(),m.height(),m.get_current_extent(),offset_x,offset_y),
font_engine_(),
font_manager_(font_engine_),
detector_(detector)
{
setup(m);
}
void metawriter_renderer::setup(Map const &m)
{
MAPNIK_LOG_DEBUG(metawriter_renderer) << "metawriter_renderer: Scale=" << m.scale();
}
metawriter_renderer::~metawriter_renderer() {}
void metawriter_renderer::start_map_processing(Map const& m)
{
MAPNIK_LOG_DEBUG(metawriter_renderer) << "metawriter_renderer: Start map processing bbox=" << m.get_current_extent();
projection proj(m.srs());
Map::const_metawriter_iterator metaItr = m.begin_metawriters();
Map::const_metawriter_iterator metaItrEnd = m.end_metawriters();
for (;metaItr!=metaItrEnd; ++metaItr)
{
set_size(metaItr->second, m.width(), m.height());
set_map_srs(metaItr->second, proj);
start(metaItr->second, m.metawriter_output_properties);
}
}
void metawriter_renderer::end_map_processing(Map const& m)
{
Map::const_metawriter_iterator metaItr = m.begin_metawriters();
Map::const_metawriter_iterator metaItrEnd = m.end_metawriters();
for (;metaItr!=metaItrEnd; ++metaItr)
{
stop(metaItr->second);
}
MAPNIK_LOG_DEBUG(metawriter_renderer) << "metawriter_renderer: End map processing";
}
void metawriter_renderer::start_layer_processing(layer const& lay, box2d<double> const& query_extent)
{
MAPNIK_LOG_DEBUG(metawriter_renderer) << "metawriter_renderer: Start processing layer=" << lay.name();
MAPNIK_LOG_DEBUG(metawriter_renderer) << "metawriter_renderer: -- datasource=" << lay.datasource().get();
MAPNIK_LOG_DEBUG(metawriter_renderer) << "metawriter_renderer: -- query_extent=" << query_extent;
if (lay.clear_label_cache())
{
detector_->clear();
}
query_extent_ = query_extent;
}
void metawriter_renderer::end_layer_processing(layer const&)
{
MAPNIK_LOG_DEBUG(metawriter_renderer) << "metawriter_renderer: End layer processing";
}
void metawriter_renderer::start_style_processing(feature_type_style const& st)
{
MAPNIK_LOG_DEBUG(metawriter_renderer) << "metawriter_renderer: Start processing style";
}
void metawriter_renderer::end_style_processing(feature_type_style const& st)
{
MAPNIK_LOG_DEBUG(metawriter_renderer) << "metawriter_renderer: End processing style";
}
void metawriter_renderer::painted(bool painted)
{
//
}
}

View file

@ -0,0 +1,93 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
// boost
#include <boost/foreach.hpp>
// mapnik
#include <mapnik/metawriter_renderer.hpp>
#include <mapnik/metawriter_factory.hpp>
#include <mapnik/line_symbolizer.hpp>
#include <mapnik/vertex_converters.hpp>
// stl
#include <string>
#include <cmath>
namespace mapnik {
struct metawriter_wrap
{
metawriter_wrap(metawriter_with_properties const& w, feature_impl const& f, CoordTransform const& t)
: writer(w),
feature(f),
tr(t)
{}
template <typename T>
void add_path(T & path)
{
if (check_metawriter(writer.first))
{
std::cout << "ADD PATH " << std::endl;
add_line(writer.first, path, feature, tr, writer.second);
}
}
metawriter_with_properties const& writer;
feature_impl const& feature;
CoordTransform const& tr;
};
void metawriter_renderer::process(line_symbolizer const& sym,
mapnik::feature_ptr const& feature,
proj_transform const& prj_trans)
{
agg::trans_affine tr;
evaluate_transform(tr, *feature, sym.get_transform());
metawriter_with_properties writer = sym.get_metawriter();
metawriter_wrap wrap(writer,*feature,t_);
typedef boost::mpl::vector<clip_line_tag,
transform_tag,
offset_transform_tag,
affine_transform_tag,
smooth_tag,
dash_tag,
stroke_tag> conv_types;
vertex_converter<box2d<double>,metawriter_wrap,line_symbolizer,CoordTransform, proj_transform, agg::trans_affine, conv_types>
converter(query_extent_,wrap,sym,t_,prj_trans,tr,scale_factor_);
if (sym.clip()) converter.set<clip_line_tag>(); // optional clip (default: true)
converter.set<transform_tag>(); // always transform
BOOST_FOREACH( geometry_type & geom, feature->paths())
{
if (geom.num_points() > 1)
{
converter.apply(geom);
}
}
}
}

View file

@ -38,42 +38,49 @@ using std::string;
namespace mapnik namespace mapnik
{ {
metawriter_ptr metawriter metawriter_create(xml_node const& pt)
metawriter_create(xml_node const& pt)
{ {
metawriter_ptr writer; metawriter writer;
string type = pt.get_attr<string>("type"); string type = pt.get_attr<string>("type");
optional<string> properties = pt.get_opt_attr<string>("default-output"); optional<string> properties = pt.get_opt_attr<string>("default-output");
if (type == "json") { if (type == "json")
{
string file = pt.get_attr<string>("file"); string file = pt.get_attr<string>("file");
metawriter_json_ptr json = boost::make_shared<metawriter_json>(properties, parse_path(file)); metawriter_json_ptr json = boost::make_shared<metawriter_json>(properties, parse_path(file));
optional<boolean> output_empty = pt.get_opt_attr<boolean>("output-empty"); optional<boolean> output_empty = pt.get_opt_attr<boolean>("output-empty");
if (output_empty) { if (output_empty)
{
json->set_output_empty(*output_empty); json->set_output_empty(*output_empty);
} }
optional<boolean> pixel_coordinates = pt.get_opt_attr<boolean>("pixel-coordinates"); optional<boolean> pixel_coordinates = pt.get_opt_attr<boolean>("pixel-coordinates");
if (pixel_coordinates) { if (pixel_coordinates)
{
json->set_pixel_coordinates(*pixel_coordinates); json->set_pixel_coordinates(*pixel_coordinates);
} }
writer = json; writer = json;
} else if (type == "inmem") { }
else if (type == "inmem")
{
metawriter_inmem_ptr inmem = boost::make_shared<metawriter_inmem>(properties); metawriter_inmem_ptr inmem = boost::make_shared<metawriter_inmem>(properties);
writer = inmem; writer = inmem;
} else { }
else
{
throw config_error(string("Unknown type '") + type + "'", pt); throw config_error(string("Unknown type '") + type + "'", pt);
} }
return writer; return writer;
} }
void void metawriter_save(metawriter const& writer,
metawriter_save(const metawriter_ptr &metawriter, boost::property_tree::ptree & metawriter_node,
boost::property_tree::ptree &metawriter_node, bool explicit_defaults) bool explicit_defaults)
{ {
// FIXME
/*
metawriter_json *json = dynamic_cast<metawriter_json *>(metawriter.get()); metawriter_json *json = dynamic_cast<metawriter_json *>(metawriter.get());
if (json) { if (json) {
set_attr(metawriter_node, "type", "json"); set_attr(metawriter_node, "type", "json");
@ -91,6 +98,7 @@ metawriter_save(const metawriter_ptr &metawriter,
if (!metawriter->get_default_properties().empty() || explicit_defaults) { if (!metawriter->get_default_properties().empty() || explicit_defaults) {
set_attr(metawriter_node, "default-output", metawriter->get_default_properties().to_string()); set_attr(metawriter_node, "default-output", metawriter->get_default_properties().to_string());
} }
*/
} }
} // namespace mapnik } // namespace mapnik

View file

@ -28,49 +28,27 @@
// Boost // Boost
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
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<string,value> intersect_properties(Feature const& feature, metawriter_properties const& properties) {
map<string,value> nprops;
BOOST_FOREACH(string p, properties)
{
if (feature.has_key(p))
nprops.insert(std::make_pair(p,feature.get(p)));
}
return nprops;
}} // end anonymous namespace
namespace mapnik { namespace mapnik {
metawriter_inmem::metawriter_inmem(metawriter_properties dflt_properties) metawriter_inmem::metawriter_inmem(metawriter_properties dflt_properties)
: metawriter(dflt_properties) { : metawriter_base(dflt_properties) {
} }
metawriter_inmem::~metawriter_inmem() { metawriter_inmem::~metawriter_inmem() {
} }
void void metawriter_inmem::add_box(box2d<double> const& box, Feature const& feature,
metawriter_inmem::add_box(box2d<double> const& box, Feature const& feature,
CoordTransform const& /*t*/, CoordTransform const& /*t*/,
metawriter_properties const& properties) { metawriter_properties const& properties)
{
meta_instance inst; meta_instance inst;
inst.box = box; inst.box = box;
inst.properties = intersect_properties(feature, properties); inst.properties = intersect_properties(feature, properties);
instances_.push_back(inst); instances_.push_back(inst);
} }
void void metawriter_inmem::add_text(
metawriter_inmem::add_text(
boost::ptr_vector<text_path> & /*text*/, boost::ptr_vector<text_path> & /*text*/,
box2d<double> const& extents, box2d<double> const& extents,
Feature const& feature, Feature const& feature,
@ -86,27 +64,21 @@ metawriter_inmem::add_text(
} }
} }
void template <typename T>
metawriter_inmem::add_polygon(path_type & path, void metawriter_inmem::add_polygon(T & path,
Feature const& feature, Feature const& feature,
CoordTransform const& t, CoordTransform const& t,
metawriter_properties const& properties) { metawriter_properties const& properties)
{
add_vertices(path, feature, t, 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 template <typename T>
metawriter_inmem::add_vertices(path_type & path, void metawriter_inmem::add_vertices(T & path,
Feature const& feature, Feature const& feature,
CoordTransform const& /*t*/, CoordTransform const& /*t*/,
metawriter_properties const& properties) { metawriter_properties const& properties) {
box2d<double> box; box2d<double> box;
unsigned cmd; unsigned cmd;
double x = 0.0, y = 0.0; double x = 0.0, y = 0.0;

View file

@ -698,8 +698,8 @@ void serialize_layer( ptree & map_node, const layer & layer, bool explicit_defau
void serialize_metawriter(ptree & map_node, Map::const_metawriter_iterator metawriter_it, bool explicit_defaults) void serialize_metawriter(ptree & map_node, Map::const_metawriter_iterator metawriter_it, bool explicit_defaults)
{ {
std::string const& name = metawriter_it->first; std::string const& name = metawriter_it->first;
metawriter_ptr const& metawriter = metawriter_it->second; metawriter const& metawriter = metawriter_it->second;
ptree & metawriter_node = map_node.push_back( ptree & metawriter_node = map_node.push_back(
ptree::value_type("MetaWriter", ptree()))->second; ptree::value_type("MetaWriter", ptree()))->second;

View file

@ -48,7 +48,7 @@ symbolizer_base::symbolizer_base()
: properties_(), : properties_(),
properties_complete_(), properties_complete_(),
writer_name_(), writer_name_(),
writer_ptr_(), writer_(),
comp_op_(src_over), comp_op_(src_over),
clip_(true), clip_(true),
smooth_value_(0.0) smooth_value_(0.0)
@ -57,7 +57,11 @@ symbolizer_base::symbolizer_base()
// copy ctor // copy ctor
symbolizer_base::symbolizer_base(symbolizer_base const& other) symbolizer_base::symbolizer_base(symbolizer_base const& other)
: comp_op_(other.comp_op_), : properties_(other.properties_),
properties_complete_(other.properties_complete_),
writer_name_(other.writer_name_),
writer_(other.writer_),
comp_op_(other.comp_op_),
affine_transform_(other.affine_transform_), affine_transform_(other.affine_transform_),
clip_(other.clip_), clip_(other.clip_),
smooth_value_(other.smooth_value_) {} smooth_value_(other.smooth_value_) {}
@ -68,16 +72,19 @@ void symbolizer_base::add_metawriter(std::string const& name, metawriter_propert
properties_ = properties; properties_ = properties;
} }
void symbolizer_base::add_metawriter(metawriter_ptr writer_ptr, metawriter_properties const& properties, void symbolizer_base::add_metawriter(metawriter const& writer, metawriter_properties const& properties,
std::string const& name) std::string const& name)
{ {
writer_ptr_ = writer_ptr; writer_ = writer;
properties_ = properties; properties_ = properties;
writer_name_ = name; writer_name_ = name;
if (writer_ptr) { if (check_metawriter(writer))
properties_complete_ = writer_ptr->get_default_properties(); {
//properties_complete_ = writer_->get_default_properties(); FIXME
properties_complete_.insert(properties_.begin(), properties_.end()); properties_complete_.insert(properties_.begin(), properties_.end());
} else { }
else
{
properties_complete_.clear(); properties_complete_.clear();
} }
} }
@ -86,15 +93,17 @@ void symbolizer_base::cache_metawriters(Map const &m)
{ {
if (writer_name_.empty()) { if (writer_name_.empty()) {
properties_complete_.clear(); properties_complete_.clear();
writer_ptr_ = metawriter_ptr();
return; // No metawriter return; // No metawriter
} }
writer_ptr_ = m.find_metawriter(writer_name_); writer_ = m.find_metawriter(writer_name_);
if (writer_ptr_) { if (check_metawriter(writer_))
properties_complete_ = writer_ptr_->get_default_properties(); {
// properties_complete_ = writer_->get_default_properties(); FIXME
properties_complete_.insert(properties_.begin(), properties_.end()); properties_complete_.insert(properties_.begin(), properties_.end());
} else { }
else
{
properties_complete_.clear(); properties_complete_.clear();
MAPNIK_LOG_WARN(symbolizer) << "Metawriter '" << writer_name_ << "' used but not defined."; MAPNIK_LOG_WARN(symbolizer) << "Metawriter '" << writer_name_ << "' used but not defined.";
} }
@ -102,7 +111,7 @@ void symbolizer_base::cache_metawriters(Map const &m)
metawriter_with_properties symbolizer_base::get_metawriter() const metawriter_with_properties symbolizer_base::get_metawriter() const
{ {
return metawriter_with_properties(writer_ptr_, properties_complete_); return metawriter_with_properties(writer_, properties_complete_);
} }
void symbolizer_base::set_comp_op(composite_mode_e comp_op) void symbolizer_base::set_comp_op(composite_mode_e comp_op)

View file

@ -71,9 +71,9 @@ bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_line_placement()
finder_->update_detector(); finder_->update_detector();
} }
geo_itr_ = geometries_to_process_.erase(geo_itr_); geo_itr_ = geometries_to_process_.erase(geo_itr_);
if (writer_.first) writer_.first->add_text( //if (writer_.first) writer_.first->add_text(
finder_->get_results(), finder_->get_extents(), // finder_->get_results(), finder_->get_extents(),
feature_, t_, writer_.second); // feature_, t_, writer_.second);
return true; return true;
} }
//No placement for this geometry. Keep it in geometries_to_process_ for next try. //No placement for this geometry. Keep it in geometries_to_process_ for next try.
@ -101,9 +101,9 @@ bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_point_placement()
{ {
//Found a placement //Found a placement
point_itr_ = points_.erase(point_itr_); point_itr_ = points_.erase(point_itr_);
if (writer_.first) writer_.first->add_text( // if (writer_.first) writer_.first->add_text(
finder_->get_results(), finder_->get_extents(), // finder_->get_results(), finder_->get_extents(),
feature_, t_, writer_.second); // feature_, t_, writer_.second);
finder_->update_detector(); finder_->update_detector();
return true; return true;
} }
@ -240,7 +240,7 @@ bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_placement()
finder_ = boost::shared_ptr<placement_finder<DetectorT> >(new placement_finder<DetectorT>(feature_, *placement_, *info_, detector_, dims_)); finder_ = boost::shared_ptr<placement_finder<DetectorT> >(new placement_finder<DetectorT>(feature_, *placement_, *info_, detector_, dims_));
// boost::make_shared<placement_finder<DetectorT> >(feature_, *placement_, *info_, detector_, dims_); // boost::make_shared<placement_finder<DetectorT> >(feature_, *placement_, *info_, detector_, dims_);
if (writer_.first) finder_->set_collect_extents(true); if (check_metawriter(writer_.first)) finder_->set_collect_extents(true);
placement_valid_ = true; placement_valid_ = true;
return true; return true;
@ -316,11 +316,11 @@ bool shield_symbolizer_helper<FaceManagerT, DetectorT>::next_point_placement()
{ {
detector_.insert(marker_ext_); detector_.insert(marker_ext_);
finder_->update_detector(); finder_->update_detector();
if (writer_.first) { //if (writer_.first) {
writer_.first->add_box(marker_ext_, feature_, t_, writer_.second); // writer_.first->add_box(marker_ext_, feature_, t_, writer_.second);
writer_.first->add_text(finder_->get_results(), finder_->get_extents(), // writer_.first->add_text(finder_->get_results(), finder_->get_extents(),
feature_, t_, writer_.second); // feature_, t_, writer_.second);
} //}
point_itr_ = points_.erase(point_itr_); point_itr_ = points_.erase(point_itr_);
return true; return true;
} }
@ -393,7 +393,7 @@ pixel_position shield_symbolizer_helper<FaceManagerT, DetectorT>::get_marker_pos
marker_ext_.re_center(lx, ly); marker_ext_.re_center(lx, ly);
//label is added to detector by get_line_placement(), but marker isn't //label is added to detector by get_line_placement(), but marker isn't
detector_.insert(marker_ext_); detector_.insert(marker_ext_);
if (writer_.first) writer_.first->add_box(marker_ext_, feature_, t_, writer_.second); //if (writer_.first) writer_.first->add_box(marker_ext_, feature_, t_, writer_.second); // FIXME
return pixel_position(px, py); return pixel_position(px, py);
} else { } else {
//collision_detector is already updated for point placement in get_point_placement() //collision_detector is already updated for point placement in get_point_placement()