Support ShieldSymbolizer.

This commit is contained in:
Hermann Kraus 2012-08-17 18:31:55 +02:00
parent d8fad34aa3
commit a1f0af112e
9 changed files with 126 additions and 129 deletions

View file

@ -70,8 +70,6 @@ public:
/** Return all placements.*/
placements_list const& get();
marker_ptr get_marker() const;
agg::trans_affine const& get_image_transform() const;
protected:
bool next_point_placement();
bool next_line_placement();
@ -104,8 +102,6 @@ protected:
placement_finder_ng finder_;
//ShieldSymbolizer only
marker_ptr marker_;
agg::trans_affine marker_transform_;
void init_marker();
};

View file

@ -68,16 +68,24 @@ public:
bool next_position();
placements_list const& placements() const;
void set_marker(marker_info_ptr m, box2d<double> box, bool marker_unlocked, pixel_position const& marker_displacement);
private:
void init_alignment();
pixel_position alignment_offset() const;
double jalign_offset(double line_width) const;
bool single_line_placement(vertex_cache &pp, text_upright_e orientation);
/** Moves dx pixels but makes sure not to fall of the end. */
void path_move_dx(vertex_cache &pp);
/** Normalize angle in range [-pi, +pi]. */
static double normalize_angle(double angle);
/** Adjusts user defined spacing to place an integer number of labels. */
double get_spacing(double path_length, double layout_width) const;
/** Checks for collision. */
bool collision(box2d<double> const& box) const;
/** Adds marker to glyph_positions and to collision detector. Returns false if there is a collision. */
bool add_marker(glyph_positions_ptr glyphs, pixel_position const& pos) const;
box2d<double> get_bbox(glyph_info const& glyph, pixel_position const& pos, rotation const& rot);
Feature const& feature_;
DetectorType &detector_;
@ -94,6 +102,13 @@ private:
double scale_factor_;
placements_list placements_;
//ShieldSymbolizer
bool has_marker_;
marker_info_ptr marker_;
box2d<double> marker_box_;
bool marker_unlocked_;
pixel_position marker_displacement_;
};
typedef boost::shared_ptr<placement_finder_ng> placement_finder_ng_ptr;

View file

@ -26,6 +26,10 @@
#include <mapnik/pixel_position.hpp>
#include <mapnik/text/glyph_info.hpp>
#include <mapnik/text/rotation.hpp>
#include <mapnik/marker_cache.hpp>
// agg
#include "agg_trans_affine.h"
//stl
#include <vector>
@ -45,9 +49,19 @@ struct glyph_position
rotation rot;
};
struct marker_info
{
marker_info() : marker(), transform() {}
marker_info(marker_ptr marker, agg::trans_affine const& transform) :
marker(marker), transform(transform) {}
marker_ptr marker;
agg::trans_affine transform;
};
typedef boost::shared_ptr<marker_info> marker_info_ptr;
/** Stores positions of glphys.
*
* The actual glyphs and their format is stored in text_layout.
* The actual glyphs and their format are stored in text_layout.
*/
class glyph_positions
{
@ -62,9 +76,14 @@ public:
pixel_position const& get_base_point() const;
void set_base_point(pixel_position base_point);
void set_marker(marker_info_ptr marker, pixel_position const& marker_pos);
marker_info_ptr marker() const;
pixel_position const& marker_pos() const;
private:
std::vector<glyph_position> data_;
pixel_position base_point_;
marker_info_ptr marker_;
pixel_position marker_pos_;
};
typedef boost::shared_ptr<glyph_positions> glyph_positions_ptr;

View file

