You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
172 lines
5.1 KiB
172 lines
5.1 KiB
//---------------------------------------------------------------------------- |
|
// Anti-Grain Geometry - Version 2.4 |
|
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) |
|
// |
|
// Permission to copy, use, modify, sell and distribute this software |
|
// is granted provided this copyright notice appears in all copies. |
|
// This software is provided "as is" without express or implied |
|
// warranty, and with no claim as to its suitability for any purpose. |
|
// |
|
//---------------------------------------------------------------------------- |
|
// Contact: mcseem@antigrain.com |
|
// mcseemagg@yahoo.com |
|
// http://www.antigrain.com |
|
//---------------------------------------------------------------------------- |
|
// |
|
// vertex_sequence container and vertex_dist struct |
|
// |
|
//---------------------------------------------------------------------------- |
|
#ifndef AGG_VERTEX_SEQUENCE_INCLUDED |
|
#define AGG_VERTEX_SEQUENCE_INCLUDED |
|
|
|
#include "agg_basics.h" |
|
#include "agg_array.h" |
|
#include "agg_math.h" |
|
|
|
namespace agg |
|
{ |
|
|
|
//----------------------------------------------------------vertex_sequence |
|
// Modified agg::pod_bvector. The data is interpreted as a sequence |
|
// of vertices. It means that the type T must expose: |
|
// |
|
// bool T::operator() (const T& val) |
|
// |
|
// that is called every time new vertex is being added. The main purpose |
|
// of this operator is the possibility to calculate some values during |
|
// adding and to return true if the vertex fits some criteria or false if |
|
// it doesn't. In the last case the new vertex is not added. |
|
// |
|
// The simple example is filtering coinciding vertices with calculation |
|
// of the distance between the current and previous ones: |
|
// |
|
// struct vertex_dist |
|
// { |
|
// double x; |
|
// double y; |
|
// double dist; |
|
// |
|
// vertex_dist() {} |
|
// vertex_dist(double x_, double y_) : |
|
// x(x_), |
|
// y(y_), |
|
// dist(0.0) |
|
// { |
|
// } |
|
// |
|
// bool operator () (const vertex_dist& val) |
|
// { |
|
// return (dist = calc_distance(x, y, val.x, val.y)) > EPSILON; |
|
// } |
|
// }; |
|
// |
|
// Function close() calls this operator and removes the last vertex if |
|
// necessary. |
|
//------------------------------------------------------------------------ |
|
template<class T, unsigned S=6> |
|
class vertex_sequence : public pod_bvector<T, S> |
|
{ |
|
public: |
|
typedef pod_bvector<T, S> base_type; |
|
|
|
void add(const T& val); |
|
void modify_last(const T& val); |
|
void close(bool remove_flag); |
|
}; |
|
|
|
|
|
|
|
//------------------------------------------------------------------------ |
|
template<class T, unsigned S> |
|
void vertex_sequence<T, S>::add(const T& val) |
|
{ |
|
if(base_type::size() > 1) |
|
{ |
|
if(!(*this)[base_type::size() - 2]((*this)[base_type::size() - 1])) |
|
{ |
|
base_type::remove_last(); |
|
} |
|
} |
|
base_type::add(val); |
|
} |
|
|
|
|
|
//------------------------------------------------------------------------ |
|
template<class T, unsigned S> |
|
void vertex_sequence<T, S>::modify_last(const T& val) |
|
{ |
|
base_type::remove_last(); |
|
add(val); |
|
} |
|
|
|
|
|
|
|
//------------------------------------------------------------------------ |
|
template<class T, unsigned S> |
|
void vertex_sequence<T, S>::close(bool closed) |
|
{ |
|
while(base_type::size() > 1) |
|
{ |
|
if((*this)[base_type::size() - 2]((*this)[base_type::size() - 1])) break; |
|
T t = (*this)[base_type::size() - 1]; |
|
base_type::remove_last(); |
|
modify_last(t); |
|
} |
|
|
|
if(closed) |
|
{ |
|
while(base_type::size() > 1) |
|
{ |
|
if((*this)[base_type::size() - 1]((*this)[0])) break; |
|
base_type::remove_last(); |
|
} |
|
} |
|
} |
|
|
|
|
|
//-------------------------------------------------------------vertex_dist |
|
// Vertex (x, y) with the distance to the next one. The last vertex has |
|
// distance between the last and the first points if the polygon is closed |
|
// and 0.0 if it's a polyline. |
|
struct vertex_dist |
|
{ |
|
double x; |
|
double y; |
|
double dist; |
|
|
|
vertex_dist() {} |
|
vertex_dist(double x_, double y_) : |
|
x(x_), |
|
y(y_), |
|
dist(0.0) |
|
{ |
|
} |
|
|
|
bool operator () (const vertex_dist& val) |
|
{ |
|
bool ret = (dist = calc_distance(x, y, val.x, val.y)) > vertex_dist_epsilon; |
|
if(!ret) dist = 1.0 / vertex_dist_epsilon; |
|
return ret; |
|
} |
|
}; |
|
|
|
|
|
|
|
//--------------------------------------------------------vertex_dist_cmd |
|
// Save as the above but with additional "command" value |
|
struct vertex_dist_cmd : public vertex_dist |
|
{ |
|
unsigned cmd; |
|
|
|
vertex_dist_cmd() {} |
|
vertex_dist_cmd(double x_, double y_, unsigned cmd_) : |
|
vertex_dist(x_, y_), |
|
cmd(cmd_) |
|
{ |
|
} |
|
}; |
|
|
|
|
|
} |
|
|
|
#endif
|
|
|