[301] | 1 | // ----------------------------------------------------------------------- |
---|
| 2 | // Object2D.cc: Member functions for the Object2D 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 | // ----------------------------------------------------------------------- |
---|
[619] | 28 | #include <duchamp/PixelMap/Object2D.hh> |
---|
[393] | 29 | #include <duchamp/PixelMap/Scan.hh> |
---|
| 30 | #include <duchamp/PixelMap/Voxel.hh> |
---|
[238] | 31 | #include <iostream> |
---|
| 32 | #include <vector> |
---|
[773] | 33 | #include <list> |
---|
[469] | 34 | #include <algorithm> |
---|
| 35 | #include <math.h> |
---|
[238] | 36 | |
---|
[252] | 37 | namespace PixelInfo |
---|
| 38 | { |
---|
[243] | 39 | |
---|
[365] | 40 | Object2D::Object2D() |
---|
| 41 | { |
---|
| 42 | this->numPix = 0; |
---|
| 43 | } |
---|
| 44 | |
---|
[252] | 45 | Object2D::Object2D(const Object2D& o) |
---|
| 46 | { |
---|
[365] | 47 | operator=(o); |
---|
[252] | 48 | } |
---|
[243] | 49 | |
---|
[252] | 50 | Object2D& Object2D::operator= (const Object2D& o) |
---|
| 51 | { |
---|
[270] | 52 | if(this == &o) return *this; |
---|
[252] | 53 | this->scanlist = o.scanlist; |
---|
| 54 | this->numPix = o.numPix; |
---|
| 55 | this->xSum = o.xSum; |
---|
| 56 | this->ySum = o.ySum; |
---|
| 57 | this->xmin = o.xmin; |
---|
| 58 | this->ymin = o.ymin; |
---|
| 59 | this->xmax = o.xmax; |
---|
| 60 | this->ymax = o.ymax; |
---|
[270] | 61 | return *this; |
---|
[252] | 62 | } |
---|
| 63 | //------------------------------------------------------ |
---|
[238] | 64 | |
---|
[577] | 65 | Object2D operator+ (Object2D lhs, Object2D rhs) |
---|
| 66 | { |
---|
| 67 | Object2D output = lhs; |
---|
[773] | 68 | for(std::vector<Scan>::iterator s=rhs.scanlist.begin();s!=rhs.scanlist.end();s++) |
---|
| 69 | output.addScan(*s); |
---|
| 70 | // for(size_t s=0;s<rhs.scanlist.size();s++) output.addScan(rhs.scanlist[s]); |
---|
[577] | 71 | return output; |
---|
| 72 | } |
---|
| 73 | |
---|
| 74 | //------------------------------------------------------ |
---|
[770] | 75 | void Object2D::addPixel(long &x, long &y) |
---|
[252] | 76 | { |
---|
[528] | 77 | /// This function has three parts to it: |
---|
| 78 | /// <ul><li> First, it searches through the existing scans to see if |
---|
| 79 | /// a) there is a scan of the same y-value present, and |
---|
| 80 | /// b) whether the (x,y) pixel lies in or next to an existing |
---|
| 81 | /// Scan. If so, it is added and the Scan is grown if need be. |
---|
| 82 | /// If this isn't the case, a new Scan of length 1 is added to |
---|
| 83 | /// the list. |
---|
| 84 | /// <li> If the Scan list was altered, all are checked to see whether |
---|
| 85 | /// there is now a case of Scans touching. If so, they are |
---|
| 86 | /// combined and added to the end of the list. |
---|
| 87 | /// <li> If the pixel was added, the parameters are updated and the |
---|
| 88 | /// pixel counter incremented. |
---|
| 89 | /// </ul> |
---|
[238] | 90 | |
---|
| 91 | |
---|
[252] | 92 | bool flagDone=false,flagChanged=false, isNew=false; |
---|
| 93 | |
---|
[773] | 94 | // size_t scanCount = 0, size=this->scanlist.size(); |
---|
| 95 | // while(!flagDone && (scanCount<size) ){ |
---|
| 96 | // if(y == this->scanlist[scanCount].itsY){ // if the y value is already in the list |
---|
| 97 | // if(this->scanlist[scanCount].isInScan(x,y)) flagDone = true; // pixel already here. |
---|
| 98 | // else{ // it's a new pixel! |
---|
| 99 | // if((x==(this->scanlist[scanCount].itsX-1)) || (x == (this->scanlist[scanCount].getXmax()+1)) ){ |
---|
| 100 | // // if it is adjacent to the existing range, add to that range |
---|
| 101 | // if(x==(this->scanlist[scanCount].itsX-1)) this->scanlist[scanCount].growLeft(); |
---|
| 102 | // else this->scanlist[scanCount].growRight(); |
---|
| 103 | // flagDone = true; |
---|
| 104 | // flagChanged = true; |
---|
| 105 | // isNew = true; |
---|
| 106 | // } |
---|
| 107 | // } |
---|
| 108 | // } |
---|
| 109 | // scanCount++; |
---|
| 110 | // } |
---|
| 111 | for (std::vector<Scan>::iterator scan=this->scanlist.begin(); !flagDone && scan!=this->scanlist.end(); scan++){ |
---|
| 112 | if(y == scan->itsY){ // if the y value is already in the list |
---|
| 113 | if(scan->isInScan(x,y)) flagDone = true; // pixel already here. |
---|
[252] | 114 | else{ // it's a new pixel! |
---|
[773] | 115 | if((x==(scan->itsX-1)) || (x == (scan->getXmax()+1)) ){ |
---|
[252] | 116 | // if it is adjacent to the existing range, add to that range |
---|
[773] | 117 | if(x==(scan->itsX-1)) scan->growLeft(); |
---|
| 118 | else scan->growRight(); |
---|
[252] | 119 | flagDone = true; |
---|
| 120 | flagChanged = true; |
---|
| 121 | isNew = true; |
---|
[238] | 122 | } |
---|
[252] | 123 | } |
---|
[239] | 124 | } |
---|
[238] | 125 | } |
---|
| 126 | |
---|
[744] | 127 | if(!flagDone){ |
---|
| 128 | // we got to the end of the scanlist, so there is no pre-existing scan with this y value |
---|
| 129 | // add a new scan consisting of just this pixel |
---|
[252] | 130 | Scan newOne(y,x,1); |
---|
| 131 | this->scanlist.push_back(newOne); |
---|
[773] | 132 | // if(this->scanlist.size()>1) this->order(); |
---|
[252] | 133 | isNew = true; |
---|
| 134 | } |
---|
[744] | 135 | else if(flagChanged){ |
---|
[252] | 136 | // this is true only if one of the pre-existing scans has changed |
---|
| 137 | // |
---|
| 138 | // need to clean up, to see if there is a case of two scans when |
---|
[744] | 139 | // there should be one. Only need to look at scans with matching |
---|
| 140 | // y-value |
---|
[252] | 141 | // |
---|
| 142 | // because there has been only one pixel added, only 2 AT MOST |
---|
| 143 | // scans will need to be combined, so once we meet a pair that |
---|
| 144 | // overlap, we can finish. |
---|
[238] | 145 | |
---|
[252] | 146 | bool combined = false; |
---|
[773] | 147 | // int size = this->scanlist.size(); |
---|
| 148 | // int count1=0; |
---|
| 149 | // while(!combined && count1<size){ |
---|
| 150 | // if(this->scanlist[count1].itsY==y){ |
---|
| 151 | // int count2 = count1 + 1; |
---|
| 152 | // while(!combined && count2<size){ |
---|
| 153 | // if(this->scanlist[count2].itsY==y){ |
---|
| 154 | // combined = touching(this->scanlist[count1], this->scanlist[count2]); |
---|
| 155 | // if(combined){ |
---|
| 156 | // for(int i=0;i<this->scanlist[count2].getXlen();i++) this->scanlist[count1].growRight(); |
---|
| 157 | // iter = this->scanlist.begin() + count2; |
---|
| 158 | // this->scanlist.erase(iter); |
---|
| 159 | // } |
---|
| 160 | // } |
---|
| 161 | // count2++; |
---|
| 162 | // } |
---|
| 163 | // } |
---|
| 164 | // count1++; |
---|
| 165 | // } |
---|
| 166 | std::vector<Scan>::iterator scan1=this->scanlist.begin(),scan2; |
---|
| 167 | for (; !combined && scan1!=this->scanlist.end(); scan1++){ |
---|
| 168 | if(scan1->itsY==y){ |
---|
| 169 | scan2=scan1; |
---|
| 170 | scan2++; |
---|
| 171 | for(; !combined && scan2!=this->scanlist.end(); scan2++){ |
---|
| 172 | if(scan2->itsY==y){ |
---|
| 173 | combined = touching(*scan1,*scan2); |
---|
[744] | 174 | if(combined){ |
---|
[773] | 175 | // for(int i=0;i<scan2->getXlen();i++) scan1->growRight(); |
---|
| 176 | scan1->addScan(*scan2); |
---|
| 177 | this->scanlist.erase(scan2); |
---|
[744] | 178 | } |
---|
| 179 | } |
---|
| 180 | } |
---|
[252] | 181 | } |
---|
| 182 | } |
---|
| 183 | |
---|
[246] | 184 | } |
---|
[252] | 185 | |
---|
| 186 | if(isNew){ |
---|
| 187 | // update the centres, mins, maxs and increment the pixel counter |
---|
| 188 | if(this->numPix==0){ |
---|
| 189 | this->xSum = this->xmin = this->xmax = x; |
---|
| 190 | this->ySum = this->ymin = this->ymax = y; |
---|
| 191 | } |
---|
| 192 | else{ |
---|
| 193 | this->xSum += x; |
---|
| 194 | this->ySum += y; |
---|
| 195 | if(x<this->xmin) this->xmin = x; |
---|
| 196 | if(x>this->xmax) this->xmax = x; |
---|
| 197 | if(y<this->ymin) this->ymin = y; |
---|
| 198 | if(y>this->ymax) this->ymax = y; |
---|
| 199 | } |
---|
| 200 | this->numPix++; |
---|
[246] | 201 | } |
---|
[252] | 202 | |
---|
[246] | 203 | } |
---|
[252] | 204 | //------------------------------------------------------ |
---|
[246] | 205 | |
---|
[773] | 206 | void Object2D::addScan(Scan &scan) |
---|
[252] | 207 | { |
---|
[770] | 208 | long y=scan.getY(); |
---|
| 209 | for(long x=scan.getX();x<=scan.getXmax();x++) this->addPixel(x,y); |
---|
[238] | 210 | |
---|
[577] | 211 | } |
---|
[252] | 212 | //------------------------------------------------------ |
---|
[238] | 213 | |
---|
[252] | 214 | bool Object2D::isInObject(long x, long y) |
---|
| 215 | { |
---|
[371] | 216 | |
---|
[667] | 217 | std::vector<Scan>::iterator scn; |
---|
| 218 | bool returnval=false; |
---|
[773] | 219 | for(scn=this->scanlist.begin();scn!=this->scanlist.end()&&!returnval;scn++){ |
---|
[238] | 220 | |
---|
[667] | 221 | returnval = ((y == scn->itsY) && (x>= scn->itsX) && (x<=scn->getXmax())); |
---|
[238] | 222 | |
---|
[667] | 223 | } |
---|
| 224 | |
---|
| 225 | return returnval; |
---|
[238] | 226 | |
---|
[252] | 227 | } |
---|
| 228 | //------------------------------------------------------ |
---|
[238] | 229 | |
---|
[252] | 230 | std::ostream& operator<< ( std::ostream& theStream, Object2D& obj) |
---|
| 231 | { |
---|
[773] | 232 | if(obj.scanlist.size()>1) obj.order(); |
---|
| 233 | // for(size_t i=0;i<obj.scanlist.size();i++) |
---|
| 234 | // theStream << obj.scanlist[i] << "\n"; |
---|
| 235 | for(std::vector<Scan>::iterator s=obj.scanlist.begin();s!=obj.scanlist.end();s++) |
---|
| 236 | theStream << *s << "\n"; |
---|
[252] | 237 | theStream<<"---\n"; |
---|
[270] | 238 | return theStream; |
---|
[238] | 239 | |
---|
[252] | 240 | } |
---|
| 241 | //------------------------------------------------------ |
---|
[238] | 242 | |
---|
[252] | 243 | void Object2D::calcParams() |
---|
| 244 | { |
---|
| 245 | this->xSum = 0; |
---|
| 246 | this->ySum = 0; |
---|
[623] | 247 | std::vector<Scan>::iterator s; |
---|
[773] | 248 | for(s=this->scanlist.begin();s!=this->scanlist.end();s++){ |
---|
[238] | 249 | |
---|
[623] | 250 | if(s==this->scanlist.begin()){ |
---|
| 251 | this->ymin = this->ymax = s->itsY; |
---|
| 252 | this->xmin = s->itsX; |
---|
| 253 | this->xmax = s->getXmax(); |
---|
[252] | 254 | } |
---|
| 255 | else{ |
---|
[623] | 256 | if(this->ymin>s->itsY) this->ymin = s->itsY; |
---|
| 257 | if(this->xmin>s->itsX) this->xmin = s->itsX; |
---|
| 258 | if(this->ymax<s->itsY) this->ymax = s->itsY; |
---|
| 259 | if(this->xmax<s->getXmax()) this->xmax = s->getXmax(); |
---|
[252] | 260 | } |
---|
[238] | 261 | |
---|
[623] | 262 | this->ySum += s->itsY*s->getXlen(); |
---|
| 263 | for(int x=s->itsX;x<=s->getXmax();x++) |
---|
[252] | 264 | this->xSum += x; |
---|
| 265 | |
---|
[238] | 266 | } |
---|
| 267 | |
---|
| 268 | } |
---|
[252] | 269 | //------------------------------------------------------ |
---|
[238] | 270 | |
---|
[252] | 271 | void Object2D::cleanup() |
---|
| 272 | { |
---|
[773] | 273 | // size_t counter=0, compCounter=1; |
---|
| 274 | // std::vector<Scan>::iterator iter; |
---|
| 275 | // while(counter < this->scanlist.size()) |
---|
| 276 | // { |
---|
| 277 | // compCounter = counter + 1; |
---|
[238] | 278 | |
---|
[773] | 279 | // while( compCounter < this->scanlist.size() ) { |
---|
[238] | 280 | |
---|
[773] | 281 | // Scan scan1 = this->scanlist[counter]; |
---|
| 282 | // Scan scan2 = this->scanlist[compCounter]; |
---|
| 283 | // if(overlap(scan1,scan2)){ |
---|
| 284 | // Scan newscan = unite(scan1,scan2); |
---|
| 285 | // iter = this->scanlist.begin()+compCounter; |
---|
| 286 | // this->scanlist.erase(iter); |
---|
| 287 | // iter = this->scanlist.begin()+counter; |
---|
| 288 | // this->scanlist.erase(iter); |
---|
| 289 | // this->scanlist.push_back(newscan); |
---|
| 290 | // compCounter = counter + 1; |
---|
| 291 | // } |
---|
| 292 | // else compCounter++; |
---|
[238] | 293 | |
---|
[773] | 294 | // } |
---|
[238] | 295 | |
---|
[773] | 296 | // counter++; |
---|
| 297 | // } |
---|
| 298 | std::vector<Scan>::iterator s1=this->scanlist.begin(),s2; |
---|
| 299 | for (; s1!=this->scanlist.end(); s1++){ |
---|
| 300 | s2=s1; s2++; |
---|
| 301 | for (; s2!=this->scanlist.end(); s2++){ |
---|
[238] | 302 | |
---|
[773] | 303 | if(overlap(*s1,*s2)){ |
---|
| 304 | s1->addScan(*s2); |
---|
| 305 | this->scanlist.erase(s2); |
---|
| 306 | } |
---|
| 307 | } |
---|
| 308 | } |
---|
| 309 | |
---|
[238] | 310 | } |
---|
[252] | 311 | //------------------------------------------------------ |
---|
[238] | 312 | |
---|
[252] | 313 | long Object2D::getNumDistinctY() |
---|
| 314 | { |
---|
| 315 | std::vector<long> ylist; |
---|
| 316 | if(this->scanlist.size()==0) return 0; |
---|
| 317 | if(this->scanlist.size()==1) return 1; |
---|
[773] | 318 | // ylist.push_back(this->scanlist[0].itsY); |
---|
[623] | 319 | std::vector<Scan>::iterator scn; |
---|
[773] | 320 | for(scn=this->scanlist.begin();scn!=this->scanlist.end();scn++){ |
---|
[238] | 321 | bool inList = false; |
---|
[541] | 322 | unsigned int j=0; |
---|
[623] | 323 | long y = scn->itsY; |
---|
[252] | 324 | while(!inList && j<ylist.size()){ |
---|
| 325 | if(y==ylist[j]) inList=true; |
---|
[238] | 326 | j++; |
---|
| 327 | }; |
---|
[252] | 328 | if(!inList) ylist.push_back(y); |
---|
[238] | 329 | } |
---|
[252] | 330 | return ylist.size(); |
---|
[238] | 331 | } |
---|
[252] | 332 | //------------------------------------------------------ |
---|
[238] | 333 | |
---|
[252] | 334 | long Object2D::getNumDistinctX() |
---|
| 335 | { |
---|
| 336 | std::vector<long> xlist; |
---|
| 337 | if(this->scanlist.size()==0) return 0; |
---|
| 338 | if(this->scanlist.size()==1) return 1; |
---|
[773] | 339 | // for(int x=this->scanlist[0].itsX;x<this->scanlist[0].getXmax();x++) |
---|
| 340 | // xlist.push_back(x); |
---|
[623] | 341 | std::vector<Scan>::iterator scn; |
---|
[773] | 342 | for(scn=this->scanlist.begin();scn!=this->scanlist.end();scn++){ |
---|
[623] | 343 | for(int x=scn->itsX;x<scn->getXmax();x++){ |
---|
[252] | 344 | bool inList = false; |
---|
[541] | 345 | unsigned int j=0; |
---|
[252] | 346 | while(!inList && j<xlist.size()){ |
---|
| 347 | if(x==xlist[j]) inList=true; |
---|
| 348 | j++; |
---|
| 349 | }; |
---|
| 350 | if(!inList) xlist.push_back(x); |
---|
| 351 | } |
---|
| 352 | } |
---|
| 353 | return xlist.size(); |
---|
[238] | 354 | } |
---|
[252] | 355 | //------------------------------------------------------ |
---|
| 356 | |
---|
[773] | 357 | bool Object2D::scanOverlaps(Scan &scan) |
---|
[252] | 358 | { |
---|
| 359 | bool returnval = false; |
---|
[773] | 360 | // unsigned int scanCount=0; |
---|
| 361 | for(std::vector<Scan>::iterator s=this->scanlist.begin();!returnval&&s!=this->scanlist.end();s++){ |
---|
| 362 | // while(!returnval && scanCount<this->scanlist.size()){ |
---|
| 363 | // returnval = returnval || overlap(scan,this->scanlist[scanCount++]); |
---|
| 364 | returnval = returnval || s->overlaps(scan); |
---|
[252] | 365 | } |
---|
| 366 | return returnval; |
---|
| 367 | } |
---|
| 368 | |
---|
[399] | 369 | //------------------------------------------------------ |
---|
| 370 | |
---|
| 371 | void Object2D::addOffsets(long xoff, long yoff) |
---|
| 372 | { |
---|
[623] | 373 | std::vector<Scan>::iterator scn; |
---|
[773] | 374 | for(scn=this->scanlist.begin();scn!=this->scanlist.end();scn++) |
---|
[623] | 375 | scn->addOffsets(xoff,yoff); |
---|
[399] | 376 | this->xSum += xoff*numPix; |
---|
| 377 | this->xmin += xoff; xmax += xoff; |
---|
| 378 | this->ySum += yoff*numPix; |
---|
| 379 | this->ymin += yoff; ymax += yoff; |
---|
| 380 | } |
---|
| 381 | |
---|
[469] | 382 | //------------------------------------------------------ |
---|
| 383 | |
---|
| 384 | double Object2D::getPositionAngle() |
---|
| 385 | { |
---|
| 386 | |
---|
| 387 | int sumxx=0; |
---|
| 388 | int sumyy=0; |
---|
| 389 | int sumxy=0; |
---|
| 390 | std::vector<Scan>::iterator scn=this->scanlist.begin(); |
---|
[773] | 391 | for(;scn!=this->scanlist.end();scn++){ |
---|
[469] | 392 | sumyy += (scn->itsY*scn->itsY)*scn->itsXLen; |
---|
| 393 | for(int x=scn->itsX;x<=scn->getXmax();x++){ |
---|
| 394 | sumxx += x*x; |
---|
| 395 | sumxy += x*scn->itsY; |
---|
| 396 | } |
---|
| 397 | } |
---|
| 398 | |
---|
| 399 | // Calculate net moments |
---|
| 400 | double mxx = sumxx - this->xSum*this->xSum / double(this->numPix); |
---|
| 401 | double myy = sumyy - this->ySum*this->ySum / double(this->numPix); |
---|
| 402 | double mxy = sumxy - this->xSum*this->ySum / double(this->numPix); |
---|
| 403 | |
---|
[472] | 404 | if(mxy==0){ |
---|
| 405 | if(mxx>myy) return M_PI/2.; |
---|
| 406 | else return 0.; |
---|
| 407 | } |
---|
[469] | 408 | |
---|
| 409 | // Angle of the minimum moment |
---|
| 410 | double tantheta = (mxx - myy + sqrt( (mxx-myy)*(mxx-myy) + 4.*mxy*mxy))/(2.*mxy); |
---|
| 411 | |
---|
| 412 | return atan(tantheta); |
---|
| 413 | } |
---|
| 414 | |
---|
| 415 | //------------------------------------------------------ |
---|
| 416 | |
---|
| 417 | std::pair<double,double> Object2D::getPrincipleAxes() |
---|
| 418 | { |
---|
| 419 | |
---|
[470] | 420 | double theta = this->getPositionAngle(); |
---|
[570] | 421 | double x0 = this->getXaverage(); |
---|
| 422 | double y0 = this->getYaverage(); |
---|
[469] | 423 | std::vector<double> majorAxes, minorAxes; |
---|
| 424 | std::vector<Scan>::iterator scn=this->scanlist.begin(); |
---|
[773] | 425 | for(;scn!=this->scanlist.end();scn++){ |
---|
[469] | 426 | for(int x=scn->itsX;x<=scn->getXmax();x++){ |
---|
[472] | 427 | majorAxes.push_back((x-x0+0.5)*cos(theta) + (scn->itsY-y0+0.5)*sin(theta)); |
---|
| 428 | minorAxes.push_back((x-x0+0.5)*sin(theta) + (scn->itsY-y0+0.5)*cos(theta)); |
---|
[469] | 429 | } |
---|
| 430 | } |
---|
| 431 | |
---|
| 432 | std::sort(majorAxes.begin(),majorAxes.end()); |
---|
| 433 | std::sort(minorAxes.begin(),minorAxes.end()); |
---|
| 434 | int size = majorAxes.size(); |
---|
| 435 | std::pair<double,double> axes; |
---|
| 436 | axes.first = fabs(majorAxes[0]-majorAxes[size-1]); |
---|
| 437 | axes.second = fabs(minorAxes[0]-minorAxes[size-1]); |
---|
[472] | 438 | if(axes.first<0.5) axes.first=0.5; |
---|
| 439 | if(axes.second<0.5) axes.second=0.5; |
---|
[469] | 440 | return axes; |
---|
| 441 | |
---|
| 442 | } |
---|
| 443 | |
---|
[770] | 444 | |
---|
| 445 | //------------------------------------------------------ |
---|
| 446 | |
---|
| 447 | |
---|
| 448 | bool Object2D::canMerge(Object2D &other, float threshS, bool flagAdj) |
---|
| 449 | { |
---|
| 450 | long gap; |
---|
| 451 | if(flagAdj) gap = 1; |
---|
| 452 | else gap = long( ceil(threshS) ); |
---|
| 453 | bool near = this->isNear(other,gap); |
---|
| 454 | if(near) return this->isClose(other,threshS,flagAdj); |
---|
| 455 | else return near; |
---|
| 456 | } |
---|
| 457 | |
---|
| 458 | //------------------------------------------------------ |
---|
| 459 | |
---|
| 460 | bool Object2D::isNear(Object2D &other, long gap) |
---|
| 461 | { |
---|
| 462 | bool areNear; |
---|
| 463 | // Test X ranges |
---|
| 464 | if((this->xmin-gap)<other.xmin) areNear=((this->xmax+gap)>=other.xmin); |
---|
| 465 | else areNear=(other.xmax>=(this->xmin-gap)); |
---|
| 466 | // Test Y ranges |
---|
| 467 | if(areNear){ |
---|
| 468 | if((this->ymin-gap)<other.ymin) areNear=areNear&&((this->ymax+gap)>=other.ymin); |
---|
| 469 | else areNear=areNear&&(other.ymax>=(this->ymin-gap)); |
---|
| 470 | } |
---|
| 471 | return areNear; |
---|
| 472 | } |
---|
| 473 | |
---|
| 474 | //------------------------------------------------------ |
---|
| 475 | |
---|
| 476 | bool Object2D::isClose(Object2D &other, float threshS, bool flagAdj) |
---|
| 477 | { |
---|
| 478 | |
---|
| 479 | long gap = long(ceil(threshS)); |
---|
| 480 | if(flagAdj) gap=1; |
---|
| 481 | |
---|
| 482 | bool close = false; |
---|
| 483 | |
---|
| 484 | long ycommonMin=std::max(this->ymin-gap,other.ymin)-gap; |
---|
| 485 | long ycommonMax=std::min(this->ymax+gap,other.ymax)+gap; |
---|
| 486 | |
---|
| 487 | std::vector<Scan>::iterator iter1,iter2; |
---|
[773] | 488 | for(iter1=this->scanlist.begin();!close && iter1!=this->scanlist.end();iter1++){ |
---|
[770] | 489 | if(iter1->itsY >= ycommonMin && iter1->itsY<=ycommonMax){ |
---|
[773] | 490 | for(iter2=other.scanlist.begin();!close && iter2!=other.scanlist.end();iter2++){ |
---|
[770] | 491 | if(iter2->itsY >= ycommonMin && iter2->itsY<=ycommonMax){ |
---|
| 492 | |
---|
| 493 | if(abs(iter1->itsY-iter2->itsY)<=gap){ |
---|
| 494 | if(flagAdj) { |
---|
[771] | 495 | if((iter1->itsX-gap)>iter2->itsX) close=((iter2->itsX+iter2->itsXLen-1)>=(iter1->itsX-gap)); |
---|
| 496 | else close = ( (iter1->itsX+iter1->itsXLen+gap-1)>=iter2->itsX); |
---|
[770] | 497 | } |
---|
| 498 | else close = (minSep(*iter1,*iter2) < threshS); |
---|
| 499 | } |
---|
| 500 | |
---|
| 501 | } |
---|
| 502 | } |
---|
| 503 | } |
---|
| 504 | } |
---|
| 505 | |
---|
| 506 | return close; |
---|
| 507 | |
---|
| 508 | } |
---|
| 509 | |
---|
| 510 | |
---|
| 511 | |
---|
[238] | 512 | } |
---|