avoid relying on x and y in SEG_CLOSE command - instead cache MOVE_TO's coordinates

This commit is contained in:
artemp 2015-03-26 17:30:00 +01:00
parent 6a827f5018
commit 330bc5686c

View file

@ -34,7 +34,8 @@ struct weighted_vertex : private util::noncopyable
double nominalWeight()
{
if (prev == nullptr || next == nullptr || coord.cmd != SEG_LINETO) {
if (prev == nullptr || next == nullptr || coord.cmd != SEG_LINETO)
{
return std::numeric_limits<double>::infinity();
}
vertex2d const& A = prev->coord;
@ -92,7 +93,7 @@ template <typename Geometry>
struct MAPNIK_DECL simplify_converter
{
public:
simplify_converter(Geometry& geom)
simplify_converter(Geometry & geom)
: geom_(geom),
tolerance_(0.0),
status_(initial),
@ -135,7 +136,8 @@ public:
void set_simplify_tolerance(double value)
{
if (tolerance_ != value) {
if (tolerance_ != value)
{
tolerance_ = value;
reset();
}
@ -184,7 +186,8 @@ private:
return SEG_END;
}
unsigned output_vertex_cached(double* x, double* y) {
unsigned output_vertex_cached(double* x, double* y)
{
if (pos_ >= vertices_.size())
return SEG_END;
@ -195,11 +198,10 @@ private:
return previous_vertex_.cmd;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
unsigned output_vertex_distance(double* x, double* y) {
if (status_ == closing) {
unsigned output_vertex_distance(double* x, double* y)
{
if (status_ == closing)
{
status_ = end;
return SEG_CLOSE;
}
@ -209,19 +211,26 @@ private:
while ((vtx.cmd = geom_.vertex(&vtx.x, &vtx.y)) != SEG_END)
{
if (vtx.cmd == SEG_LINETO) {
if (distance_to_previous(vtx) > tolerance_) {
if (distance_to_previous(vtx) > tolerance_)
{
// Only output a vertex if it's far enough away from the previous
break;
} else {
} else
{
last = vtx;
// continue
}
} else if (vtx.cmd == SEG_CLOSE) {
if (last.cmd == SEG_END) {
}
else if (vtx.cmd == SEG_CLOSE)
{
if (last.cmd == SEG_END)
{
// The previous vertex was already output in the previous call.
// We can now safely output SEG_CLOSE.
status_ = end;
} else {
}
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.
@ -229,9 +238,13 @@ private:
status_ = closing;
}
break;
} else if (vtx.cmd == SEG_MOVETO) {
}
else if (vtx.cmd == SEG_MOVETO)
{
break;
} else {
}
else
{
throw std::runtime_error("Unknown vertex command");
}
}
@ -283,6 +296,7 @@ private:
}
vertices_.push_back(vtx);
sleeve_cont_.push_back(vtx);
start_vertex_ = vtx;
if (status_ == process) break;
}
else if (vtx.cmd == SEG_LINETO)
@ -309,7 +323,7 @@ private:
vertices_.push_back(sleeve_cont_.back());
sleeve_cont_.clear();
}
vertices_.push_back(vtx);
vertices_.push_back(start_vertex_);
if (status_ == process) break;
}
}
@ -342,7 +356,8 @@ private:
return SEG_END;
}
double distance_to_previous(vertex2d const& vtx) {
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;
@ -402,7 +417,8 @@ private:
{
VertexSet::iterator lowest = v.begin();
weighted_vertex *removed = *lowest;
if (removed->weight >= tolerance_) {
if (removed->weight >= tolerance_)
{
break;
}
@ -412,12 +428,14 @@ private:
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) {
if (removed->prev)
{
v.erase(removed->prev);
removed->prev->weight = std::max(removed->weight, removed->prev->nominalWeight());
v.insert(removed->prev);
}
if (removed->next) {
if (removed->next)
{
v.erase(removed->next);
removed->next->weight = std::max(removed->weight, removed->next->nominalWeight());
v.insert(removed->next);
@ -548,13 +566,14 @@ private:
return status_ = process;
}
Geometry& geom_;
Geometry & geom_;
double tolerance_;
status status_;
simplify_algorithm_e algorithm_;
std::deque<vertex2d> vertices_;
std::deque<vertex2d> sleeve_cont_;
vertex2d previous_vertex_;
vertex2d start_vertex_;
mutable size_t pos_;
};