00001 #include "query_point.hpp"
00002 #include <CGAL/Orthogonal_k_neighbor_search.h>
00003
00004 using namespace Arak;
00005
00006 QueryPointIndex::QueryPointIndex(const Geometry::Rectangle& r,
00007 int rows, int cols) {
00008
00009 int n = rows * cols;
00010 color = new Color[n];
00011 listenerLists = new QueryPointListenerList[n];
00012
00013 qpoints.reserve(n);
00014 typedef Geometry::Kernel::FT FT;
00015 FT gridx = (r.xmax() - r.xmin()) / FT(rows + 1);
00016 FT gridy = (r.ymax() - r.ymin()) / FT(cols + 1);
00017 FT x = r.xmin() + gridx;
00018 int k = 0;
00019 for (int i = 0; i < rows; i++) {
00020 FT y = r.ymin() + gridy;
00021 for (int j = 0; j < cols; j++) {
00022 color[k] = INVALID_COLOR;
00023 qpoints.push_back(QueryPoint(Geometry::Point(x, y),
00024 &(listenerLists[k]),
00025 &(color[k])));
00026 k++;
00027 y += gridy;
00028 }
00029 x += gridx;
00030 }
00031
00032 tree = new KDTree(qpoints.begin(), qpoints.end());
00033 }
00034
00035 QueryPointIndex::QueryPointIndex(const QueryPointIndex& q1,
00036 const QueryPointIndex& q2) {
00037 int m = q1.size();
00038 int n = q2.size();
00039
00040 color = new Color[m + n];
00041 listenerLists = new QueryPointListenerList[m + n];
00042 for (int i = 0; i < m; i++) {
00043 color[i] = q1.color[i];
00044 listenerLists[i] = q1.listenerLists[i];
00045 }
00046 for (int i = 0; i < n; i++) {
00047 color[i + m] = q2.color[i];
00048 listenerLists[i + m] = q2.listenerLists[i];
00049 }
00050
00051 qpoints.reserve(m + n);
00052 for (int i = 0; i < m; i++)
00053 qpoints.push_back(QueryPoint(q1.point(i),
00054 &(listenerLists[i]),
00055 &(color[i])));
00056 for (int i = 0; i < n; i++)
00057 qpoints.push_back(QueryPoint(q2.point(i),
00058 &(listenerLists[i + m]),
00059 &(color[i + m])));
00060
00061 tree = new KDTree(qpoints.begin(), qpoints.end());
00062 }
00063
00064 QueryPointIndex::~QueryPointIndex() {
00065 delete [] color;
00066 delete [] listenerLists;
00067 delete tree;
00068 }
00069
00070 void QueryPointIndex::addListeners(QueryPointListenerFactory& factory) {
00071 for (int i = 0; i < int(qpoints.size()); i++)
00072 listenerLists[i].push_back(factory.create(qpoints[i]));
00073 }
00074
00075 const QueryPoint& QueryPointIndex::closest(const Geometry::Point& p) const {
00076 typedef CGAL::Orthogonal_k_neighbor_search<SearchTraits> NeighborSearch;
00077 SearchTraits::Point_d q = p;
00078 NeighborSearch ns(const_cast<KDTree&>(*tree), q);
00079 return ns.begin()->first;
00080 }
00081
00082 void QueryPointIndex::recolor(const Geometry::Point& a,
00083 const Geometry::Point& b,
00084 const Geometry::Point& c) {
00085 const Geometry::Point* xmin = &a;
00086 const Geometry::Point* xmax = &a;
00087 const Geometry::Point* ymin = &a;
00088 const Geometry::Point* ymax = &a;
00089 if (xmin->x() > b.x()) xmin = &b;
00090 if (xmin->x() > c.x()) xmin = &c;
00091 if (xmax->x() < b.x()) xmax = &b;
00092 if (xmax->x() < c.x()) xmax = &c;
00093 if (ymin->y() > b.y()) ymin = &b;
00094 if (ymin->y() > c.y()) ymin = &c;
00095 if (ymax->y() < b.y()) ymax = &b;
00096 if (ymax->y() < c.y()) ymax = &c;
00097 Geometry::Rectangle r(*xmin, *xmax, *ymin, *ymax);
00098 #ifdef SANITY_CHECK
00099 assert(!r.has_on_unbounded_side(a));
00100 assert(!r.has_on_unbounded_side(b));
00101 assert(!r.has_on_unbounded_side(c));
00102 #endif
00103 Geometry::Triangle t(a, b, c);
00104 RecolorTriangleFunction f(t);
00105 apply(r, f);
00106 }
00107
00108 void QueryPointIndex::recolor(const Geometry::Point& a,
00109 const Geometry::Point& b,
00110 const Geometry::Point& c,
00111 const Geometry::Point& d) {
00112 #ifdef SANITY_CHECK
00113 assert(!do_intersect(Geometry::Segment(a, b),
00114 Geometry::Segment(c, d)));
00115 #endif
00116 const Geometry::Point* xmin = &a;
00117 const Geometry::Point* xmax = &a;
00118 const Geometry::Point* ymin = &a;
00119 const Geometry::Point* ymax = &a;
00120 if (xmin->x() > b.x()) xmin = &b;
00121 if (xmin->x() > c.x()) xmin = &c;
00122 if (xmin->x() > d.x()) xmin = &d;
00123 if (xmax->x() < b.x()) xmax = &b;
00124 if (xmax->x() < c.x()) xmax = &c;
00125 if (xmax->x() < d.x()) xmax = &d;
00126 if (ymin->y() > b.y()) ymin = &b;
00127 if (ymin->y() > c.y()) ymin = &c;
00128 if (ymin->y() > d.y()) ymin = &d;
00129 if (ymax->y() < b.y()) ymax = &b;
00130 if (ymax->y() < c.y()) ymax = &c;
00131 if (ymax->y() < d.y()) ymax = &d;
00132 Geometry::Rectangle r(*xmin, *xmax, *ymin, *ymax);
00133 #ifdef SANITY_CHECK
00134 assert(!r.has_on_unbounded_side(a));
00135 assert(!r.has_on_unbounded_side(b));
00136 assert(!r.has_on_unbounded_side(c));
00137 assert(!r.has_on_unbounded_side(d));
00138 #endif
00139 Geometry::Triangle t1(a, b, c);
00140 Geometry::Triangle t2(a, c, d);
00141 #ifdef SANITY_CHECK
00142 assert(!t1.is_degenerate());
00143 assert(!t2.is_degenerate());
00144 #endif
00145 RecolorQuadrilateralFunction f(t1, t2);
00146 apply(r, f);
00147 }
00148