1 /******************************************************************************
2  * Project:  libspatialindex - A C++ library for spatial indexing
3  * Author:   Marios Hadjieleftheriou, mhadji@gmail.com
4  ******************************************************************************
5  * Copyright (c) 2003, Marios Hadjieleftheriou
6  *
7  * All rights reserved.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a
10  * copy of this software and associated documentation files (the "Software"),
11  * to deal in the Software without restriction, including without limitation
12  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13  * and/or sell copies of the Software, and to permit persons to whom the
14  * Software is furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included
17  * in all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  * DEALINGS IN THE SOFTWARE.
26 ******************************************************************************/
27 
28 #include <assert.h>
29 #include <iostream>
30 #include <fstream>
31 #include <map>
32 #include <queue>
33 #include <cmath>
34 #include <cstring>
35 #include <limits>
36 #include <cmath>
37 
38 using namespace std;
39 
40 #define DELETE 0
41 #define INSERT 1
42 #define QUERY 2
43 
44 
45 #include <spatialindex/tools/Tools.h>
46 
47 class TimeRegion
48 {
49 public:
50 	double m_xmin, m_ymin, m_xmax, m_ymax;
51 	double m_startTime, m_endTime;
52 
TimeRegion()53 	TimeRegion() {}
54 
TimeRegion(double x1,double y1,double x2,double y2,double t1,double t2)55 	TimeRegion(double x1, double y1, double x2, double y2, double t1, double t2)
56 	{
57 		m_xmin = (x1 < x2) ? x1 : x2;
58 		m_ymin = (y1 < y2) ? y1 : y2;
59 		m_xmax = (x1 > x2) ? x1 : x2;
60 		m_ymax = (y1 > y2) ? y1 : y2;
61 		m_startTime = t1;
62 		m_endTime = (t2 <= 0) ? std::numeric_limits<double>::max() : t2;
63 	}
64 
intersects(TimeRegion & r)65 	bool intersects(TimeRegion& r)
66 	{
67 		if (m_xmin > r.m_xmax || m_xmax < r.m_xmin ||
68 				m_ymin > r.m_ymax || m_ymax < r.m_ymin) return false;
69 
70 		return true;
71 	}
72 
intersectsInTime(TimeRegion & r)73 	bool intersectsInTime(TimeRegion& r)
74 	{
75 		//if (m_startTime != r.m_startTime && (m_endTime <= r.m_startTime || m_startTime >= r.m_endTime)) return false;
76 		if (m_endTime <= r.m_startTime || m_startTime >= r.m_endTime) return false;
77 		return intersects(r);
78 	}
79 
getMinDist(const TimeRegion & r)80 	double getMinDist(const TimeRegion& r)
81 	{
82 		double ret = 0.0;
83 
84 		if (r.m_xmax < m_xmin)
85 			ret += std::pow(m_xmin - r.m_xmax, 2.0);
86 		else if (r.m_xmin > m_xmax)
87 			ret += std::pow(r.m_xmin - m_xmax, 2.0);
88 
89 		if (r.m_ymax < m_ymin)
90 			ret += std::pow(m_ymin - r.m_ymax, 2.0);
91 		else if (r.m_ymin > m_ymax)
92 			ret += std::pow(r.m_ymin - m_ymax, 2.0);
93 
94 		return ret;
95 	}
96 };
97 
98 class NNEntry
99 {
100 public:
101 	size_t m_id;
102 	double m_dist;
103 
NNEntry(size_t id,double dist)104 	NNEntry(size_t id, double dist) : m_id(id), m_dist(dist) {}
105 
106 	struct greater : public binary_function<NNEntry*, NNEntry*, bool>
107 	{
operator ()NNEntry::greater108 		bool operator()(const NNEntry* __x, const NNEntry* __y) const { return __x->m_dist > __y->m_dist; }
109 	};
110 };
111 
main(int argc,char ** argv)112 int main(int argc, char** argv)
113 {
114 	if (argc != 3)
115 	{
116 		cerr << "Usage: " << argv[0] << " data_file query_type [intersection | 10NN]." << endl;
117 		return -1;
118 	}
119 
120 	uint32_t queryType = 0;
121 
122 	if (strcmp(argv[2], "intersection") == 0) queryType = 0;
123 	else if (strcmp(argv[2], "10NN") == 0) queryType = 1;
124 	else
125 	{
126 		cerr << "Unknown query type." << endl;
127 		return -1;
128 	}
129 
130 	ifstream fin(argv[1]);
131 	if (! fin)
132 	{
133 		cerr << "Cannot open data file" << argv[1] << "." << endl;
134 		return -1;
135 	}
136 
137 	multimap<size_t, TimeRegion> data;
138 	size_t id;
139 	uint32_t op;
140 	double x1, x2, y1, y2, t;
141 
142 	while (fin)
143 	{
144 		fin >> t >> op >> id >> x1 >> y1 >> x2 >> y2;
145 		if (! fin.good()) continue;
146 
147 		if (op == INSERT)
148 		{
149 			//insert
150 			data.insert(pair<size_t, TimeRegion>(id, TimeRegion(x1, y1, x2, y2, t, std::numeric_limits<double>::max())));
151 		}
152 		else if (op == DELETE)
153 		{
154 			//delete
155 			// find the live instance of id.
156 			multimap<size_t, TimeRegion>::iterator it = data.find(id);
157 			assert(it != data.end());
158 			while (it->first == id && it->second.m_endTime < std::numeric_limits<double>::max()) it++;
159 			assert(it->first == id);
160 			(*it).second.m_endTime = t;
161 		}
162 		else if (op == QUERY)
163 		{
164 			size_t qt1, qt2;
165 			fin >> qt1 >> qt2;
166 			if (! fin.good()) continue;
167 
168 			//query
169 			if (queryType == 0)
170 			{
171 				TimeRegion query = TimeRegion(x1, y1, x2, y2, qt1, qt2);
172 				for (multimap<size_t, TimeRegion>::iterator it = data.begin(); it != data.end(); it++)
173 				{
174 					if (query.intersectsInTime((*it).second)) cout << (*it).first << endl;
175 				}
176 			}
177 			else
178 			{
179 				/*
180 				TimeRegion query = TimeRegion(x1, y1, x1, y1, qt1, qt2);
181 
182 				priority_queue<NNEntry*, vector<NNEntry*>, NNEntry::greater > queue;
183 
184 				for (multimap<size_t, Region>::iterator it = data.begin(); it != data.end(); it++)
185 				{
186 					queue.push(new NNEntry((*it).first, (*it).second.getMinDist(query)));
187 				}
188 
189 				size_t count = 0;
190 				double knearest = 0.0;
191 
192 				while (! queue.empty())
193 				{
194 					NNEntry* e = queue.top(); queue.pop();
195 
196 					if (count >= 10 && e->m_dist > knearest) break;
197 
198 					//cout << e->m_id << " " << e->m_dist << endl;
199 					cout << e->m_id << endl;
200 					count++;
201 					knearest = e->m_dist;
202 					delete e;
203 				}
204 
205 				while (! queue.empty())
206 				{
207 					NNEntry* e = queue.top(); queue.pop();
208 					delete e;
209 				}
210 			*/
211 			}
212 		}
213 	}
214 
215 	return 0;
216 }
217