OverSim
VastDefs.cc
Go to the documentation of this file.
1 //
2 // Copyright (C) 2006 Institut fuer Telematik, Universitaet Karlsruhe (TH)
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 2
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 //
18 
24 #include "VastDefs.h"
25 
27 {
28  type = UNDEF;
29  innerEdge[0] = false;
30  innerEdge[1] = false;
31  innerEdge[2] = false;
32  outerEdge = false;
33  isAdded = false;
34  neighborCount = 0;
36  tstamp = 0.0;
37 }
38 
39 std::ostream& operator<<(std::ostream& Stream, const Site s)
40 {
41  Stream << "Type: ";
42  if(s.type & UNDEF) Stream << "Undefined ";
43  if(s.type & THIS) Stream << "This ";
44  if(s.type & ENCLOSING) Stream << "Enclosing ";
45  if(s.type & NEIGHBOR) Stream << "Inner ";
46  if(s.type & BOUNDARY) Stream << "Boundary ";
47  if(s.type & NEW) Stream << "Discovered ";
48  return Stream << " IP: " << s.addr.getIp();
49 }
50 
52 {
53  a = 0.0;
54  b = 0.0;
55  c = 0.0;
56  ep[0] = NULL;
57  ep[1] = NULL;
58  reg[0] = NULL;
59  reg[1] = NULL;
60 }
61 
63 {
64  ELleft = NULL;
65  ELright = NULL;
66  ELedge = NULL;
67  ELpm = 0;
68  vertex = NULL;
69  ystar = 0.0;
70  PQnext = NULL;
71 }
72 
74 {
75  PQhash = NULL;
76 }
77 
78 void HeapPQ::PQinitialize(int sqrt_nsites, double ymin, double deltay)
79 {
80  PQcount = 0;
81  PQmin = 0;
82  PQhashsize = 4 * sqrt_nsites;
83  PQhash = new Halfedge[PQhashsize];
84  this->ymin = ymin;
85  this->deltay = deltay;
86 }
87 
89 {
90  delete[] PQhash;
91 }
92 
93 void HeapPQ::PQinsert(Halfedge *he, Site *v, double offset)
94 {
95  Halfedge *last, *next;
96 
97  he->vertex = v;
98  he->ystar = v->coord.y + offset;
99  last = &PQhash[PQbucket(he)];
100  while((next = last->PQnext) != NULL && (he->ystar > next->ystar || (he->ystar == next->ystar && v->coord.x > next->vertex->coord.x))) {
101  last = next;
102  }
103  he->PQnext = last->PQnext;
104  last->PQnext = he;
105  PQcount++;
106 }
107 
109 {
110  Halfedge *last;
111 
112  if(he->vertex != NULL) {
113  last = &PQhash[PQbucket(he)];
114  while(last->PQnext != he) last = last->PQnext;
115 
116  last->PQnext = he->PQnext;
117  PQcount--;
118  he->vertex = NULL;
119  }
120 }
121 
123 {
124  int bucket;
125 
126  bucket = (int)((he->ystar - ymin)/deltay) * PQhashsize;
127  if(bucket < 0) bucket = 0;
128  if(bucket >= PQhashsize) bucket = PQhashsize-1;
129  if(bucket < PQmin) PQmin = bucket;
130  return bucket;
131 }
132 
134 {
135  return PQcount==0;
136 }
137 
139 {
140  Vector2D answer;
141 
142  while(PQhash[PQmin].PQnext == NULL) PQmin++;
143 
144  answer.x = PQhash[PQmin].PQnext->vertex->coord.x;
145  answer.y = PQhash[PQmin].PQnext->ystar;
146  return answer;
147 }
148 
150 {
151  Halfedge *curr;
152 
153  curr = PQhash[PQmin].PQnext;
154  PQhash[PQmin].PQnext = curr->PQnext;
155  PQcount--;
156  return curr;
157 }
158 
159 void Geometry::initialize(double deltax, double deltay, Vector2D center, Vector2D old_pos, Vector2D new_pos, double radius)
160 {
161  this->deltay = deltay;
162  this->deltax = deltax;
163  this->center[0] = center;
164  this->center[1] = old_pos;
165  this->center[2] = new_pos;
166  if((old_pos.x != new_pos.x) || (old_pos.y != new_pos.y)) doDiscovery = true;
167  else doDiscovery = false;
168  this->sq_radius = radius*radius;
169 }
170 
172 {
173  for(std::vector<Site*>::iterator itTemp = SITEVector.begin(); itTemp != SITEVector.end(); ++itTemp) {
174  delete *itTemp;
175  }
176  for(std::vector<Edge*>::iterator itTemp = EDGEVector.begin(); itTemp != EDGEVector.end(); ++itTemp) {
177  delete *itTemp;
178  }
179  SITEVector.clear();
180  EDGEVector.clear();
181 }
182 
183 void Geometry::setDebug(bool debugOutput)
184 {
185  this->debugOutput = debugOutput;
186 }
187 
189 {
190  double sq_distance;
191  Vector2D temp;
192  temp.x = s->coord.x - center.x;
193  temp.y = s->coord.y - center.y;
194  sq_distance = temp.x*temp.x + temp.y*temp.y;
195  return sq_distance < sq_radius ? true : false;
196 }
197 
198 bool Geometry::intersectCircleLine(Vector2D start, Vector2D dir, Vector2D center, bool lowerBound, bool upperBound)
199 {
200  Vector2D StartMinusCenter;
201  double DirDotStartMinusCenter, DirSq, StartMinusCenterSq, discriminant;
202  StartMinusCenter.x = start.x - center.x;
203  StartMinusCenter.y = start.y - center.y;
204  StartMinusCenterSq = StartMinusCenter.x * StartMinusCenter.x + StartMinusCenter.y * StartMinusCenter.y;
205 
206  DirDotStartMinusCenter = dir.x * StartMinusCenter.x + dir.y * StartMinusCenter.y;
207  DirSq = dir.x * dir.x + dir.y * dir.y;
208 
209  discriminant = DirDotStartMinusCenter * DirDotStartMinusCenter - DirSq * (StartMinusCenterSq - sq_radius);
210 
211  if(discriminant <= 0.0f) return false;
212  else if(lowerBound) {
213  double s = (-DirDotStartMinusCenter - sqrtf(discriminant)) / DirSq;
214  if(s < 0.0f) return false;
215  else if(upperBound && s > 1.0f) return false;
216  }
217  return true;
218 }
219 
221 {
222  bool leftEndpoint_In[3], rightEndpoint_In[3];
223  int i, numTest;
224  // test the edge just against our own AOI or also against AOI's of a moving neighbor
225  numTest = doDiscovery ? 3 : 1;
226 
227  for(i = 0; i < numTest; i++) {
228  if(e->ep[le]) leftEndpoint_In[i] = intersectCircleSite(e->ep[le], center[i]);
229  else leftEndpoint_In[i] = false;
230  if(e->ep[re]) rightEndpoint_In[i] = intersectCircleSite(e->ep[re], center[i]);
231  else rightEndpoint_In[i] = false;
232  }
233  for(i = 0; i < numTest; i++) {
234  if(leftEndpoint_In[i] || rightEndpoint_In[i]) {
235  if(!e->reg[le]->innerEdge[i]) e->reg[le]->innerEdge[i] = true;
236  if(!e->reg[re]->innerEdge[i]) e->reg[re]->innerEdge[i] = true;
237  }
238  }
239  if(!leftEndpoint_In[0] || !rightEndpoint_In[0]) {
240  if(!e->reg[le]->outerEdge) e->reg[le]->outerEdge = true;
241  if(!e->reg[re]->outerEdge) e->reg[re]->outerEdge = true;
242  }
243  for(i = 0; i < numTest; i++) {
244  if(!(leftEndpoint_In[i] || rightEndpoint_In[i])) {
245  bool lineTest = false;
246  if(e->ep[le] && e->ep[re]) {
247  Vector2D t_dir;
248  t_dir.x = e->ep[re]->coord.x - e->ep[le]->coord.x;
249  t_dir.y = e->ep[re]->coord.y - e->ep[le]->coord.y;
250  lineTest = intersectCircleLine(e->ep[le]->coord, t_dir, center[i], true, true);
251  }
252  if((e->ep[le] && !e->ep[re]) || (!e->ep[le] && e->ep[re])) {
253  Vector2D t_dir;
254  t_dir.x = e->b;
255  t_dir.y = -(e->a);
256  if(e->ep[le]) {
257  if(t_dir.x < 0.0f) {
258  t_dir.x = -t_dir.x;
259  t_dir.y = -t_dir.y;
260  }
261  lineTest = intersectCircleLine(e->ep[le]->coord, t_dir, center[i], true, false);
262  }
263  else {
264  if(t_dir.x >= 0.0f) {
265  t_dir.x = -t_dir.x;
266  t_dir.y = -t_dir.y;
267  }
268  lineTest = intersectCircleLine(e->ep[re]->coord, t_dir, center[i], true, false);
269  }
270  }
271  if(!(e->ep[le] || e->ep[re])) {
272  Vector2D t_start, t_dir;
273  if(e->b == 0.0f) {
274  t_start.x = e->c / e->a;
275  t_start.y = 0.0f;
276  }
277  else {
278  t_start.x = 0.0f;
279  t_start.y = e->c / e->b;
280  }
281  t_dir.x = e->b;
282  t_dir.y = -(e->a);
283  lineTest = intersectCircleLine(t_start, t_dir, center[i], false, false);
284  }
285 
286  if(lineTest) {
287  if(!e->reg[le]->innerEdge[i]) e->reg[le]->innerEdge[i] = true;
288  if(!e->reg[re]->innerEdge[i]) e->reg[re]->innerEdge[i] = true;
289  }
290  }
291  }
292  // enhanced enclosing test
293  e->reg[re]->enclosingSet.insert(e->reg[le]->addr);
294  e->reg[le]->enclosingSet.insert(e->reg[re]->addr);
295 
296  // test if one of the nodes bisected by the edge is an enclosing neighbor
297  if(e->reg[le]->type == THIS) {
298  e->reg[re]->type |= ENCLOSING;
299  // Debug output
300  if(debugOutput) EV << "[Geometry::processEdge()]\n"
301  << " Site at [" << e->reg[re]->coord.x << ", " << e->reg[re]->coord.y << "] is an enclosing neighbor."
302  << endl;
303  }
304  if(e->reg[re]->type == THIS) {
305  e->reg[le]->type |= ENCLOSING;
306  // Debug output
307  if(debugOutput) EV << "[Geometry::processEdge()]\n"
308  << " Site at [" << e->reg[le]->coord.x << ", " << e->reg[le]->coord.y << "] is an enclosing neighbor."
309  << endl;
310  }
311 }
312 
314 {
315  double dx, dy, adx, ady;
316  Edge *newedge;
317 
318  newedge = new Edge;
319 
320  newedge->reg[0] = s1;
321  newedge->reg[1] = s2;
322  newedge->ep[0] = NULL;
323  newedge->ep[1] = NULL;
324 
325  dx = s2->coord.x - s1->coord.x;
326  dy = s2->coord.y - s1->coord.y;
327  adx = dx > 0 ? dx : -dx;
328  ady = dy > 0 ? dy : -dy;
329  newedge->c = s1->coord.x * dx + s1->coord.y * dy + (dx*dx + dy*dy)*0.5;
330  if(adx>ady) {
331  newedge->a = 1.0;
332  newedge->b = dy/dx;
333  newedge->c /= dx;
334  }
335  else {
336  newedge->b = 1.0;
337  newedge->a = dx/dy;
338  newedge->c /= dy;
339  }
340 
341  EDGEVector.push_back(newedge);
342  return newedge;
343 }
344 
346 {
347  Edge *e1, *e2, *e;
348  Halfedge *el;
349  double d, xint, yint;
350  int right_of_site;
351  Site *v;
352 
353  e1 = el1->ELedge;
354  e2 = el2->ELedge;
355  if(e1 == NULL || e2 == NULL) return NULL;
356  if(e1->reg[1] == e2->reg[1]) return NULL;
357 
358  d = e1->a * e2->b - e1->b * e2->a;
359  if(-1.0e-10 < d && d < 1.0e-10) return NULL;
360 
361  xint = (e1->c * e2->b - e2->c * e1->b)/d;
362  yint = (e2->c * e1->a - e1->c * e2->a)/d;
363 
364  if((e1->reg[1]->coord.y < e2->reg[1]->coord.y) || (e1->reg[1]->coord.y == e2->reg[1]->coord.y && e1->reg[1]->coord.x < e2->reg[1]->coord.x)) {
365  el = el1;
366  e = e1;
367  }
368  else {
369  el = el2;
370  e = e2;
371  }
372 
373  right_of_site = xint >= e->reg[1]->coord.x;
374  if((right_of_site && el->ELpm == le) || (!right_of_site && el->ELpm == re)) return NULL;
375 
376  v = new Site;
377 
378  v->coord.x = xint;
379  v->coord.y = yint;
380 
381  SITEVector.push_back(v);
382  return v;
383 }
384 
385 void Geometry::endpoint(Edge *e, int lr, Site *s)
386 {
387  e->ep[lr] = s;
388  if(e->ep[re-lr] == NULL) return;
389  processEdge(e);
390 }
391 
392 double Geometry::dist(Site *s, Site *t)
393 {
394  double dx, dy;
395  dx = s->coord.x - t->coord.x;
396  dy = s->coord.y - t->coord.y;
397  return sqrt(dx*dx + dy*dy);
398 }
399 
401 {
402  ELhash = NULL;
403 }
404 
405 void EdgeList::initialize(int sqrt_nsites, double xmin, double deltax, Site *bottomsite)
406 {
407  int i;
408 
409  HEcount = 0;
410  ELhashsize = 2 * sqrt_nsites;
411 
412  HEmemmap = new Halfedge*[ELhashsize];
413 
414  ELhash = new Halfedge*[ELhashsize];
415  for(i=0; i<ELhashsize; i++) ELhash[i] = NULL;
416  ELleftend = HEcreate(NULL, 0);
417  ELrightend = HEcreate(NULL, 0);
418  ELleftend->ELleft = NULL;
421  ELrightend->ELright = NULL;
422  ELhash[0] = ELleftend;
423  ELhash[ELhashsize-1] = ELrightend;
424  this->xmin = xmin;
425  this->deltax = deltax;
426  this->bottomsite = bottomsite;
427 }
428 
430 {
431  delete[] ELhash;
432  // free all allocated memory
433  for(int i=0; i<HEcount; i++) delete HEmemmap[i];
434  delete[] HEmemmap;
435 }
436 
438 {
439  Halfedge *answer = new Halfedge;
440  answer->ELedge = e;
441  answer->ELpm = pm;
442 
443  HEmemmap[HEcount++] = answer;
444  if(HEcount%ELhashsize == 0) {
445  Halfedge **Temp = new Halfedge*[HEcount + ELhashsize];
446  for(int i=0; i<HEcount; i++) Temp[i] = HEmemmap[i];
447  delete[] HEmemmap;
448  HEmemmap = Temp;
449  }
450  return answer;
451 }
452 
454 {
455  new_he->ELleft = lb;
456  new_he->ELright = lb->ELright;
457  (lb->ELright)->ELleft = new_he;
458  lb->ELright = new_he;
459 }
460 
461 /* Get entry from hash table, pruning any deleted nodes */
463 {
464  Halfedge *he;
465 
466  if(b < 0 || b >= ELhashsize) return NULL;
467  he = ELhash[b];
468  if(he == NULL || he->ELedge != (Edge*)DELETED) return he;
469 
470  /* Hash table points to deleted half edge. */
471  ELhash[b] = NULL;
472  return NULL;
473 }
474 
475 /* returns 1 if p is to right of halfedge e */
477 {
478  Edge *e;
479  Site *topsite;
480  int right_of_site, above, fast;
481  double dxp, dyp, dxs, t1, t2, t3, yl;
482 
483  e = el->ELedge;
484  topsite = e->reg[1];
485  right_of_site = p->x > topsite->coord.x;
486  if(right_of_site && el->ELpm == le) return 1;
487  if(!right_of_site && el->ELpm == re) return 0;
488 
489  if(e->a == 1.0) {
490  dyp = p->y - topsite->coord.y;
491  dxp = p->x - topsite->coord.x;
492  fast = 0;
493  if((!right_of_site && (e->b < 0.0)) || (right_of_site && (e->b >= 0.0))) {
494  above = dyp >= e->b * dxp;
495  fast = above;
496  }
497  else {
498  above = p->x + p->y * e->b > e->c;
499  if(e->b < 0.0) above = !above;
500  if(!above) fast = 1;
501  }
502  if(!fast) {
503  dxs = topsite->coord.x - (e->reg[0])->coord.x;
504  above = e->b * (dxp*dxp - dyp*dyp) < dxs * dyp * (1.0 + 2.0*dxp/dxs + e->b*e->b);
505  if(e->b < 0.0) above = !above;
506  }
507  }
508  else {
509  yl = e->c - e->a * p->x;
510  t1 = p->y - yl;
511  t2 = p->x - topsite->coord.x;
512  t3 = yl - topsite->coord.y;
513  above = t1*t1 > t2*t2 + t3*t3;
514  }
515  return el->ELpm == le ? above : !above;
516 }
517 
519 {
520  int i, bucket;
521  Halfedge *he;
522 
523  /* Use hash table to get close to desired halfedge */
524  bucket = (int)((p->x - xmin) / deltax) * ELhashsize;
525  if(bucket < 0) bucket =0;
526  if(bucket >= ELhashsize) bucket = ELhashsize - 1;
527  he = ELgethash(bucket);
528  if(he == NULL) {
529  for(i=1; 1; i++) {
530  if((he = ELgethash(bucket-i)) != NULL) break;
531  if((he = ELgethash(bucket+i)) != NULL) break;
532  }
533  totalsearch++;
534  }
535  ntry++;
536  /* Now search linear list of halfedges for the corect one */
537  if(he == ELleftend || (he != ELrightend && right_of(he, p))) {
538  do {he = he->ELright;} while(he != ELrightend && right_of(he, p));
539  he = he->ELleft;
540  }
541  else do {he = he->ELleft;} while(he != ELleftend && !right_of(he, p));
542 
543  /* Update hash table and reference counts */
544  if(bucket > 0 && bucket < ELhashsize-1) {
545  ELhash[bucket] = he;
546  }
547  return he;
548 }
549 
551 {
552  (he->ELleft)->ELright = he->ELright;
553  (he->ELright)->ELleft = he->ELleft;
554  he->ELedge = (Edge*)DELETED;
555 }
556 
558 {
559  return he->ELright;
560 }
561 
563 {
564  return he->ELleft;
565 }
566 
567 
569 {
570  if(he->ELedge == NULL) return(bottomsite);
571  return he->ELpm == le ? he->ELedge->reg[le] : he->ELedge->reg[re];
572 }
573 
575 {
576  if(he->ELedge == NULL) return(bottomsite);
577  return he->ELpm == le ? he->ELedge->reg[re] : he->ELedge->reg[le];
578 }