source: trunk/src/PixelMap/Object3D.cc @ 658

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

Fixed a bug in addOffsets that didn't add some offsets.

Also made a new function to return a subsection that bounds the object.

File size: 12.1 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    int maxnumchan=0;
354    int zcurrent, zprevious,zcount=0;
355    std::map<long, Object2D>::iterator it = this->chanlist.begin();
356    zcurrent = it->first;
357    zcount++;
358    it++;
359    for(; it!=this->chanlist.end();it++)
360      {
361        zprevious = zcurrent;
362        zcurrent = it->first;
363        if(zcurrent-zprevious>1){
364          maxnumchan = std::max(maxnumchan, zcount);
365          zcount=1;
366        }
367        else zcount++;
368      }
369    maxnumchan = std::max(maxnumchan,zcount);
370    return maxnumchan;
371  }
372
373  //--------------------------------------------------------------------
374
375  void Object3D::addOffsets(long xoff, long yoff, long zoff)
376  {
377    std::map<long,Object2D> newmap;
378    for(std::map<long, Object2D>::iterator it = this->chanlist.begin(); it!=this->chanlist.end();it++){
379      std::pair<long,Object2D> newOne(it->first+zoff, it->second);
380      newOne.second.addOffsets(xoff,yoff);
381      newmap.insert(newOne);
382    }
383    this->chanlist.clear();
384    this->chanlist = newmap;
385    if(this->numVox>0){
386      this->xSum += xoff*numVox;
387      this->xmin += xoff; this->xmax += xoff;
388      this->ySum += yoff*numVox;
389      this->ymin += yoff; this->ymax += yoff;
390      this->zSum += zoff*numVox;
391      this->zmin += zoff; this->zmax += zoff;
392    }
393  }
394
395
396  duchamp::Section Object3D::getBoundingSection(int boundary)
397  {
398    std::stringstream ss;
399    ss << "[" << this->xmin-boundary <<":"<<this->xmax+boundary<<","<< this->ymin-boundary <<":"<<this->ymax+boundary<<","<< this->zmin-boundary <<":"<<this->zmax+boundary<<"]";
400    std::string sec=ss.str();
401    duchamp::Section section(sec);
402    return section;
403  }
404
405}
Note: See TracBrowser for help on using the repository browser.