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/to_python_converter.hpp>
#include <boost/python.hpp>
#include <boost/scoped_array.hpp>
// mapnik
#include <mapnik/feature.hpp>

View file

@ -70,7 +70,7 @@ public:
void end_map_processing(Map const& map);
void start_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,
mapnik::feature_ptr const& feature,

View file

@ -75,10 +75,19 @@ class hextree : private boost::noncopyable
~node ()
{
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];
// sum of values for computing mean value using count or pixel_count
double reds;
@ -101,8 +110,10 @@ class hextree : private boost::noncopyable
bool operator() (const node * lhs, const node* rhs) const
{
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};
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);
}
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),
colors_(0),
has_holes_(false),
@ -142,18 +153,23 @@ public:
setGamma(g);
}
~hextree() { delete root_;}
~hextree()
{
delete root_;
}
void setMaxColors(unsigned max_colors)
{
max_colors_ = max_colors;
}
void setGamma(const double &g)
void setGamma(double g)
{
gamma_ = g;
for (unsigned i=0; i<256; i++)
{
gammaLUT_[i] = gamma(i, 1/gamma_);
}
}
void setTransMode(unsigned t)
@ -201,7 +217,9 @@ public:
if (level == InsertPolicy::MAX_LEVELS)
{
if (cur_node->pixel_count == 1)
{
++colors_;
}
break;
}
@ -222,9 +240,13 @@ public:
byte a = preprocessAlpha(c.a);
unsigned ind=0;
if (a < InsertPolicy::MIN_ALPHA || colors_ == 0)
{
return 0;
}
if (colors_ == 1)
{
return pal_remap_[has_holes_?1:0];
}
rgba_hash_table::iterator it = color_hashmap_.find(c);
if (it == color_hashmap_.end())
@ -253,8 +275,10 @@ public:
db = sorted_pal_[i].b - c.b;
da = sorted_pal_[i].a - a;
// 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;
}
newdist = dr*dr + dg*dg + db*db + da*da;
if (newdist < dist)
{
@ -270,7 +294,9 @@ public:
da = sorted_pal_[i].a - a;
// stop criteria based on properties of used sorting
if ((dr+db+dg+da) * (dr+db+dg+da) / 4 > dist)
{
break;
}
newdist = dr*dr + dg*dg + db*db + da*da;
if (newdist < dist)
{
@ -282,7 +308,9 @@ public:
color_hashmap_[c] = ind;
}
else
{
ind = it->second;
}
return pal_remap_[ind];
}
@ -303,7 +331,7 @@ public:
root_ = new node();
// 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
pal_remap_.resize(sorted_pal_.size());
@ -332,25 +360,34 @@ private:
void print_tree(node *r, int d=0, int id=0) const
{
for (int i=0; i<d; i++)
{
printf("\t");
}
if (r->count>0)
{
printf("%d: (+%d/%d/%.5f) (%d %d %d %d)\n",
id, (int)r->count, (int)r->pixel_count, r->reduce_cost,
(int)round(gamma(r->reds / r->count, gamma_)),
(int)round(gamma(r->greens / r->count, gamma_)),
(int)round(gamma(r->blues / r->count, gamma_)),
(int)(r->alphas / r->count));
}
else
{
printf("%d: (%d/%d/%.5f) (%d %d %d %d)\n", id,
(int)r->count, (int)r->pixel_count, r->reduce_cost,
(int)round(gamma(r->reds / r->pixel_count, gamma_)),
(int)round(gamma(r->greens / r->pixel_count, gamma_)),
(int)round(gamma(r->blues / r->pixel_count, gamma_)),
(int)(r->alphas / r->pixel_count));
for (unsigned idx=0; idx < 16; ++idx) if (r->children_[idx] != 0)
{
print_tree(r->children_[idx], d+1, idx);
}
}
for (unsigned idx=0; idx < 16; ++idx)
{
if (r->children_[idx] != 0)
{
print_tree(r->children_[idx], d+1, idx);
}
}
}
// traverse tree and search for nodes with count!=0, that represent single color.
@ -368,10 +405,13 @@ private:
(byte)round(gamma(itr->greens / count, gamma_)),
(byte)round(gamma(itr->blues / count, gamma_)), a));
}
for (unsigned idx=0; idx < 16; ++idx) if (itr->children_[idx] != 0)
{
create_palette_rek(palette, itr->children_[idx]);
}
for (unsigned idx=0; idx < 16; ++idx)
{
if (itr->children_[idx] != 0)
{
create_palette_rek(palette, itr->children_[idx]);
}
}
}
// assign value to r, representing some penalty for assigning one
@ -381,7 +421,9 @@ private:
//initial small value, so that all nodes have >0 cost
r->reduce_cost = r->pixel_count/1000.0;
if (r->children_count==0)
{
return;
}
// mean color of all pixels in subtree
double mean_r = r->reds / 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;
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
node * cur_node = *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++;
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
if ((cur_node->reduce_cost / cur_node->pixel_count + 1) * std::log(double(cur_node->pixel_count)) > 15
&& cur_node->children_count > 0)
if (((cur_node->reduce_cost / cur_node->pixel_count + 1) * std::log(double(cur_node->pixel_count))) > 15
&& (cur_node->children_count > 0))
{
colors_--;
cur_node->count = 0;

View file

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

View file

@ -498,7 +498,7 @@ void csv_datasource::parse_csv(T& stream,
(
qi::lit("POINT") >> '('
>> double_[ref(x) = _1]
>> double_[ref(y) = _1] >> ')'
>> double_[ref(y) = _1] >> ')'
),
ascii::space);

View file

@ -75,6 +75,7 @@
// boost
#include <boost/utility.hpp>
#include <boost/make_shared.hpp>
#include <boost/math/special_functions/round.hpp>
// stl
#ifdef MAPNIK_DEBUG
@ -223,7 +224,7 @@ void agg_renderer<T>::end_layer_processing(layer const&)
}
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())
{
@ -262,7 +263,11 @@ void agg_renderer<T>::render_marker(int x, int y, marker & marker, agg::trans_af
}
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_renderer.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/symbolizer_helpers.hpp>
// stl
#include <cmath>
// boost
#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]);
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 y = std::floor(placement->placements[ii].starting_y);
double x = placement->placements[ii].starting_x;
double y = placement->placements[ii].starting_y;
ren.prepare_glyphs(&(placement->placements[ii]));
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
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;
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_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
distance += ci.width;
distance += cwidth;
end_x = old_x + dx*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];
}
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
find_line_circle_intersection(
start_x, start_y, ci.width,
start_x, start_y, cwidth,
old_x, old_y, new_x, new_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)
{
// rotate in place
render_x += ci.width*cosa - (char_height-2)*sina;
render_y -= ci.width*sina + (char_height-2)*cosa;
render_x += cwidth*cosa - (char_height-2)*sina;
render_y -= cwidth*sina + (char_height-2)*cosa;
render_angle += M_PI;
}
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
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;
double x, y, angle;
char_properties *properties;
@ -863,8 +865,8 @@ bool placement_finder<DetectorT>::test_placement(const std::auto_ptr<text_path>
{
// rotate in place
/* TODO: What's the meaning of -2? */
x += ci.width*cosa - (string_height_-2)*sina;
y -= ci.width*sina + (string_height_-2)*cosa;
x += cwidth*cosa - (string_height_-2)*sina;
y -= cwidth*sina + (string_height_-2)*cosa;
angle += M_PI;
//sin(x+PI) = -sin(x)
sina = -sina;
@ -879,12 +881,12 @@ bool placement_finder<DetectorT>::test_placement(const std::auto_ptr<text_path>
else
{
// put four corners of the letter into envelope
e.init(x, y, x + ci.width*cosa,
y - ci.width*sina);
e.init(x, y, x + cwidth*cosa,
y - cwidth*sina);
e.expand_to_include(x - ci.height()*sina,
y - ci.height()*cosa);
e.expand_to_include(x + (ci.width*cosa - ci.height()*sina),
y - (ci.width*sina + ci.height()*cosa));
e.expand_to_include(x + (cwidth*cosa - ci.height()*sina),
y - (cwidth*sina + ci.height()*cosa));
}
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
double lx = x - pos.first;
double ly = y - pos.second;
marker_x_ = int(floor(lx - (0.5 * marker_w_))) + 1;
marker_y_ = int(floor(ly - (0.5 * marker_h_))) + 1;
marker_x_ = lx - 0.5 * marker_w_;
marker_y_ = ly - 0.5 * marker_h_;
marker_ext_.re_center(lx, ly);
}
else
{ // center image at reference location
marker_x_ = int(floor(label_x - 0.5 * marker_w_));
marker_y_ = int(floor(label_y - 0.5 * marker_h_));
marker_x_ = label_x - 0.5 * marker_w_;
marker_y_ = label_y - 0.5 * marker_h_;
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 ly = y - pos.second;
int px = int(floor(lx - (0.5*marker_w_))) + 1;
int py = int(floor(ly - (0.5*marker_h_))) + 1;
int px = lx - 0.5*marker_w_;
int py = ly - 0.5*marker_h_;
marker_ext_.re_center(lx, ly);
// detector_->insert(label_ext); //TODO: Is this done by placement_finder?