source: tags/release-1.1.9/src/PixelMap/Object3D.cc @ 1441

Last change on this file since 1441 was 691, checked in by MatthewWhiting, 14 years ago

New parameter that allows us to turn off the use of mergeIntoList. Fully documented!

File size: 12.4 KB
Line 
1// -----------------------------------------------------------------------
2// Object3D.cc: Member functions for Object3D class.
3// -----------------------------------------------------------------------
4// Copyright (C) 2006, Matthew Whiting, ATNF
5//
6// This program is free software; you can redistribute it and/or modify it
7// under the terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 2 of the License, or (at your
9// option) any later version.
10//
11// Duchamp is distributed in the hope that it will be useful, but WITHOUT
12// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14// for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with Duchamp; if not, write to the Free Software Foundation,
18// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
19//
20// Correspondence concerning Duchamp may be directed to:
21//    Internet email: Matthew.Whiting [at] atnf.csiro.au
22//    Postal address: Dr. Matthew Whiting
23//                    Australia Telescope National Facility, CSIRO
24//                    PO Box 76
25//                    Epping NSW 1710
26//                    AUSTRALIA
27// -----------------------------------------------------------------------
28#include <iostream>
29#include <sstream>
30#include <duchamp/PixelMap/Voxel.hh>
31#include <duchamp/PixelMap/Scan.hh>
32#include <duchamp/PixelMap/Object2D.hh>
33#include <duchamp/PixelMap/Object3D.hh>
34#include <vector>
35#include <map>
36
37namespace PixelInfo
38{
39  Object3D::Object3D()
40  {
41    this->numVox=0;
42    this->xSum = 0;
43    this->ySum = 0;
44    this->zSum = 0;
45    this->xmin = this->xmax = this->ymin = this->ymax = this->zmin = this->zmax = -1;
46  }
47  //--------------------------------------------
48
49  Object3D::Object3D(const Object3D& o)
50  {
51    operator=(o);
52  }
53  //--------------------------------------------
54
55  Object3D& Object3D::operator= (const Object3D& o)
56  {
57    if(this == &o) return *this;
58    this->chanlist = o.chanlist;
59    this->numVox  = o.numVox;
60    this->xSum    = o.xSum;
61    this->ySum    = o.ySum;
62    this->zSum    = o.zSum;
63    this->xmin    = o.xmin;
64    this->ymin    = o.ymin;
65    this->zmin    = o.zmin;
66    this->xmax    = o.xmax;
67    this->ymax    = o.ymax;
68    this->zmax    = o.zmax;
69    return *this;
70  }
71  //--------------------------------------------
72
73  Object3D operator+ (Object3D lhs, Object3D rhs)
74  {
75    Object3D output = lhs;
76    for(std::map<long, Object2D>::iterator it = rhs.chanlist.begin(); it!=rhs.chanlist.end();it++)
77      output.addChannel(it->first, it->second);
78    return output;
79  }
80
81  //--------------------------------------------
82  float Object3D::getXaverage()
83  {
84    if(numVox>0) return xSum/float(numVox);
85    else return 0.;
86  }
87  //--------------------------------------------
88
89  float Object3D::getYaverage()
90  {
91    if(numVox>0) return ySum/float(numVox);
92    else return 0.;
93  }
94  //--------------------------------------------
95
96  float Object3D::getZaverage()
97  {
98    if(numVox>0) return zSum/float(numVox);
99    else return 0.;
100  }
101  //--------------------------------------------
102 
103  bool Object3D::isInObject(long x, long y, long z)
104  {
105    std::map<long,Object2D>::iterator it=this->chanlist.begin();
106    while(it!=this->chanlist.end() && it->first!=z) it++;
107
108    if(it==this->chanlist.end()) return false;
109    else                         return it->second.isInObject(x,y);
110  }
111  //--------------------------------------------
112
113  void Object3D::addPixel(long x, long y, long z)
114  {
115 
116    std::map<long,Object2D>::iterator it=this->chanlist.begin();
117    while(it!=this->chanlist.end() && it->first!=z) it++;
118
119    if(it==this->chanlist.end()){ //new channel
120      Object2D obj;
121      obj.addPixel(x,y);
122      chanlist.insert( std::pair<int,Object2D>(z,obj) );
123      // update the centres, min & max, as well as the number of voxels
124      if(this->numVox==0){
125        this->xSum = this->xmin = this->xmax = x;
126        this->ySum = this->ymin = this->ymax = y;
127        this->zSum = this->zmin = this->zmax = z;
128      }
129      else{
130        this->xSum += x;
131        this->ySum += y;
132        this->zSum += z;
133        if(x<this->xmin) this->xmin = x;
134        if(x>this->xmax) this->xmax = x;
135        if(y<this->ymin) this->ymin = y;
136        if(y>this->ymax) this->ymax = y;
137        // since we've ordered the maplist, the min & max z fall out naturally
138        this->zmin = this->chanlist.begin()->first;
139        this->zmax = this->chanlist.rbegin()->first;
140      }
141      this->numVox++;   
142    }
143    else{ // existing channel
144      // This method deals with the case of a new pixel being added AND
145      // with the new pixel already existing in the Object2D
146 
147      // Remove that channel's information from the Object's information
148      long oldChanSize = it->second.numPix;
149      this->xSum -= it->second.xSum;
150      this->ySum -= it->second.ySum;
151      this->zSum -= z*oldChanSize;
152
153      // Add the pixel
154      it->second.addPixel(x,y);
155   
156      // and update the information...
157     long newChanSize = it->second.numPix;
158   
159      this->numVox += (newChanSize - oldChanSize);
160      this->xSum += it->second.xSum;
161      this->ySum += it->second.ySum;
162      this->zSum += z*newChanSize;
163      if(x<this->xmin) this->xmin = x;
164      if(x>this->xmax) this->xmax = x;
165      if(y<this->ymin) this->ymin = y;
166      if(y>this->ymax) this->ymax = y;
167      // don't need to do anything to zmin/zmax -- the z-value is
168      // already in the list
169    }
170
171  }
172  //--------------------------------------------
173
174  void Object3D::addScan(Scan s, long z)
175  {
176    long y=s.getY();
177    for(int x=s.getX(); x<=s.getXmax(); x++)
178      this->addPixel(x,y,z);
179  }
180
181  //--------------------------------------------
182
183  void Object3D::addChannel(const long &z, Object2D &obj)
184  {
185
186    std::map<long,Object2D>::iterator it=this->chanlist.begin();
187    while(it!=this->chanlist.end() && it->first!=z) it++;
188
189    if(it == this->chanlist.end()){ // channel z is not already in object, so add it.
190      this->chanlist.insert(std::pair<long,Object2D>(z,obj));
191      if(this->numVox == 0){ // if there are no other pixels, so initialise mins,maxs,sums
192        this->xmin = obj.xmin;
193        this->xmax = obj.xmax;
194        this->ymin = obj.ymin;
195        this->ymax = obj.ymax;
196        this->zmin = this->zmax = z;
197        this->xSum = obj.xSum;
198        this->ySum = obj.ySum;
199        this->zSum = z * obj.getSize();
200      }
201      else{ // there are other pixels in other channels, so update mins, maxs, sums
202        if(obj.xmin<this->xmin) this->xmin = obj.xmin;
203        if(obj.xmax>this->xmax) this->xmax = obj.xmax;
204        if(obj.ymin<this->ymin) this->ymin = obj.ymin;
205        if(obj.ymax>this->ymax) this->ymax = obj.ymax;
206        if(z<this->zmin) this->zmin = z;
207        if(z>this->zmax) this->zmax = z;
208        this->xSum += obj.xSum;
209        this->ySum += obj.ySum;
210        this->zSum += z * obj.getSize();
211      }
212      this->numVox += obj.getSize();
213    }
214    else{ // channel is already present, so need to combine objects.
215      this->xSum -= it->second.xSum;
216      this->ySum -= it->second.ySum;
217      this->zSum -= z*it->second.getSize();
218      this->numVox -= it->second.getSize();
219      it->second = it->second + obj;
220      this->xSum += it->second.xSum;
221      this->ySum += it->second.ySum;
222      this->zSum += z*it->second.getSize();
223      this->numVox += it->second.getSize();
224      if(obj.xmin<this->xmin) this->xmin = obj.xmin;
225      if(obj.xmax>this->xmax) this->xmax = obj.xmax;
226      if(obj.ymin<this->ymin) this->ymin = obj.ymin;
227      if(obj.ymax>this->ymax) this->ymax = obj.ymax;
228    }
229  }
230
231  //--------------------------------------------
232
233  unsigned long Object3D::getSpatialSize()
234  {
235    Object2D spatialMap = this->getSpatialMap();
236    return spatialMap.getSize();
237  }
238  //--------------------------------------------
239
240  Object2D Object3D::getSpatialMap()
241  {
242    Object2D spatialMap;
243    for(std::map<long, Object2D>::iterator it = this->chanlist.begin();
244        it!=this->chanlist.end();it++){
245      spatialMap = spatialMap + it->second;
246    }
247    return spatialMap;
248  }
249  //--------------------------------------------
250 
251  void Object3D::calcParams()
252  {
253    this->xSum = 0;
254    this->ySum = 0;
255    this->zSum = 0;
256    this->numVox = 0;
257
258    this->zmin = this->chanlist.begin()->first;
259    this->zmax = this->chanlist.rbegin()->first;
260    for(std::map<long, Object2D>::iterator it = this->chanlist.begin();
261        it!=this->chanlist.end();it++){
262
263      it->second.calcParams();
264
265      if(it==this->chanlist.begin()){
266        this->xmin = it->second.getXmin();
267        this->xmax = it->second.getXmax();
268        this->ymin = it->second.getYmin();
269        this->ymax = it->second.getYmax();
270      }
271      else{
272        if(it->second.xmin<this->xmin) this->xmin = it->second.xmin;
273        if(it->second.xmax>this->xmax) this->xmax = it->second.xmax;
274        if(it->second.ymin<this->ymin) this->ymin = it->second.ymin;
275        if(it->second.ymax>this->ymax) this->ymax = it->second.ymax;
276      }
277
278      this->xSum += it->second.xSum;
279      this->ySum += it->second.ySum;
280      this->zSum += it->first * it->second.getSize();
281      this->numVox += it->second.getSize();
282
283    }
284
285  }
286  //------------------------------------------------------
287
288  std::ostream& operator<< ( std::ostream& theStream, Object3D& obj)
289  {
290    for(std::map<long, Object2D>::iterator it = obj.chanlist.begin();
291        it!=obj.chanlist.end();it++){
292      for(int s=0;s<it->second.getNumScan();s++){
293        Scan tempscan = it->second.getScan(s);
294        theStream << tempscan << ", " << it->first << "\n";
295      }
296    } 
297    theStream << "\n";
298    return theStream;
299  }
300  //--------------------------------------------
301
302  std::vector<Voxel> Object3D::getPixelSet()
303  {
304    std::vector<Voxel> voxList(this->numVox);
305    long count = 0;
306    for(std::map<long, Object2D>::iterator it = this->chanlist.begin();
307        it!=this->chanlist.end();it++){
308      long z = it->first;
309      for(int s=0;s<it->second.getNumScan();s++){
310        Scan scn = it->second.getScan(s);
311        long y = scn.getY();
312        for(long x=scn.getX(); x<=scn.getXmax(); x++){
313          voxList[count].setXYZF(x,y,z,0);
314          count++;
315        }
316      }
317    }
318    return voxList;
319
320  }
321
322  //--------------------------------------------------------------------
323
324  std::vector<long> Object3D::getChannelList()
325  {
326
327    std::vector<long> chanlist;
328    for(std::map<long, Object2D>::iterator it = this->chanlist.begin();
329        it != this->chanlist.end(); it++){
330      chanlist.push_back(it->first);
331    }
332    return chanlist;
333  }
334
335  //--------------------------------------------------------------------
336
337  Object2D Object3D::getChanMap(long z)
338  {
339    Object2D obj;
340    std::map<long,Object2D>::iterator it=this->chanlist.begin();
341    while(it!=this->chanlist.end() && it->first!=z) it++;
342
343    if(it==this->chanlist.end()) obj = Object2D();
344    else obj = it->second;
345
346    return obj;
347  }
348
349  //--------------------------------------------------------------------
350
351  int Object3D::getMaxAdjacentChannels()
352  {
353    /// @details Find the maximum number of contiguous channels in the
354    /// object. Since there can be gaps in the channels included in an
355    /// object, we run through the list of channels and keep track of
356    /// sizes of contiguous segments. Then return the largest size.
357
358    int maxnumchan=0;
359    int zcurrent=0, zprevious,zcount=0;
360    std::map<long, Object2D>::iterator it;
361    for(it = this->chanlist.begin(); it!=this->chanlist.end();it++)
362      {
363        if(it==this->chanlist.begin()){
364          zcount++;
365          zcurrent = it->first;
366        }
367        else{
368          zprevious = zcurrent;
369          zcurrent = it->first;
370          if(zcurrent-zprevious>1){
371            maxnumchan = std::max(maxnumchan, zcount);
372            zcount=1;
373          }
374          else zcount++;
375        }
376      }
377    maxnumchan = std::max(maxnumchan,zcount);
378    return maxnumchan;
379  }
380
381  //--------------------------------------------------------------------
382
383  void Object3D::addOffsets(long xoff, long yoff, long zoff)
384  {
385    std::map<long,Object2D> newmap;
386    for(std::map<long, Object2D>::iterator it = this->chanlist.begin(); it!=this->chanlist.end();it++){
387      std::pair<long,Object2D> newOne(it->first+zoff, it->second);
388      newOne.second.addOffsets(xoff,yoff);
389      newmap.insert(newOne);
390    }
391    this->chanlist.clear();
392    this->chanlist = newmap;
393    if(this->numVox>0){
394      this->xSum += xoff*numVox;
395      this->xmin += xoff; this->xmax += xoff;
396      this->ySum += yoff*numVox;
397      this->ymin += yoff; this->ymax += yoff;
398      this->zSum += zoff*numVox;
399      this->zmin += zoff; this->zmax += zoff;
400    }
401  }
402
403
404  duchamp::Section Object3D::getBoundingSection(int boundary)
405  {
406    std::stringstream ss;
407    ss << "[" << this->xmin-boundary <<":"<<this->xmax+boundary<<","<< this->ymin-boundary <<":"<<this->ymax+boundary<<","<< this->zmin-boundary <<":"<<this->zmax+boundary<<"]";
408    std::string sec=ss.str();
409    duchamp::Section section(sec);
410    return section;
411  }
412
413}
Note: See TracBrowser for help on using the repository browser.