| 1 |
/* |
|---|
| 2 |
Clustr. Copyright (c) 2007-2009 Yahoo! Inc. |
|---|
| 3 |
|
|---|
| 4 |
All rights reserved. This code is free software; you can redistribute it |
|---|
| 5 |
and/or modify it under the terms of the GNU General Public License (GPL), |
|---|
| 6 |
version 2 only. This code is distributed WITHOUT ANY WARRANTY, whether |
|---|
| 7 |
express or implied. See the GNU GPL for more details |
|---|
| 8 |
(http://www.gnu.org/licenses/gpl.html) |
|---|
| 9 |
|
|---|
| 10 |
AS A SPECIAL EXCEPTION, YOU HAVE PERMISSION TO LINK THIS PROGRAM WITH THE |
|---|
| 11 |
CGAL LIBRARY AND DISTRIBUTE EXECUTABLES, AS LONG AS YOU FOLLOW THE REQUIREMENTS |
|---|
| 12 |
OF THE GNU GPL VERSION 2 IN REGARD TO ALL OF THE SOFTWARE IN THE EXECUTABLE |
|---|
| 13 |
ASIDE FROM CGAL. |
|---|
| 14 |
*/ |
|---|
| 15 |
|
|---|
| 16 |
#ifndef CLUSTR_H |
|---|
| 17 |
#define CLUSTR_H |
|---|
| 18 |
|
|---|
| 19 |
#define VERSION "0.21" |
|---|
| 20 |
#define AUTHOR "Schuyler Erle <schuyler@nocat.net>" |
|---|
| 21 |
#define COPYRIGHT "(c) 2007-2009 Yahoo!, Inc." |
|---|
| 22 |
|
|---|
| 23 |
#include <CGAL/Simple_cartesian.h> |
|---|
| 24 |
#include <CGAL/Filtered_kernel.h> |
|---|
| 25 |
#include <CGAL/algorithm.h> |
|---|
| 26 |
#include <CGAL/Delaunay_triangulation_2.h> |
|---|
| 27 |
#include <CGAL/Alpha_shape_2.h> |
|---|
| 28 |
#include <CGAL/Polygon_2.h> |
|---|
| 29 |
|
|---|
| 30 |
#include <cmath> |
|---|
| 31 |
#include <vector> |
|---|
| 32 |
#define KM_PER_DEGREE (40075.16/360) |
|---|
| 33 |
|
|---|
| 34 |
namespace Clustr { |
|---|
| 35 |
typedef float coord_type; |
|---|
| 36 |
|
|---|
| 37 |
typedef CGAL::Simple_cartesian<coord_type> SC; |
|---|
| 38 |
typedef CGAL::Filtered_kernel<SC> K; |
|---|
| 39 |
|
|---|
| 40 |
typedef K::Point_2 Point; |
|---|
| 41 |
typedef K::Segment_2 Segment; |
|---|
| 42 |
typedef K::Direction_2 Direction; |
|---|
| 43 |
|
|---|
| 44 |
typedef CGAL::Alpha_shape_vertex_base_2<K> Vb; |
|---|
| 45 |
typedef CGAL::Alpha_shape_face_base_2<K> Fb; |
|---|
| 46 |
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> Tds; |
|---|
| 47 |
typedef CGAL::Delaunay_triangulation_2<K,Tds> Triangulation_2; |
|---|
| 48 |
|
|---|
| 49 |
template < class Gt, class Vb = CGAL::Alpha_shape_vertex_base_2<Gt> > |
|---|
| 50 |
class Vertex_counter_base : public Vb { |
|---|
| 51 |
typedef typename Vb::Triangulation_data_structure TDS; |
|---|
| 52 |
unsigned int counter; |
|---|
| 53 |
public: |
|---|
| 54 |
typedef TDS Triangulation_data_structure; |
|---|
| 55 |
typedef typename TDS::Vertex_handle Vertex_handle; |
|---|
| 56 |
typedef typename TDS::Face_handle Face_handle; |
|---|
| 57 |
|
|---|
| 58 |
typedef typename Gt::FT Coord_type; |
|---|
| 59 |
typedef std::pair< Coord_type, Coord_type > Interval2; |
|---|
| 60 |
typedef typename Vb::Point Point; |
|---|
| 61 |
|
|---|
| 62 |
template < typename TDS2 > |
|---|
| 63 |
struct Rebind_TDS { |
|---|
| 64 |
typedef typename Vb::template Rebind_TDS<TDS2>::Other Vb2; |
|---|
| 65 |
typedef Vertex_counter_base<Gt,Vb2> Other; |
|---|
| 66 |
}; |
|---|
| 67 |
|
|---|
| 68 |
Vertex_counter_base() : Vb(), counter(0) {}; |
|---|
| 69 |
Vertex_counter_base(const Point & p) : Vb(p), counter(0) {}; |
|---|
| 70 |
Vertex_counter_base(const Point & p, Face_handle f) : Vb(f,p), counter(0) {}; |
|---|
| 71 |
Vertex_counter_base(Face_handle f) : Vb(f), counter(0) {}; |
|---|
| 72 |
|
|---|
| 73 |
unsigned int operator++ (void) { return ++counter; }; |
|---|
| 74 |
unsigned int operator++ (int) { return counter++; }; |
|---|
| 75 |
unsigned int count (void) { return counter; }; |
|---|
| 76 |
}; |
|---|
| 77 |
typedef CGAL::Triangulation_data_structure_2<Vertex_counter_base<K>,Fb> Tds_with_counter; |
|---|
| 78 |
typedef CGAL::Delaunay_triangulation_2<K,Tds_with_counter> Triangulation_with_counter; |
|---|
| 79 |
typedef CGAL::Alpha_shape_2<Triangulation_with_counter> Alpha_shape; |
|---|
| 80 |
|
|---|
| 81 |
typedef Alpha_shape::Face Face; |
|---|
| 82 |
typedef Alpha_shape::Vertex Vertex; |
|---|
| 83 |
typedef Alpha_shape::Edge Edge; |
|---|
| 84 |
typedef Alpha_shape::Face_handle Face_handle; |
|---|
| 85 |
typedef Alpha_shape::Vertex_handle Vertex_handle; |
|---|
| 86 |
|
|---|
| 87 |
typedef Alpha_shape::Face_iterator Face_iterator; |
|---|
| 88 |
typedef Alpha_shape::Vertex_iterator Vertex_iterator; |
|---|
| 89 |
typedef Alpha_shape::Edge_circulator Edge_circulator; |
|---|
| 90 |
typedef Alpha_shape::Face_circulator Face_circulator; |
|---|
| 91 |
|
|---|
| 92 |
typedef Alpha_shape::Alpha_iterator Alpha_iterator; |
|---|
| 93 |
typedef Alpha_shape::Alpha_shape_vertices_iterator Alpha_shape_vertices_iterator; |
|---|
| 94 |
|
|---|
| 95 |
class Mesh : public Alpha_shape { |
|---|
| 96 |
public: |
|---|
| 97 |
class vertex_circulator; |
|---|
| 98 |
|
|---|
| 99 |
class component { |
|---|
| 100 |
typedef Alpha_shape_vertices_iterator Mesh_iterator; |
|---|
| 101 |
Mesh *mesh; |
|---|
| 102 |
Mesh_iterator base; |
|---|
| 103 |
Mesh_iterator end; |
|---|
| 104 |
public: |
|---|
| 105 |
component (Mesh &mesh, Mesh_iterator b) : mesh(&mesh), base(b) {}; |
|---|
| 106 |
component (Mesh &mesh) : mesh(&mesh) { |
|---|
| 107 |
base = mesh.alpha_shape_vertices_begin(); |
|---|
| 108 |
end = mesh.alpha_shape_vertices_end(); |
|---|
| 109 |
}; |
|---|
| 110 |
bool operator!=(const component &other) { return mesh!=other.mesh || base!=other.base; }; |
|---|
| 111 |
bool operator==(const component &other) { return mesh==other.mesh && base==other.base; }; |
|---|
| 112 |
vertex_circulator operator*() { return vertex_circulator(*this); }; |
|---|
| 113 |
component& operator++ (int) { return ++(*this); }; |
|---|
| 114 |
component& operator++() { |
|---|
| 115 |
if (base != end) { |
|---|
| 116 |
do {++base;} while ((*base)->count() && base != end); |
|---|
| 117 |
} |
|---|
| 118 |
return *this; |
|---|
| 119 |
}; |
|---|
| 120 |
friend class vertex_circulator; |
|---|
| 121 |
}; |
|---|
| 122 |
|
|---|
| 123 |
class vertex_circulator { |
|---|
| 124 |
component *ring; |
|---|
| 125 |
Vertex_handle vertex; |
|---|
| 126 |
Edge previous; |
|---|
| 127 |
|
|---|
| 128 |
Vertex_handle target (const Edge &e); |
|---|
| 129 |
Vertex_handle origin (const Edge &e); |
|---|
| 130 |
public: |
|---|
| 131 |
vertex_circulator (component &c): ring(&c), vertex(*c.base), previous() {}; |
|---|
| 132 |
Vertex_handle operator*() const { return vertex; }; |
|---|
| 133 |
Vertex_handle operator->() const { return vertex; }; |
|---|
| 134 |
vertex_circulator& operator++ (int) { return ++(*this); }; |
|---|
| 135 |
vertex_circulator& operator++(); |
|---|
| 136 |
}; |
|---|
| 137 |
|
|---|
| 138 |
private: |
|---|
| 139 |
component end_component; |
|---|
| 140 |
public: |
|---|
| 141 |
Mesh(coord_type alpha = coord_type(0)) : Alpha_shape(alpha, Alpha_shape::REGULARIZED), |
|---|
| 142 |
end_component(*this, alpha_shape_vertices_end()) {}; |
|---|
| 143 |
|
|---|
| 144 |
template <class InputIterator> |
|---|
| 145 |
Mesh(const InputIterator& first, const InputIterator& last, |
|---|
| 146 |
const coord_type& alpha = coord_type(0)) |
|---|
| 147 |
: Alpha_shape(first, last, alpha, Alpha_shape::REGULARIZED), |
|---|
| 148 |
end_component(*this, alpha_shape_vertices_end()) {}; |
|---|
| 149 |
|
|---|
| 150 |
component components_begin () { return component(*this); }; |
|---|
| 151 |
component components_end () { return end_component; }; |
|---|
| 152 |
}; |
|---|
| 153 |
|
|---|
| 154 |
/* BIG ASSUMPTION: Point<K> is actually a lon/lat point |
|---|
| 155 |
* -- this underlies all of the following distance and |
|---|
| 156 |
* area calculations. */ |
|---|
| 157 |
|
|---|
| 158 |
//using std::tr1::cos; |
|---|
| 159 |
//using std::tr1::acos; |
|---|
| 160 |
|
|---|
| 161 |
typedef CGAL::Polygon_2<K> Ring_base; |
|---|
| 162 |
class Ring : public Ring_base { |
|---|
| 163 |
coord_type area_; |
|---|
| 164 |
coord_type perimeter_; |
|---|
| 165 |
coord_type scale_x(coord_type lat) { return cos(lat*acos(-1.0)/180); }; |
|---|
| 166 |
public: |
|---|
| 167 |
typedef Ring_base::Vertex_iterator iterator; |
|---|
| 168 |
Ring() : Ring_base(), area_(0), perimeter_(0) {}; |
|---|
| 169 |
void reverse_orientation (void) { area_ *= -1.0; this->Ring_base::reverse_orientation(); }; |
|---|
| 170 |
bool is_ccw (void) { return area_ >= 0; }; |
|---|
| 171 |
coord_type area (void) { return area_*KM_PER_DEGREE*KM_PER_DEGREE; }; |
|---|
| 172 |
coord_type perimeter (void) { return perimeter_*KM_PER_DEGREE; }; |
|---|
| 173 |
void push_back (const Point &p); |
|---|
| 174 |
iterator begin (void) { return vertices_begin(); }; |
|---|
| 175 |
iterator end (void) { return vertices_end(); }; |
|---|
| 176 |
bool encloses (const Point &p) { bounded_side(p) == CGAL::ON_BOUNDED_SIDE; }; |
|---|
| 177 |
}; |
|---|
| 178 |
|
|---|
| 179 |
typedef std::vector<Ring> Polygon_base; |
|---|
| 180 |
class Polygon : public Polygon_base { |
|---|
| 181 |
public: |
|---|
| 182 |
void push_back (Ring &ring); |
|---|
| 183 |
coord_type area (void); |
|---|
| 184 |
coord_type perimeter (void); |
|---|
| 185 |
}; |
|---|
| 186 |
|
|---|
| 187 |
struct Config { |
|---|
| 188 |
std::string in_file; |
|---|
| 189 |
std::string out_file; |
|---|
| 190 |
coord_type alpha; |
|---|
| 191 |
bool points_only; |
|---|
| 192 |
bool verbose; |
|---|
| 193 |
|
|---|
| 194 |
Config() { |
|---|
| 195 |
in_file = "-"; |
|---|
| 196 |
out_file = "clustr.shp"; |
|---|
| 197 |
alpha = 0; |
|---|
| 198 |
points_only = false; |
|---|
| 199 |
verbose = false; |
|---|
| 200 |
}; |
|---|
| 201 |
}; |
|---|
| 202 |
}; |
|---|
| 203 |
|
|---|
| 204 |
#endif /* CLUSTR_H */ |
|---|