00001 #ifndef _QUERY_POINT_HPP
00002 #define _QUERY_POINT_HPP
00003
00004 #include <CGAL/Kd_tree.h>
00005 #include <CGAL/Fuzzy_iso_box.h>
00006 #include <CGAL/Search_traits.h>
00007 #include "function_output_iterator.hpp"
00008 #include "global.hpp"
00009 #include "geometry.hpp"
00010
00011 namespace Arak {
00012
00017 class QueryPointListener {
00018
00019 public:
00020
00024 QueryPointListener() { }
00025
00033 virtual void recolor(Color color) = 0;
00034
00035 };
00036
00040 typedef std::list<QueryPointListener*> QueryPointListenerList;
00041
00049 class QueryPoint : public Geometry::Point {
00050
00051 protected:
00052
00056 QueryPointListenerList* listeners;
00057
00061 Color* c;
00062
00063 public:
00064
00073 QueryPoint(const Geometry::Point& p,
00074 QueryPointListenerList* listeners,
00075 Color* color)
00076 : Geometry::Point(p), listeners(listeners), c(color) { }
00077
00084 QueryPoint(const Geometry::Point p = CGAL::ORIGIN)
00085 : Geometry::Point(p), listeners(NULL), c(NULL){ }
00086
00090 Color color() const { return *c; }
00091
00096 void setColor(Color color) const {
00097 if (color != *c) {
00098 *c = opposite(color);
00099 recolor();
00100 }
00101 }
00102
00107 void recolor() const {
00108 *c = opposite(*c);
00109 typedef QueryPointListenerList::iterator Iterator;
00110 for (Iterator it = listeners->begin(); it != listeners->end(); it++) {
00111 QueryPointListener* listener = *it;
00112 listener->recolor(*c);
00113 }
00114 }
00115
00121 void addListener(QueryPointListener* listener) const {
00122 listener->recolor(*c);
00123 listeners->push_front(listener);
00124 }
00125
00126 };
00127
00132 class QueryPointListenerFactory {
00133
00134 public:
00135
00139 virtual QueryPointListener* create(const QueryPoint& q) = 0;
00140
00141 };
00142
00148 class QueryPointIndex {
00149
00150 protected:
00151
00155 std::vector<QueryPoint> qpoints;
00156
00160 QueryPointListenerList* listenerLists;
00161
00166 Color* color;
00167
00171 class SearchTraits {
00172 public:
00173 typedef Geometry::Kernel K;
00174 typedef Arak::QueryPoint Point_d;
00175 typedef K::Iso_rectangle_2 Iso_box_d;
00176 typedef K::Circle_2 Sphere_d;
00177 typedef K::Cartesian_const_iterator_2 Cartesian_const_iterator_d;
00178 typedef K::Construct_cartesian_const_iterator_2 Construct_cartesian_const_iterator_d;
00179
00180 typedef K::Construct_min_vertex_2 Construct_min_vertex_d;
00181 typedef K::Construct_max_vertex_2 Construct_max_vertex_d;
00182 typedef K::Construct_center_2 Construct_center_d;
00183 typedef K::Compute_squared_radius_2 Compute_squared_radius_d;
00184
00185 typedef K::Construct_iso_rectangle_2 Construct_iso_box_d;
00186 typedef K::FT FT;
00187 };
00188
00192 typedef CGAL::Kd_tree<SearchTraits> KDTree;
00193
00197 KDTree* tree;
00198
00203 friend class RecolorTriangleFunction {
00204
00205 private:
00206
00213 const Geometry::Triangle* t;
00214
00215 public:
00216
00222 RecolorTriangleFunction(const Geometry::Triangle& t) : t(&t) { }
00223
00230 void operator() (const QueryPoint& q) {
00231 if (!t->has_on_unbounded_side(q)) q.recolor();
00232 }
00233 };
00234
00241 friend class RecolorQuadrilateralFunction {
00242
00243 private:
00244
00253 const Geometry::Triangle *t1;
00254
00263 const Geometry::Triangle *t2;
00264
00265 public:
00266
00278 RecolorQuadrilateralFunction(const Geometry::Triangle& t1,
00279 const Geometry::Triangle& t2)
00280 : t1(&t1), t2(&t2) { }
00281
00288 void operator() (const QueryPoint& q) {
00294 if (!t1->has_on_unbounded_side(q)) q.recolor();
00295 if (!t2->has_on_unbounded_side(q)) q.recolor();
00296 }
00297 };
00298
00299 public:
00300
00308 template <class QueryPointListenerType>
00309 QueryPointIndex(const std::vector<Geometry::Point>& points,
00310 const std::vector<QueryPointListenerType*>& listeners) {
00311
00312 int n = points.size();
00313 color = new Color[n];
00314 listenerLists = new QueryPointListenerList[n];
00315
00316 qpoints.reserve(n);
00317 for (int i = 0; i < n; i++) {
00318 color[i] = INVALID_COLOR;
00319 QueryPoint q(points[i], &(listenerLists[i]), &(color[i]));
00320 qpoints.push_back(q);
00321 q.addListener(listeners[i]);
00322 }
00323
00324 tree = new KDTree(qpoints.begin(), qpoints.end());
00325 }
00326
00335 QueryPointIndex(const Geometry::Rectangle& r, int rows, int cols);
00336
00344 QueryPointIndex(const QueryPointIndex& q1,
00345 const QueryPointIndex& q2);
00346
00350 ~QueryPointIndex();
00351
00358 void addListeners(QueryPointListenerFactory& factory);
00359
00368 template <class OutputIterator>
00369 void output(const Geometry::Rectangle& r, OutputIterator it) const {
00370 using namespace Geometry;
00371 typedef CGAL::Fuzzy_iso_box<SearchTraits> FuzzyBox;
00372 FuzzyBox box(r.min(), r.max());
00373 tree->search(it, box);
00374 }
00375
00384 template <class UnaryFunction>
00385 void apply(const Geometry::Rectangle& r, UnaryFunction& f) const {
00386 output(r, boost::make_function_output_iterator(f));
00387 }
00388
00395 template <class UnaryFunction>
00396 void applyToAll(UnaryFunction& f) const {
00397 tree->report_all_points(boost::make_function_output_iterator(f));
00398 }
00399
00403 int size() const { return qpoints.size(); }
00404
00408 const QueryPoint& point(int i) const { return qpoints[i]; }
00409
00413 QueryPoint& point(int i) { return qpoints[i]; }
00414
00421 const QueryPoint& closest(const Geometry::Point& p) const;
00422
00431 void recolor(const Geometry::Point& a,
00432 const Geometry::Point& b,
00433 const Geometry::Point& c);
00434
00445 void recolor(const Geometry::Point& a,
00446 const Geometry::Point& b,
00447 const Geometry::Point& c,
00448 const Geometry::Point& d);
00449
00450 };
00451
00452 }
00453
00454 #endif