#ifndef _RTS_DTGRID2D_H #define _RTS_DTGRID2D_H #include #include using namespace std; #include "rtsDTGrid1D.h" struct IndexPair { //int toValue; int toConn; int numConn; }; struct Coord2D { int x1; int x2; }; #include using namespace std; class ColumnUnion { private: list Q; vector* toConn; public: void InsertColumn(IndexPair col) { Q.push_back(col); } void RemoveColumn() { Q.pop_front(); } vector MergeColumns(vector *Pc, vector *n, int H) { int i_Pc = 0; int i_n = 0; int smallest_column; ConnectedComponent smallest_cc; vector result; //iterate while there are remaining connected components in each column while(i_Pc < Pc->size() || i_n < n->size()) { //find the smallest coordMin value at the two index locations //if the index is at the end of the primary array if(i_Pc == Pc->size()) { smallest_cc = n->at(i_n); smallest_cc.coordMin -= H; smallest_cc.coordMax += H; i_n++; } //if n is at the end of the array else if(i_n == n->size()) { smallest_cc = Pc->at(i_Pc); i_Pc++; } else if(n->at(i_n).coordMin - H < Pc->at(i_Pc).coordMin) { smallest_cc = n->at(i_n); smallest_cc.coordMin -= H; smallest_cc.coordMax += H; i_n++; } else { smallest_cc = Pc->at(i_Pc); i_Pc++; } //merge the connected component into result //if the result array is empty or the last connected component doesn't overlap with smallest_cc if(result.size() == 0 || result.back().coordMax + 1 < smallest_cc.coordMin) result.push_back(smallest_cc); else if(result.back().coordMax < smallest_cc.coordMax) result.back().coordMax = smallest_cc.coordMax; } return result; } vector ComputeUnion(int H) { //create a vector to store the result vector result; //for each column in the list, merge it with the result vector list::iterator i; vector::iterator start; vector::iterator end; for(i = Q.begin(); i != Q.end(); i++) { start = toConn->begin() + (*i).toConn; end = start + (*i).numConn; vector column(start, end); result = MergeColumns(&result, &column, H); } //output result //for(int i=0; i *cc_list) { toConn = cc_list; } }; /*vector ColumnUnion::MergeColumns(vector *Pc, vector *n, int H) { int i_Pc = 0; int i_n = 0; int smallest_column; ConnectedComponent smallest_cc; vector result; //iterate while there are remaining connected components in each column while(i_Pc < Pc->size() || i_n < n->size()) { //find the smallest coordMin value at the two index locations //if the index is at the end of the primary array if(i_Pc == Pc->size()) { smallest_cc = n->at(i_n); smallest_cc.coordMin -= H; smallest_cc.coordMax += H; i_n++; } //if n is at the end of the array else if(i_n == n->size()) { smallest_cc = Pc->at(i_Pc); i_Pc++; } else if(n->at(i_n).coordMin - H < Pc->at(i_Pc).coordMin) { smallest_cc = n->at(i_n); smallest_cc.coordMin -= H; smallest_cc.coordMax += H; i_n++; } else { smallest_cc = Pc->at(i_Pc); i_Pc++; } //merge the connected component into result //if the result array is empty or the last connected component doesn't overlap with smallest_cc if(result.size() == 0 || result.back().coordMax + 1 < smallest_cc.coordMin) result.push_back(smallest_cc); else if(result.back().coordMax < smallest_cc.coordMax) result.back().coordMax = smallest_cc.coordMax; } return result; }*/ /*vector ColumnUnion::ComputeUnion(int H) { //create a vector to store the result vector result; //for each column in the list, merge it with the result vector list::iterator i; vector::iterator start; vector::iterator end; for(i = Q.begin(); i != Q.end(); i++) { start = toConn->begin() + (*i).toConn; end = start + (*i).numConn; vector column(start, end); result = MergeColumns(&result, &column, H); } //output result //for(int i=0; i class rtsDTGrid2D { private: //main arrays vector value; vector conn; rtsDTGrid1D proj1D; bool randomIndex(rtsDTGrid1D::iterator &iter1D, int &v_i, int &c_i, int x1, int x2); //variables to keep track of insertion int max_coord; bool grid_insertion_started; bool column_insertion_started; public: rtsDTGrid2D() { grid_insertion_started = false; column_insertion_started = false; proj1D.background.toConn = -1; max_coord = 0; } bool push(int x1, int x2, T v); T random(int x1, int x2); T& back(); T background; void print(); friend class ColumnUnion; void dilate(int H); void insert(rtsDTGrid2D toInsert); void operator=(T rhs); void getBounds(int &min_x1, int &min_x2, int &max_x1, int &max_x2); void dumpValue(); void dumpConn(); //iterator class iterator; friend class iterator; class stencil_iterator; iterator randomIterator(int x1, int x2); iterator begin(); iterator before(); iterator end(); iterator after(); //other types of iteration iterator begin_pn(); iterator end_pn(); iterator begin_np(); iterator end_np(); }; /**********ITERATOR***********************/ template class rtsDTGrid2D::iterator { friend class rtsDTGrid2D; rtsDTGrid2D* parent; rtsDTGrid1D::iterator loc1D; int iv; int ic; int x2; public: T Value(){return parent->value[iv];} int X1(){return loc1D.X1();} int X2(){return x2;} iterator(){parent = NULL;} void SetValue(T value){parent->value[iv] = value;} void pp() { //increment the value iv++; //if this exceeds the length of the value array, we are at the end of the grid if(iv == parent->value.size()) { (*this) = parent->after(); return; } //increment the current coordinate x2++; //if we are outside of the current connected component if(x2 > parent->conn[ic].coordMax) { //move to the next connected component ic++; //if this is the last connected component in the column if(ic == loc1D.Value().toConn + loc1D.Value().numConn) loc1D++; //if there are no more connected components if(ic == parent->conn.size()) { //we're at the end, return end (*this) = parent->end(); return; } x2 = parent->conn[ic].coordMin; } } void nn() { //decrement the value iv--; //if this is less than 0, we are at the beginning of the grid if(iv < 0) { (*this) = parent->before(); return; } //decrement the current coordinate x2--; //if we are outside of the current connected component if(x2 < parent->conn[ic].coordMin) { //move to the previous connected component ic--; //if this is the first connected component in the column if(ic < loc1D.Value().toConn) loc1D--; //if there are no more connected components if(ic < 0) { //we're at the beginning, return begin (*this) = parent->before(); return; } x2 = parent->conn[ic].coordMax; } } void pn() { //for the most part we will be going backwards through the array //so first decrement iv iv--; x2--; //if iv is less than the current connected component if(iv < parent->conn[ic].toValue) { //go to the previous connected component ic--; //if we are before the first connected component in the column if(ic < loc1D.Value().toConn) { //increment the 1D iterator loc1D++; //reset ic to the last component of the new column ic = loc1D.Value().toConn + loc1D.Value().numConn - 1; //find the new value identifier iv = parent->conn[ic].toValue + (parent->conn[ic].coordMax - parent->conn[ic].coordMin); } //compute the currect coordinate x2 = parent->conn[ic].coordMax; } } void np() { //for the most part we will be going forward through the grid //increment iv iv++; x2++; //if we are outside of the current connected component if(x2 > parent->conn[ic].coordMax) { //move to the next connected component ic++; //if this is the last connected component in the column if(ic == loc1D.Value().toConn + loc1D.Value().numConn) { loc1D--; ic = loc1D.Value().toConn; iv = parent->conn[ic].toValue; } x2 = parent->conn[ic].coordMin; } } //boolean operators for comparing iterators bool operator==(iterator &rhs) { if(parent == rhs.parent && iv == rhs.iv) return true; //if(loc1D == rhs.loc1D && x2 == rhs.x2) // return true; return false; } bool operator!=(iterator &rhs){return !((*this) == rhs);} bool operator<(iterator &rhs) { if(parent == rhs.parent && iv < rhs.iv) return true; //if(loc1D < rhs.loc1D) // return true; //else if(loc1D == rhs.loc1D && x2 < rhs.x2) // return true; return false; } bool operator<=(iterator &rhs) { if(parent == rhs.parent && iv <= rhs.iv) return true; //if(loc1D <= rhs.loc1D) // return true; //else if(loc1D == rhs.loc1D && x2 <= rhs.x2) // return true; return false; } void operator++(){pp();} void operator--(){nn();} void increment_until(int p1, int p2) { while((*this) != parent->end()) { if(X1() > p1) return; else if(X1() == p1 && X2() >= p2) return; pp(); } } }; /********STENCIL ITERATOR*****************/ template class rtsDTGrid2D::stencil_iterator : public iterator { private: //list of iterators that make up the template vector iterator_list; //iterator positions (relative to the position of the stencil iterator) vector position_list; //list containing the values for each position in the stencil vector value_list; void refresh_iterators(); void set_values(); void increment_all(); public: typename rtsDTGrid2D::stencil_iterator operator=(const iterator rhs); void addPosition(int p1, int p2); void increment(); void operator++() { increment(); } T getValue(int id){return value_list[id];} bool exists(int id); }; template void rtsDTGrid2D::stencil_iterator::increment_all() { //run through each iterator and increment to the correct position int i; Coord2D dest; for(i=0; i void rtsDTGrid2D::stencil_iterator::increment() { //increment the current position rtsDTGrid2D::iterator::pp(); increment_all(); } template void rtsDTGrid2D::stencil_iterator::refresh_iterators() { //make sure that the iterator position has been set if(parent == NULL) { cout<<"Iterator location not set."<begin(); iterator_list[i] = parent->randomIterator(X1() + position_list[i].x1, X2() + position_list[i].x2); } //increment_all(); //set the values for all of the iterators set_values(); } template void rtsDTGrid2D::stencil_iterator::set_values() { int i; Coord2D dest; for(i=0; ibackground; } } template typename rtsDTGrid2D::stencil_iterator rtsDTGrid2D::stencil_iterator::operator=(const iterator rhs) { parent = rhs.parent; loc1D = rhs.loc1D; iv = rhs.iv; ic = rhs.ic; x2 = rhs.x2; refresh_iterators(); return (*this); } template void rtsDTGrid2D::stencil_iterator::addPosition(int p1, int p2) { //add a position to the position list and add a new iterator to the iterator list Coord2D p; p.x1 = p1; p.x2 = p2; position_list.push_back(p); rtsDTGrid2D::iterator new_iter; iterator_list.push_back(new_iter); T empty; value_list.push_back(empty); } template bool rtsDTGrid2D::stencil_iterator::exists(int id) { int i; Coord2D dest; //determine the appropriate position for the iterator dest.x1 = X1() + position_list[id].x1; dest.x2 = X2() + position_list[id].x2; //now add the value to the value list if(iterator_list[id].X1() == dest.x1 && iterator_list[id].X2() == dest.x2) return true; else return false; } /**************ITERATOR METHODS IN DT GRID*******************/ template typename rtsDTGrid2D::iterator rtsDTGrid2D::begin() { //if the grid is empty, return an iterator to "after" if(value.size() == 0) return after(); iterator result; result.parent = this; result.ic = 0; result.iv = 0; result.x2 = conn[0].coordMin; result.loc1D = proj1D.begin(); return result; } template typename rtsDTGrid2D::iterator rtsDTGrid2D::before() { if(value.size() == 0) return after(); iterator result; result.parent = this; result.ic = 0; result.iv = -1; //result.x2 = conn[0].coordMin; result.loc1D = proj1D.before(); return result; } template typename rtsDTGrid2D::iterator rtsDTGrid2D::end() { //if the grid is empty, return after() if(value.size() == 0) return after(); iterator result; result.parent = this; result.ic = conn.size() - 1; result.iv = value.size() - 1; result.x2 = conn[result.ic].coordMax; result.loc1D = proj1D.end(); return result; } template typename rtsDTGrid2D::iterator rtsDTGrid2D::randomIterator(int x1, int x2) { rtsDTGrid2D::iterator result; result.parent = this; //perform the random search int v_i, c_i; rtsDTGrid1D::iterator iter1D; //if the value exists in the grid, create the iterator and return if(randomIndex(iter1D, v_i, c_i, x1, x2)) { result.loc1D = iter1D; result.iv = v_i; result.ic = c_i; int offset = v_i - conn[c_i].toValue; result.x2 = conn[c_i].coordMin + offset; } //if the value doesn't exist else { //if the 1D iterator is at the end of the grid, return after() if(iter1D == proj1D.after()) return after(); //if the value lies before the current column if(x1 < iter1D.X1() || (x1 == iter1D.X1() && x2 < conn[c_i].coordMin) ) { result.ic = c_i; } //else if the value lies after the current column else { //increment the 1D iterator iter1D++; //if this is the last connected component if(c_i >= conn.size() - 1) return after(); else { c_i++; result.ic = c_i; } } result.loc1D = iter1D; result.iv = conn[c_i].toValue; result.x2 = conn[c_i].coordMin; } return result; } template typename rtsDTGrid2D::iterator rtsDTGrid2D::after() { iterator result; result.parent = this; result.ic = conn.size() - 1; result.iv = value.size(); //result.x2 = conn[result.ic].coordMax; result.loc1D = proj1D.after(); return result; } template typename rtsDTGrid2D::iterator rtsDTGrid2D::begin_pn() { if(value.size() == 0) return after(); iterator result; result.parent = this; result.loc1D = proj1D.begin(); result.ic = result.loc1D.Value().toConn + result.loc1D.Value().numConn - 1; result.iv = conn[result.ic].toValue + (conn[result.ic].coordMax - conn[result.ic].coordMin); result.x2 = conn[result.ic].coordMax; return result; } template typename rtsDTGrid2D::iterator rtsDTGrid2D::begin_np() { //this is the opposite corner of pn return end_pn(); } template typename rtsDTGrid2D::iterator rtsDTGrid2D::end_pn() { if(value.size() == 0) return after(); iterator result; result.parent = this; result.loc1D = proj1D.end(); result.ic = result.loc1D.Value().toConn; result.iv = conn[result.ic].toValue; result.x2 = conn[result.ic].coordMin; return result; } template typename rtsDTGrid2D::iterator rtsDTGrid2D::end_np() { //this is the opposite corner of pn return begin_pn(); } template void rtsDTGrid2D::print() { rtsDTGrid2D::iterator i; i = begin(); while(i!=end()) { cout< bool rtsDTGrid2D::push(int x1, int x2, T v) { //run this code if we have to start a new column in X1. This happens when: //(a) we have just inserted the first value into the grid //(b) the value of x1 is greater than the last value of x1 if(grid_insertion_started == false || x1 != proj1D.getMaxX1()) { //assume that a new column is being created //create the column in proj1D IndexPair newPair; newPair.toConn = conn.size(); //newPair.toValue = value.size(); newPair.numConn = 0; //if this insertion throws an error, the value was inserted incorrectly //the error will get thrown by DTGrid1D, so just return if(!proj1D.push(x1, newPair)) { cout<<"Out-of-order insertion in D = 2: X1 = "< result = CUqueue.ComputeUnion(H); //compute the new IndexPair representing the column new_pair.toConn = new_grid.conn.size(); new_pair.numConn = result.size(); //store the index pair iteratorNew.SetValue(new_pair); //insert each of the connected components for(ccIterator = result.begin(); ccIterator!=result.end(); ccIterator++) { new_grid.conn.push_back(*ccIterator); new_grid.conn.back().toValue = numValues; numValues += (*ccIterator).coordMax - (*ccIterator).coordMin + 1; } //if a column is leaving the stencil if(iteratorDilate.getValue(0).numConn) CUqueue.RemoveColumn(); } //allocate space for the new value array new_grid.value.resize(numValues, background); //copy the data from this grid into the new grid new_grid.insert(*this); //replace this grid with the new grid conn = new_grid.conn; value = new_grid.value; proj1D = new_grid.proj1D; } template void rtsDTGrid2D::insert(rtsDTGrid2D toInsert) { //create source and destination iterators rtsDTGrid2D::iterator source = toInsert.begin(); rtsDTGrid2D::iterator dest = begin(); for(source = toInsert.begin(); source != toInsert.after(); source++) { //move the destination iterator to the current source position dest.increment_until(source.X1(), source.X2()); //cout<<"source: "< void rtsDTGrid2D::getBounds(int &min_x1, int &min_x2, int &max_x1, int &max_x2) { //if the grid is empty, return an empty bounding volume if(value.size() == 0) { min_x1 = min_x2 = max_x1 = max_x2 = 0; return; } //get the min and max values for the 1D grid (x1 coordinate) proj1D.getBounds(min_x1, max_x1); //initialize the min and max values min_x2 = conn[0].coordMin; max_x2 = conn.back().coordMax; //iterate through all columns finding the smallest and largest coordinate values rtsDTGrid1D::iterator i; IndexPair col; for(i=proj1D.begin(); i!=proj1D.after(); i++) { col = i.Value(); if(conn[col.toConn].coordMin < min_x2) min_x2 = conn[col.toConn].coordMin; if(conn[col.toConn + col.numConn - 1].coordMax > max_x2) max_x2 = conn[col.toConn + col.numConn - 1].coordMax; } } template void rtsDTGrid2D::operator =(T rhs) { for(int i=0; i void rtsDTGrid2D::dumpValue() { for(int i=0; i void rtsDTGrid2D::dumpConn() { for(int i=0; i