source: trunk/src/PixelMap/Scan.cc @ 773

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

A large number of changes made to the use of scanlist in Object2D. We now don't keep it sorted until it is printed out. We've made more use of iterators - this was to explore using a std::list instead of std::vector, but that seemed to be a lot slower. A new function in Scan, and better use of references in function calls as well.

File size: 8.0 KB
RevLine 
[301]1// -----------------------------------------------------------------------
2// Scan.cc: Member functions for the Scan 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// -----------------------------------------------------------------------
[393]28#include <duchamp/PixelMap/Scan.hh>
[238]29#include <iostream>
[505]30#include <math.h>
[238]31
[252]32namespace PixelInfo
[238]33{
34
[365]35  Scan::Scan()
36  {
37    this->itsY=-1;
38    this->itsX=-1;
39    this->itsXLen=0;
40  }
41
[770]42  Scan::Scan(long y, long x, long xl):
43    itsY(y), itsX(x),itsXLen(xl)
44  {
45  }
46
[270]47  Scan::Scan(const Scan& s)
48  {
[365]49    operator=(s);
[270]50  }
51  //------------------------------------------------------
52 
[770]53  Scan& Scan::operator= (const Scan& s)
54  {   
55    if(this == &s) return *this;
56    this->itsY=s.itsY;
57    this->itsX=s.itsX;
58    this->itsXLen=s.itsXLen;
59    return *this;
60  }
[270]61  //------------------------------------------------------
62
[773]63  bool Scan::addScan(const Scan &other)
64  {
65    bool altered=this->touches(other);
66    if(altered){
67      long x = std::min(this->itsX,other.itsX);
68      long xmax = std::max(this->itsX+this->itsXLen-1,other.itsX+other.itsXLen-1);
69      for(int ix=x;ix<this->itsX;ix++) this->growLeft();
70      for(int ix=this->itsX+this->itsXLen-1;ix<xmax;ix++) this->growRight();
71    }
72    return altered;
73  }
74
75
[252]76  Scan nullScan()
77  {
[528]78    /// A simple way of returning a scan with zero length.
[252]79    Scan null(-1,-1,0);
80    return null;
[243]81  }
[527]82
83  bool Scan::isNull()
84  {
85    return (itsY==-1 && itsX==-1 && itsXLen==0);
86  }
87
[252]88  //------------------------------------------------------
89
90  Scan unite(Scan &scan1, Scan &scan2)
91  {
[528]92    /// Return a scan that includes all pixels from both scans, but
93    /// only if they overlap. If they do not, return the null scan.
[252]94
95    Scan joined;
[527]96    if(!touching(scan1,scan2)){
[252]97      //     std::cerr << "Joining scans failed! ("
98      //              << scan1 <<"),("<<scan2<<") don't overlap\n";
99      joined = nullScan();
100    }
101    else{
102      long y = scan1.getY();
[527]103      long x = std::min(scan1.getX(),scan2.getX());
104      long xmax = std::max(scan1.getXmax(),scan2.getXmax());
[252]105      joined.define(y,x,xmax-x+1);
106    }
107    return joined;
[238]108  }
[244]109
[252]110  //------------------------------------------------------
[238]111
[252]112  Scan intersect(Scan &scan1, Scan &scan2)
113  {
[528]114    /// Return a scan that includes all pixels that lie in both scans.
115    ///
116    /// If they do not overlap, return the null scan.
[246]117
[252]118    Scan intersection;
[770]119    if(!scan1.overlaps(scan2)){
[252]120      intersection = nullScan();
121    }
122    else{
123      long y = scan1.getY();
[527]124      long x = std::max(scan1.getX(),scan2.getX());
125      long xmax = std::min(scan1.getXmax(),scan2.getXmax());
[252]126      intersection.define(y,x,xmax-x+1);
127    }
128    return intersection;
[238]129  }
[252]130  //------------------------------------------------------
[238]131
[773]132  bool Scan::touches(const Scan &other)
[770]133  {
134    return this->overlaps(other) || this->isAdjacentTo(other);
135  }
136
[773]137  bool Scan::overlaps(const Scan &other)
[770]138  {
139    if(this->itsY != other.itsY) return false;
140    else if(this->itsX <= other.itsX){
141      return (other.itsX < (this->itsX+this->itsXLen));
142    }
143    else{
144      return (this->itsX < (other.itsX+other.itsXLen));
145    }
146  }
147
[773]148  bool Scan::isAdjacentTo(const Scan &other)
[770]149  {
150    if(this->itsY != other.itsY) return false;
151    else if(this->itsX <= other.itsX){
152      return (this->itsX == (other.itsX+other.itsXLen));
153    }
154    else{
155      return (other.itsX == (this->itsX+this->itsXLen));
156    }
157  }
158  //------------------------------------------------------
159
[252]160  bool touching(Scan &scan1, Scan &scan2)
161  {
[528]162    ///  Test whether two scans either overlap, or lie adjacent
163    ///  (ie. there are no pixels lying between the two scans).
164    /// \return A bool value.
165
[527]166    return overlap(scan1,scan2) || adjacent(scan1,scan2);
[238]167 
[252]168  }
169  //------------------------------------------------------
[238]170
[252]171  bool overlap(Scan &scan1, Scan &scan2)
172  {
[528]173    ///  Test whether two scans overlap, ie. they have pixels in
174    ///  common.
175    /// \return A bool value.
176
[252]177    if(scan1.getY()!=scan2.getY()) return false;
178    else if(scan1.getX() <= scan2.getX())
179      return (scan2.getX() <= scan1.getXmax());
180    else
181      return (scan1.getX() <= scan2.getXmax());
[238]182 
[252]183  }
184  //------------------------------------------------------
[238]185
[252]186  bool adjacent(Scan &scan1, Scan &scan2)
187  {
[528]188     /// Test whether two scans lie adjacent (ie. there are no pixels
189     /// lying between the two scans).  If they overlap, return false.
190     /// \return A bool value.
191
[252]192    if(scan1.getY()!=scan2.getY()) return false;
193    else if(scan1.getX() <= scan2.getX())
194      return (scan2.getX() == scan1.getXmax()+1);
195    else
196      return (scan1.getX() == scan2.getXmax()+1);
[238]197 
[252]198  }
199  //------------------------------------------------------
[238]200
[252]201  std::ostream& operator<< ( std::ostream& theStream, Scan& scan)
202  {
[528]203    ///  Output the three key parameters of the scan.
204
[527]205    if(scan.isNull()) theStream << "NULL";
206    else{
207      theStream << scan.itsX;
208      theStream << "-" << scan.getXmax();
209      theStream << ", " << scan.itsY;
210    }
[270]211    return theStream;
[252]212  }
213  //------------------------------------------------------
[238]214
[252]215  bool operator< (Scan lhs, Scan rhs)
216  {
[528]217    /// Test for less-than first on the y-values, and if they are
218    /// equal, test on the starting x-value, and then finally on the
219    /// length.
220    ///
221    /// This is necessary for sorting functions on lists of Scans (used
222    /// by the Object2D class).
223
[252]224    if(lhs.itsY != rhs.itsY)      return (lhs.itsY    < rhs.itsY);
225    else if(lhs.itsX != rhs.itsX) return (lhs.itsX    < rhs.itsX);
226    else                          return (lhs.itsXLen < rhs.itsXLen);
227  }
228  //------------------------------------------------------
[238]229
[252]230  bool operator== (Scan lhs, Scan rhs)
231  {
[528]232    /// For two scans to be equal, all three parameters must be equal.
233
[252]234    return (lhs.itsY == rhs.itsY) &&
235      (lhs.itsX == rhs.itsX) &&
236      (lhs.itsXLen == rhs.itsXLen);
237  }
238  //------------------------------------------------------
[238]239
[252]240  bool Scan::isInScan(long x, long y)
241  {
242    return (y == this->itsY) &&
243      ( (x>= this->itsX) && (x < (this->itsXLen+this->itsX)) );
244  }
[253]245  //------------------------------------------------------
[252]246
[505]247  float minSep(Scan &s1, Scan &s2)
248  {
249 
250    if(s1.getX() > s2.getXmax()) return hypot(s1.getX()-s2.getXmax(),s1.getY()-s2.getY());
251    else if(s2.getX() > s1.getXmax()) return hypot(s2.getX()-s1.getXmax(),s1.getY()-s2.getY());
252    else return fabsf(s1.getY()-s2.getY());
253   
254  }
255  //------------------------------------------------------
256 
257 
[253]258  void mergeList(std::vector<Scan> scanlist)
259  {
260    std::vector<Scan>::iterator iter;
[541]261    unsigned int counter=0,compCounter;
[253]262    while(counter<(scanlist.size()-1)){
[252]263
[253]264     
265      compCounter = counter+1;
266     
267      do{
268       
269        if(touching(scanlist[counter],scanlist[compCounter])){
270          Scan temp = unite(scanlist[counter],scanlist[compCounter]);
271          iter = scanlist.begin()+compCounter;
272          scanlist.erase(iter);
273          iter = scanlist.begin()+counter;
274          scanlist.erase(iter);
275          scanlist.push_back(temp);
276        }
277        else compCounter ++;
278      }while(compCounter < scanlist.size());
279
280      counter++;
281    }
282
283  }
284
285
[238]286}
Note: See TracBrowser for help on using the repository browser.