// -*- C++ -*-
// $RCSfile: expandsel.C,v $
// $Revision: 1.4 $
// $Author: langer $
// $Date: 2000/10/30 19:23:24 $
/* This software was produced by NIST, an agency of the U.S. government,
* and by statute is not subject to copyright in the United States.
* Recipients of this software assume all responsibilities associated
* with its operation, modification and maintenance. However, to
* facilitate maintenance we ask that before distributing modifed
* versions of this software, you first contact the authors at
* oof_manager@ctcms.nist.gov.
*/
#include "expandsel.h"
#include "goof.h"
#include "ppm2oof.h"
// Expand a group by howfar pixels in all directions
enum Marker {UNMARKED, MARKED, UNMARKABLE};
int Goof::expandgroup(PixelGroup &grp, double howfar) {
// Make an array in which to mark added pixels
Array<Marker> newcells(height, width);
newcells.clear(UNMARKED);
for(int k=0; k<grp.size(); k++) // pixels currently in group
newcells[grp[k]] = UNMARKABLE;
int count = 0;
double d2 = howfar*howfar;
for(int i=0; i<grp.size(); i++) {
const Cell_coordinate &here(grp[i]);
int xmin = int(here.x - howfar);
int xmax = int(here.x + howfar);
int ymin = int(here.y - howfar);
int ymax = int(here.y + howfar);
if(xmin < 0) xmin = 0;
if(xmax >= width) xmax = width - 1;
if(ymin < 0) ymin = 0;
if(ymax >= height) ymax = height - 1;
// Mark all pixels within howfar of a group member
// g++ doesn't like this!
// ArrayIterator iter(ImageRect(Cell_coordinate(xmin, ymin),
// Cell_coordinate(xmax, ymax)));
ImageRect r(Cell_coordinate(xmin, ymin), Cell_coordinate(xmax, ymax));
ArrayIterator iter(r);
Cell_coordinate test;
while(iter(test)) {
if(newcells[test] == UNMARKED) {
int dx = test.x - here.x;
int dy = test.y - here.y;
if((dx != 0 || dy != 0) && (dx*dx + dy*dy <= d2)) {
++count;
newcells[test] = MARKED;
}
}
}
}
// Make a list of all active marked pixels
Vec<Cell_coordinate> list(count);
ArrayIterator iter2(newcells);
Cell_coordinate pxl;
int m=0;
while(iter2(pxl))
if(current_goof->active(pxl) && newcells[pxl] == MARKED)
list[m++] = pxl;
// Put marked pixels in the group
grp.append(list);
grp.weed();
return count;
}
int Goof::expandselection(double howfar) {
init_selection(1);
return expandgroup(*selected_grp, howfar);
}
//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//
// remove all pixels that aren't completely surrounded by other pixels
// in the group.
int Goof::shrinkgroup(PixelGroup &grp, double howfar) {
PixelGroup oldgrp(grp); // make a copy of the group
oldgrp.weed();
grp.clear();
Array<int> cells(height, width);
cells.clear(0);
for(int i=0; i<oldgrp.size(); i++)
cells[oldgrp[i]] = 1;
double d2 = howfar*howfar;
for(int j=0; j<oldgrp.size(); j++) {
const Cell_coordinate &here(oldgrp[j]);
if(active(here)) {
int xmin = int(here.x - howfar);
int xmax = int(here.x + howfar);
int ymin = int(here.y - howfar);
int ymax = int(here.y + howfar);
if(xmin < 0) xmin = 0;
if(xmax >= width) xmax = width - 1;
if(ymin < 0) ymin = 0;
if(ymax >= height) ymax = height - 1;
// g++ doesn't like this!
// ArrayIterator iter(ImageRect(Cell_coordinate(xmin, ymin),
// Cell_coordinate(xmax, ymax)));
ImageRect r(Cell_coordinate(xmin, ymin), Cell_coordinate(xmax, ymax));
ArrayIterator iter(r);
Cell_coordinate test;
int surrounded = 1;
while(surrounded && iter(test)) {
int dx = test.x - here.x;
int dy = test.y - here.y;
if(!cells[test] && (dx*dx + dy*dy <= d2))
surrounded = 0;
}
if(surrounded)
grp.append(here);
}
else // inactive cells stay selected
grp.append(here);
}
return oldgrp.size() - grp.size();
}
int Goof::shrinkselection(double howfar) {
init_selection(1);
return shrinkgroup(*selected_grp, howfar);
}
//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//
CommandFn ExpandSelectionCmd::func() {
if(goofinit()) {
int n = current_goof->expandselection(range);
garcon()->msout << ms_info << n << " additional pixels selected."
<< endl << ms_normal;
current_goof->redraw();
}
}
CommandM *ExpandSelectionCmd::clone() const {
ExpandSelectionCmd *esc = new ExpandSelectionCmd;
esc->range = range;
return esc;
}
CommandFn ShrinkSelectionCmd::func() {
if(goofinit()) {
int n = current_goof->shrinkselection(range);
garcon()->msout << ms_info << n << " pixels deselected."
<< endl << ms_normal;
current_goof->redraw();
}
}
CommandM *ShrinkSelectionCmd::clone() const {
ShrinkSelectionCmd *esc = new ShrinkSelectionCmd;
esc->range = range;
return esc;
}
syntax highlighted by Code2HTML, v. 0.9.1