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

Last change on this file since 482 was 478, checked in by MatthewWhiting, 16 years ago

Fixed a bug in the WCS conversions that led to crashes if no spectral axis was specified.

File size: 13.4 KB
Line 
1// -----------------------------------------------------------------------
2// Object3D.cc: Member functions for Object3D and ChanMap classes.
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 <duchamp/PixelMap/Voxel.hh>
30#include <duchamp/PixelMap/Scan.hh>
31#include <duchamp/PixelMap/Object2D.hh>
32#include <duchamp/PixelMap/Object3D.hh>
33#include <vector>
34
35namespace PixelInfo
36{
37
38  ChanMap::ChanMap()
39  {
40    this->itsZ = -1;
41  }
42
43  ChanMap::ChanMap(const ChanMap& m){
44    operator=(m);
45  }
46
47  ChanMap& ChanMap::operator= (const ChanMap& m)
48  {
49    if(this == &m) return *this;
50    this->itsZ=m.itsZ;
51    this->itsObject=m.itsObject;
52    return *this;
53  }
54  //--------------------------------------------
55  //============================================
56  //--------------------------------------------
57
58  Object3D::Object3D()
59  {
60    this->numVox=0;
61  }
62
63  Object3D::Object3D(const Object3D& o)
64  {
65    operator=(o);
66  }
67  //--------------------------------------------
68
69  Object3D& Object3D::operator= (const Object3D& o)
70  {
71    if(this == &o) return *this;
72    this->maplist = o.maplist;
73    this->numVox  = o.numVox;
74    this->xSum    = o.xSum;
75    this->ySum    = o.ySum;
76    this->zSum    = o.zSum;
77    this->xmin    = o.xmin;
78    this->ymin    = o.ymin;
79    this->zmin    = o.zmin;
80    this->xmax    = o.xmax;
81    this->ymax    = o.ymax;
82    this->zmax    = o.zmax;
83    return *this;
84  }
85  //--------------------------------------------
86 
87  bool Object3D::isInObject(long x, long y, long z)
88  {
89    bool returnval = false;
90    int mapCount = 0;
91    while(!returnval && mapCount < this->maplist.size()){
92      if(z == this->maplist[mapCount].itsZ){
93        returnval = returnval ||
94          this->maplist[mapCount].itsObject.isInObject(x,y);
95      }
96      mapCount++;
97    }
98    return returnval;
99  }
100  //--------------------------------------------
101
102  void Object3D::addPixel(long x, long y, long z)
103  {
104    // first test to see if we have a chanmap of same z
105    bool haveZ = false;
106    int mapCount = 0;
107    while(!haveZ && mapCount < this->maplist.size()){
108      haveZ = haveZ || (z==this->maplist[mapCount++].itsZ);
109    }
110
111    if(!haveZ){ // need to add a new ChanMap
112      ChanMap newMap(z);
113      newMap.itsObject.addPixel(x,y);
114      this->maplist.push_back(newMap);
115      this->order();
116      // update the centres, min & max, as well as the number of voxels
117      if(this->numVox==0){
118        this->xSum = this->xmin = this->xmax = x;
119        this->ySum = this->ymin = this->ymax = y;
120        this->zSum = this->zmin = this->zmax = z;
121      }
122      else{
123        this->xSum += x;
124        this->ySum += y;
125        this->zSum += z;
126        if(x<this->xmin) this->xmin = x;
127        if(x>this->xmax) this->xmax = x;
128        if(y<this->ymin) this->ymin = y;
129        if(y>this->ymax) this->ymax = y;
130        // since we've ordered the maplist, the min & max z fall out
131        // naturally
132        this->zmin = this->maplist[0].itsZ;
133        this->zmax = this->maplist[this->maplist.size()-1].itsZ;
134      }
135      this->numVox++;   
136    }
137    else{
138      // there is a ChanMap of matching z. Find it..
139      mapCount=0;
140      while(this->maplist[mapCount].itsZ!=z) mapCount++;
141
142      // Remove that channel's information from the Object's information
143      long oldChanSize = this->maplist[mapCount].itsObject.numPix;
144      this->xSum -= this->maplist[mapCount].itsObject.xSum;
145      this->ySum -= this->maplist[mapCount].itsObject.ySum;
146      this->zSum -= z*oldChanSize;
147
148      // Add the channel
149      this->maplist[mapCount].itsObject.addPixel(x,y);
150   
151      // and update the information...
152      // This method deals with the case of a new pixel being added AND
153      // with the new pixel already existing in the Object2D
154      long newChanSize = this->maplist[mapCount].itsObject.numPix;
155   
156      this->numVox += (newChanSize - oldChanSize);
157      this->xSum += this->maplist[mapCount].itsObject.xSum;
158      this->ySum += this->maplist[mapCount].itsObject.ySum;
159      this->zSum += z*newChanSize;
160      if(x<this->xmin) this->xmin = x;
161      if(x>this->xmax) this->xmax = x;
162      if(y<this->ymin) this->ymin = y;
163      if(y>this->ymax) this->ymax = y;
164      // don't need to do anything to zmin/zmax -- the z-value is
165      // already in the list
166    }
167
168  }
169  //--------------------------------------------
170
171  void Object3D::addScan(Scan s, long z)
172  {
173    long y=s.getY();
174    for(int x=s.getX(); x<=s.getXmax(); x++)
175      this->addPixel(x,y,z);
176  }
177
178  //--------------------------------------------
179
180  void Object3D::addChannel(ChanMap channel)
181  {
182    // first test to see if we have a chanmap of same z
183    bool haveZ = false;
184    int mapCount = 0;
185    while( !haveZ && (mapCount < this->maplist.size()) ){
186      haveZ = haveZ || (channel.itsZ==this->maplist[mapCount].itsZ);
187      mapCount++;
188    }
189
190    if(!haveZ){ // need to add a new ChanMap
191      this->maplist.push_back(channel);
192      this->order();
193      // update the centres, min & max, as well as the number of voxels
194      if(this->numVox==0){ // ie. if it is the only channel map
195        this->xSum = channel.itsObject.xSum;
196        this->xmin = channel.itsObject.xmin;
197        this->xmax = channel.itsObject.xmax;
198        this->ySum = channel.itsObject.ySum;
199        this->ymin = channel.itsObject.ymin;
200        this->ymax = channel.itsObject.ymax;
201        this->zSum = channel.itsObject.numPix*channel.itsZ;
202        this->zmin = this->zmax = channel.itsZ;
203      }
204      else{
205        this->xSum += channel.itsObject.xSum;
206        this->ySum += channel.itsObject.ySum;
207        this->zSum += channel.itsZ*channel.itsObject.numPix;
208        if(channel.itsObject.xmin<this->xmin)
209          this->xmin = channel.itsObject.xmin;
210        if(channel.itsObject.xmax>this->xmax)
211          this->xmax = channel.itsObject.xmax;
212        if(channel.itsObject.ymin<this->ymin)
213          this->ymin = channel.itsObject.ymin;
214        if(channel.itsObject.ymax>this->ymax)
215          this->ymax = channel.itsObject.ymax;
216        // since we've ordered the maplist, the min & max z fall out
217        // naturally
218        this->zmin = this->maplist[0].itsZ;
219        this->zmax = this->maplist[this->maplist.size()-1].itsZ;
220      }
221      this->numVox += channel.itsObject.numPix;
222    }
223    else{
224      // there is a ChanMap of matching z. Find it and add the channel
225      // map to the correct existing channel map
226      mapCount=0; 
227      while(this->maplist[mapCount].itsZ!=channel.itsZ) mapCount++;
228
229      // Remove the new channel's information from the Object's information
230      long oldChanSize = this->maplist[mapCount].itsObject.numPix;
231      this->xSum -= this->maplist[mapCount].itsObject.xSum;
232      this->ySum -= this->maplist[mapCount].itsObject.ySum;
233      this->zSum -= this->maplist[mapCount].itsZ*oldChanSize;
234
235      // Delete the old map and add the new one on the end. Order the list.
236      ChanMap newMap = this->maplist[mapCount] + channel;
237      std::vector <ChanMap>::iterator iter;
238      iter = this->maplist.begin() + mapCount;
239      this->maplist.erase(iter);
240      this->maplist.push_back(newMap);
241      this->order();   
242
243      // and update the information...
244      // This method deals correctly with all cases of adding an object.
245      long newChanSize = newMap.itsObject.numPix;
246      this->numVox += (newChanSize - oldChanSize);
247      this->xSum += newMap.itsObject.xSum;
248      this->ySum += newMap.itsObject.ySum;
249      this->zSum += newMap.itsZ*newChanSize;
250      if(channel.itsObject.xmin<this->xmin) this->xmin = channel.itsObject.xmin;
251      if(channel.itsObject.xmax>this->xmax) this->xmax = channel.itsObject.xmax;
252      if(channel.itsObject.ymin<this->ymin) this->ymin = channel.itsObject.ymin;
253      if(channel.itsObject.ymax>this->ymax) this->ymax = channel.itsObject.ymax;
254      // don't need to do anything to zmin/zmax -- the z-value is
255      // already in the list
256
257    }
258
259  }
260  //--------------------------------------------
261 
262  void Object3D::order(){
263    std::vector<ChanMap>::iterator map;
264    for(map=maplist.begin();map<maplist.end();map++) map->itsObject.order();
265    std::stable_sort(maplist.begin(),maplist.end());
266  }
267  //--------------------------------------------
268
269  long Object3D::getNumDistinctZ()
270  {
271    return this->maplist.size();
272  }
273  //--------------------------------------------
274
275  long Object3D::getSpatialSize()
276  {
277    Object2D spatialMap;
278    for(int i=0;i<this->maplist.size();i++){
279      for(int s=0;s<this->maplist[i].itsObject.getNumScan();s++){
280        spatialMap.addScan(this->maplist[i].itsObject.getScan(s));
281      }
282    }
283    return spatialMap.getSize();
284  }
285  //--------------------------------------------
286
287  Object2D Object3D::getSpatialMap()
288  {
289    Object2D spatialMap = this->maplist[0].itsObject;
290    for(int i=1;i<this->maplist.size();i++){
291      spatialMap = spatialMap + this->maplist[i].itsObject;
292    }
293    return spatialMap;
294  }
295  //--------------------------------------------
296 
297  void Object3D::calcParams()
298  {
299    this->xSum = 0;
300    this->ySum = 0;
301    this->zSum = 0;
302    for(int m=0;m<this->maplist.size();m++){
303
304      this->maplist[m].itsObject.calcParams();
305
306      if(m==0){
307        this->xmin = this->maplist[m].itsObject.getXmin();
308        this->xmax = this->maplist[m].itsObject.getXmax();
309        this->ymin = this->maplist[m].itsObject.getYmin();
310        this->ymax = this->maplist[m].itsObject.getYmax();
311        this->zmin = this->zmax = this->maplist[m].itsZ;
312      }
313      else{
314        if(this->xmin>this->maplist[m].itsObject.getXmin())
315          this->xmin = this->maplist[m].itsObject.getXmin();
316        if(this->xmax<this->maplist[m].itsObject.getXmax())
317          this->xmax = this->maplist[m].itsObject.getXmax();
318        if(this->ymin>this->maplist[m].itsObject.getYmin())
319          this->ymin = this->maplist[m].itsObject.getYmin();
320        if(this->ymax<this->maplist[m].itsObject.getYmax())
321          this->ymax = this->maplist[m].itsObject.getYmax();
322        if(this->zmin>this->maplist[m].itsZ) this->zmin = this->maplist[m].itsZ;
323        if(this->zmax<this->maplist[m].itsZ) this->zmax = this->maplist[m].itsZ;
324      }
325
326      long size = this->maplist[m].itsObject.getSize();
327      this->xSum += this->maplist[m].itsObject.xSum;
328      this->ySum += this->maplist[m].itsObject.ySum;
329      this->zSum += this->maplist[m].itsZ * size;
330
331    }
332
333  }
334  //------------------------------------------------------
335
336  std::ostream& operator<< ( std::ostream& theStream, Object3D& obj)
337  {
338    std::vector<ChanMap>::iterator map;
339    for(map=obj.maplist.begin();map<obj.maplist.end();map++){
340      Object2D tempObject = map->getObject();
341      for(int s=0;s<tempObject.getNumScan();s++){
342        Scan tempscan = tempObject.getScan(s);
343        theStream << tempscan << ", " << map->getZ() << "\n";
344      }
345    } 
346    theStream << "\n";
347    return theStream;
348  }
349  //--------------------------------------------
350
351  Voxel Object3D::getPixel(int pixNum)
352  {
353    Voxel returnVox(-1,-1,-1,0.);
354    if((pixNum<0)||(pixNum>=this->getSize())) return returnVox;
355    int count1=0;
356    for(int m=0;m<this->maplist.size();m++)
357      {
358        if(pixNum-count1<this->maplist[m].itsObject.getSize())
359          {
360            returnVox.setZ(this->maplist[m].getZ());
361            int count2=0;
362            for(int s=0;s<this->maplist[m].getNumScan();s++)
363              {
364                if(pixNum-count1-count2<this->maplist[m].getScan(s).getXlen())
365                  {
366                    returnVox.setY(this->maplist[m].getScan(s).getY());
367                    returnVox.setX(this->maplist[m].getScan(s).getX()
368                                   + pixNum - count1 - count2);
369                    return returnVox;
370                  }
371                count2+=this->maplist[m].getScan(s).getXlen();
372              }
373          }
374        count1+=this->maplist[m].itsObject.getSize();     
375      }
376    return returnVox;
377  }
378  //--------------------------------------------------------------------
379
380  std::vector<Voxel> Object3D::getPixelSet()
381  {
382    std::vector<Voxel> voxList(this->numVox);
383    long count = 0;
384    for(int m=0;m<this->maplist.size();m++){
385      Object2D obj = this->maplist[m].itsObject;
386      long z = this->maplist[m].itsZ;
387      for(int s=0;s<obj.getNumScan();s++){
388        Scan scn = obj.getScan(s);
389        long y = scn.getY();
390        for(long x=scn.getX(); x<=scn.getXmax(); x++){
391          voxList[count].setXYZF(x,y,z,0);
392          count++;
393        }
394      }
395    }
396    return voxList;
397
398  }
399
400  //--------------------------------------------------------------------
401
402  void ChanMap::addOffsets(long xoff, long yoff, long zoff)
403  {
404    this->itsZ += zoff;
405    this->itsObject.addOffsets(xoff,yoff);
406  }
407 
408  //--------------------------------------------------------------------
409
410  void Object3D::addOffsets(long xoff, long yoff, long zoff)
411  {
412    for(unsigned int i=0;i<this->maplist.size();i++)
413      this->maplist[i].addOffsets(xoff,yoff,zoff);
414    this->xSum += xoff*numVox;
415    this->xmin += xoff; xmax += xoff;
416    this->ySum += yoff*numVox;
417    this->ymin += yoff; ymax += yoff;
418    this->zSum += zoff*numVox;
419    this->zmin += zoff; zmax += zoff;
420  }
421
422}
Note: See TracBrowser for help on using the repository browser.