LSSTApplications  8.0.0.0+107,8.0.0.1+13,9.1+18,9.2,master-g084aeec0a4,master-g0aced2eed8+6,master-g15627eb03c,master-g28afc54ef9,master-g3391ba5ea0,master-g3d0fb8ae5f,master-g4432ae2e89+36,master-g5c3c32f3ec+17,master-g60f1e072bb+1,master-g6a3ac32d1b,master-g76a88a4307+1,master-g7bce1f4e06+57,master-g8ff4092549+31,master-g98e65bf68e,master-ga6b77976b1+53,master-gae20e2b580+3,master-gb584cd3397+53,master-gc5448b162b+1,master-gc54cf9771d,master-gc69578ece6+1,master-gcbf758c456+22,master-gcec1da163f+63,master-gcf15f11bcc,master-gd167108223,master-gf44c96c709
LSSTDataManagementBasePackage
SweepStructure.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008, 2009, 2010 LSST Corporation.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <http://www.lsstcorp.org/LegalNotices/>.
23  */
24 
31 #ifndef LSST_AP_MATCH_DETAIL_SWEEPSTRUCTURE_CC
32 #define LSST_AP_MATCH_DETAIL_SWEEPSTRUCTURE_CC
33 
34 #include "SweepStructure.h"
35 
36 #include <math.h>
37 #include <climits>
38 #include <algorithm>
39 
40 #include "lsst/pex/exceptions.h"
41 #include "lsst/afw/geom/Angle.h"
42 #include "../../utils/SpatialUtils.h"
43 
44 
45 namespace lsst { namespace ap { namespace match { namespace detail {
46 
47 // -- CartesianNode implementation ----
48 
52  color(BLACK),
53  reach(0.0),
54  minCoord0(0.0),
55  maxCoord0(0.0),
56  bbox(0)
57 {
58  link[0] = 0;
59  link[1] = 0;
60 }
61 
66  color(RED),
67  reach(b->getMaxCoord0()),
68  minCoord0(b->getMinCoord0()),
69  maxCoord0(reach),
70  bbox(b)
71 {
72  link[0] = 0;
73  link[1] = 0;
74 }
75 
77 #ifndef NDEBUG
78  link[0] = 0;
79  link[1] = 0;
80  bbox = 0;
81 #endif
82 }
83 
87 inline bool lessThan(CartesianNode const *a, CartesianNode const *b) {
88  return (a->minCoord0 == b->minCoord0) ?
89  a->bbox < b->bbox : a->minCoord0 < b->minCoord0;
90 }
91 
92 inline bool operator<(std::pair<double, CartesianNode *> const &n1,
93  std::pair<double, CartesianNode *> const &n2)
94 {
95  return n1.first > n2.first;
96 }
97 
98 
99 // -- SphericalNode implementation ----
100 
104  color(BLACK),
105  foundBy(0),
106  reach(0.0),
107  minCoord0(0.0),
108  maxCoord0(0.0),
109  bbox(0),
110  twin(0)
111 {
112  link[0] = 0;
113  link[1] = 0;
114 }
115 
120  double minC0,
121  double maxC0
122  ) :
123  color(RED),
124  foundBy(0),
125  reach(maxC0),
126  minCoord0(minC0),
127  maxCoord0(maxC0),
128  bbox(b),
129  twin(0)
130 {
131  link[0] = 0;
132  link[1] = 0;
133 }
134 
136  if (twin != 0) {
137  twin->twin = 0;
138  }
139 #ifndef NDEBUG
140  link[0] = 0;
141  link[1] = 0;
142  bbox = 0;
143  twin = 0;
144 #endif
145 }
146 
147 inline bool SphericalNode::markFound(unsigned int searchId) {
148  unsigned int id = foundBy;
149  foundBy = searchId;
150  return (id == searchId || (twin != 0 && twin->foundBy == searchId));
151 }
152 
156 inline bool lessThan(SphericalNode const *a, SphericalNode const *b) {
157  return (a->minCoord0 == b->minCoord0) ?
158  a->bbox < b->bbox : a->minCoord0 < b->minCoord0;
159 }
160 
161 inline bool operator<(std::pair<double, SphericalNode *> const &left,
162  std::pair<double, SphericalNode *> const &right)
163 {
164  return left.first > right.first;
165 }
166 
167 
168 // -- SweepStructure implementation ---
169 
172 template <typename Node>
173 inline size_t SweepStructure<Node>::size() const {
174  return _heap.size();
175 }
176 
179 template <typename Node>
180 inline bool SweepStructure<Node>::empty() const {
181  return size() == 0;
182 }
183 
187 template <typename Node>
188 inline size_t SweepStructure<Node>::getNumBytes() const {
189  return _arena.getNumBytes() + _heap.capacity()*sizeof(HeapEntry);
190 }
191 
196 template <typename Node>
197 inline double SweepStructure<Node>::_reach(Node const *n) {
198  double reach = n->maxCoord0;
199  Node const *c0 = n->link[0];
200  if (c0 != 0 && c0->reach > reach) {
201  reach = c0->reach;
202  }
203  Node const *c1 = n->link[1];
204  if (c1 != 0 && c1->reach > reach) {
205  reach = c1->reach;
206  }
207  return reach;
208 }
209 
212 template <typename Node>
213 inline Node * SweepStructure<Node>::_rotate(Node *n, int dir) {
214  Node *r = n->link[!dir];
215  n->link[!dir] = r->link[dir];
216  r->link[dir] = n;
217  r->color = BLACK;
218  r->reach = n->reach;
219  n->color = RED;
220  n->reach = _reach(n);
221  return r;
222 }
223 
226 template <typename Node>
227 inline Node * SweepStructure<Node>::_doubleRotate(Node *n, int dir) {
228  n->link[!dir] = _rotate(n->link[!dir], !dir);
229  return _rotate(n, dir);
230 }
231 
232 // -- CartesianSweep implementation ---
233 
237 template <typename Region>
238 inline void CartesianSweep<Region>::insert(Region *region) {
239  _insert(region);
240 }
241 
250 template <typename Region>
251  template <typename RegionProcessor>
253  RegionProcessor &f
254  )
255 {
256  while (!_heap.empty() && _heap.front().first < to) {
257  std::pop_heap(_heap.begin(), _heap.end());
258  CartesianNode *n = _heap.back().second;
259  _heap.pop_back();
260  _remove(n);
261  f(dynamic_cast<Region *>(n->bbox));
262  _arena.destroy(n);
263  }
264 }
265 
274 template <typename Region>
275  template <typename RegionProcessor>
276 void CartesianSweep<Region>::clear(RegionProcessor &f) {
277  typedef std::vector<HeapEntry>::iterator Iter;
278  for (Iter i = _heap.begin(), e = _heap.end(); i != e; ++i) {
279  CartesianNode *n = i->second;
280  f(dynamic_cast<Region *>(n->bbox));
281  _arena.destroy(n);
282  }
283  _heap.clear();
284  _root = 0;
285 }
286 
298 template <typename Region>
299  template <typename OtherRegion, typename MatchProcessor>
300 void CartesianSweep<Region>::search(OtherRegion *r,
301  MatchProcessor &f
302  )
303 {
304  CartesianNode *node[2*sizeof(size_t)*CHAR_BIT];
305  int dir[2*sizeof(size_t)*CHAR_BIT];
306  CartesianNode *n = _root;
307  if (n == 0) {
308  return;
309  }
310  double const min = r->getMinCoord0();
311  double const max = r->getMaxCoord0();
312  int s = 0;
313 
314  while (true) {
315  if (n->reach >= min) {
316  if (n->minCoord0 <= max && n->maxCoord0 >= min) {
317  f(r, dynamic_cast<Region *>(n->bbox));
318  }
319  if (n->link[0] != 0) {
320  node[s] = n;
321  dir[s] = 0;
322  ++s;
323  n = n->link[0];
324  continue;
325  } else if (n->link[1] != 0) {
326  node[s] = n;
327  dir[s] = 1;
328  ++s;
329  n = n->link[1];
330  continue;
331  }
332  }
333  for (--s; s >= 0 && (dir[s] == 1 || node[s]->link[1] == 0); --s) { }
334  if (s < 0 || node[s]->minCoord0 > max) {
335  break;
336  }
337  dir[s] = 1;
338  n = node[s]->link[1];
339  ++s;
340  }
341 }
342 
343 
344 // -- SphericalSweep implementation ----
345 
349 template <typename Region>
350 inline void SphericalSweep<Region>::insert(Region *region) {
351  _insert(region);
352 }
353 
363 template <typename Region>
364  template <typename RegionProcessor>
366  RegionProcessor &f
367  )
368 {
369  while (!_heap.empty() && _heap.front().first < to) {
370  std::pop_heap(_heap.begin(), _heap.end());
371  SphericalNode *n = _heap.back().second;
372  _heap.pop_back();
373  _remove(n);
374  if (n->twin == 0) {
375  // Note that if a node n is deleted by this loop,
376  // so is its twin. Only invoke the region processor
377  // on nodes that never had or no longer have a twin -
378  // this avoids double invoking on the same region.
379  f(dynamic_cast<Region *>(n->bbox));
380  }
381  _arena.destroy(n);
382  }
383 }
384 
393 template <typename Region>
394  template <typename RegionProcessor>
395 void SphericalSweep<Region>::clear(RegionProcessor &f) {
396  typedef std::vector<HeapEntry>::iterator Iter;
397  for (Iter i = _heap.begin(), e = _heap.end(); i != e; ++i) {
398  SphericalNode *n = i->second;
399  if (n->twin == 0) {
400  // Note that if a node n is deleted by this loop,
401  // so is its twin. Only invoke the region processor
402  // on nodes that never had or no longer have a twin -
403  // this avoids double invoking on the same region.
404  f(dynamic_cast<Region *>(n->bbox));
405  }
406  _arena.destroy(n);
407  }
408  _heap.clear();
409  _root = 0;
410  _searchId = 1;
411 }
412 
424 template <typename Region>
425  template <typename OtherRegion, typename MatchProcessor>
426 void SphericalSweep<Region>::search(OtherRegion *r,
427  MatchProcessor &f
428  )
429 {
433 
434  if (_root == 0) {
435  return;
436  }
437  Angle min = r->getMinCoord0() * radians;
438  Angle max = r->getMaxCoord0() * radians;
440  if (min > max) {
441  _search(r, f, 0.0, static_cast<double>(max));
442  max = TWOPI * radians;
443  }
444  _search(r, f, static_cast<double>(min), static_cast<double>(max));
445  ++_searchId;
446  if (_searchId == 0) {
447  // _searchId wrapped to zero. Without further action, a region
448  // last reported by search N will never be reported once the search
449  // id reaches N again. Therefore, whenever _searchId wraps to
450  // zero, set the search id of all nodes to 0 and set _searchId to
451  // 1.
452  typedef std::vector<HeapEntry>::iterator Iter;
453  for (Iter i = _heap.begin(), e = _heap.end(); i != e; ++i) {
454  i->second->foundBy = 0;
455  }
456  _searchId = 1;
457  }
458 }
459 
460 template <typename Region>
463  return false;
464  }
465  // check that the search id of every node is less than the id
466  // of the next search call
467  typedef std::vector<HeapEntry>::const_iterator Iter;
468  for (Iter i = _heap.begin(), e = _heap.end(); i != e; ++i) {
469  if (i->second->foundBy >= _searchId) {
470  return false;
471  }
472  }
473  return true;
474 }
475 
480 template <typename Region>
481 void SphericalSweep<Region>::setSearchId(unsigned int searchId) {
482  typedef std::vector<HeapEntry>::iterator Iter;
483  if (searchId == 0) {
484  // a search id of 0 is reserved to mean "not found by any search"
485  searchId = 1;
486  }
487  if (searchId < _searchId) {
488  // the tree may contain nodes with search id equal to searchId
489  for (Iter i = _heap.begin(), e = _heap.end(); i != e; ++i) {
490  i->second->foundBy = 0;
491  }
492  }
493  _searchId = searchId;
494 }
495 
499 template <typename Region>
500  template <typename OtherRegion, typename MatchProcessor>
502  MatchProcessor &f,
503  double min,
504  double max
505  )
506 {
507  SphericalNode *node[2*sizeof(size_t)*CHAR_BIT];
508  int dir[2*sizeof(size_t)*CHAR_BIT];
509  int s = 0;
510  SphericalNode *n = _root;
511 
512  while (true) {
513  if (n->reach >= min) {
514  if (n->minCoord0 <= max && n->maxCoord0 >= min) {
515  if (!n->markFound(_searchId)) {
516  // found a match to an as yet unreported region -
517  // invoke the match processor on it
518  f(r, dynamic_cast<Region *>(n->bbox));
519  }
520  }
521  if (n->link[0] != 0) {
522  node[s] = n;
523  dir[s] = 0;
524  ++s;
525  n = n->link[0];
526  continue;
527  } else if (n->link[1] != 0) {
528  node[s] = n;
529  dir[s] = 1;
530  ++s;
531  n = n->link[1];
532  continue;
533  }
534  }
535  for (--s; s >= 0 && (dir[s] == 1 || node[s]->link[1] == 0); --s) { }
536  if (s < 0 || node[s]->minCoord0 > max) {
537  break;
538  }
539  dir[s] = 1;
540  n = node[s]->link[1];
541  ++s;
542  }
543 }
544 
545 
546 }}}} // namespace lsst::ap::match::detail
547 
548 #endif // LSST_AP_MATCH_DETAIL_SWEEPSTRUCTURE_CC
549 
An include file to include the public header files for lsst::afw::math.
lsst::afw::geom::Angle Angle
Definition: misc.h:37
void search(OtherRegion *r, MatchProcessor &f)
void advance(double to, RegionProcessor &f)
void _search(OtherRegion *r, MatchProcessor &f, double min, double max)
void search(OtherRegion *r, MatchProcessor &f)
std::pair< double, Node * > HeapEntry
Node * _doubleRotate(Node *n, int dir)
void advance(double to, RegionProcessor &f)
double min
Definition: attributes.cc:216
static double _reach(Node const *n)
double max
Definition: attributes.cc:218
Include files required for standard LSST Exception handling.
AngleUnit const radians
constant with units of radians
Definition: Angle.h:91
bool markFound(unsigned int searchId)
bool lessThan(CartesianNode const *a, CartesianNode const *b)
void setSearchId(unsigned int searchId)
double const TWOPI
Definition: Angle.h:19
std::vector< std::pair< Angle, Ref * > > _heap
Arena< MatchablePos > _arena
afw::table::Key< double > b
Sweep line data structures useful for region-region matching.
void thetaRangeReduce(Angle &min, Angle &max)
Definition: SpatialUtils.cc:56