00001 #include "ImageSelectionCube.h" 00002 #include <math.h> 00003 00004 ImageSelectionCube::ImageSelectionCube(int x1, int y1, int w1, int h1, ImageInterface* theimage) : 00005 ImageCube( x1, y1, w1, h1, theimage){;} 00006 00007 ImageSelectionCube::ImageSelectionCube(int x1, int y1, int w1, int h1) : 00008 ImageCube( x1, y1, w1, h1){;} 00009 00010 ImageSelectionCube::~ImageSelectionCube(){ 00011 for(unsigned int i=0; i < theCube.size(); i++){ 00012 // @todo 2006-07-25 dls cleaning up doubles seems to be causing crash -- need to reexamine this section to see if clean-up is needed 00013 //delete (theCube[i].values) ; 00014 } 00015 } 00016 00017 void ImageSelectionCube::setSelection(std::vector<ImageCube::ThreeDPoint> points) { 00018 00019 selectionPoints = removeDuplicates(points); 00020 //do all setup of selection here 00021 //i.e. figure out what pixels are in, and put them in the array 00022 00023 if(points.size()<3){//if we don't have 3 pix, we don't have a poly 00024 if (points.size() == 1){//if it's a point, just add the pixel 00025 00026 ImageCube::Pixel temp_pix; 00027 temp_pix.x = (int)(points[0].x) ; 00028 temp_pix.y = (int)(points[0].y) ; 00029 00030 selectionPixels.push_back(temp_pix); 00031 00032 } else if (points.size() == 2){//if it's a line, handle that here 00033 00034 //use generate full line to get all values in the line 00035 std::vector<ImageCube::ThreeDPoint> temp = generateFullLine(points[0], points[1]); 00036 00037 for(unsigned int i=0; i<temp.size(); i++){//for each pixels 00038 ImageCube::Pixel temp_pix; 00039 temp_pix.x = (int)(temp[i].x) ; 00040 temp_pix.y = (int)(temp[i].y) ; 00041 00042 selectionPixels.push_back(temp_pix); 00043 } 00044 00045 } 00046 00047 } 00048 else {//we have a polygon 00049 std::vector<ImageCube::ThreeDPoint> borderPixels; 00050 00051 //set up iterators to get two consecutive points 00052 std::vector<ImageCube::ThreeDPoint>::iterator main = points.begin(); 00053 std::vector<ImageCube::ThreeDPoint>::iterator oneAhead = points.begin(); 00054 oneAhead++; 00055 00056 while (main != points.end()){//once for each point 00057 if(((*oneAhead).x == (*main).x) && ((*oneAhead).y == (*main).y)){ 00058 oneAhead++; 00059 main++; 00060 continue; 00061 } 00062 00063 00064 //generate the y-border pixels 00065 std::vector<ImageCube::ThreeDPoint> temp = generateLine(*main, *oneAhead); 00066 00067 //combine them into a sorted vector 00068 //borderPixels = combineSortedVectors(removeDuplicates(borderPixels), removeDuplicates(temp)); 00069 borderPixels = combineSortedVectors(borderPixels, temp); 00070 00071 main++; 00072 oneAhead++; 00073 //handle wraparound 00074 if(oneAhead == points.end()){ 00075 oneAhead = points.begin(); 00076 00077 if(((*oneAhead).x == (*main).x) && ((*oneAhead).y == (*main).y)) break; 00078 } 00079 } 00080 00081 borderPixels = removeDuplicates(borderPixels); 00082 00083 //now we have a vector of all the edges in the order or L->R, T->B 00084 //(how we read) now we just grab the first, add pixels until we 00085 //reach the end of that row, move to the next row and repeat 00086 00087 for(unsigned int i=0; i < borderPixels.size(); i++){//while we have pixels 00088 00089 ImageCube::Pixel temp_pix; 00090 temp_pix.x = (int)(borderPixels[i].x) ; 00091 temp_pix.y = (int)(borderPixels[i].y) ; 00092 00093 selectionPixels.push_back(temp_pix); 00094 00095 if(borderPixels[i+1].y == borderPixels[i].y){//if the next pixel is on this row 00096 00097 //then we add all the pixels between the boundaries on this row 00098 for(int j = (int)(borderPixels[i].x)+1 ; j <= (int)(borderPixels[i+1].x) ; j++) { 00099 if( j == borderPixels[i+1].x && (borderPixels[i+1].z == 1)){ 00100 j++; 00101 continue; 00102 } 00103 00104 ImageCube::Pixel temp_pix; 00105 temp_pix.x = j; 00106 temp_pix.y = (int)(borderPixels[i].y); 00107 00108 selectionPixels.push_back(temp_pix); 00109 00110 } 00111 i++;//increment i, because we're adding the end boundary 00112 } 00113 } 00114 } 00115 } 00116 00117 00118 void ImageSelectionCube::setSelection(std::vector<ImageCube::Pixel> pixs){ 00119 00120 borderPixels = pixs; 00121 00122 selectionPixels = pixs; 00123 selectionPoints = generatePoints(pixs); 00124 00125 00126 //TODO generate the Points that outline this shape 00127 00128 00129 00130 } 00131 00132 00133 std::string ImageSelectionCube::getAsString(){ 00134 00135 return getAsString(";"); 00136 } 00137 00138 00139 std::string ImageSelectionCube::getAsString(std::string delim, std::ofstream &f){ 00140 pixelArray.clearAll(); 00141 00142 // for each pixel in the selection area 00143 int i = 0 ; 00144 for( i = 0; i < (int)(selectionPixels.size()) ; i++){ 00145 // create a new pixel element in pixelArray with the image x-y coords of the current pixel location 00146 pixelArray.add(selectionPixels[i].x, selectionPixels[i].y); 00147 } 00148 00149 int x = 0 ; 00150 int y = 0 ; 00151 00152 // for each pixel in the selection area 00153 for( i = 0; i < (int)(selectionPixels.size()) ; i++){ 00154 00155 // for each band ("layer") in the image 00156 for(int k = 0; k<this->layers; k++){ 00157 00158 // get the associated PixelProfile element from pixel array and 00159 // add the values to the element 00160 x = selectionPixels[i].x ; 00161 y = selectionPixels[i].y ; 00162 00163 PixelProfile * newPix = pixelArray.getPixel(x, y) ; 00164 if (newPix != NULL) { 00165 if (x > 0 && y > 0) { 00166 newPix->add(ImageCube::getValueAtOverall(x, y, k)); 00167 } 00168 } 00169 } 00170 } 00171 00172 00173 pixelArray.getAsString(delim, f); 00174 return "" ; 00175 } 00176 00177 00178 std::string ImageSelectionCube::getAsString(std::string delim){ 00179 pixelArray.clearAll(); 00180 00181 // for each pixel in the selection area 00182 int i = 0 ; 00183 for( i = 0 ; i < (int)(selectionPixels.size()) ; i++ ) { 00184 // create a new pixel element in pixelArray with the image x-y coords of the current pixel location 00185 pixelArray.add(selectionPixels[i].x, selectionPixels[i].y); 00186 } 00187 00188 int x = 0 ; 00189 int y = 0 ; 00190 00191 // for each pixel in the selection area 00192 for( i = 0 ; i < (int)(selectionPixels.size()) ; i++ ) { 00193 // for each band ("layer") in the image 00194 for(int k = 0; k<this->layers; k++){ 00195 // get the associated PixelProfile element from pixel array and 00196 // add the values to the element 00197 x = selectionPixels[i].x ; 00198 y = selectionPixels[i].y ; 00199 PixelProfile * newPix = pixelArray.getPixel(x, y) ; 00200 if (newPix != NULL) { 00201 newPix->add(ImageCube::getValueAtOverall(x, y, k)); 00202 } 00203 } 00204 } 00205 00206 return pixelArray.getAsString(delim) ; 00207 } 00208 00209 00210 std::vector<ImageCube::ThreeDPoint> ImageSelectionCube::getPoints(){ 00211 return selectionPoints; 00212 } 00213 00214 00215 std::vector<ImageCube::Pixel> ImageSelectionCube::getPixels(){ 00216 return selectionPixels; 00217 } 00218 00219 00220 std::vector<ImageCube::ThreeDPoint> ImageSelectionCube::generateFullLine(ImageCube::ThreeDPoint s, ImageCube::ThreeDPoint f){ 00221 00222 //if it's effectivly a straight line, we've already handled that in genLine 00223 if ((-1<(f.x - s.x) && (f.x - s.x)<1) || (-1<(f.y - s.y) && (f.y - s.y)<1)){ 00224 return generateLine(s, f); 00225 } 00226 00227 double m; 00228 double b; 00229 00230 int lx, ly, hx, hy; 00231 00232 //figure out m and b (y=mx+b) 00233 if(s.x > f.x) {//if slope is negative 00234 m = ((double)(s.y - f.y))/((double)(s.x - f.x)); 00235 b = s.y - (m*(s.x)); 00236 } else {//if slope is positive 00237 m = ((double)(f.y - s.y))/((double)(f.x - s.x)); 00238 b = s.y - (m*(s.x)); 00239 } 00240 00241 //figure out high and low y 00242 if(s.y > f.y) { 00243 hy = (int)(s.y); 00244 ly = (int)(f.y); 00245 } else { 00246 hy = (int)(f.y); 00247 ly = (int)(s.y); 00248 } 00249 00250 //figure out high and low x 00251 if(s.x > f.x) { 00252 hx = (int)(s.x) ; 00253 lx = (int)(f.x) ; 00254 } 00255 else { 00256 hx = (int)(f.x) ; 00257 lx = (int)(s.x) ; 00258 } 00259 00260 std::vector<ImageCube::ThreeDPoint> temp; 00261 00262 if(m > 1){//if longer in x direction 00263 for (int i=lx; i<=hx; i++){ 00264 double val = (m*(double)i)+b; 00265 ImageCube::ThreeDPoint borderPoint; 00266 borderPoint.y = (int)(val+0.5); 00267 borderPoint.x = i; 00268 borderPoint.z = 0; 00269 00270 temp.push_back(borderPoint); 00271 00272 if((int)(val+0.15) != (int)(val+0.5)){ 00273 //if we're really close to the upper edge 00274 //grab the next pixel over too 00275 ImageCube::ThreeDPoint borderPoint2; 00276 borderPoint2.y = (int)(val+0.15); 00277 borderPoint2.x = i; 00278 borderPoint2.z = 0; 00279 00280 temp.push_back(borderPoint2); 00281 00282 } else if ((int)(val-0.15) != (int)(val)){ 00283 //if we're really close to the lower edge 00284 //grab the next pixel over too 00285 ImageCube::ThreeDPoint borderPoint2; 00286 borderPoint2.y = (int)(val-0.15); 00287 borderPoint2.x = i; 00288 borderPoint2.z = 0; 00289 00290 temp.push_back(borderPoint2); 00291 } 00292 } 00293 00294 }else {//if equal or longer in y direction 00295 00296 for (int i=ly; i<=hy; i++){ 00297 double val = ((double)i-b)/m; 00298 ImageCube::ThreeDPoint borderPoint; 00299 borderPoint.x = (int)(val+0.5); 00300 borderPoint.y = i; 00301 borderPoint.z = 0; 00302 00303 temp.push_back(borderPoint); 00304 00305 if((int)(val+0.15) != (int)(val+0.5)){ 00306 //if we're really close to the upper edge 00307 //grab the next pixel over too 00308 ImageCube::ThreeDPoint borderPoint2; 00309 borderPoint2.x = abs((int)(val+0.15)); 00310 borderPoint2.y = i; 00311 borderPoint2.z = 0; 00312 00313 temp.push_back(borderPoint2); 00314 00315 } else if ((int)(val-0.15) != (int)(val)){ 00316 //if we're really close to the lower edge 00317 //grab the next pixel over too 00318 ImageCube::ThreeDPoint borderPoint2; 00319 borderPoint2.x = (int)(val-0.15); 00320 borderPoint2.y = i; 00321 borderPoint2.z = 0; 00322 00323 temp.push_back(borderPoint2); 00324 00325 } 00326 } 00327 } 00328 return temp; 00329 } 00330 00331 00332 std::vector<ImageCube::ThreeDPoint> ImageSelectionCube::generateLine(ImageCube::ThreeDPoint s, ImageCube::ThreeDPoint f) { 00333 00334 //TODO check for div by zero first 00335 if(-1<(f.y - s.y) && (f.y - s.y)<1){//if the line is effectivly straight vertical 00336 00337 int lx, hx; 00338 00339 //figure out highs and lows 00340 if(s.x > f.x) { 00341 hx = (int)(s.x) ; 00342 lx = (int)(f.x) ; 00343 } else { 00344 hx = (int)(f.x) ; 00345 lx = (int)(s.x) ; 00346 } 00347 00348 std::vector<ImageCube::ThreeDPoint> temp; 00349 00350 ImageCube::ThreeDPoint borderPoint; 00351 borderPoint.x = (int)lx; 00352 borderPoint.y = (int)f.y; 00353 borderPoint.z = 0; 00354 00355 temp.push_back(borderPoint); 00356 00357 ImageCube::ThreeDPoint borderPoint2; 00358 borderPoint2.x = (int)hx; 00359 borderPoint2.y = (int)f.y; 00360 borderPoint2.z = 0; 00361 00362 temp.push_back(borderPoint2); 00363 00364 return temp; 00365 00366 } 00367 else if(-1<(f.x - s.x) && (f.x - s.x)<1){//if the line is straight horizantal 00368 00369 int ly, hy; 00370 00371 //figure out highs and lows 00372 if(s.y > f.y) { 00373 hy = (int)(s.y) ; 00374 ly = (int)(f.y) ; 00375 } else { 00376 hy = (int)(f.y) ; 00377 ly = (int)(s.y) ; 00378 } 00379 00380 std::vector<ImageCube::ThreeDPoint> temp; 00381 00382 //walk along and add pixels 00383 for(int i=ly; i<=hy; i++){ 00384 ImageCube::ThreeDPoint borderPoint; 00385 borderPoint.x = (int)(f.x); 00386 borderPoint.y = (int)i; 00387 borderPoint.z = 0; 00388 00389 temp.push_back(borderPoint); 00390 } 00391 00392 return temp; 00393 00394 } 00395 00396 //if the line is not vertical or horizantal, we have more work 00397 else { 00398 00399 double m; 00400 double b; 00401 00402 int ly, hy; 00403 00404 //figure out m and b (y=mx+b) 00405 if(s.x > f.x) { 00406 m = ((double)(s.y - f.y))/((double)(s.x - f.x)); 00407 b = s.y - (m*(s.x)); 00408 00409 } else { 00410 m = ((double)(f.y - s.y))/((double)(f.x - s.x)); 00411 b = s.y - (m*(s.x)); 00412 } 00413 00414 //figure out high and lowy 00415 if(s.y > f.y) { 00416 hy = (int)(s.y) ; 00417 ly = (int)(f.y) ; 00418 } else { 00419 hy = (int)(f.y) ; 00420 ly = (int)(s.y) ; 00421 } 00422 00423 std::vector<ImageCube::ThreeDPoint> temp; 00424 00425 for (int i=ly; i<=hy; i++){ 00426 //for each y, we generate the x value and add that 00427 //we'll fill in the middle later 00428 00429 double val = (i-b)/m;//get x 00430 ImageCube::ThreeDPoint borderPoint; 00431 borderPoint.x = abs((int)(val+0.5)) ; 00432 borderPoint.y = i; 00433 00434 //if we round, we want know that later 00435 if((int)val != int(val+0.5)) borderPoint.z = 1; 00436 else borderPoint.z = 0; 00437 00438 temp.push_back(borderPoint); 00439 } 00440 return temp; 00441 } 00442 } 00443 00444 00445 std::vector<ImageCube::ThreeDPoint> ImageSelectionCube::combineSortedVectors(std::vector<ImageCube::ThreeDPoint> a, std::vector<ImageCube::ThreeDPoint> b){ 00446 00447 std::vector<ImageCube::ThreeDPoint> temp; 00448 std::vector<ImageCube::ThreeDPoint>::iterator control = a.begin(); 00449 std::vector<ImageCube::ThreeDPoint>::iterator adding = b.begin(); 00450 00451 while (adding < b.end()){//while we have stuff in b 00452 if(control < a.end()){//as long as there's stuff in a 00453 if((*adding).y < (*control).y) { 00454 temp.push_back(*adding); 00455 adding++; 00456 }else if((*control).y < (*adding).y){ 00457 temp.push_back(*control); 00458 control++; 00459 }else{//y's are the same, so base off x's 00460 if((*adding).x < (*control).x) { 00461 temp.push_back(*adding); 00462 adding++; 00463 }else if((*control).x < (*adding).x){ 00464 temp.push_back(*control); 00465 control++; 00466 }else {//both x and y the same, we only need one copy 00467 temp.push_back(*control); 00468 control++; 00469 adding++; 00470 } 00471 } 00472 00473 }else{ //only b's left 00474 temp.push_back(*adding); 00475 adding++; 00476 } 00477 }//if no more in b, 00478 while(control < a.end()){//add anything left in a 00479 temp.push_back(*control); 00480 control++; 00481 } 00482 return temp; 00483 } 00484 00485 00486 std::vector<ImageCube::ThreeDPoint> ImageSelectionCube::removeDuplicates(std::vector<ImageCube::ThreeDPoint> theVec){ 00487 std::vector<ImageCube::ThreeDPoint> temp = *(new std::vector<ImageCube::ThreeDPoint>()); 00488 00489 int tempsize = 0; 00490 00491 // temp.push_back(theVec[0]); 00492 // tempsize++; 00493 00494 for(int i=0; i < (int)(theVec.size()) ; i++){ 00495 int j = theVec.size() - 1; 00496 bool match = false; 00497 00498 while (j > i){ 00499 if((theVec[i].x == theVec[j].x)&&(theVec[i].y == theVec[j].y)){ 00500 match = true; 00501 break; 00502 } 00503 j--; 00504 } 00505 00506 if(!match){ 00507 temp.push_back(theVec[i]); 00508 tempsize++; 00509 } 00510 /* 00511 if((theVec[i].x != temp[tempsize-1].x)&&(theVec[i].y != temp[tempsize-1].y)&&(theVec[i].z != temp[tempsize-1].z)){ 00512 temp.push_back(theVec[i]); 00513 tempsize++; 00514 } 00515 */ 00516 } 00517 00518 return temp; 00519 00520 } 00521 00522 /* 00523 std::vector<ImageCube::Pixel> ImageSelectionCube::getBoundaryPixels(std::vector<ImageCube::Pixel> pixs){ 00524 //for this algorithm, a boundary pixel will be defined as 00525 //a pixels with at least one edge not connected to another 00526 //pixel in the shape 00527 //the output will be a vector which contains the boundary 00528 //pixels in clockwise order around the shape 00529 00530 std::vector<ImageCube::Pixel> temp; 00531 00532 return temp; 00533 } 00534 */ 00535 00536 std::vector<ImageCube::ThreeDPoint> ImageSelectionCube::generatePoints(std::vector<ImageCube::Pixel> pixs){ 00537 00538 00539 return getPointsFromAngles(getAngles(pixs)); 00540 /* 00541 //take in the boundary pixels, and create lines 00542 std::vector<ImageCube::ThreeDPoint> temp; 00543 00544 00545 //add the first pixel as the first point, 00546 //this will be the upper left corner 00547 ImageCube::ThreeDPoint point; 00548 point.x = pixs[0].x; 00549 point.y = pixs[0].y; 00550 point.z = 0; 00551 00552 temp.push_back(point); 00553 00554 ImageCube::ThreeDPoint* lastPoint = &point; 00555 ImageCube::Pixel* lastPix = &pixs[0]; 00556 00557 00558 //loop through the rest of the pixels to find more points 00559 for(int i=1; i<pixs.size(); i++){ 00560 00561 } 00562 return temp; 00563 */ 00564 } 00565 00566 00567 std::vector<double> ImageSelectionCube::getAngles(std::vector<ImageCube::Pixel> points){ 00568 //most of this code was taken from another project and modified 00569 //just so you know 00570 00571 //basically we're looking for the angles between pixels here 00572 //later, we use these angles to place points 00573 00574 int xySize = points.size(); 00575 //std::vector<double> results = *(new std::vector<double>(xySize)); 00576 std::vector<double> results(xySize); 00577 00578 int i; 00579 double x,y; 00580 double x1, x2, y1, y2, difx, dify; 00581 x1 = x2 = y1 = y2 = difx = dify = 0.0; 00582 00583 00584 std::vector<ImageCube::Pixel>::iterator sitor = points.begin(); 00585 //for each pixel in the vector 00586 for(i=0; i<xySize; sitor++, i++){ 00587 if(i==0){ 00588 x1 = (*sitor).x; 00589 y1 = (*sitor).y; 00590 continue; 00591 } 00592 x = (*sitor).x; 00593 y = (*sitor).y; 00594 x2 = x; 00595 y2 = y; 00596 difx = x1-x2; 00597 dify = y1-y2; 00598 00599 //calculate the angle from this to the last and store 00600 results[i] = atan2(dify,difx); 00601 x1 = x2; 00602 y1 = y2; 00603 } 00604 00605 //redo first number to handle wraparound 00606 /* sitor = points->begin(); 00607 x2 = (*sitor).x; 00608 y2 = (*sitor).y; 00609 difx = x1-x2; 00610 dify = y1-y2; 00611 results[xySize] = atan2(dify, difx); 00612 */ 00613 return results; 00614 } 00615 00616 00617 std::vector<ImageCube::ThreeDPoint> ImageSelectionCube::getPointsFromAngles(std::vector<double> angles){ 00618 //this code was taken from another project... 00619 //just so you know 00620 00621 //here we're taking the angles, and finding local maximums, these 00622 //will be points. We also make points out of inflection points 00623 00624 //std::vector<ImageCube::ThreeDPoint> results = *(new std::vector<ImageCube::ThreeDPoint>()); 00625 std::vector<ImageCube::ThreeDPoint> results; 00626 00627 00628 double lastangle = 0.0; 00629 double thisangle = 0.0; 00630 00631 int xySize = angles.size(); 00632 00633 double *deltaAngles = new double[xySize]; 00634 00635 std::vector<double>::iterator itor = angles.begin(); 00636 //loop through and create an array of delta angles, 00637 //this will later be used to find max Curvature points 00638 int i = 0 ; 00639 for(i = 0; i<xySize; i++, itor++) { 00640 // get the max points by checking the angle value 00641 thisangle = (*itor); 00642 if(i==0){ 00643 lastangle = thisangle; 00644 continue; 00645 } 00646 else 00647 { 00648 double delta = thisangle-lastangle; 00649 if(delta > 3.14159){ 00650 delta = -6.2831853 + delta; 00651 } 00652 else if(delta < -3.14159){ 00653 delta = 6.2831853 + delta; 00654 } 00655 deltaAngles[i-1] = delta; 00656 } 00657 lastangle = thisangle; 00658 } 00659 00660 //handle wrap around 00661 /* itor = mySmoothedPoints->begin(); 00662 thisangle = (*itor); 00663 double delta = thisangle-lastangle; 00664 if(delta > 3.14159){ 00665 delta = -6.2831853 + delta; 00666 } 00667 else if(delta < -3.14159){ 00668 delta = 6.2831853 + delta; 00669 } 00670 deltaAngles[xySize-1] = delta; 00671 */ 00672 00673 lastangle = 0.0; 00674 thisangle = 0.0; 00675 double nextangle = 0.0; 00676 00677 //now we use the change in angle to find local max and inflection 00678 for( i = 0 ; i < xySize ; i++ ) { 00679 thisangle = deltaAngles[i]; 00680 00681 //handles wrap-around 00682 if(i==0){ 00683 lastangle = deltaAngles[xySize-1]; 00684 nextangle = deltaAngles[i+1]; 00685 } 00686 else if(i == (xySize - 1)){ 00687 lastangle = deltaAngles[i-1]; 00688 nextangle = deltaAngles[0]; 00689 } 00690 else{ 00691 lastangle = deltaAngles[i-1]; 00692 nextangle = deltaAngles[i+1]; 00693 } 00694 00695 //this is a max curvature point 00696 if((fabs(thisangle) > fabs(lastangle)) && (fabs(thisangle) > fabs(nextangle))){ 00697 00698 ImageCube::ThreeDPoint temp = *(new ImageCube::ThreeDPoint()); 00699 // ImageCube::ThreeDPoint temp; 00700 temp.x = borderPixels[i].x; 00701 temp.y = borderPixels[i].y; 00702 results.push_back(temp); 00703 } 00704 //this is an inflection point 00705 if((thisangle > 0 && lastangle <0) || (thisangle < 0 && lastangle >0)){ 00706 ImageCube::ThreeDPoint temp = *(new ImageCube::ThreeDPoint()); 00707 // ImageCube::ThreeDPoint temp; 00708 temp.x = borderPixels[i].x; 00709 temp.y = borderPixels[i].y; 00710 results.push_back(temp); 00711 } 00712 } 00713 00714 delete[] deltaAngles; 00715 00716 return results; 00717 } 00718 00719 00720
Home |
Search |
Disclaimers & Privacy |
Contact Us GLIMSView Maintainer: dsoltesz@usgs.gov |