Merge commit 'a537c58afa450e1ffe6bbd8978d2e122b55c9942' into harfbuzz
Conflicts: include/mapnik/symbolizer.hpp
This commit is contained in:
commit
784ef8f76a
19 changed files with 612 additions and 11 deletions
|
@ -48,6 +48,10 @@ void export_line_symbolizer()
|
||||||
(&line_symbolizer::get_stroke,
|
(&line_symbolizer::get_stroke,
|
||||||
return_value_policy<reference_existing_object>()),
|
return_value_policy<reference_existing_object>()),
|
||||||
&line_symbolizer::set_stroke)
|
&line_symbolizer::set_stroke)
|
||||||
|
.add_property("simplify_tolerance",
|
||||||
|
&line_symbolizer::simplify_tolerance,
|
||||||
|
&line_symbolizer::set_simplify_tolerance,
|
||||||
|
"simplification tolerance measure")
|
||||||
.add_property("offset",
|
.add_property("offset",
|
||||||
&line_symbolizer::offset,
|
&line_symbolizer::offset,
|
||||||
&line_symbolizer::set_offset,
|
&line_symbolizer::set_offset,
|
||||||
|
|
|
@ -60,6 +60,10 @@ void export_polygon_symbolizer()
|
||||||
&polygon_symbolizer::smooth,
|
&polygon_symbolizer::smooth,
|
||||||
&polygon_symbolizer::set_smooth,
|
&polygon_symbolizer::set_smooth,
|
||||||
"Set/get the polygon geometry's smooth value")
|
"Set/get the polygon geometry's smooth value")
|
||||||
|
.add_property("simplify_tolerance",
|
||||||
|
&polygon_symbolizer::simplify_tolerance,
|
||||||
|
&polygon_symbolizer::set_simplify_tolerance,
|
||||||
|
"simplfication tolerance measure")
|
||||||
;
|
;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
25
include/mapnik/simplify.hpp
Normal file
25
include/mapnik/simplify.hpp
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef MAPNIK_SIMPLIFY_HPP
|
||||||
|
#define MAPNIK_SIMPLIFY_HPP
|
||||||
|
|
||||||
|
#include <mapnik/debug.hpp>
|
||||||
|
|
||||||
|
// Boost
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
|
namespace mapnik
|
||||||
|
{
|
||||||
|
|
||||||
|
enum simplify_algorithm_e
|
||||||
|
{
|
||||||
|
radial_distance = 0,
|
||||||
|
douglas_peucker,
|
||||||
|
visvalingam_whyatt,
|
||||||
|
zhao_saalfeld
|
||||||
|
};
|
||||||
|
|
||||||
|
MAPNIK_DECL boost::optional<simplify_algorithm_e> simplify_algorithm_from_string(std::string const& name);
|
||||||
|
MAPNIK_DECL boost::optional<std::string> simplify_algorithm_to_string(simplify_algorithm_e algorithm);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MAPNIK_SIMPLIFY_HPP
|
443
include/mapnik/simplify_converter.hpp
Normal file
443
include/mapnik/simplify_converter.hpp
Normal file
|
@ -0,0 +1,443 @@
|
||||||
|
#ifndef MAPNIK_SIMPLIFY_CONVERTER_HPP
|
||||||
|
#define MAPNIK_SIMPLIFY_CONVERTER_HPP
|
||||||
|
|
||||||
|
#include <mapnik/debug.hpp>
|
||||||
|
#include <mapnik/box2d.hpp>
|
||||||
|
#include <mapnik/vertex.hpp>
|
||||||
|
#include <mapnik/simplify.hpp>
|
||||||
|
|
||||||
|
// STL
|
||||||
|
#include <limits>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
#include <deque>
|
||||||
|
// Boost
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
|
namespace mapnik
|
||||||
|
{
|
||||||
|
|
||||||
|
struct weighted_vertex : private boost::noncopyable {
|
||||||
|
vertex2d coord;
|
||||||
|
double weight;
|
||||||
|
weighted_vertex *prev;
|
||||||
|
weighted_vertex *next;
|
||||||
|
|
||||||
|
weighted_vertex(vertex2d coord_) :
|
||||||
|
coord(coord_),
|
||||||
|
weight(std::numeric_limits<double>::infinity()),
|
||||||
|
prev(NULL),
|
||||||
|
next(NULL) { }
|
||||||
|
|
||||||
|
double nominalWeight() {
|
||||||
|
if (prev == NULL || next == NULL || coord.cmd != SEG_LINETO) {
|
||||||
|
return std::numeric_limits<double>::infinity();
|
||||||
|
}
|
||||||
|
vertex2d& A = prev->coord;
|
||||||
|
vertex2d& B = next->coord;
|
||||||
|
vertex2d& C = coord;
|
||||||
|
return std::abs((double)((A.x - C.x) * (B.y - A.y) - (A.x - B.x) * (C.y - A.y))) / 2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ascending_sort {
|
||||||
|
bool operator() (const weighted_vertex *a, const weighted_vertex *b) {
|
||||||
|
return b->weight > a->weight;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sleeve
|
||||||
|
{
|
||||||
|
vertex2d v[5];
|
||||||
|
|
||||||
|
sleeve(vertex2d const& v0, vertex2d const& v1, double offset)
|
||||||
|
{
|
||||||
|
double a = atan2((v1.y - v0.y), (v1.x - v0.x));
|
||||||
|
double dx = offset * cos(a);
|
||||||
|
double dy = offset * sin(a);
|
||||||
|
v[0].x = v0.x + dy;
|
||||||
|
v[0].y = v0.y - dx;
|
||||||
|
v[1].x = v0.x - dy;
|
||||||
|
v[1].y = v0.y + dx;
|
||||||
|
v[2].x = v1.x - dy;
|
||||||
|
v[2].y = v1.y + dx;
|
||||||
|
v[3].x = v1.x + dy;
|
||||||
|
v[3].y = v1.y - dx;
|
||||||
|
v[4].x = v0.x + dy;
|
||||||
|
v[4].y = v0.y - dx;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool inside(vertex2d const& q)
|
||||||
|
{
|
||||||
|
bool inside=false;
|
||||||
|
|
||||||
|
for (unsigned i=0;i<4;++i)
|
||||||
|
{
|
||||||
|
if ((((v[i+1].y <= q.y) && (q.y < v[i].y)) ||
|
||||||
|
((v[i].y <= q.y) && (q.y < v[i+1].y))) &&
|
||||||
|
(q.x < (v[i].x - v[i+1].x) * (q.y - v[i+1].y)/ (v[i].y - v[i+1].y) + v[i+1].x))
|
||||||
|
inside=!inside;
|
||||||
|
}
|
||||||
|
return inside;
|
||||||
|
}
|
||||||
|
void print()
|
||||||
|
{
|
||||||
|
std::cerr << "LINESTRING("
|
||||||
|
<< v[0].x << " " << -v[0].y << ","
|
||||||
|
<< v[1].x << " " << -v[1].y << ","
|
||||||
|
<< v[2].x << " " << -v[2].y << ","
|
||||||
|
<< v[3].x << " " << -v[3].y << ","
|
||||||
|
<< v[0].x << " " << -v[0].y << ")" << std::endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Geometry>
|
||||||
|
struct MAPNIK_DECL simplify_converter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
simplify_converter(Geometry& geom)
|
||||||
|
: geom_(geom)
|
||||||
|
, tolerance_(0.0)
|
||||||
|
, status_(initial)
|
||||||
|
, algorithm_(radial_distance)
|
||||||
|
{}
|
||||||
|
|
||||||
|
enum status
|
||||||
|
{
|
||||||
|
initial,
|
||||||
|
process,
|
||||||
|
closing,
|
||||||
|
end,
|
||||||
|
cache
|
||||||
|
};
|
||||||
|
|
||||||
|
simplify_algorithm_e get_simplify_algorithm()
|
||||||
|
{
|
||||||
|
return algorithm_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_simplify_algorithm(simplify_algorithm_e value) {
|
||||||
|
if (algorithm_ != value) {
|
||||||
|
algorithm_ = value;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double get_simplify_tolerance()
|
||||||
|
{
|
||||||
|
return tolerance_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_simplify_tolerance(double value)
|
||||||
|
{
|
||||||
|
if (tolerance_ != value) {
|
||||||
|
tolerance_ = value;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
geom_.rewind(0);
|
||||||
|
vertices_.clear();
|
||||||
|
status_ = initial;
|
||||||
|
pos_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rewind(unsigned int)
|
||||||
|
{
|
||||||
|
pos_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
if (tolerance_ == 0.0)
|
||||||
|
return geom_.vertex(x, y);
|
||||||
|
|
||||||
|
if (status_ == initial)
|
||||||
|
init_vertices();
|
||||||
|
|
||||||
|
return output_vertex(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned output_vertex(double* x, double* y)
|
||||||
|
{
|
||||||
|
switch (algorithm_)
|
||||||
|
{
|
||||||
|
case visvalingam_whyatt:
|
||||||
|
return output_vertex_cached(x, y);
|
||||||
|
case radial_distance:
|
||||||
|
return output_vertex_distance(x, y);
|
||||||
|
case zhao_saalfeld:
|
||||||
|
return output_vertex_sleeve(x, y);
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("simplification algorithm not yet implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
return SEG_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned output_vertex_cached(double* x, double* y) {
|
||||||
|
if (pos_ >= vertices_.size())
|
||||||
|
return SEG_END;
|
||||||
|
|
||||||
|
previous_vertex_ = vertices_[pos_];
|
||||||
|
*x = previous_vertex_.x;
|
||||||
|
*y = previous_vertex_.y;
|
||||||
|
pos_++;
|
||||||
|
return previous_vertex_.cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned output_vertex_distance(double* x, double* y) {
|
||||||
|
if (status_ == closing) {
|
||||||
|
status_ = end;
|
||||||
|
return SEG_CLOSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex2d last(vertex2d::no_init);
|
||||||
|
vertex2d vtx(vertex2d::no_init);
|
||||||
|
while ((vtx.cmd = geom_.vertex(&vtx.x, &vtx.y)) != SEG_END)
|
||||||
|
{
|
||||||
|
if (vtx.cmd == SEG_LINETO) {
|
||||||
|
if (distance_to_previous(vtx) > tolerance_) {
|
||||||
|
// Only output a vertex if it's far enough away from the previous
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
last = vtx;
|
||||||
|
// continue
|
||||||
|
}
|
||||||
|
} else if (vtx.cmd == SEG_CLOSE) {
|
||||||
|
if (last.cmd == vertex2d::no_init) {
|
||||||
|
// The previous vertex was already output in the previous call.
|
||||||
|
// We can now safely output SEG_CLOSE.
|
||||||
|
status_ = end;
|
||||||
|
} else {
|
||||||
|
// We eliminated the previous point because it was too close, but
|
||||||
|
// we have to output it now anyway, since this is the end of the
|
||||||
|
// vertex stream. Make sure that we output SEG_CLOSE in the next call.
|
||||||
|
vtx = last;
|
||||||
|
status_ = closing;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if (vtx.cmd == SEG_MOVETO) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Unknown vertex command");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
previous_vertex_ = vtx;
|
||||||
|
*x = vtx.x;
|
||||||
|
*y = vtx.y;
|
||||||
|
return vtx.cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Iterator>
|
||||||
|
bool fit_sleeve(Iterator itr,Iterator end, vertex2d const& v)
|
||||||
|
{
|
||||||
|
sleeve s(*itr,v,tolerance_);
|
||||||
|
++itr; // skip first vertex
|
||||||
|
for (; itr!=end; ++itr)
|
||||||
|
{
|
||||||
|
if (!s.inside(*itr))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned output_vertex_sleeve(double* x, double* y)
|
||||||
|
{
|
||||||
|
vertex2d vtx(vertex2d::no_init);
|
||||||
|
std::size_t min_size = 1;
|
||||||
|
while ((vtx.cmd = geom_.vertex(&vtx.x, &vtx.y)) != SEG_END)
|
||||||
|
{
|
||||||
|
//if ((std::fabs(vtx.x - previous_vertex_.x) < 0.5) &&
|
||||||
|
// (std::fabs(vtx.y - previous_vertex_.y) < 0.5))
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
if (status_ == cache &&
|
||||||
|
vertices_.size() >= min_size)
|
||||||
|
status_ = process;
|
||||||
|
|
||||||
|
previous_vertex_ = vtx;
|
||||||
|
|
||||||
|
if (vtx.cmd == SEG_MOVETO)
|
||||||
|
{
|
||||||
|
if (sleeve_cont_.size() > 1)
|
||||||
|
{
|
||||||
|
vertices_.push_back(sleeve_cont_.back());
|
||||||
|
sleeve_cont_.clear();
|
||||||
|
}
|
||||||
|
vertices_.push_back(vtx);
|
||||||
|
sleeve_cont_.push_back(vtx);
|
||||||
|
if (status_ == process) break;
|
||||||
|
}
|
||||||
|
else if (vtx.cmd == SEG_LINETO)
|
||||||
|
{
|
||||||
|
if (sleeve_cont_.size() > 1 && !fit_sleeve(sleeve_cont_.begin(), sleeve_cont_.end(), vtx))
|
||||||
|
{
|
||||||
|
vertex2d last = vtx;
|
||||||
|
vtx = sleeve_cont_.back();
|
||||||
|
sleeve_cont_.clear();
|
||||||
|
sleeve_cont_.push_back(vtx);
|
||||||
|
sleeve_cont_.push_back(last);
|
||||||
|
vertices_.push_back(vtx);
|
||||||
|
if (status_ == process) break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sleeve_cont_.push_back(vtx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (vtx.cmd == SEG_CLOSE)
|
||||||
|
{
|
||||||
|
if (sleeve_cont_.size() > 1)
|
||||||
|
{
|
||||||
|
vertices_.push_back(sleeve_cont_.back());
|
||||||
|
sleeve_cont_.clear();
|
||||||
|
}
|
||||||
|
vertices_.push_back(vtx);
|
||||||
|
if (status_ == process) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status_ == cache)
|
||||||
|
{
|
||||||
|
if (vertices_.size() < min_size)
|
||||||
|
return SEG_END;
|
||||||
|
status_ = process;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vtx.cmd == SEG_END)
|
||||||
|
{
|
||||||
|
if (sleeve_cont_.size() > 1)
|
||||||
|
{
|
||||||
|
vertices_.push_back(sleeve_cont_.back());
|
||||||
|
}
|
||||||
|
sleeve_cont_.clear();
|
||||||
|
vertices_.push_back(vtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vertices_.size() > 0)
|
||||||
|
{
|
||||||
|
vertex2d v = vertices_.front();
|
||||||
|
vertices_.pop_front();
|
||||||
|
*x = v.x;
|
||||||
|
*y = v.y;
|
||||||
|
return v.cmd;
|
||||||
|
}
|
||||||
|
return SEG_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
double distance_to_previous(vertex2d const& vtx) {
|
||||||
|
double dx = previous_vertex_.x - vtx.x;
|
||||||
|
double dy = previous_vertex_.y - vtx.y;
|
||||||
|
return dx * dx + dy * dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
status init_vertices()
|
||||||
|
{
|
||||||
|
if (status_ != initial) // already initialized
|
||||||
|
return status_;
|
||||||
|
|
||||||
|
reset();
|
||||||
|
|
||||||
|
switch (algorithm_) {
|
||||||
|
case visvalingam_whyatt:
|
||||||
|
return init_vertices_visvalingam_whyatt();
|
||||||
|
case radial_distance:
|
||||||
|
// Use
|
||||||
|
vertices_.push_back(vertex2d(vertex2d::no_init));
|
||||||
|
return status_ = process;
|
||||||
|
case zhao_saalfeld:
|
||||||
|
return status_ = cache;
|
||||||
|
default:
|
||||||
|
throw std::runtime_error("simplification algorithm not yet implemented");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status init_vertices_visvalingam_whyatt() {
|
||||||
|
typedef std::set<weighted_vertex *, weighted_vertex::ascending_sort> VertexSet;
|
||||||
|
typedef std::vector<weighted_vertex *> VertexList;
|
||||||
|
|
||||||
|
std::vector<weighted_vertex *> v_list;
|
||||||
|
vertex2d vtx(vertex2d::no_init);
|
||||||
|
while ((vtx.cmd = geom_.vertex(&vtx.x, &vtx.y)) != SEG_END)
|
||||||
|
{
|
||||||
|
v_list.push_back(new weighted_vertex(vtx));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!v_list.size()) {
|
||||||
|
return status_ = process;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect the vertices in a linked list and insert them into the set.
|
||||||
|
VertexSet v;
|
||||||
|
for (VertexList::iterator i = v_list.begin(); i != v_list.end(); i++)
|
||||||
|
{
|
||||||
|
(*i)->prev = i == v_list.begin() ? NULL : *(i - 1);
|
||||||
|
(*i)->next = i + 1 == v_list.end() ? NULL : *(i + 1);
|
||||||
|
(*i)->weight = (*i)->nominalWeight();
|
||||||
|
v.insert(*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use Visvalingam-Whyatt algorithm to calculate each point's weight.
|
||||||
|
while (v.size() > 0)
|
||||||
|
{
|
||||||
|
VertexSet::iterator lowest = v.begin();
|
||||||
|
weighted_vertex *removed = *lowest;
|
||||||
|
if (removed->weight >= tolerance_) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
v.erase(lowest);
|
||||||
|
|
||||||
|
// Connect adjacent vertices with each other
|
||||||
|
if (removed->prev) removed->prev->next = removed->next;
|
||||||
|
if (removed->next) removed->next->prev = removed->prev;
|
||||||
|
// Adjust weight and reinsert prev/next to move them to their correct position.
|
||||||
|
if (removed->prev) {
|
||||||
|
v.erase(removed->prev);
|
||||||
|
removed->prev->weight = std::max(removed->weight, removed->prev->nominalWeight());
|
||||||
|
v.insert(removed->prev);
|
||||||
|
}
|
||||||
|
if (removed->next) {
|
||||||
|
v.erase(removed->next);
|
||||||
|
removed->next->weight = std::max(removed->weight, removed->next->nominalWeight());
|
||||||
|
v.insert(removed->next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v.clear();
|
||||||
|
|
||||||
|
// Traverse the remaining list and insert them into the vertex cache.
|
||||||
|
for (VertexList::iterator i = v_list.begin(); i != v_list.end(); i++)
|
||||||
|
{
|
||||||
|
if ((*i)->weight >= tolerance_) {
|
||||||
|
vertices_.push_back((*i)->coord);
|
||||||
|
}
|
||||||
|
delete *i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialization finished.
|
||||||
|
return status_ = process;
|
||||||
|
}
|
||||||
|
|
||||||
|
Geometry& geom_;
|
||||||
|
double tolerance_;
|
||||||
|
status status_;
|
||||||
|
simplify_algorithm_e algorithm_;
|
||||||
|
size_t pos_;
|
||||||
|
std::deque<vertex2d> vertices_;
|
||||||
|
std::deque<vertex2d> sleeve_cont_;
|
||||||
|
vertex2d previous_vertex_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MAPNIK_SIMPLIFY_CONVERTER_HPP
|
|
@ -28,7 +28,7 @@
|
||||||
#include <mapnik/parse_path.hpp>
|
#include <mapnik/parse_path.hpp>
|
||||||
#include <mapnik/image_compositing.hpp>
|
#include <mapnik/image_compositing.hpp>
|
||||||
#include <mapnik/transform_expression.hpp>
|
#include <mapnik/transform_expression.hpp>
|
||||||
//#include <mapnik/metawriter/properties.hpp>
|
#include <mapnik/simplify.hpp>
|
||||||
|
|
||||||
// boost
|
// boost
|
||||||
#include <boost/array.hpp>
|
#include <boost/array.hpp>
|
||||||
|
@ -56,12 +56,18 @@ public:
|
||||||
std::string get_transform_string() const;
|
std::string get_transform_string() const;
|
||||||
void set_clip(bool clip);
|
void set_clip(bool clip);
|
||||||
bool clip() const;
|
bool clip() const;
|
||||||
|
void set_simplify_algorithm(simplify_algorithm_e algorithm);
|
||||||
|
simplify_algorithm_e simplify_algorithm() const;
|
||||||
|
void set_simplify_tolerance(double simplify_tolerance);
|
||||||
|
double simplify_tolerance() const;
|
||||||
void set_smooth(double smooth);
|
void set_smooth(double smooth);
|
||||||
double smooth() const;
|
double smooth() const;
|
||||||
private:
|
private:
|
||||||
composite_mode_e comp_op_;
|
composite_mode_e comp_op_;
|
||||||
transform_type affine_transform_;
|
transform_type affine_transform_;
|
||||||
bool clip_;
|
bool clip_;
|
||||||
|
simplify_algorithm_e simplify_algorithm_value_;
|
||||||
|
double simplify_tolerance_value_;
|
||||||
double smooth_value_;
|
double smooth_value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -140,6 +140,7 @@ public:
|
||||||
{
|
{
|
||||||
if (destroyed_)
|
if (destroyed_)
|
||||||
{
|
{
|
||||||
|
destroyed_ = false;
|
||||||
onDeadReference();
|
onDeadReference();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -48,9 +48,9 @@
|
||||||
#include <boost/array.hpp>
|
#include <boost/array.hpp>
|
||||||
|
|
||||||
// mapnik
|
// mapnik
|
||||||
#include <mapnik/ctrans.hpp>
|
|
||||||
#include <mapnik/agg_helpers.hpp>
|
#include <mapnik/agg_helpers.hpp>
|
||||||
#include <mapnik/offset_converter.hpp>
|
#include <mapnik/offset_converter.hpp>
|
||||||
|
#include <mapnik/simplify_converter.hpp>
|
||||||
|
|
||||||
// agg
|
// agg
|
||||||
#include "agg_conv_clip_polygon.h"
|
#include "agg_conv_clip_polygon.h"
|
||||||
|
@ -60,12 +60,14 @@
|
||||||
#include "agg_conv_dash.h"
|
#include "agg_conv_dash.h"
|
||||||
#include "agg_conv_transform.h"
|
#include "agg_conv_transform.h"
|
||||||
|
|
||||||
|
|
||||||
namespace mapnik {
|
namespace mapnik {
|
||||||
|
|
||||||
struct transform_tag {};
|
struct transform_tag {};
|
||||||
struct clip_line_tag {};
|
struct clip_line_tag {};
|
||||||
struct clip_poly_tag {};
|
struct clip_poly_tag {};
|
||||||
struct smooth_tag {};
|
struct smooth_tag {};
|
||||||
|
struct simplify_tag {};
|
||||||
struct stroke_tag {};
|
struct stroke_tag {};
|
||||||
struct dash_tag {};
|
struct dash_tag {};
|
||||||
struct affine_transform_tag {};
|
struct affine_transform_tag {};
|
||||||
|
@ -98,6 +100,19 @@ struct converter_traits<T,mapnik::smooth_tag>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct converter_traits<T,mapnik::simplify_tag>
|
||||||
|
{
|
||||||
|
typedef T geometry_type;
|
||||||
|
typedef simplify_converter<geometry_type> conv_type;
|
||||||
|
|
||||||
|
template <typename Args>
|
||||||
|
static void setup(geometry_type & geom, Args const& args)
|
||||||
|
{
|
||||||
|
geom.set_simplify_algorithm(boost::fusion::at_c<2>(args).simplify_algorithm());
|
||||||
|
geom.set_simplify_tolerance(boost::fusion::at_c<2>(args).simplify_tolerance());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct converter_traits<T, mapnik::clip_line_tag>
|
struct converter_traits<T, mapnik::clip_line_tag>
|
||||||
|
|
|
@ -109,13 +109,14 @@ void agg_renderer<T>::process(line_pattern_symbolizer const& sym,
|
||||||
clipping_extent.init(x0 - padding, y0 - padding, x1 + padding , y1 + padding);
|
clipping_extent.init(x0 - padding, y0 - padding, x1 + padding , y1 + padding);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef boost::mpl::vector<clip_line_tag,transform_tag,smooth_tag> conv_types;
|
typedef boost::mpl::vector<clip_line_tag,transform_tag,simplify_tag,smooth_tag> conv_types;
|
||||||
vertex_converter<box2d<double>, rasterizer_type, line_pattern_symbolizer,
|
vertex_converter<box2d<double>, rasterizer_type, line_pattern_symbolizer,
|
||||||
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
converter(clipping_extent,ras,sym,t_,prj_trans,tr,scale_factor_);
|
converter(clipping_extent,ras,sym,t_,prj_trans,tr,scale_factor_);
|
||||||
|
|
||||||
if (sym.clip()) converter.set<clip_line_tag>(); //optional clip (default: true)
|
if (sym.clip()) converter.set<clip_line_tag>(); //optional clip (default: true)
|
||||||
converter.set<transform_tag>(); //always transform
|
converter.set<transform_tag>(); //always transform
|
||||||
|
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
|
||||||
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
||||||
|
|
||||||
BOOST_FOREACH(geometry_type & geom, feature.paths())
|
BOOST_FOREACH(geometry_type & geom, feature.paths())
|
||||||
|
|
|
@ -76,7 +76,7 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
|
||||||
typedef agg::renderer_base<pixfmt_comp_type> renderer_base;
|
typedef agg::renderer_base<pixfmt_comp_type> renderer_base;
|
||||||
typedef boost::mpl::vector<clip_line_tag, transform_tag,
|
typedef boost::mpl::vector<clip_line_tag, transform_tag,
|
||||||
offset_transform_tag, affine_transform_tag,
|
offset_transform_tag, affine_transform_tag,
|
||||||
smooth_tag, dash_tag, stroke_tag> conv_types;
|
simplify_tag, smooth_tag, dash_tag, stroke_tag> conv_types;
|
||||||
|
|
||||||
pixfmt_comp_type pixf(buf);
|
pixfmt_comp_type pixf(buf);
|
||||||
pixf.comp_op(static_cast<agg::comp_op_e>(sym.comp_op()));
|
pixf.comp_op(static_cast<agg::comp_op_e>(sym.comp_op()));
|
||||||
|
@ -121,6 +121,7 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
|
||||||
converter.set<transform_tag>(); // always transform
|
converter.set<transform_tag>(); // always transform
|
||||||
if (fabs(sym.offset()) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
|
if (fabs(sym.offset()) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
|
||||||
converter.set<affine_transform_tag>(); // optional affine transform
|
converter.set<affine_transform_tag>(); // optional affine transform
|
||||||
|
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
|
||||||
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
||||||
|
|
||||||
BOOST_FOREACH( geometry_type & geom, feature.paths())
|
BOOST_FOREACH( geometry_type & geom, feature.paths())
|
||||||
|
@ -141,6 +142,7 @@ void agg_renderer<T>::process(line_symbolizer const& sym,
|
||||||
converter.set<transform_tag>(); // always transform
|
converter.set<transform_tag>(); // always transform
|
||||||
if (fabs(sym.offset()) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
|
if (fabs(sym.offset()) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
|
||||||
converter.set<affine_transform_tag>(); // optional affine transform
|
converter.set<affine_transform_tag>(); // optional affine transform
|
||||||
|
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
|
||||||
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
||||||
if (stroke_.has_dash()) converter.set<dash_tag>();
|
if (stroke_.has_dash()) converter.set<dash_tag>();
|
||||||
converter.set<stroke_tag>(); //always stroke
|
converter.set<stroke_tag>(); //always stroke
|
||||||
|
|
|
@ -139,13 +139,14 @@ void agg_renderer<T>::process(polygon_pattern_symbolizer const& sym,
|
||||||
agg::trans_affine tr;
|
agg::trans_affine tr;
|
||||||
evaluate_transform(tr, feature, sym.get_transform());
|
evaluate_transform(tr, feature, sym.get_transform());
|
||||||
|
|
||||||
typedef boost::mpl::vector<clip_poly_tag,transform_tag,smooth_tag> conv_types;
|
typedef boost::mpl::vector<clip_poly_tag,transform_tag,simplify_tag,smooth_tag> conv_types;
|
||||||
vertex_converter<box2d<double>, rasterizer, polygon_pattern_symbolizer,
|
vertex_converter<box2d<double>, rasterizer, polygon_pattern_symbolizer,
|
||||||
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
converter(query_extent_,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_);
|
converter(query_extent_,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_);
|
||||||
|
|
||||||
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||||
converter.set<transform_tag>(); //always transform
|
converter.set<transform_tag>(); //always transform
|
||||||
|
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
|
||||||
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
||||||
|
|
||||||
BOOST_FOREACH( geometry_type & geom, feature.paths())
|
BOOST_FOREACH( geometry_type & geom, feature.paths())
|
||||||
|
|
|
@ -51,7 +51,7 @@ void agg_renderer<T>::process(polygon_symbolizer const& sym,
|
||||||
agg::trans_affine tr;
|
agg::trans_affine tr;
|
||||||
evaluate_transform(tr, feature, sym.get_transform());
|
evaluate_transform(tr, feature, sym.get_transform());
|
||||||
|
|
||||||
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag> conv_types;
|
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,simplify_tag,smooth_tag> conv_types;
|
||||||
vertex_converter<box2d<double>, rasterizer, polygon_symbolizer,
|
vertex_converter<box2d<double>, rasterizer, polygon_symbolizer,
|
||||||
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
converter(query_extent_,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_);
|
converter(query_extent_,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_);
|
||||||
|
@ -59,6 +59,7 @@ void agg_renderer<T>::process(polygon_symbolizer const& sym,
|
||||||
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||||
converter.set<transform_tag>(); //always transform
|
converter.set<transform_tag>(); //always transform
|
||||||
converter.set<affine_transform_tag>();
|
converter.set<affine_transform_tag>();
|
||||||
|
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
|
||||||
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
||||||
|
|
||||||
BOOST_FOREACH( geometry_type & geom, feature.paths())
|
BOOST_FOREACH( geometry_type & geom, feature.paths())
|
||||||
|
|
|
@ -150,6 +150,7 @@ source = Split(
|
||||||
proj_transform.cpp
|
proj_transform.cpp
|
||||||
distance.cpp
|
distance.cpp
|
||||||
scale_denominator.cpp
|
scale_denominator.cpp
|
||||||
|
simplify.cpp
|
||||||
memory_datasource.cpp
|
memory_datasource.cpp
|
||||||
stroke.cpp
|
stroke.cpp
|
||||||
symbolizer.cpp
|
symbolizer.cpp
|
||||||
|
|
|
@ -850,7 +850,7 @@ void cairo_renderer_base::process(polygon_symbolizer const& sym,
|
||||||
agg::trans_affine tr;
|
agg::trans_affine tr;
|
||||||
evaluate_transform(tr, feature, sym.get_transform());
|
evaluate_transform(tr, feature, sym.get_transform());
|
||||||
|
|
||||||
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag> conv_types;
|
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,simplify_tag,smooth_tag> conv_types;
|
||||||
vertex_converter<box2d<double>, cairo_context, polygon_symbolizer,
|
vertex_converter<box2d<double>, cairo_context, polygon_symbolizer,
|
||||||
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
converter(query_extent_,context,sym,t_,prj_trans,tr,1.0);
|
converter(query_extent_,context,sym,t_,prj_trans,tr,1.0);
|
||||||
|
@ -858,6 +858,7 @@ void cairo_renderer_base::process(polygon_symbolizer const& sym,
|
||||||
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||||
converter.set<transform_tag>(); //always transform
|
converter.set<transform_tag>(); //always transform
|
||||||
converter.set<affine_transform_tag>();
|
converter.set<affine_transform_tag>();
|
||||||
|
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
|
||||||
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
||||||
|
|
||||||
BOOST_FOREACH( geometry_type & geom, feature.paths())
|
BOOST_FOREACH( geometry_type & geom, feature.paths())
|
||||||
|
@ -974,7 +975,7 @@ void cairo_renderer_base::process(line_symbolizer const& sym,
|
||||||
{
|
{
|
||||||
typedef boost::mpl::vector<clip_line_tag, transform_tag,
|
typedef boost::mpl::vector<clip_line_tag, transform_tag,
|
||||||
offset_transform_tag, affine_transform_tag,
|
offset_transform_tag, affine_transform_tag,
|
||||||
smooth_tag, dash_tag, stroke_tag> conv_types;
|
simplify_tag, smooth_tag, dash_tag, stroke_tag> conv_types;
|
||||||
cairo_context context(context_);
|
cairo_context context(context_);
|
||||||
mapnik::stroke const& stroke_ = sym.get_stroke();
|
mapnik::stroke const& stroke_ = sym.get_stroke();
|
||||||
context.set_operator(sym.comp_op());
|
context.set_operator(sym.comp_op());
|
||||||
|
@ -1015,6 +1016,7 @@ void cairo_renderer_base::process(line_symbolizer const& sym,
|
||||||
converter.set<transform_tag>(); // always transform
|
converter.set<transform_tag>(); // always transform
|
||||||
if (fabs(sym.offset()) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
|
if (fabs(sym.offset()) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
|
||||||
converter.set<affine_transform_tag>(); // optional affine transform
|
converter.set<affine_transform_tag>(); // optional affine transform
|
||||||
|
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
|
||||||
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
||||||
|
|
||||||
BOOST_FOREACH( geometry_type & geom, feature.paths())
|
BOOST_FOREACH( geometry_type & geom, feature.paths())
|
||||||
|
@ -1374,7 +1376,7 @@ void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym,
|
||||||
agg::trans_affine tr;
|
agg::trans_affine tr;
|
||||||
evaluate_transform(tr, feature, sym.get_transform());
|
evaluate_transform(tr, feature, sym.get_transform());
|
||||||
|
|
||||||
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag> conv_types;
|
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,simplify_tag,smooth_tag> conv_types;
|
||||||
vertex_converter<box2d<double>, cairo_context, polygon_pattern_symbolizer,
|
vertex_converter<box2d<double>, cairo_context, polygon_pattern_symbolizer,
|
||||||
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
converter(query_extent_,context,sym,t_,prj_trans,tr, scale_factor_);
|
converter(query_extent_,context,sym,t_,prj_trans,tr, scale_factor_);
|
||||||
|
@ -1382,6 +1384,7 @@ void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym,
|
||||||
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||||
converter.set<transform_tag>(); //always transform
|
converter.set<transform_tag>(); //always transform
|
||||||
converter.set<affine_transform_tag>();
|
converter.set<affine_transform_tag>();
|
||||||
|
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
|
||||||
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
||||||
|
|
||||||
BOOST_FOREACH( geometry_type & geom, feature.paths())
|
BOOST_FOREACH( geometry_type & geom, feature.paths())
|
||||||
|
|
|
@ -54,7 +54,7 @@ void grid_renderer<T>::process(line_symbolizer const& sym,
|
||||||
typedef agg::renderer_scanline_bin_solid<renderer_base> renderer_type;
|
typedef agg::renderer_scanline_bin_solid<renderer_base> renderer_type;
|
||||||
typedef boost::mpl::vector<clip_line_tag, transform_tag,
|
typedef boost::mpl::vector<clip_line_tag, transform_tag,
|
||||||
offset_transform_tag, affine_transform_tag,
|
offset_transform_tag, affine_transform_tag,
|
||||||
smooth_tag, dash_tag, stroke_tag> conv_types;
|
simplify_tag, smooth_tag, dash_tag, stroke_tag> conv_types;
|
||||||
agg::scanline_bin sl;
|
agg::scanline_bin sl;
|
||||||
|
|
||||||
grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_);
|
grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_);
|
||||||
|
@ -93,6 +93,7 @@ void grid_renderer<T>::process(line_symbolizer const& sym,
|
||||||
converter.set<transform_tag>(); // always transform
|
converter.set<transform_tag>(); // always transform
|
||||||
if (fabs(sym.offset()) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
|
if (fabs(sym.offset()) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
|
||||||
converter.set<affine_transform_tag>(); // optional affine transform
|
converter.set<affine_transform_tag>(); // optional affine transform
|
||||||
|
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
|
||||||
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
||||||
if (stroke_.has_dash()) converter.set<dash_tag>();
|
if (stroke_.has_dash()) converter.set<dash_tag>();
|
||||||
converter.set<stroke_tag>(); //always stroke
|
converter.set<stroke_tag>(); //always stroke
|
||||||
|
|
|
@ -53,7 +53,7 @@ void grid_renderer<T>::process(polygon_symbolizer const& sym,
|
||||||
agg::trans_affine tr;
|
agg::trans_affine tr;
|
||||||
evaluate_transform(tr, feature, sym.get_transform());
|
evaluate_transform(tr, feature, sym.get_transform());
|
||||||
|
|
||||||
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag> conv_types;
|
typedef boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,simplify_tag,smooth_tag> conv_types;
|
||||||
vertex_converter<box2d<double>, grid_rasterizer, polygon_symbolizer,
|
vertex_converter<box2d<double>, grid_rasterizer, polygon_symbolizer,
|
||||||
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
CoordTransform, proj_transform, agg::trans_affine, conv_types>
|
||||||
converter(query_extent_,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_);
|
converter(query_extent_,*ras_ptr,sym,t_,prj_trans,tr,scale_factor_);
|
||||||
|
@ -61,6 +61,7 @@ void grid_renderer<T>::process(polygon_symbolizer const& sym,
|
||||||
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
if (prj_trans.equal() && sym.clip()) converter.set<clip_poly_tag>(); //optional clip (default: true)
|
||||||
converter.set<transform_tag>(); //always transform
|
converter.set<transform_tag>(); //always transform
|
||||||
converter.set<affine_transform_tag>();
|
converter.set<affine_transform_tag>();
|
||||||
|
if (sym.simplify_tolerance() > 0.0) converter.set<simplify_tag>(); // optional simplify converter
|
||||||
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
if (sym.smooth() > 0.0) converter.set<smooth_tag>(); // optional smooth converter
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -858,6 +858,25 @@ void map_parser::parse_symbolizer_base(symbolizer_base &sym, xml_node const &pt)
|
||||||
optional<boolean> clip = pt.get_opt_attr<boolean>("clip");
|
optional<boolean> clip = pt.get_opt_attr<boolean>("clip");
|
||||||
if (clip) sym.set_clip(*clip);
|
if (clip) sym.set_clip(*clip);
|
||||||
|
|
||||||
|
// simplify algorithm
|
||||||
|
optional<std::string> simplify_algorithm_name = pt.get_opt_attr<std::string>("simplify-algorithm");
|
||||||
|
if (simplify_algorithm_name)
|
||||||
|
{
|
||||||
|
optional<simplify_algorithm_e> simplify_algorithm = simplify_algorithm_from_string(*simplify_algorithm_name);
|
||||||
|
if (simplify_algorithm)
|
||||||
|
{
|
||||||
|
sym.set_simplify_algorithm(*simplify_algorithm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw config_error("failed to parse simplify-algorithm: '" + *simplify_algorithm_name + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// simplify value
|
||||||
|
optional<double> simplify_tolerance = pt.get_opt_attr<double>("simplify-tolerance");
|
||||||
|
if (simplify_tolerance) sym.set_simplify_tolerance(*simplify_tolerance);
|
||||||
|
|
||||||
// smooth value
|
// smooth value
|
||||||
optional<double> smooth = pt.get_opt_attr<double>("smooth");
|
optional<double> smooth = pt.get_opt_attr<double>("smooth");
|
||||||
if (smooth) sym.set_smooth(*smooth);
|
if (smooth) sym.set_smooth(*smooth);
|
||||||
|
|
|
@ -350,6 +350,14 @@ private:
|
||||||
{
|
{
|
||||||
set_attr( node, "clip", sym.clip() );
|
set_attr( node, "clip", sym.clip() );
|
||||||
}
|
}
|
||||||
|
if (sym.simplify_algorithm() != dfl.simplify_algorithm() || explicit_defaults_)
|
||||||
|
{
|
||||||
|
set_attr( node, "simplify-algorithm", *simplify_algorithm_to_string(sym.simplify_algorithm()) );
|
||||||
|
}
|
||||||
|
if (sym.simplify_tolerance() != dfl.simplify_tolerance() || explicit_defaults_)
|
||||||
|
{
|
||||||
|
set_attr( node, "simplify-tolerance", sym.simplify_tolerance() );
|
||||||
|
}
|
||||||
if (sym.smooth() != dfl.smooth() || explicit_defaults_)
|
if (sym.smooth() != dfl.smooth() || explicit_defaults_)
|
||||||
{
|
{
|
||||||
set_attr( node, "smooth", sym.smooth() );
|
set_attr( node, "smooth", sym.smooth() );
|
||||||
|
|
41
src/simplify.cpp
Normal file
41
src/simplify.cpp
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
// mapnik
|
||||||
|
#include <mapnik/simplify.hpp>
|
||||||
|
|
||||||
|
// boost
|
||||||
|
#include <boost/assign/list_of.hpp>
|
||||||
|
#include <boost/bimap.hpp>
|
||||||
|
|
||||||
|
namespace mapnik
|
||||||
|
{
|
||||||
|
|
||||||
|
typedef boost::bimap<simplify_algorithm_e, std::string> simplify_algorithm_lookup_type;
|
||||||
|
static const simplify_algorithm_lookup_type simplify_lookup = boost::assign::list_of<simplify_algorithm_lookup_type::relation>
|
||||||
|
(radial_distance,"radial-distance")
|
||||||
|
(douglas_peucker,"douglas-peucker")
|
||||||
|
(visvalingam_whyatt,"visvalingam-whyatt")
|
||||||
|
(zhao_saalfeld,"zhao-saalfeld")
|
||||||
|
;
|
||||||
|
|
||||||
|
boost::optional<simplify_algorithm_e> simplify_algorithm_from_string(std::string const& name)
|
||||||
|
{
|
||||||
|
boost::optional<simplify_algorithm_e> algo;
|
||||||
|
simplify_algorithm_lookup_type::right_const_iterator right_iter = simplify_lookup.right.find(name);
|
||||||
|
if (right_iter != simplify_lookup.right.end())
|
||||||
|
{
|
||||||
|
algo.reset(right_iter->second);
|
||||||
|
}
|
||||||
|
return algo;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<std::string> simplify_algorithm_to_string(simplify_algorithm_e value)
|
||||||
|
{
|
||||||
|
boost::optional<std::string> algo;
|
||||||
|
simplify_algorithm_lookup_type::left_const_iterator left_iter = simplify_lookup.left.find(value);
|
||||||
|
if (left_iter != simplify_lookup.left.end())
|
||||||
|
{
|
||||||
|
algo.reset(left_iter->second);
|
||||||
|
}
|
||||||
|
return algo;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -45,6 +45,8 @@ void evaluate_transform(agg::trans_affine& tr, Feature const& feature,
|
||||||
symbolizer_base::symbolizer_base()
|
symbolizer_base::symbolizer_base()
|
||||||
: comp_op_(src_over),
|
: comp_op_(src_over),
|
||||||
clip_(true),
|
clip_(true),
|
||||||
|
simplify_algorithm_value_(radial_distance),
|
||||||
|
simplify_tolerance_value_(0.0),
|
||||||
smooth_value_(0.0)
|
smooth_value_(0.0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -54,6 +56,8 @@ symbolizer_base::symbolizer_base(symbolizer_base const& other)
|
||||||
: comp_op_(other.comp_op_),
|
: comp_op_(other.comp_op_),
|
||||||
affine_transform_(other.affine_transform_),
|
affine_transform_(other.affine_transform_),
|
||||||
clip_(other.clip_),
|
clip_(other.clip_),
|
||||||
|
simplify_algorithm_value_(other.simplify_algorithm_value_),
|
||||||
|
simplify_tolerance_value_(other.simplify_tolerance_value_),
|
||||||
smooth_value_(other.smooth_value_) {}
|
smooth_value_(other.smooth_value_) {}
|
||||||
|
|
||||||
void symbolizer_base::set_comp_op(composite_mode_e comp_op)
|
void symbolizer_base::set_comp_op(composite_mode_e comp_op)
|
||||||
|
@ -101,6 +105,26 @@ bool symbolizer_base::clip() const
|
||||||
return clip_;
|
return clip_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void symbolizer_base::set_simplify_algorithm(simplify_algorithm_e algo)
|
||||||
|
{
|
||||||
|
simplify_algorithm_value_ = algo;
|
||||||
|
}
|
||||||
|
|
||||||
|
simplify_algorithm_e symbolizer_base::simplify_algorithm() const
|
||||||
|
{
|
||||||
|
return simplify_algorithm_value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void symbolizer_base::set_simplify_tolerance(double simplify_tolerance)
|
||||||
|
{
|
||||||
|
simplify_tolerance_value_ = simplify_tolerance;
|
||||||
|
}
|
||||||
|
|
||||||
|
double symbolizer_base::simplify_tolerance() const
|
||||||
|
{
|
||||||
|
return simplify_tolerance_value_;
|
||||||
|
}
|
||||||
|
|
||||||
void symbolizer_base::set_smooth(double smooth)
|
void symbolizer_base::set_smooth(double smooth)
|
||||||
{
|
{
|
||||||
smooth_value_ = smooth;
|
smooth_value_ = smooth;
|
||||||
|
|
Loading…
Add table
Reference in a new issue