@ -22,15 +22,8 @@
// mapnik
#include <mapnik/agg_renderer.hpp>
#include <mapnik/agg_rasterizer.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/svg/svg_converter.hpp>
#include <mapnik/svg/svg_renderer.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/symbolizer_helpers.hpp>
// boost
#include <boost/make_shared.hpp>
#include <mapnik/text/renderer.hpp>
namespace mapnik {
@ -39,47 +32,25 @@ void agg_renderer<T>::process(shield_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans)
{
#if 0
shield_symbolizer_helper<face_manager<freetype_engine>,
label_collision_detector4> helper(
text_symbolizer_helper helper(
sym, feature, prj_trans,
width_, height_,
scale_factor_,
t_, font_manager_, *detector_,
query_extent_);
text_renderer<T> ren(*current_buffer_,
font_manager_,
*(font_manager_.get_stroker()),
sym.comp_op(),
scale_factor_);
agg_text_renderer<T> ren(*current_buffer_, *(font_manager_.get_stroker()), sym.comp_op(), scale_factor_);
while (helper.next())
placements_list const& placements = helper.get();
BOOST_FOREACH(glyph_positions_ptr glyphs, placements)
{
placements_type const& placements = helper.placements();
for (unsigned int ii = 0; ii < placements.size(); ++ii)
{
// get_marker_position returns (minx,miny) corner position,
// while (currently only) agg_renderer::render_marker newly
// expects center position;
// until all renderers and shield_symbolizer_helper are
// modified accordingly, we must adjust the position here
pixel_position pos = helper.get_marker_position(placements[ii]);
pos.x += 0.5 * helper.get_marker_width();
pos.y += 0.5 * helper.get_marker_height();
render_marker(pos,
helper.get_marker(),
helper.get_image_transform(),
sym.get_opacity(),
sym.comp_op());
ren.prepare_glyphs(placements[ii]);
ren.render(placements[ii].center);
}
if (glyphs->marker())
render_marker(glyphs->marker_pos(),
*(glyphs->marker()->marker),
glyphs->marker()->transform,
sym.get_opacity(), sym.comp_op());
ren.render(glyphs);
}
#else
#warning AGG: ShieldSymbolizer disabled!
#endif
}

View file

@ -21,15 +21,9 @@
*****************************************************************************/
// mapnik
#include <mapnik/grid/grid_rasterizer.hpp>
#include <mapnik/grid/grid_renderer.hpp>
#include <mapnik/grid/grid_pixfmt.hpp>
#include <mapnik/grid/grid_pixel.hpp>
#include <mapnik/grid/grid.hpp>
#include <mapnik/symbolizer_helpers.hpp>
#include <mapnik/svg/svg_converter.hpp>
#include <mapnik/svg/svg_renderer.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/text/renderer.hpp>
// agg
#include "agg_trans_affine.h"
@ -41,54 +35,28 @@ void grid_renderer<T>::process(shield_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans)
{
#if 0
shield_symbolizer_helper<face_manager<freetype_engine>,
label_collision_detector4> helper(
text_symbolizer_helper helper(
sym, feature, prj_trans,
width_, height_,
scale_factor_,
scale_factor_ * (1.0/pixmap_.get_resolution()),
t_, font_manager_, *detector_,
query_extent_);
bool placement_found = false;
text_renderer<T> ren(pixmap_,
font_manager_,
*(font_manager_.get_stroker()),
sym.comp_op(),
scale_factor_);
grid_text_renderer<T> ren(pixmap_, *(font_manager_.get_stroker()), sym.comp_op(), scale_factor_);
text_placement_info_ptr placement;
while (helper.next())
placements_list const& placements = helper.get();
if (!placements.size()) return;
BOOST_FOREACH(glyph_positions_ptr glyphs, placements)
{
placement_found = true;
placements_type const& placements = helper.placements();
for (unsigned int ii = 0; ii < placements.size(); ++ii)
{
// get_marker_position returns (minx,miny) corner position,
// while (currently only) agg_renderer::render_marker newly
// expects center position;
// until all renderers and shield_symbolizer_helper are
// modified accordingly, we must adjust the position here
pixel_position pos = helper.get_marker_position(placements[ii]);
pos.x += 0.5 * helper.get_marker_width();
pos.y += 0.5 * helper.get_marker_height();
render_marker(feature,
pixmap_.get_resolution(),
pos,
helper.get_marker(),
helper.get_image_transform(),
sym.get_opacity(),
sym.comp_op());
ren.prepare_glyphs(placements[ii]);
ren.render_id(feature.id(), placements[ii].center, 2);
}
if (glyphs->marker()->marker)
render_marker(feature, pixmap_.get_resolution(),
glyphs->marker_pos(),
*(glyphs->marker()->marker),
glyphs->marker()->transform,
sym.get_opacity(), sym.comp_op());
ren.render(glyphs, feature.id(), 2);
}
if (placement_found)
pixmap_.add_feature(feature);
#else
#warning GRID: TextSymbolizer disabled!
#endif
pixmap_.add_feature(feature);
}
template void grid_renderer<grid>::process(shield_symbolizer const&,

View file

@ -267,45 +267,34 @@ void text_symbolizer_helper::init_marker()
{
shield_symbolizer const& sym = static_cast<shield_symbolizer const&>(sym_);
std::string filename = path_processor_type::evaluate(*sym.get_filename(), feature_);
evaluate_transform(marker_transform_, feature_, sym.get_image_transform());
#if 0
marker_.reset();
agg::trans_affine trans;
evaluate_transform(trans, feature_, sym.get_image_transform());
boost::optional<marker_ptr> opt_marker; //TODO: Why boost::optional?
if (!filename.empty())
{
marker_ = marker_cache::instance()->find(filename, true);
opt_marker = marker_cache::instance()->find(filename, true);
}
if (!marker_) {
marker_size_.clear();
marker_ext_.init(0, 0, 0, 0);
return;
}
marker_size_.set((*marker_)->width(), (*marker_)->height());
double px0 = - 0.5 * marker_size_.x;
double py0 = - 0.5 * marker_size_.y;
double px1 = 0.5 * marker_size_.x;
double py1 = 0.5 * marker_size_.y;
marker_ptr m;
if (opt_marker) m = *opt_marker;
if (!m) return;
double width = m->width();
double height = m->height();
double px0 = - 0.5 * width;
double py0 = - 0.5 * height;
double px1 = 0.5 * width;
double py1 = 0.5 * height;
double px2 = px1;
double py2 = py0;
double px3 = px0;
double py3 = py1;
marker_transform_.transform(&px0,&py0);
marker_transform_.transform(&px1,&py1);
marker_transform_.transform(&px2,&py2);
marker_transform_.transform(&px3,&py3);
marker_ext_.init(px0, py0, px1, py1);
marker_ext_.expand_to_include(px2, py2);
marker_ext_.expand_to_include(px3, py3);
#endif
}
marker_ptr text_symbolizer_helper::get_marker() const
{
return marker_;
}
agg::trans_affine const& text_symbolizer_helper::get_image_transform() const
{
return marker_transform_;
trans.transform(&px0, &py0);
trans.transform(&px1, &py1);
trans.transform(&px2, &py2);
trans.transform(&px3, &py3);
box2d<double> bbox(px0, py0, px1, py1);
bbox.expand_to_include(px2, py2);
bbox.expand_to_include(px3, py3);
finder_.set_marker(boost::make_shared<marker_info>(m, trans), bbox, sym.get_unlock_image(), sym.get_shield_displacement());
}
template text_symbolizer_helper::text_symbolizer_helper(const text_symbolizer &sym, const Feature &feature,

View file

@ -43,7 +43,7 @@ namespace mapnik
{
placement_finder_ng::placement_finder_ng(Feature const& feature, DetectorType &detector, box2d<double> const& extent, text_placement_info_ptr placement_info, face_manager_freetype &font_manager, double scale_factor)
: feature_(feature), detector_(detector), extent_(extent), layout_(font_manager), info_(placement_info), valid_(true), scale_factor_(scale_factor), placements_()
: feature_(feature), detector_(detector), extent_(extent), layout_(font_manager), info_(placement_info), valid_(true), scale_factor_(scale_factor), placements_(), has_marker_(false), marker_(), marker_box_()
{
}
@ -83,7 +83,6 @@ const placements_list &placement_finder_ng::placements() const
return placements_;
}
void placement_finder_ng::init_alignment()
{
text_symbolizer_properties const& p = info_->properties;
@ -191,7 +190,7 @@ bool placement_finder_ng::find_point_placement(pixel_position pos)
rotated_box2d(bbox, orientation_, layout_.width(), layout_.height());
bbox.re_center(glyphs->get_base_point().x, glyphs->get_base_point().y);
if (collision(bbox)) return false;
if (has_marker_ && !add_marker(glyphs, pos)) return false;
detector_.insert(bbox, layout_.get_text());
/* IMPORTANT NOTE:
@ -438,6 +437,27 @@ bool placement_finder_ng::collision(const box2d<double> &box) const
return false;
}
void placement_finder_ng::set_marker(marker_info_ptr m, box2d<double> box, bool marker_unlocked, const pixel_position &marker_displacement)
{
marker_ = m;
marker_box_ = box;
marker_unlocked_ = marker_unlocked;
marker_displacement_ = marker_displacement;
has_marker_ = true;
}
bool placement_finder_ng::add_marker(glyph_positions_ptr glyphs, const pixel_position &pos) const
{
pixel_position real_pos = (marker_unlocked_ ? pos : glyphs->get_base_point()) + marker_displacement_;
box2d<double> bbox = marker_box_;
bbox.move(real_pos.x, real_pos.y);
glyphs->set_marker(marker_, real_pos);
if (collision(bbox)) return false;
detector_.insert(bbox);
return true;
}
box2d<double> placement_finder_ng::get_bbox(glyph_info const& glyph, pixel_position const& pos, rotation const& rot)
{
/*
@ -507,6 +527,22 @@ void glyph_positions::set_base_point(pixel_position base_point)
base_point_ = base_point;
}
void glyph_positions::set_marker(marker_info_ptr marker, const pixel_position &marker_pos)
{
marker_ = marker;
marker_pos_ = marker_pos;
}
marker_info_ptr glyph_positions::marker() const
{
return marker_;
}
const pixel_position &glyph_positions::marker_pos() const
{
return marker_pos_;
}
/*************************************************************************************/
typedef agg::conv_clip_polyline<geometry_type> clipped_geometry_type;

View file

@ -50,7 +50,7 @@
</Rule>
<Rule>
<Filter>[nr] = '10'</Filter>
<ShieldSymbolizer face-name="DejaVu Sans Book" size="16" placement="point" file="../../data/images/crosshair16x16.png" unlock-image="false" shield-dx="15">'X'</ShieldSymbolizer>
<ShieldSymbolizer face-name="DejaVu Sans Book" size="16" placement="point" file="../../data/images/crosshair16x16.png" unlock-image="false" shield-dx="15" dy="20">'X'</ShieldSymbolizer>
</Rule>
<Rule>
<PointSymbolizer allow-overlap="true" file="../../data/raster/white-alpha.png"/>

View file

@ -50,11 +50,14 @@
</Rule>
<Rule>
<Filter>[nr] = '10'</Filter>
<ShieldSymbolizer face-name="DejaVu Sans Book" size="16" placement="point" file="../../data/images/crosshair16x16.png" unlock-image="true" shield-dx="15">'X'</ShieldSymbolizer>
<ShieldSymbolizer face-name="DejaVu Sans Book" size="16" placement="point" file="../../data/images/crosshair16x16.png" unlock-image="true" shield-dx="15" dy="20">'X'</ShieldSymbolizer>
</Rule>
<Rule>
<PointSymbolizer allow-overlap="true" file="../../data/raster/white-alpha.png"/>
</Rule>
<Rule>
<DebugSymbolizer />
</Rule>
</Style>
</Map>