Metawriter support for TextSymbolizer.
This commit is contained in:
parent
85cd4b67c3
commit
30470bd52b
5 changed files with 164 additions and 53 deletions
|
@ -27,6 +27,7 @@
|
||||||
// Mapnik
|
// Mapnik
|
||||||
#include <mapnik/box2d.hpp>
|
#include <mapnik/box2d.hpp>
|
||||||
#include <mapnik/feature.hpp>
|
#include <mapnik/feature.hpp>
|
||||||
|
#include <mapnik/font_engine_freetype.hpp>
|
||||||
|
|
||||||
// Boost
|
// Boost
|
||||||
#include <boost/utility.hpp>
|
#include <boost/utility.hpp>
|
||||||
|
@ -81,6 +82,12 @@ class metawriter
|
||||||
virtual void add_box(box2d<double> const& box, Feature const& feature,
|
virtual void add_box(box2d<double> const& box, Feature const& feature,
|
||||||
CoordTransform const& t,
|
CoordTransform const& t,
|
||||||
metawriter_properties const& properties = metawriter_properties())=0;
|
metawriter_properties const& properties = metawriter_properties())=0;
|
||||||
|
virtual void add_text(placement const& placement,
|
||||||
|
face_set_ptr face,
|
||||||
|
Feature const& feature,
|
||||||
|
CoordTransform const& t,
|
||||||
|
metawriter_properties const& properties = metawriter_properties())=0;
|
||||||
|
|
||||||
/** Start processing.
|
/** Start processing.
|
||||||
* Write file header, init database connection, ...
|
* Write file header, init database connection, ...
|
||||||
*
|
*
|
||||||
|
|
|
@ -43,6 +43,11 @@ public:
|
||||||
virtual void add_box(box2d<double> const& box, Feature const& feature,
|
virtual 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(placement const& p,
|
||||||
|
face_set_ptr face,
|
||||||
|
Feature const& feature,
|
||||||
|
CoordTransform const& t,
|
||||||
|
metawriter_properties const& properties = metawriter_properties());
|
||||||
|
|
||||||
virtual void start(metawriter_property_map const& properties);
|
virtual void start(metawriter_property_map const& properties);
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
|
@ -56,6 +61,11 @@ public:
|
||||||
bool get_only_nonempty() { return only_nonempty_; }
|
bool get_only_nonempty() { return only_nonempty_; }
|
||||||
virtual void set_map_srs(projection const& proj);
|
virtual void set_map_srs(projection const& proj);
|
||||||
protected:
|
protected:
|
||||||
|
enum {
|
||||||
|
HEADER_NOT_WRITTEN = -1,
|
||||||
|
STOPPED = -2,
|
||||||
|
STARTED = 0,
|
||||||
|
};
|
||||||
/** Features written. */
|
/** Features written. */
|
||||||
int count_;
|
int count_;
|
||||||
bool only_nonempty_;
|
bool only_nonempty_;
|
||||||
|
@ -63,6 +73,29 @@ protected:
|
||||||
proj_transform *trans_;
|
proj_transform *trans_;
|
||||||
projection output_srs_;
|
projection output_srs_;
|
||||||
virtual void write_header();
|
virtual void write_header();
|
||||||
|
inline void write_feature_header(std::string type) {
|
||||||
|
if (count_ == HEADER_NOT_WRITTEN) write_header();
|
||||||
|
if (count_++) *f_ << ",\n";
|
||||||
|
#ifdef MAPNIK_DEBUG
|
||||||
|
if (count_ == STOPPED)
|
||||||
|
{
|
||||||
|
std::cerr << "WARNING: Metawriter not started before using it.\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
*f_ << "{ \"type\": \"Feature\",\n \"geometry\": { \"type\": \""<<type<<"\",\n \"coordinates\":";
|
||||||
|
}
|
||||||
|
void write_properties(Feature const& feature, metawriter_properties const& properties);
|
||||||
|
inline void write_point(CoordTransform const& t, double x, double y, bool last = false)
|
||||||
|
{
|
||||||
|
double z = 0.0;
|
||||||
|
t.backward(&x, &y);
|
||||||
|
trans_->forward(x, y, z);
|
||||||
|
*f_ << "["<<x<<","<<y<<"]";
|
||||||
|
if (!last) {
|
||||||
|
*f_ << ",";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::ostream *f_;
|
std::ostream *f_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -121,6 +121,7 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
|
||||||
finder.find_line_placements<path_type>(text_placement,path);
|
finder.find_line_placements<path_type>(text_placement,path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ii)
|
for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ii)
|
||||||
{
|
{
|
||||||
double x = text_placement.placements[ii].starting_x;
|
double x = text_placement.placements[ii].starting_x;
|
||||||
|
@ -128,6 +129,9 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
|
||||||
box2d<double> dim = ren.prepare_glyphs(&text_placement.placements[ii]);
|
box2d<double> dim = ren.prepare_glyphs(&text_placement.placements[ii]);
|
||||||
ren.render(x,y);
|
ren.render(x,y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
metawriter_with_properties writer = sym.get_metawriter();
|
||||||
|
if (writer.first) writer.first->add_text(text_placement, faces, feature, t_, writer.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
// Mapnik
|
// Mapnik
|
||||||
#include <mapnik/metawriter.hpp>
|
#include <mapnik/metawriter.hpp>
|
||||||
#include <mapnik/metawriter_json.hpp>
|
#include <mapnik/metawriter_json.hpp>
|
||||||
|
#include <mapnik/placement_finder.hpp>
|
||||||
|
|
||||||
// Boost
|
// Boost
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
@ -32,10 +33,6 @@
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#define HEADER_NOT_WRITTEN -1
|
|
||||||
#define STOPPED -2
|
|
||||||
#define STARTED 0
|
|
||||||
|
|
||||||
namespace mapnik {
|
namespace mapnik {
|
||||||
|
|
||||||
UnicodeString const& metawriter_property_map::operator[](std::string const& key) const
|
UnicodeString const& metawriter_property_map::operator[](std::string const& key) const
|
||||||
|
@ -68,7 +65,7 @@ void metawriter_json_stream::start(metawriter_property_map const& properties)
|
||||||
void metawriter_json_stream::write_header()
|
void metawriter_json_stream::write_header()
|
||||||
{
|
{
|
||||||
assert(f_);
|
assert(f_);
|
||||||
*f_ << "{ \"type\": \"FeatureCollection\", \"features\": [\n";
|
*f_ << "{ \"type\": \"FeatureCollection\", \"features\": [\n" << std::fixed << std::setprecision(8);
|
||||||
count_ = STARTED;
|
count_ = STARTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,50 +95,9 @@ metawriter_json_stream::metawriter_json_stream(metawriter_properties dflt_proper
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void metawriter_json_stream::write_properties(Feature const& feature, metawriter_properties const& properties)
|
||||||
void metawriter_json_stream::add_box(box2d<double> const &box, Feature const& feature,
|
|
||||||
CoordTransform const& t, metawriter_properties const& properties)
|
|
||||||
{
|
{
|
||||||
/* Check if feature is in bounds. */
|
*f_ << "}," << //Close coordinates object
|
||||||
if (box.maxx() < 0 || box.maxy() < 0 || box.minx() > width_ || box.miny() > height_) return;
|
|
||||||
|
|
||||||
if (count_ == HEADER_NOT_WRITTEN) write_header();
|
|
||||||
#ifdef MAPNIK_DEBUG
|
|
||||||
if (count_ == STOPPED)
|
|
||||||
{
|
|
||||||
std::cerr << "WARNING: Metawriter not started before using it.\n";
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Coordinate transform in renderer:
|
|
||||||
input: layer srs
|
|
||||||
prj_trans.backwards() [prj_trans: map -> layer]
|
|
||||||
intermediate: map srs
|
|
||||||
t_.forward()
|
|
||||||
output: pixels
|
|
||||||
|
|
||||||
Our transform:
|
|
||||||
input: pixels
|
|
||||||
t_.backward()
|
|
||||||
intermediate: map srs
|
|
||||||
trans_.forward()
|
|
||||||
output: WGS84
|
|
||||||
*/
|
|
||||||
|
|
||||||
//t_ coord transform has transform for box2d combined with proj_transform
|
|
||||||
box2d<double> transformed = t.backward(box, *trans_);
|
|
||||||
|
|
||||||
double minx = transformed.minx();
|
|
||||||
double miny = transformed.miny();
|
|
||||||
double maxx = transformed.maxx();
|
|
||||||
double maxy = transformed.maxy();
|
|
||||||
|
|
||||||
if (count_++) *f_ << ",\n";
|
|
||||||
*f_ << std::fixed << std::setprecision(8) << "{ \"type\": \"Feature\",\n \"geometry\": { \"type\": \"Polygon\",\n \"coordinates\": [ [ [" <<
|
|
||||||
minx << ", " << miny << "], [" <<
|
|
||||||
maxx << ", " << miny << "], [" <<
|
|
||||||
maxx << ", " << maxy << "], [" <<
|
|
||||||
minx << ", " << maxy << "] ] ] }," <<
|
|
||||||
"\n \"properties\": {";
|
"\n \"properties\": {";
|
||||||
std::map<std::string, value> fprops = feature.props();
|
std::map<std::string, value> fprops = feature.props();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -161,6 +117,113 @@ void metawriter_json_stream::add_box(box2d<double> const &box, Feature const& fe
|
||||||
*f_ << "\n} }";
|
*f_ << "\n} }";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Coordinate transform in renderer:
|
||||||
|
input: layer srs
|
||||||
|
prj_trans.backwards() [prj_trans: map -> layer]
|
||||||
|
intermediate: map srs
|
||||||
|
t_.forward()
|
||||||
|
output: pixels
|
||||||
|
|
||||||
|
Our transform:
|
||||||
|
input: pixels
|
||||||
|
t_.backward()
|
||||||
|
intermediate: map srs
|
||||||
|
trans_.forward()
|
||||||
|
output: WGS84
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
void metawriter_json_stream::add_box(box2d<double> const &box, Feature const& feature,
|
||||||
|
CoordTransform const& t, metawriter_properties const& properties)
|
||||||
|
{
|
||||||
|
/* Check if feature is in bounds. */
|
||||||
|
if (box.maxx() < 0 || box.maxy() < 0 || box.minx() > width_ || box.miny() > height_) return;
|
||||||
|
|
||||||
|
//t_ coord transform has transform for box2d combined with proj_transform
|
||||||
|
box2d<double> transformed = t.backward(box, *trans_);
|
||||||
|
|
||||||
|
double minx = transformed.minx();
|
||||||
|
double miny = transformed.miny();
|
||||||
|
double maxx = transformed.maxx();
|
||||||
|
double maxy = transformed.maxy();
|
||||||
|
|
||||||
|
write_feature_header("Polygon");
|
||||||
|
|
||||||
|
*f_ << " [ [ [" <<
|
||||||
|
minx << ", " << miny << "], [" <<
|
||||||
|
maxx << ", " << miny << "], [" <<
|
||||||
|
maxx << ", " << maxy << "], [" <<
|
||||||
|
minx << ", " << maxy << "] ] ]";
|
||||||
|
|
||||||
|
write_properties(feature, properties);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Remove this
|
||||||
|
inline void combined_backward(double &x, double &y, CoordTransform const& t, proj_transform const* trans_)
|
||||||
|
{
|
||||||
|
double z = 0.0;
|
||||||
|
t.backward(&x, &y);
|
||||||
|
trans_->forward(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void metawriter_json_stream::add_text(placement const& p,
|
||||||
|
face_set_ptr face,
|
||||||
|
Feature const& feature,
|
||||||
|
CoordTransform const& t,
|
||||||
|
metawriter_properties const& properties)
|
||||||
|
{
|
||||||
|
for (unsigned n = 0; n < p.placements.size(); n++) {
|
||||||
|
placement_element & current_placement = const_cast<placement_element &>(p.placements[n]);
|
||||||
|
|
||||||
|
bool inside = false;
|
||||||
|
for (int i = 0; i < current_placement.num_nodes(); ++i) {
|
||||||
|
current_placement.rewind();
|
||||||
|
int c; double x, y, angle;
|
||||||
|
current_placement.vertex(&c, &x, &y, &angle);
|
||||||
|
if (x > 0 && x < width_ && y > 0 && y < height_) {
|
||||||
|
inside = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!inside) continue;
|
||||||
|
|
||||||
|
write_feature_header("MultiPolygon");
|
||||||
|
*f_ << "[";
|
||||||
|
|
||||||
|
for (int i = 0; i < current_placement.num_nodes(); ++i) {
|
||||||
|
if (i) {
|
||||||
|
*f_ << ",";
|
||||||
|
}
|
||||||
|
int c; double x, y, angle;
|
||||||
|
current_placement.vertex(&c, &x, &y, &angle);
|
||||||
|
font_face_set::dimension_t ci = face->character_dimensions(c);
|
||||||
|
|
||||||
|
//TODO: Optimize for angle == 0
|
||||||
|
double sina = sin(angle);
|
||||||
|
double cosa = cos(angle);
|
||||||
|
double x0 = current_placement.starting_x + x - sina*ci.ymin;
|
||||||
|
double y0 = current_placement.starting_y - y - cosa*ci.ymin;
|
||||||
|
double x1 = x0 + ci.width * cosa;
|
||||||
|
double y1 = y0 - ci.width * sina;
|
||||||
|
double x2 = x0 + (ci.width * cosa - ci.height * sina);
|
||||||
|
double y2 = y0 - (ci.width * sina + ci.height * cosa);
|
||||||
|
double x3 = x0 - ci.height * sina;
|
||||||
|
double y3 = y0 - ci.height * cosa;
|
||||||
|
|
||||||
|
*f_ << "\n [[";
|
||||||
|
write_point(t, x0, y0);
|
||||||
|
write_point(t, x1, y1);
|
||||||
|
write_point(t, x2, y2);
|
||||||
|
write_point(t, x3, y3, true);
|
||||||
|
*f_ << "]]";
|
||||||
|
}
|
||||||
|
*f_ << "]";
|
||||||
|
write_properties(feature, properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void metawriter_json_stream::set_map_srs(projection const& input_srs_)
|
void metawriter_json_stream::set_map_srs(projection const& input_srs_)
|
||||||
{
|
{
|
||||||
if (trans_) delete trans_;
|
if (trans_) delete trans_;
|
||||||
|
|
|
@ -83,7 +83,8 @@ IMPLEMENT_ENUM( text_convert_e, text_convert_strings );
|
||||||
|
|
||||||
|
|
||||||
text_symbolizer::text_symbolizer(expression_ptr name, std::string const& face_name, unsigned size, color const& fill)
|
text_symbolizer::text_symbolizer(expression_ptr name, std::string const& face_name, unsigned size, color const& fill)
|
||||||
: name_(name),
|
: symbolizer_base(),
|
||||||
|
name_(name),
|
||||||
face_name_(face_name),
|
face_name_(face_name),
|
||||||
//fontset_(default_fontset),
|
//fontset_(default_fontset),
|
||||||
size_(size),
|
size_(size),
|
||||||
|
@ -113,7 +114,8 @@ text_symbolizer::text_symbolizer(expression_ptr name, std::string const& face_na
|
||||||
jalign_(J_MIDDLE) {}
|
jalign_(J_MIDDLE) {}
|
||||||
|
|
||||||
text_symbolizer::text_symbolizer(expression_ptr name, unsigned size, color const& fill)
|
text_symbolizer::text_symbolizer(expression_ptr name, unsigned size, color const& fill)
|
||||||
: name_(name),
|
: symbolizer_base(),
|
||||||
|
name_(name),
|
||||||
//face_name_(""),
|
//face_name_(""),
|
||||||
//fontset_(default_fontset),
|
//fontset_(default_fontset),
|
||||||
size_(size),
|
size_(size),
|
||||||
|
@ -143,7 +145,8 @@ text_symbolizer::text_symbolizer(expression_ptr name, unsigned size, color const
|
||||||
jalign_(J_MIDDLE) {}
|
jalign_(J_MIDDLE) {}
|
||||||
|
|
||||||
text_symbolizer::text_symbolizer(text_symbolizer const& rhs)
|
text_symbolizer::text_symbolizer(text_symbolizer const& rhs)
|
||||||
: name_(rhs.name_),
|
: symbolizer_base(rhs),
|
||||||
|
name_(rhs.name_),
|
||||||
orientation_(rhs.orientation_),
|
orientation_(rhs.orientation_),
|
||||||
face_name_(rhs.face_name_),
|
face_name_(rhs.face_name_),
|
||||||
fontset_(rhs.fontset_),
|
fontset_(rhs.fontset_),
|
||||||
|
@ -206,6 +209,7 @@ text_symbolizer& text_symbolizer::operator=(text_symbolizer const& other)
|
||||||
wrap_before_ = other.wrap_before_;
|
wrap_before_ = other.wrap_before_;
|
||||||
halign_ = other.halign_;
|
halign_ = other.halign_;
|
||||||
jalign_ = other.jalign_;
|
jalign_ = other.jalign_;
|
||||||
|
std::cout << "TODO: Metawriter (text_symbolizer::operator=)\n";
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue