00001 #ifndef READS_IN_RECT_H 00002 #define READS_IN_RECT_H 00003 00004 #include <cassert> 00005 00006 #include "generaldata.h" 00007 #include "trappertypes.h" 00008 #include "readdata.h" 00009 00010 class ReadsInRect 00011 { 00012 public: 00013 ReadsInRect(TrapperDoc * doc) { 00014 cursor_positioned = false; 00015 need_to_call_first = true; 00016 readIt = new Database::SecondaryIterator<ReadData>( "pos", doc, "ReadData" ); 00017 x_dna = 0; 00018 y_dna = 0; 00019 w_dna = 0; 00020 h_dna = 0; 00021 } 00022 ~ReadsInRect() { 00023 delete readIt; 00024 } 00025 void setWindowCoord(TR_DNA x_dna_, TR_DNA y_dna_,TR_DNA w_dna_,TR_DNA h_dna_ ) { 00026 x_dna = x_dna_; 00027 y_dna = y_dna_; 00028 w_dna = w_dna_; 00029 h_dna = h_dna_; 00030 return; 00031 } 00032 ReadData * first() 00033 { 00034 y_iter = y_dna; 00035 x_iter = x_dna; 00036 cursor_positioned = false; 00037 need_to_call_first = false; 00038 return find(); 00039 } 00040 ReadData * next() 00041 { 00042 return find(); 00043 } 00044 private: 00045 ReadData * find() { 00046 if ( need_to_call_first ) { 00047 return NULL; 00048 } 00049 00050 if ( w_dna <= 0 ) { 00051 //Bug fix 00052 return NULL; 00053 } 00054 00055 while ( y_iter < y_dna + h_dna ) { 00056 00057 while ( x_iter < x_dna + w_dna ) { 00058 int ret; 00059 /* 00060 It is faster to get the next data item by invoking next() on the cursor, 00061 than doing a new search ( i.e. setRange() ). 00062 Because the data item are sorted in the berkeley db first y-wise and 00063 then x-wise we use next() when we want to get the next Read to the right 00064 in the same row. If we change rows we have to do a new search ( i.e. setRange() ). 00065 We use the boolean cursor_positioned to indicate which of them to use. 00066 */ 00067 if ( cursor_positioned ) { 00068 ret = readIt->next(); 00069 } 00070 else { 00071 readIt->key()->setRow( y_iter ); 00072 readIt->key()->setEndPos( x_iter ); 00073 ret = readIt->setRange(); 00074 00075 } 00076 if ( ret != 0 ) { 00077 00078 // no records left in the sorted index 00079 need_to_call_first = true; 00080 return NULL; 00081 } 00082 ReadData * d = readIt->answer(); 00083 assert( d ); 00084 if ( hasRightEndInsideWindow( d ) ) { 00085 cursor_positioned = true; 00086 00087 } 00088 else { 00089 00090 cursor_positioned = false; 00091 x_iter = x_dna; 00092 y_iter = d->row(); 00093 if ( d->endPos() >= x_dna + w_dna ) { // we won't find any more reads on this row 00094 ++y_iter; 00095 00096 } 00097 } 00098 if ( hasAnythingInsideWindow( d ) ) { 00099 00100 return d; 00101 } 00102 00103 } 00104 } 00105 need_to_call_first = true; 00106 cursor_positioned = false; 00107 return NULL; 00108 } 00109 bool hasAnythingInsideWindow( ReadData * d ) { 00110 if ( d->endPos() < x_dna ) 00111 return false; 00112 if (( d->startPos() < x_dna + w_dna ) && ( d->row() < y_dna + h_dna )) 00113 return true; 00114 //default 00115 return false; 00116 } 00117 00118 bool hasRightEndInsideWindow( ReadData * d ) { 00119 return (( d->endPos() < x_dna + w_dna ) 00120 && ( d->endPos() >= x_dna ) ); 00121 } 00122 00123 00124 00125 bool cursor_positioned; 00126 bool need_to_call_first; 00127 TR_DNA x_dna; 00128 TR_DNA y_dna; 00129 TR_DNA w_dna; 00130 TR_DNA h_dna; 00131 TR_DNA x_iter; 00132 TR_DNA y_iter; 00133 Database::SecondaryIterator<ReadData> * readIt; 00134 }; 00135 00136 #endif //READS_IN_RECT_H