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
|
||||
#include <mapnik/box2d.hpp>
|
||||
#include <mapnik/feature.hpp>
|
||||
#include <mapnik/font_engine_freetype.hpp>
|
||||
|
||||
// Boost
|
||||
#include <boost/utility.hpp>
|
||||
|
@ -81,6 +82,12 @@ class metawriter
|
|||
virtual void add_box(box2d<double> const& box, Feature const& feature,
|
||||
CoordTransform const& t,
|
||||
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.
|
||||
* Write file header, init database connection, ...
|
||||
*
|
||||
|
|
|
@ -43,6 +43,11 @@ public:
|
|||
virtual void add_box(box2d<double> 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 = metawriter_properties());
|
||||
|
||||
virtual void start(metawriter_property_map const& properties);
|
||||
virtual void stop();
|
||||
|
@ -56,6 +61,11 @@ public:
|
|||
bool get_only_nonempty() { return only_nonempty_; }
|
||||
virtual void set_map_srs(projection const& proj);
|
||||
protected:
|
||||
enum {
|
||||
HEADER_NOT_WRITTEN = -1,
|
||||
STOPPED = -2,
|
||||
STARTED = 0,
|
||||
};
|
||||
/** Features written. */
|
||||
int count_;
|
||||
bool only_nonempty_;
|
||||
|
@ -63,6 +73,29 @@ protected:
|
|||
proj_transform *trans_;
|
||||
projection output_srs_;
|
||||
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:
|
||||
std::ostream *f_;
|
||||
};
|
||||
|
|
|
@ -120,14 +120,18 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
|
|||
path_type path(t_,geom,prj_trans);
|
||||
finder.find_line_placements<path_type>(text_placement,path);
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ii)
|
||||
{
|
||||
double x = text_placement.placements[ii].starting_x;
|
||||
double y = text_placement.placements[ii].starting_y;
|
||||
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
|
||||
#include <mapnik/metawriter.hpp>
|
||||
#include <mapnik/metawriter_json.hpp>
|
||||
#include <mapnik/placement_finder.hpp>
|
||||
|
||||
// Boost
|
||||
#include <boost/foreach.hpp>
|
||||
|
@ -32,10 +33,6 @@
|
|||
#include <iomanip>
|
||||
#include <cstdio>
|
||||
|
||||
#define HEADER_NOT_WRITTEN -1
|
||||
#define STOPPED -2
|
||||
#define STARTED 0
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
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()
|
||||
{
|
||||
assert(f_);
|
||||
*f_ << "{ \"type\": \"FeatureCollection\", \"features\": [\n";
|
||||
*f_ << "{ \"type\": \"FeatureCollection\", \"features\": [\n" << std::fixed << std::setprecision(8);
|
||||
count_ = STARTED;
|
||||
}
|
||||
|
||||
|
@ -98,50 +95,9 @@ metawriter_json_stream::metawriter_json_stream(metawriter_properties dflt_proper
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
void metawriter_json_stream::add_box(box2d<double> const &box, Feature const& feature,
|
||||
CoordTransform const& t, metawriter_properties const& properties)
|
||||
void metawriter_json_stream::write_properties(Feature const& feature, metawriter_properties const& properties)
|
||||
{
|
||||
/* Check if feature is in bounds. */
|
||||
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 << "] ] ] }," <<
|
||||
*f_ << "}," << //Close coordinates object
|
||||
"\n \"properties\": {";
|
||||
std::map<std::string, value> fprops = feature.props();
|
||||
int i = 0;
|
||||
|
@ -161,6 +117,113 @@ void metawriter_json_stream::add_box(box2d<double> const &box, Feature const& fe
|
|||
*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_)
|
||||
{
|
||||
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)
|
||||
: name_(name),
|
||||
: symbolizer_base(),
|
||||
name_(name),
|
||||
face_name_(face_name),
|
||||
//fontset_(default_fontset),
|
||||
size_(size),
|
||||
|
@ -113,7 +114,8 @@ text_symbolizer::text_symbolizer(expression_ptr name, std::string const& face_na
|
|||
jalign_(J_MIDDLE) {}
|
||||
|
||||
text_symbolizer::text_symbolizer(expression_ptr name, unsigned size, color const& fill)
|
||||
: name_(name),
|
||||
: symbolizer_base(),
|
||||
name_(name),
|
||||
//face_name_(""),
|
||||
//fontset_(default_fontset),
|
||||
size_(size),
|
||||
|
@ -143,7 +145,8 @@ text_symbolizer::text_symbolizer(expression_ptr name, unsigned size, color const
|
|||
jalign_(J_MIDDLE) {}
|
||||
|
||||
text_symbolizer::text_symbolizer(text_symbolizer const& rhs)
|
||||
: name_(rhs.name_),
|
||||
: symbolizer_base(rhs),
|
||||
name_(rhs.name_),
|
||||
orientation_(rhs.orientation_),
|
||||
face_name_(rhs.face_name_),
|
||||
fontset_(rhs.fontset_),
|
||||
|
@ -206,6 +209,7 @@ text_symbolizer& text_symbolizer::operator=(text_symbolizer const& other)
|
|||
wrap_before_ = other.wrap_before_;
|
||||
halign_ = other.halign_;
|
||||
jalign_ = other.jalign_;
|
||||
std::cout << "TODO: Metawriter (text_symbolizer::operator=)\n";
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue