Merge remote-tracking branch 'origin/master'

This commit is contained in:
Artem Pavlenko 2012-02-17 10:48:49 +00:00
commit b5bc17304c
9 changed files with 102 additions and 54 deletions

View file

@ -31,7 +31,6 @@
#include <boost/python/tuple.hpp> #include <boost/python/tuple.hpp>
#include <boost/python/to_python_converter.hpp> #include <boost/python/to_python_converter.hpp>
#include <boost/python.hpp> #include <boost/python.hpp>
#include <boost/scoped_array.hpp>
// mapnik // mapnik
#include <mapnik/feature.hpp> #include <mapnik/feature.hpp>

View file

@ -70,7 +70,7 @@ public:
void end_map_processing(Map const& map); void end_map_processing(Map const& map);
void start_layer_processing(layer const& lay); void start_layer_processing(layer const& lay);
void end_layer_processing(layer const& lay); void end_layer_processing(layer const& lay);
void render_marker(int x, int y, marker & marker, agg::trans_affine const& tr, double opacity); void render_marker(double x, double y, marker & marker, agg::trans_affine const& tr, double opacity);
void process(point_symbolizer const& sym, void process(point_symbolizer const& sym,
mapnik::feature_ptr const& feature, mapnik::feature_ptr const& feature,

View file

@ -75,10 +75,19 @@ class hextree : private boost::noncopyable
~node () ~node ()
{ {
for (unsigned i = 0; i < 16; ++i) for (unsigned i = 0; i < 16; ++i)
if (children_[i] != 0) delete children_[i],children_[i]=0; {
if (children_[i] != 0)
{
delete children_[i];
children_[i]=0;
}
}
} }
bool is_leaf() const { return children_count == 0; } bool is_leaf() const
{
return (children_count == 0);
}
node * children_[16]; node * children_[16];
// sum of values for computing mean value using count or pixel_count // sum of values for computing mean value using count or pixel_count
double reds; double reds;
@ -101,8 +110,10 @@ class hextree : private boost::noncopyable
bool operator() (const node * lhs, const node* rhs) const bool operator() (const node * lhs, const node* rhs) const
{ {
if (lhs->reduce_cost != rhs->reduce_cost) if (lhs->reduce_cost != rhs->reduce_cost)
return lhs->reduce_cost > rhs->reduce_cost; {
return lhs > rhs; return (lhs->reduce_cost > rhs->reduce_cost);
}
return (lhs > rhs);
} }
}; };
@ -126,13 +137,13 @@ class hextree : private boost::noncopyable
enum transparency_mode_t {NO_TRANSPARENCY=0, BINARY_TRANSPARENCY=1, FULL_TRANSPARENCY=2}; enum transparency_mode_t {NO_TRANSPARENCY=0, BINARY_TRANSPARENCY=1, FULL_TRANSPARENCY=2};
unsigned trans_mode_; unsigned trans_mode_;
inline double gamma(const double &b, const double &g) const inline double gamma(double b, double g) const
{ {
return 255 * std::pow(b/255, g); return 255 * std::pow(b/255, g);
} }
public: public:
explicit hextree(unsigned max_colors=256, const double &g=2.0) explicit hextree(unsigned max_colors=256, double g=2.0)
: max_colors_(max_colors), : max_colors_(max_colors),
colors_(0), colors_(0),
has_holes_(false), has_holes_(false),
@ -142,19 +153,24 @@ public:
setGamma(g); setGamma(g);
} }
~hextree() { delete root_;} ~hextree()
{
delete root_;
}
void setMaxColors(unsigned max_colors) void setMaxColors(unsigned max_colors)
{ {
max_colors_ = max_colors; max_colors_ = max_colors;
} }
void setGamma(const double &g) void setGamma(double g)
{ {
gamma_ = g; gamma_ = g;
for (unsigned i=0; i<256; i++) for (unsigned i=0; i<256; i++)
{
gammaLUT_[i] = gamma(i, 1/gamma_); gammaLUT_[i] = gamma(i, 1/gamma_);
} }
}
void setTransMode(unsigned t) void setTransMode(unsigned t)
{ {
@ -201,7 +217,9 @@ public:
if (level == InsertPolicy::MAX_LEVELS) if (level == InsertPolicy::MAX_LEVELS)
{ {
if (cur_node->pixel_count == 1) if (cur_node->pixel_count == 1)
{
++colors_; ++colors_;
}
break; break;
} }
@ -222,9 +240,13 @@ public:
byte a = preprocessAlpha(c.a); byte a = preprocessAlpha(c.a);
unsigned ind=0; unsigned ind=0;
if (a < InsertPolicy::MIN_ALPHA || colors_ == 0) if (a < InsertPolicy::MIN_ALPHA || colors_ == 0)
{
return 0; return 0;
}
if (colors_ == 1) if (colors_ == 1)
{
return pal_remap_[has_holes_?1:0]; return pal_remap_[has_holes_?1:0];
}
rgba_hash_table::iterator it = color_hashmap_.find(c); rgba_hash_table::iterator it = color_hashmap_.find(c);
if (it == color_hashmap_.end()) if (it == color_hashmap_.end())
@ -253,8 +275,10 @@ public:
db = sorted_pal_[i].b - c.b; db = sorted_pal_[i].b - c.b;
da = sorted_pal_[i].a - a; da = sorted_pal_[i].a - a;
// stop criteria based on properties of used sorting // stop criteria based on properties of used sorting
if ((dr+db+dg+da) * (dr+db+dg+da) / 4 > dist) if (((dr+db+dg+da) * (dr+db+dg+da) / 4 > dist))
{
break; break;
}
newdist = dr*dr + dg*dg + db*db + da*da; newdist = dr*dr + dg*dg + db*db + da*da;
if (newdist < dist) if (newdist < dist)
{ {
@ -270,7 +294,9 @@ public:
da = sorted_pal_[i].a - a; da = sorted_pal_[i].a - a;
// stop criteria based on properties of used sorting // stop criteria based on properties of used sorting
if ((dr+db+dg+da) * (dr+db+dg+da) / 4 > dist) if ((dr+db+dg+da) * (dr+db+dg+da) / 4 > dist)
{
break; break;
}
newdist = dr*dr + dg*dg + db*db + da*da; newdist = dr*dr + dg*dg + db*db + da*da;
if (newdist < dist) if (newdist < dist)
{ {
@ -282,7 +308,9 @@ public:
color_hashmap_[c] = ind; color_hashmap_[c] = ind;
} }
else else
{
ind = it->second; ind = it->second;
}
return pal_remap_[ind]; return pal_remap_[ind];
} }
@ -303,7 +331,7 @@ public:
root_ = new node(); root_ = new node();
// sort palette for binary searching in quantization // sort palette for binary searching in quantization
std::sort(sorted_pal_.begin(), sorted_pal_.end(),rgba::mean_sort_cmp()); std::sort(sorted_pal_.begin(), sorted_pal_.end(), rgba::mean_sort_cmp());
// returned palette is rearanged, so that colors with a<255 are at the begining // returned palette is rearanged, so that colors with a<255 are at the begining
pal_remap_.resize(sorted_pal_.size()); pal_remap_.resize(sorted_pal_.size());
@ -332,26 +360,35 @@ private:
void print_tree(node *r, int d=0, int id=0) const void print_tree(node *r, int d=0, int id=0) const
{ {
for (int i=0; i<d; i++) for (int i=0; i<d; i++)
{
printf("\t"); printf("\t");
}
if (r->count>0) if (r->count>0)
{
printf("%d: (+%d/%d/%.5f) (%d %d %d %d)\n", printf("%d: (+%d/%d/%.5f) (%d %d %d %d)\n",
id, (int)r->count, (int)r->pixel_count, r->reduce_cost, id, (int)r->count, (int)r->pixel_count, r->reduce_cost,
(int)round(gamma(r->reds / r->count, gamma_)), (int)round(gamma(r->reds / r->count, gamma_)),
(int)round(gamma(r->greens / r->count, gamma_)), (int)round(gamma(r->greens / r->count, gamma_)),
(int)round(gamma(r->blues / r->count, gamma_)), (int)round(gamma(r->blues / r->count, gamma_)),
(int)(r->alphas / r->count)); (int)(r->alphas / r->count));
}
else else
{
printf("%d: (%d/%d/%.5f) (%d %d %d %d)\n", id, printf("%d: (%d/%d/%.5f) (%d %d %d %d)\n", id,
(int)r->count, (int)r->pixel_count, r->reduce_cost, (int)r->count, (int)r->pixel_count, r->reduce_cost,
(int)round(gamma(r->reds / r->pixel_count, gamma_)), (int)round(gamma(r->reds / r->pixel_count, gamma_)),
(int)round(gamma(r->greens / r->pixel_count, gamma_)), (int)round(gamma(r->greens / r->pixel_count, gamma_)),
(int)round(gamma(r->blues / r->pixel_count, gamma_)), (int)round(gamma(r->blues / r->pixel_count, gamma_)),
(int)(r->alphas / r->pixel_count)); (int)(r->alphas / r->pixel_count));
for (unsigned idx=0; idx < 16; ++idx) if (r->children_[idx] != 0) }
for (unsigned idx=0; idx < 16; ++idx)
{
if (r->children_[idx] != 0)
{ {
print_tree(r->children_[idx], d+1, idx); print_tree(r->children_[idx], d+1, idx);
} }
} }
}
// traverse tree and search for nodes with count!=0, that represent single color. // traverse tree and search for nodes with count!=0, that represent single color.
// clip extreme alfa values // clip extreme alfa values
@ -368,11 +405,14 @@ private:
(byte)round(gamma(itr->greens / count, gamma_)), (byte)round(gamma(itr->greens / count, gamma_)),
(byte)round(gamma(itr->blues / count, gamma_)), a)); (byte)round(gamma(itr->blues / count, gamma_)), a));
} }
for (unsigned idx=0; idx < 16; ++idx) if (itr->children_[idx] != 0) for (unsigned idx=0; idx < 16; ++idx)
{
if (itr->children_[idx] != 0)
{ {
create_palette_rek(palette, itr->children_[idx]); create_palette_rek(palette, itr->children_[idx]);
} }
} }
}
// assign value to r, representing some penalty for assigning one // assign value to r, representing some penalty for assigning one
// color to all pixels in this subtree // color to all pixels in this subtree
@ -381,7 +421,9 @@ private:
//initial small value, so that all nodes have >0 cost //initial small value, so that all nodes have >0 cost
r->reduce_cost = r->pixel_count/1000.0; r->reduce_cost = r->pixel_count/1000.0;
if (r->children_count==0) if (r->children_count==0)
{
return; return;
}
// mean color of all pixels in subtree // mean color of all pixels in subtree
double mean_r = r->reds / r->pixel_count; double mean_r = r->reds / r->pixel_count;
double mean_g = r->greens / r->pixel_count; double mean_g = r->greens / r->pixel_count;
@ -421,20 +463,20 @@ private:
std::set<node*,node_rev_cmp> colored_leaves_heap; std::set<node*,node_rev_cmp> colored_leaves_heap;
colored_leaves_heap.insert(root_); colored_leaves_heap.insert(root_);
while(!colored_leaves_heap.empty() && colors_ < max_colors_ && tries < 16) while((!colored_leaves_heap.empty() && (colors_ < max_colors_) && (tries < 16)))
{ {
// select worst node to remove it from palette and replace with children // select worst node to remove it from palette and replace with children
node * cur_node = *colored_leaves_heap.begin(); node * cur_node = *colored_leaves_heap.begin();
colored_leaves_heap.erase(colored_leaves_heap.begin()); colored_leaves_heap.erase(colored_leaves_heap.begin());
if (cur_node->children_count + colors_ - 1 > max_colors_) if (((cur_node->children_count + colors_ - 1) > max_colors_))
{ {
tries++; tries++;
continue; // try few times, maybe next will have less children continue; // try few times, maybe next will have less children
} }
tries=0; tries = 0;
// ignore leaves and also nodes with small mean error and not excessive number of pixels // ignore leaves and also nodes with small mean error and not excessive number of pixels
if ((cur_node->reduce_cost / cur_node->pixel_count + 1) * std::log(double(cur_node->pixel_count)) > 15 if (((cur_node->reduce_cost / cur_node->pixel_count + 1) * std::log(double(cur_node->pixel_count))) > 15
&& cur_node->children_count > 0) && (cur_node->children_count > 0))
{ {
colors_--; colors_--;
cur_node->count = 0; cur_node->count = 0;

View file

@ -141,10 +141,10 @@ protected:
box2d<double> marker_ext_; box2d<double> marker_ext_;
boost::optional<marker_ptr> marker_; boost::optional<marker_ptr> marker_;
agg::trans_affine transform_; agg::trans_affine transform_;
int marker_w_; double marker_w_;
int marker_h_; double marker_h_;
int marker_x_; double marker_x_;
int marker_y_; double marker_y_;
// F***ing templates... // F***ing templates...
// http://womble.decadent.org.uk/c++/template-faq.html#base-lookup // http://womble.decadent.org.uk/c++/template-faq.html#base-lookup
using text_symbolizer_helper<FaceManagerT, DetectorT>::geometries_to_process_; using text_symbolizer_helper<FaceManagerT, DetectorT>::geometries_to_process_;

View file

@ -75,6 +75,7 @@
// boost // boost
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/math/special_functions/round.hpp>
// stl // stl
#ifdef MAPNIK_DEBUG #ifdef MAPNIK_DEBUG
@ -223,7 +224,7 @@ void agg_renderer<T>::end_layer_processing(layer const&)
} }
template <typename T> template <typename T>
void agg_renderer<T>::render_marker(int x, int y, marker & marker, agg::trans_affine const& tr, double opacity) void agg_renderer<T>::render_marker(double x, double y, marker & marker, agg::trans_affine const& tr, double opacity)
{ {
if (marker.is_vector()) if (marker.is_vector())
{ {
@ -262,7 +263,11 @@ void agg_renderer<T>::render_marker(int x, int y, marker & marker, agg::trans_af
} }
else else
{ {
pixmap_.set_rectangle_alpha2(**marker.get_bitmap_data(), x, y, opacity); //TODO: Add subpixel support
pixmap_.set_rectangle_alpha2(**marker.get_bitmap_data(),
boost::math::iround(x),
boost::math::iround(y),
opacity);
} }
} }

View file

@ -27,9 +27,9 @@
#include <mapnik/svg/svg_converter.hpp> #include <mapnik/svg/svg_converter.hpp>
#include <mapnik/svg/svg_renderer.hpp> #include <mapnik/svg/svg_renderer.hpp>
#include <mapnik/svg/svg_path_adapter.hpp> #include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/symbolizer_helpers.hpp> #include <mapnik/symbolizer_helpers.hpp>
// stl
#include <cmath>
// boost // boost
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
@ -57,8 +57,8 @@ void agg_renderer<T>::process(shield_symbolizer const& sym,
std::pair<int, int> marker_pos = helper.get_marker_position(placement->placements[ii]); std::pair<int, int> marker_pos = helper.get_marker_position(placement->placements[ii]);
render_marker(marker_pos.first, marker_pos.second, helper.get_marker(), helper.get_transform(), sym.get_opacity()); render_marker(marker_pos.first, marker_pos.second, helper.get_marker(), helper.get_transform(), sym.get_opacity());
double x = std::floor(placement->placements[ii].starting_x); double x = placement->placements[ii].starting_x;
double y = std::floor(placement->placements[ii].starting_y); double y = placement->placements[ii].starting_y;
ren.prepare_glyphs(&(placement->placements[ii])); ren.prepare_glyphs(&(placement->placements[ii]));
ren.render(x, y); ren.render(x, y);
} }

View file

@ -713,6 +713,7 @@ std::auto_ptr<text_path> placement_finder<DetectorT>::get_placement_offset(const
{ {
// grab the next character according to the orientation // grab the next character according to the orientation
char_info const &ci = orientation > 0 ? info_.at(i) : info_.at(info_.num_characters() - i - 1); char_info const &ci = orientation > 0 ? info_.at(i) : info_.at(info_.num_characters() - i - 1);
double cwidth = ci.width + ci.format->character_spacing;
unsigned c = ci.c; unsigned c = ci.c;
double last_character_angle = angle; double last_character_angle = angle;
@ -728,10 +729,10 @@ std::auto_ptr<text_path> placement_finder<DetectorT>::get_placement_offset(const
double end_x = 0; double end_x = 0;
double end_y = 0; double end_y = 0;
if (segment_length - distance >= ci.width) if (segment_length - distance >= cwidth)
{ {
//if the distance remaining in this segment is enough, we just go further along the segment //if the distance remaining in this segment is enough, we just go further along the segment
distance += ci.width; distance += cwidth;
end_x = old_x + dx*distance/segment_length; end_x = old_x + dx*distance/segment_length;
end_y = old_y + dy*distance/segment_length; end_y = old_y + dy*distance/segment_length;
@ -757,11 +758,11 @@ std::auto_ptr<text_path> placement_finder<DetectorT>::get_placement_offset(const
segment_length = path_distances[index]; segment_length = path_distances[index];
} }
while (std::sqrt(std::pow(start_x - new_x, 2) + std::pow(start_y - new_y, 2)) < ci.width); //Distance from start_ to new_ while (std::sqrt(std::pow(start_x - new_x, 2) + std::pow(start_y - new_y, 2)) < cwidth); //Distance from start_ to new_
//Calculate the position to place the end of the character on //Calculate the position to place the end of the character on
find_line_circle_intersection( find_line_circle_intersection(
start_x, start_y, ci.width, start_x, start_y, cwidth,
old_x, old_y, new_x, new_y, old_x, old_y, new_x, new_y,
end_x, end_y); //results are stored in end_x, end_y end_x, end_y); //results are stored in end_x, end_y
@ -803,8 +804,8 @@ std::auto_ptr<text_path> placement_finder<DetectorT>::get_placement_offset(const
if (orientation < 0) if (orientation < 0)
{ {
// rotate in place // rotate in place
render_x += ci.width*cosa - (char_height-2)*sina; render_x += cwidth*cosa - (char_height-2)*sina;
render_y -= ci.width*sina + (char_height-2)*cosa; render_y -= cwidth*sina + (char_height-2)*cosa;
render_angle += M_PI; render_angle += M_PI;
} }
current_placement->add_node(c,render_x - current_placement->starting_x, current_placement->add_node(c,render_x - current_placement->starting_x,
@ -850,6 +851,7 @@ bool placement_finder<DetectorT>::test_placement(const std::auto_ptr<text_path>
{ {
// grab the next character according to the orientation // grab the next character according to the orientation
char_info const& ci = orientation > 0 ? info_.at(i) : info_.at(info_.num_characters() - i - 1); char_info const& ci = orientation > 0 ? info_.at(i) : info_.at(info_.num_characters() - i - 1);
double cwidth = ci.width + ci.format->character_spacing;
int c; int c;
double x, y, angle; double x, y, angle;
char_properties *properties; char_properties *properties;
@ -863,8 +865,8 @@ bool placement_finder<DetectorT>::test_placement(const std::auto_ptr<text_path>
{ {
// rotate in place // rotate in place
/* TODO: What's the meaning of -2? */ /* TODO: What's the meaning of -2? */
x += ci.width*cosa - (string_height_-2)*sina; x += cwidth*cosa - (string_height_-2)*sina;
y -= ci.width*sina + (string_height_-2)*cosa; y -= cwidth*sina + (string_height_-2)*cosa;
angle += M_PI; angle += M_PI;
//sin(x+PI) = -sin(x) //sin(x+PI) = -sin(x)
sina = -sina; sina = -sina;
@ -879,12 +881,12 @@ bool placement_finder<DetectorT>::test_placement(const std::auto_ptr<text_path>
else else
{ {
// put four corners of the letter into envelope // put four corners of the letter into envelope
e.init(x, y, x + ci.width*cosa, e.init(x, y, x + cwidth*cosa,
y - ci.width*sina); y - cwidth*sina);
e.expand_to_include(x - ci.height()*sina, e.expand_to_include(x - ci.height()*sina,
y - ci.height()*cosa); y - ci.height()*cosa);
e.expand_to_include(x + (ci.width*cosa - ci.height()*sina), e.expand_to_include(x + (cwidth*cosa - ci.height()*sina),
y - (ci.width*sina + ci.height()*cosa)); y - (cwidth*sina + ci.height()*cosa));
} }
if (!detector_.extent().intersects(e) || if (!detector_.extent().intersects(e) ||

View file

@ -255,14 +255,14 @@ text_placement_info_ptr shield_symbolizer_helper<FaceManagerT, DetectorT>::get_p
// remove displacement from image label // remove displacement from image label
double lx = x - pos.first; double lx = x - pos.first;
double ly = y - pos.second; double ly = y - pos.second;
marker_x_ = int(floor(lx - (0.5 * marker_w_))) + 1; marker_x_ = lx - 0.5 * marker_w_;
marker_y_ = int(floor(ly - (0.5 * marker_h_))) + 1; marker_y_ = ly - 0.5 * marker_h_;
marker_ext_.re_center(lx, ly); marker_ext_.re_center(lx, ly);
} }
else else
{ // center image at reference location { // center image at reference location
marker_x_ = int(floor(label_x - 0.5 * marker_w_)); marker_x_ = label_x - 0.5 * marker_w_;
marker_y_ = int(floor(label_y - 0.5 * marker_h_)); marker_y_ = label_y - 0.5 * marker_h_;
marker_ext_.re_center(label_x, label_y); marker_ext_.re_center(label_x, label_y);
} }
@ -345,8 +345,8 @@ std::pair<int, int> shield_symbolizer_helper<FaceManagerT, DetectorT>::get_marke
double lx = x - pos.first; double lx = x - pos.first;
double ly = y - pos.second; double ly = y - pos.second;
int px = int(floor(lx - (0.5*marker_w_))) + 1; int px = lx - 0.5*marker_w_;
int py = int(floor(ly - (0.5*marker_h_))) + 1; int py = ly - 0.5*marker_h_;
marker_ext_.re_center(lx, ly); marker_ext_.re_center(lx, ly);
// detector_->insert(label_ext); //TODO: Is this done by placement_finder? // detector_->insert(label_ext); //TODO: Is this done by placement_finder?