avoid relying on x and y in SEG_CLOSE command - instead cache MOVE_TO's coordinates
This commit is contained in:
parent
6a827f5018
commit
330bc5686c
1 changed files with 41 additions and 22 deletions
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue