source: branches/pixel-map-branch/src/PixelMap/Object2D.cc @ 1339

Last change on this file since 1339 was 252, checked in by Matthew Whiting, 17 years ago
  • Have put all classes in the files in src/PixelMap/ into a PixelInfo? namespace.
  • Added "using namespace PixelInfo?" to all necessary files.
  • Removed "friend class Detection" from Voxel and Object3D classes -- not necessary and complicated now by them being in the namespace
  • Various minor changes, including fixing up commentary.
File size: 11.2 KB
Line 
1#include <PixelMap/Scan.hh>
2#include <PixelMap/Object2D.hh>
3#include <PixelMap/Voxel.hh>
4#include <iostream>
5#include <vector>
6
7namespace PixelInfo
8{
9
10  Object2D::Object2D(const Object2D& o)
11  {
12    this->scanlist = o.scanlist;
13    this->numPix   = o.numPix;
14    this->xSum     = o.xSum;
15    this->ySum     = o.ySum;
16    this->xmin     = o.xmin;
17    this->ymin     = o.ymin;
18    this->xmax     = o.xmax;
19    this->ymax     = o.ymax;
20  } 
21  //------------------------------------------------------
22
23  Object2D& Object2D::operator= (const Object2D& o)
24  {
25    this->scanlist = o.scanlist;
26    this->numPix   = o.numPix;
27    this->xSum     = o.xSum;
28    this->ySum     = o.ySum;
29    this->xmin     = o.xmin;
30    this->ymin     = o.ymin;
31    this->xmax     = o.xmax;
32    this->ymax     = o.ymax;
33  } 
34  //------------------------------------------------------
35
36  void Object2D::addPixel(long x, long y)
37  {
38    /**
39     *  This function has three parts to it:
40     *  <ul><li> First, it searches through the existing scans to see if
41     *            a) there is a scan of the same y-value present, and
42     *            b) whether the (x,y) pixel lies in or next to an existing
43     *            Scan. If so, it is added and the Scan is grown if need be.
44     *            If this isn't the case, a new Scan of length 1 is added to
45     *            the list.
46     *      <li> If the Scan list was altered, all are checked to see whether
47     *            there is now a case of Scans touching. If so, they are
48     *            combined and added to the end of the list.
49     *      <li> If the pixel was added, the parameters are updated and the
50     *           pixel counter incremented.
51     *  </ul>
52     */
53
54
55    bool flagDone=false,flagChanged=false, isNew=false;
56
57    int scanCount = 0;
58    while(!flagDone && (scanCount<this->scanlist.size()) ){
59      Scan scan = this->scanlist[scanCount];   
60      if(y == scan.itsY){ // if the y value is already in the list
61        if(scan.isInScan(x,y)) flagDone = true; // pixel already here.
62        else{ // it's a new pixel!
63          if((x==(scan.itsX-1)) || (x == (scan.getXmax()+1)) ){
64            // if it is adjacent to the existing range, add to that range
65            if(x==(scan.itsX-1)) this->scanlist[scanCount].growLeft();
66            else                 this->scanlist[scanCount].growRight();
67            flagDone = true;
68            flagChanged = true;
69            isNew = true;
70          }
71        }     
72      }
73      scanCount++;
74    }
75
76    if(!flagDone){
77      Scan newOne(y,x,1);
78      this->scanlist.push_back(newOne);
79      isNew = true;
80    }
81 
82    if(flagChanged){
83      // this is true only if one of the pre-existing scans has changed
84      //
85      // need to clean up, to see if there is a case of two scans when
86      // there should be one.
87      //
88      // because there has been only one pixel added, only 2 AT MOST
89      // scans will need to be combined, so once we meet a pair that
90      // overlap, we can finish.
91
92      std::vector <Scan>::iterator iter;
93      bool combined = false;
94      int size = this->scanlist.size();
95      int count1=0;
96      while(!combined && count1<size){
97        int count2 = count1 + 1;
98        while(!combined && count2<size){
99          Scan first = this->scanlist[count1];
100          Scan second = this->scanlist[count2];
101          if(y==first.itsY && y==second.itsY){
102            combined = touching(first, second);
103            if(combined){
104              Scan newOne = unite(first,second);;
105              iter = this->scanlist.begin() + count2;
106              this->scanlist.erase(iter);
107              iter = this->scanlist.begin() + count1;
108              this->scanlist.erase(iter);
109              this->scanlist.push_back(newOne);
110            }
111          }     
112          count2++;
113        }
114        count1++;
115      }
116
117    }
118
119    if(isNew){ 
120      // update the centres, mins, maxs and increment the pixel counter
121      if(this->numPix==0){
122        this->xSum = this->xmin = this->xmax = x;
123        this->ySum = this->ymin = this->ymax = y;
124      }
125      else{
126        this->xSum += x;
127        this->ySum += y;
128        if(x<this->xmin) this->xmin = x;
129        if(x>this->xmax) this->xmax = x;
130        if(y<this->ymin) this->ymin = y;
131        if(y>this->ymax) this->ymax = y;
132      }
133      this->numPix++;
134    }
135
136  }
137  //------------------------------------------------------
138
139  void Object2D::addScan(Scan scan)
140  {
141    bool flagDone=false,flagChanged=false;;
142    long y = scan.itsY;
143    int scanCount = 0;
144    std::vector <Scan>::iterator iter;
145
146    while(!flagDone && (scanCount<this->scanlist.size()) ){
147      Scan existing = this->scanlist[scanCount];   
148      if(y==existing.itsY){ //ie. if the y value has a scan present
149        if(scan == existing) flagDone = true; // the scan is already there
150        else if(touching(scan,existing)){ // if it overlaps or is next to an existing scan
151          //    Scan joined = unite(scan,existing);
152          //    iter = this->scanlist.begin() + scanCount;
153          //    this->scanlist.erase(iter);
154          //    this->scanlist.push_back(joined);
155          //    flagDone = true;
156          flagChanged = true;
157        }
158      }
159      scanCount++;
160    }
161
162    // if it is unconnected with any existing scan, add it to the end of
163    // the list
164    if(!flagDone) this->scanlist.push_back(scan);
165
166    // if the scan has been added, we need to change the centres, mins,
167    // maxs etc. First add all the pixels from the scan. We then remove
168    // any doubled up ones later.
169    if( (!flagDone) || flagChanged ){
170      if(this->numPix==0){
171        this->ySum = y*scan.itsXLen;
172        this->ymin = this->ymax = y;
173        this->xmin = scan.itsX;
174        this->xmax = scan.getXmax();
175        this->xSum = scan.itsX;
176        for(int x=scan.itsX+1;x<=scan.getXmax();x++) this->xSum += x;
177        this->numPix = scan.itsXLen;
178      }
179      else{
180        this->ySum += y*scan.itsXLen;
181        for(int x=scan.itsX; x<=scan.getXmax(); x++) this->xSum += x;
182        if(y<this->ymin) this->ymin = y;
183        if(y>this->ymax) this->ymax = y;
184        if(scan.itsX<this->xmin)      this->xmin = scan.itsX;
185        if(scan.getXmax()>this->xmax) this->xmax = scan.getXmax();
186        this->numPix += scan.itsXLen;
187      }
188    }
189
190    if(flagChanged){
191      // this is true only if one of the pre-existing scans has changed
192      //
193      // In this case, we are adding a scan, and the possibility exists
194      // that more than one other scan could be affected. We therefore
195      // need to look over all scans, not just stopping at the first
196      // match we come across (as for addPixel() above).
197      int count1=0;
198      while(count1<this->scanlist.size()-1){
199        int count2 = count1 + 1;
200        do {
201          Scan first = this->scanlist[count1];
202          Scan second = this->scanlist[count2];
203          if(y==first.itsY && y==second.itsY){
204            // only look at the y-value where there would have been a change.
205            if(touching(first,second)){
206              Scan newOne = unite(first,second);
207              iter = this->scanlist.begin() + count2;
208              this->scanlist.erase(iter);
209              iter = this->scanlist.begin() + count1;
210              this->scanlist.erase(iter);
211              this->scanlist.push_back(newOne);
212           
213              count2 = count1 + 1;
214
215              // Need to remove the doubled-up pixels from the info
216              Scan overlap = intersect(first,second);
217              this->ySum -= overlap.itsY*overlap.itsXLen;
218              for(int x=overlap.itsX; x<=overlap.getXmax(); x++)
219                this->xSum -= x;
220              this->numPix -= overlap.itsXLen;
221
222            }
223            else count2++;
224          }     
225          else count2++;
226        } while(count2 < this->scanlist.size());
227
228        count1++;
229      }
230    }
231
232  }
233  //------------------------------------------------------
234
235  bool Object2D::isInObject(long x, long y)
236  {
237    bool result = false;
238    long scanCount = 0;
239    do{
240
241      if(y == this->scanlist[scanCount].itsY){
242        // if the y value is already in the list
243
244        if((x>=this->scanlist[scanCount].itsX)&&
245           (x<this->scanlist[scanCount].getXlen())){
246          // if the x value is already in the range, the pixel is
247          //  already stored, so return true
248          result = true;
249        }
250
251      }
252
253      scanCount++;
254
255    }while( !result && (scanCount<this->scanlist.size()) );
256
257    return result;
258
259  }
260  //------------------------------------------------------
261
262  // long Object2D::getSize()
263  // {
264  //   long size=0;
265  //   for(int i=0;i<this->scanlist.size();i++){
266  //     size += this->scanlist[i].getXlen();
267  //   }
268  //   return size;
269  // }
270  //------------------------------------------------------
271
272  std::ostream& operator<< ( std::ostream& theStream, Object2D& obj)
273  {
274    for(int i=0;i<obj.scanlist.size();i++)
275      theStream << obj.scanlist[i] << "\n";
276    theStream<<"---\n";
277
278  }
279  //------------------------------------------------------
280
281  void Object2D::calcParams()
282  {
283    this->xSum = 0;
284    this->ySum = 0;
285    int count = 0;
286    for(int s=0;s<this->scanlist.size();s++){
287
288      if(s==0){
289        this->ymin = this->ymax = this->scanlist[s].itsY;
290        this->xmin = this->scanlist[s].itsX;
291        this->xmax = this->scanlist[s].getXmax();
292      }
293      else{
294        if(this->ymin>this->scanlist[s].itsY)    this->ymin = this->scanlist[s].itsY;
295        if(this->xmin>this->scanlist[s].itsX)    this->xmin = this->scanlist[s].itsX;
296        if(this->ymax<this->scanlist[s].itsY)    this->ymax = this->scanlist[s].itsY;
297        if(this->xmax<this->scanlist[s].getXmax()) this->xmax = this->scanlist[s].getXmax();
298      }
299
300      count += this->scanlist[s].getXlen();
301      this->ySum += this->scanlist[s].itsY*this->scanlist[s].getXlen();
302      for(int x=this->scanlist[s].itsX;x<this->scanlist[s].getXmax();x++)
303        this->xSum += x;
304
305    }
306
307  }
308  //------------------------------------------------------
309
310  void Object2D::cleanup()
311  {
312    int counter=0, compCounter=1;
313    std::vector<Scan>::iterator iter;
314    while(counter < this->scanlist.size())
315      {
316        compCounter = counter + 1;
317     
318        while( compCounter < this->scanlist.size() ) {
319
320          Scan scan1 = this->scanlist[counter];
321          Scan scan2 = this->scanlist[compCounter];
322          if(overlap(scan1,scan2)){
323            Scan newscan = unite(scan1,scan2);
324            iter = this->scanlist.begin()+compCounter;
325            this->scanlist.erase(iter);
326            iter = this->scanlist.begin()+counter;
327            this->scanlist.erase(iter);
328            this->scanlist.push_back(newscan);
329            compCounter = counter + 1;
330          }
331          else compCounter++;
332
333        }
334
335        counter++;
336      }
337
338    //   this->order();
339
340  }
341  //------------------------------------------------------
342
343  long Object2D::getNumDistinctY()
344  {
345    std::vector<long> ylist;
346    if(this->scanlist.size()==0) return 0;
347    if(this->scanlist.size()==1) return 1;
348    ylist.push_back(this->scanlist[0].itsY);
349    for(int i=1;i<this->scanlist.size();i++){
350      bool inList = false;
351      int j=0;
352      long y = this->scanlist[i].itsY;
353      while(!inList && j<ylist.size()){
354        if(y==ylist[j]) inList=true;
355        j++;
356      };
357      if(!inList) ylist.push_back(y);
358    }
359    return ylist.size();
360  }
361  //------------------------------------------------------
362
363  long Object2D::getNumDistinctX()
364  {
365    std::vector<long> xlist;
366    if(this->scanlist.size()==0) return 0;
367    if(this->scanlist.size()==1) return 1;
368    for(int x=this->scanlist[0].itsX;x<this->scanlist[0].getXmax();x++)
369      xlist.push_back(x);
370    for(int i=1;i<this->scanlist.size();i++){
371      for(int x=this->scanlist[0].itsX;x<this->scanlist[0].getXmax();x++){
372        bool inList = false;
373        int j=0;
374        while(!inList && j<xlist.size()){
375          if(x==xlist[j]) inList=true;
376          j++;
377        };
378        if(!inList) xlist.push_back(x);
379      }
380    }
381    return xlist.size();
382  }
383  //------------------------------------------------------
384
385  bool Object2D::scanOverlaps(Scan scan)
386  {
387    bool returnval = false;
388    int scanCount=0;
389    while(!returnval && scanCount<this->scanlist.size()){
390      returnval = returnval || overlap(scan,this->scanlist[scanCount++]);
391    }
392    return returnval;
393  }
394
395}
Note: See TracBrowser for help on using the repository browser.