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
Line 
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// -----------------------------------------------------------------------
28#include <duchamp/PixelMap/Scan.hh>
29#include <iostream>
30#include <math.h>
31
32namespace PixelInfo
33{
34
35  Scan::Scan()
36  {
37    this->itsY=-1;
38    this->itsX=-1;
39    this->itsXLen=0;
40  }
41
42  Scan::Scan(long y, long x, long xl):
43    itsY(y), itsX(x),itsXLen(xl)
44  {
45  }
46
47  Scan::Scan(const Scan& s)
48  {
49    operator=(s);
50  }
51  //------------------------------------------------------
52 
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  }
61  //------------------------------------------------------
62
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
76  Scan nullScan()
77  {
78    /// A simple way of returning a scan with zero length.
79    Scan null(-1,-1,0);
80    return null;
81  }
82
83  bool Scan::isNull()
84  {
85    return (itsY==-1 && itsX==-1 && itsXLen==0);
86  }
87
88  //------------------------------------------------------
89
90  Scan unite(Scan &scan1, Scan &scan2)
91  {
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.
94
95    Scan joined;
96    if(!touching(scan1,scan2)){
97      //     std::cerr << "Joining scans failed! ("
98      //              << scan1 <<"),("<<scan2<<") don't overlap\n";
99      joined = nullScan();
100    }
101    else{
102      long y = scan1.getY();
103      long x = std::min(scan1.getX(),scan2.getX());
104      long xmax = std::max(scan1.getXmax(),scan2.getXmax());
105      joined.define(y,x,xmax-x+1);
106    }
107    return joined;
108  }
109
110  //------------------------------------------------------
111
112  Scan intersect(Scan &scan1, Scan &scan2)
113  {
114    /// Return a scan that includes all pixels that lie in both scans.
115    ///
116    /// If they do not overlap, return the null scan.
117
118    Scan intersection;
119    if(!scan1.overlaps(scan2)){
120      intersection = nullScan();
121    }
122    else{
123      long y = scan1.getY();
124      long x = std::max(scan1.getX(),scan2.getX());
125      long xmax = std::min(scan1.getXmax(),scan2.getXmax());
126      intersection.define(y,x,xmax-x+1);
127    }
128    return intersection;
129  }
130  //------------------------------------------------------
131
132  bool Scan::touches(const Scan &other)
133  {
134    return this->overlaps(other) || this->isAdjacentTo(other);
135  }
136
137  bool Scan::overlaps(const Scan &other)
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
148  bool Scan::isAdjacentTo(const Scan &other)
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
160  bool touching(Scan &scan1, Scan &scan2)
161  {
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
166    return overlap(scan1,scan2) || adjacent(scan1,scan2);
167 
168  }
169  //------------------------------------------------------
170
171  bool overlap(Scan &scan1, Scan &scan2)
172  {
173    ///  Test whether two scans overlap, ie. they have pixels in
174    ///  common.
175    /// \return A bool value.
176
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());
182 
183  }
184  //------------------------------------------------------
185
186  bool adjacent(Scan &scan1, Scan &scan2)
187  {
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
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);
197 
198  }
199  //------------------------------------------------------
200
201  std::ostream& operator<< ( std::ostream& theStream, Scan& scan)
202  {
203    ///  Output the three key parameters of the scan.
204
205    if(scan.isNull()) theStream << "NULL";
206    else{
207      theStream << scan.itsX;
208      theStream << "-" << scan.getXmax();
209      theStream << ", " << scan.itsY;
210    }
211    return theStream;
212  }
213  //------------------------------------------------------
214
215  bool operator< (Scan lhs, Scan rhs)
216  {
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
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  //------------------------------------------------------
229
230  bool operator== (Scan lhs, Scan rhs)
231  {
232    /// For two scans to be equal, all three parameters must be equal.
233
234    return (lhs.itsY == rhs.itsY) &&
235      (lhs.itsX == rhs.itsX) &&
236      (lhs.itsXLen == rhs.itsXLen);
237  }
238  //------------------------------------------------------
239
240  bool Scan::isInScan(long x, long y)
241  {
242    return (y == this->itsY) &&
243      ( (x>= this->itsX) && (x < (this->itsXLen+this->itsX)) );
244  }
245  //------------------------------------------------------
246
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 
258  void mergeList(std::vector<Scan> scanlist)
259  {
260    std::vector<Scan>::iterator iter;
261    unsigned int counter=0,compCounter;
262    while(counter<(scanlist.size()-1)){
263
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
286}
Note: See TracBrowser for help on using the repository browser.