From 30470bd52b54b64de2f765e8c7d00a9807952d16 Mon Sep 17 00:00:00 2001 From: Hermann Kraus Date: Tue, 10 Aug 2010 12:19:19 +0000 Subject: [PATCH] Metawriter support for TextSymbolizer. --- include/mapnik/metawriter.hpp | 7 ++ include/mapnik/metawriter_json.hpp | 33 ++++++ src/agg/process_text_symbolizer.cpp | 8 +- src/metawriter.cpp | 159 +++++++++++++++++++--------- src/text_symbolizer.cpp | 10 +- 5 files changed, 164 insertions(+), 53 deletions(-) diff --git a/include/mapnik/metawriter.hpp b/include/mapnik/metawriter.hpp index 9b6f2f7a7..043876ed9 100644 --- a/include/mapnik/metawriter.hpp +++ b/include/mapnik/metawriter.hpp @@ -27,6 +27,7 @@ // Mapnik #include #include +#include // Boost #include @@ -81,6 +82,12 @@ class metawriter virtual void add_box(box2d 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, ... * diff --git a/include/mapnik/metawriter_json.hpp b/include/mapnik/metawriter_json.hpp index 921bb5173..21e25eab4 100644 --- a/include/mapnik/metawriter_json.hpp +++ b/include/mapnik/metawriter_json.hpp @@ -43,6 +43,11 @@ public: virtual void add_box(box2d const& box, Feature const& feature, CoordTransform const& t, metawriter_properties const& properties); + virtual void add_text(placement const& p, + face_set_ptr face, + Feature const& feature, + CoordTransform const& t, + metawriter_properties const& properties = 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\": \""<forward(x, y, z); + *f_ << "["<::process(text_symbolizer const& sym, path_type path(t_,geom,prj_trans); finder.find_line_placements(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 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); } } } diff --git a/src/metawriter.cpp b/src/metawriter.cpp index 3251a3e3f..bba7d52d7 100644 --- a/src/metawriter.cpp +++ b/src/metawriter.cpp @@ -23,6 +23,7 @@ // Mapnik #include #include +#include // Boost #include @@ -32,10 +33,6 @@ #include #include -#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 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 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 fprops = feature.props(); int i = 0; @@ -161,6 +117,113 @@ void metawriter_json_stream::add_box(box2d 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 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 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(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_; diff --git a/src/text_symbolizer.cpp b/src/text_symbolizer.cpp index 996503fe0..17fee7be6 100644 --- a/src/text_symbolizer.cpp +++ b/src/text_symbolizer.cpp @@ -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; }