IndexedActiveList.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2004 CSIRO ICT Centre
00003  *
00004  * $Id: IndexedActiveList.cpp 587 2004-12-03 15:06:33Z nch $
00005  */
00006 
00007 /* IndexedActiveList implements an ActiveList with a data
00008  * structure that is very efficient for:
00009  *  - adding objects in order of declination;
00010  *  - removing all objects up to a given declination limit; and
00011  *  - reporting all objects that fall within a given right
00012  *    ascension range.
00013  */
00014 
00015 #include <algorithm>
00016 
00017 #include "ActiveList.h"
00018 #include "ActiveObject.h"
00019 #include "ALStructure.h"
00020 #include "IndexedActiveList.h"
00021 #include "Object.h"
00022 #include "ObjectPairConsumer.h"
00023 #include "ObjectConsumer.h"
00024 #include "Profiler.h"
00025 
00026 
00027 IndexedActiveList::IndexedActiveList()
00028     : ActiveList()
00029 {
00030   activeStructure = new ALStructure();
00031 }
00032 
00033 IndexedActiveList::~IndexedActiveList()
00034 {
00035   profiler = 0;
00036   delete activeStructure;
00037 }
00038 
00039 
00040 void IndexedActiveList::pushBack(Object const * object, bool matchedPreviously)
00041 {
00042   activeStructure->add(new ActiveObject(object, matchedPreviously));
00043 }
00044   
00045 // a little care is needed to avoid ending up with
00046 // an invalid objecter.
00047 ALElement * IndexedActiveList::remove(ALElement * i)
00048 {
00049   ALElement * tempI = i;
00050   i = i->getPrevDec();
00051     activeStructure->remove(tempI);
00052   if (i == 0)
00053     i = activeStructure->getDecHead();
00054   else
00055     i = i->getNextDec();
00056 
00057   return i;
00058 }
00059 
00060 void IndexedActiveList::deletePriorObjects(double boundary,
00061                                            ObjectConsumer * uActiveCons)
00062 {
00063   // start at the object with lowest declination.
00064   ALElement * i = activeStructure->getDecHead();
00065 
00066   // for as long as we haven't reached the end of the list.
00067   while (i != activeStructure->getTail())
00068   {
00069     // examine a object.
00070     ActiveObject * activeObject = i->getContent();
00071     Object const * object = activeObject->getObject();
00072     if (object->getDec() < boundary)
00073     {
00074       // the object's declination is less that the bound,
00075       // so remove it.
00076 
00077       // if the object has never appeared in a candidate pair,
00078       // then report it unmatched.
00079       if (!(activeObject->isMatched()))
00080         uActiveCons->report(object);
00081 
00082       i = remove(i);
00083       delete object;
00084       delete activeObject;
00085     }
00086     else
00087     {
00088       // this object is past the boundary,
00089       // and so will every subsequent object be.
00090       // So break out now.
00091       break;
00092     }
00093   }
00094 }
00095 
00096 /* Find all objects in the active list that are near a test object.
00097  * By the time we get to this object, we already know that all
00098  * the objects in the active list are nearby in the declination
00099  * dimension, so we only need to check for proximity in right
00100  * ascension. */
00101 
00102 bool IndexedActiveList::testObject(Object const * testObject,
00103                                    double upperLimitOnDistance,
00104                                    ObjectPairConsumer * matchedConsumer)
00105 {
00106   if (profiler != 0)
00107   {
00108     profiler->registerActiveListSize(activeStructure->getSize());
00109   }
00110 
00111   bool testObjectMatched = false;
00112 
00113   // compute an upper bound on the distance away in ra of a matching object
00114   double upperLimitOnRaDistance = Object::computeRACorrection(
00115                                                           upperLimitOnDistance,
00116                                                           testObject->getDec());
00117  
00118   // compute a lower bound on right ascension.
00119   double lowerBound = testObject->getRa() - upperLimitOnRaDistance;
00120 
00121   // compute an upper bound on right ascension.
00122   double upperBound = testObject->getRa() + upperLimitOnRaDistance;
00123 
00124   // adjust bounds as required
00125   if (lowerBound < 0.0)
00126     lowerBound += 360.0;
00127   else if (lowerBound > 360.0)
00128     lowerBound -= 360.0;
00129 
00130   if (upperBound < 0.0)
00131     upperBound += 360.0;
00132   else if (upperBound > 360.0)
00133     upperBound -= 360.0;
00134 
00135   // We're about to walk from the lower bound to the
00136   // upper bound, reporting all objects encountered.
00137   // Decide if our walk will need to wrap around at the
00138   // prime meridian.
00139   bool wrap = (upperBound < lowerBound);
00140 
00141   // find the starting object for our walk.
00142   ALElement * i = activeStructure->findLeastGE(lowerBound);
00143 
00144   while (true)
00145   {
00146     if (i == activeStructure->getTail())
00147     {
00148       // We're at the end of the list.
00149       // Do we stop or wrap?
00150       if (wrap)
00151       {
00152         // Wrap around to the start of the list,
00153         // but turn wrap off so that we don't risk
00154         // wrapping around again (and again and again...)
00155         i = activeStructure->getRaHead();
00156         wrap = false;
00157         continue;
00158       }
00159       else
00160       {
00161         // we're at the end of the list but we
00162         // shouldn't wrap.  So stop.
00163         break;
00164       }
00165     }
00166     else
00167     {
00168       // Examine the current object, and decide whether
00169       // to report it and continue, or stop.
00170       ActiveObject * activeObject = i->getContent();
00171       Object const * matchingObject = activeObject->getObject();
00172 
00173       // if we haven't reached the upper bound, or if we
00174       // need to walk until we wrap around at the prime
00175       // meridian, then report this object and continue
00176       // walking.
00177 
00178       if ((matchingObject->getRa() <= upperBound) || (wrap))
00179       {
00180         if (matchedConsumer->report(testObject, matchingObject))
00181         {
00182           testObjectMatched = true;
00183           activeObject->markMatched();
00184         }
00185 
00186         i = i->getNextRa();
00187       }
00188       else
00189       {
00190         // we're past the upper bound and we're not wrapping,
00191         // so stop.
00192         break;
00193       }
00194     }
00195   }
00196 
00197   return testObjectMatched;
00198 }
00199 
00200 /* clear out the active list, reporting things unmatched if
00201  * necessary. */
00202 void IndexedActiveList::clear(ObjectConsumer * uActiveCons)
00203 {
00204   // start at the head.
00205   ALElement * i = activeStructure->getDecHead();
00206 
00207   // until we get to the end of the list.
00208   while (i != activeStructure->getTail())
00209   {
00210     // if the object has never been matched, report it unmatched.
00211     ActiveObject * activeObject = i->getContent();
00212     Object const * object = activeObject->getObject();
00213     if (!(activeObject->isMatched()))
00214       uActiveCons->report(object);
00215 
00216     i = remove(i);
00217     delete object;
00218     delete activeObject;
00219   }
00220 }
00221 
00222 /* clean up the active list, then announce completion */
00223 void IndexedActiveList::finished(ObjectConsumer * uActiveCons)
00224 {
00225   clear(uActiveCons);
00226 }
00227 
00228 bool IndexedActiveList::isEmpty()
00229 {
00230   return (activeStructure->getSize() == 0);
00231 }
00232 
00233 ActiveObject * IndexedActiveList::popFront()
00234 {
00235   ActiveObject * active = activeStructure->getDecHead()->getContent();
00236   remove(activeStructure->getDecHead());
00237 
00238   return active;
00239 }
Generated on Mon Oct 4 10:39:55 2010 for Matching.kdevelop by  doxygen 1.6.3