|
OvalRoi |
|
package ij.gui; import java.awt.*; import java.awt.image.*; import ij.*; import ij.process.*; import ij.measure.Calibration; /** Oval region of interest */ public class OvalRoi extends Roi { /** Creates a new OvalRoi.*/ public OvalRoi(int x, int y, int width, int height) { super(x, y, width, height); type = OVAL; } /** Starts the process of creating a user-defined OvalRoi. */ public OvalRoi(int x, int y, ImagePlus imp) { super(x, y, imp); type = OVAL; } /** Obsolete */ public OvalRoi(int x, int y, int width, int height, ImagePlus imp) { this(x, y, width, height); setImage(imp); } protected void moveHandle(int sx, int sy) { if (clipboard!=null) return; int ox = ic.offScreenX(sx); int oy = ic.offScreenY(sy); //IJ.log("moveHandle: "+activeHandle+" "+ox+" "+oy); int x1=x, y1=y, x2=x1+width, y2=y+height; int w2 = (int)(0.14645*width); int h2 = (int)(0.14645*height); switch (activeHandle) { case 0: x=ox-w2; y=oy-h2; break; case 1: y=oy; break; case 2: x2=ox+w2; y=oy-h2; break; case 3: x2=ox; break; case 4: x2=ox+w2; y2=oy+h2; break; case 5: y2=oy; break; case 6: x=ox-w2; y2=oy+h2; break; case 7: x=ox; break; } //if (x<0) x=0; if (y<0) y=0; if (x<x2) width=x2-x; else {width=1; x=x2;} if (y<y2) height = y2-y; else {height=1; y=y2;} if (constrain) height = width; updateClipRect(); imp.draw(clipX, clipY, clipWidth, clipHeight); oldX=x; oldY=y; oldWidth=width; oldHeight=height; cachedMask = null; } public void draw(Graphics g) { if (ic==null) return; g.setColor(instanceColor!=null?instanceColor:ROIColor); mag = ic.getMagnification(); int sw = (int)(width*mag); int sh = (int)(height*mag); int sw2 = (int)(0.14645*width*mag); int sh2 = (int)(0.14645*height*mag); int sx1 = ic.screenX(x); int sy1 = ic.screenY(y); int sx2 = sx1+sw/2; int sy2 = sy1+sh/2; int sx3 = sx1+sw; int sy3 = sy1+sh; g.drawOval(sx1, sy1, sw, sh); if (state!=CONSTRUCTING && clipboard==null) { int size2 = HANDLE_SIZE/2; drawHandle(g, sx1+sw2-size2, sy1+sh2-size2); drawHandle(g, sx3-sw2-size2, sy1+sh2-size2); drawHandle(g, sx3-sw2-size2, sy3-sh2-size2); drawHandle(g, sx1+sw2-size2, sy3-sh2-size2); drawHandle(g, sx2-size2, sy1-size2); drawHandle(g, sx3-size2, sy2-size2); drawHandle(g, sx2-size2, sy3-size2); drawHandle(g, sx1-size2, sy2-size2); } drawPreviousRoi(g); if (updateFullWindow) {updateFullWindow = false; imp.draw();} if (state!=NORMAL) showStatus(); } /** Draws an outline of this OvalRoi on the image. */ public void drawPixels(ImageProcessor ip) { Polygon p = getPolygon(); if (p.npoints>0) ip.drawPolygon(p); if (Line.getWidth()>1) updateFullWindow = true; } /** Returns this OvalRoi as a polygon. */ public Polygon getPolygon() { ImageProcessor mask = getMask(); Wand wand = new Wand(mask); wand.autoOutline(width/2,height/2, 255, 255); for (int i=0; i<wand.npoints; i++) { wand.xpoints[i] += x; wand.ypoints[i] += y; } return new Polygon(wand.xpoints, wand.ypoints, wand.npoints); } /** Tests if the specified point is inside the boundary of this OvalRoi. @author Michael Schmid */ public boolean contains(int x, int y) { // equation for an ellipse is x^2/a^2 + y^2/b^2 = 1 if (!super.contains(x, y)) return false; else { int twoDx = 2*x - (2*this.x+width-1); int twoDy = 2*y - (2*this.y+height-1); int twoRx = width; int twoRy = height; return (twoDx*twoDx/(double)(twoRx*twoRx) + twoDy*twoDy/(double)(twoRy*twoRy)) < 1; } } /** Returns a handle number if the specified screen coordinates are inside or near a handle, otherwise returns -1. */ public int isHandle(int sx, int sy) { if (clipboard!=null || ic==null) return -1; double mag = ic.getMagnification(); int size = HANDLE_SIZE+3; int halfSize = size/2; int sx1 = ic.screenX(x) - halfSize; int sy1 = ic.screenY(y) - halfSize; int sx3 = ic.screenX(x+width) - halfSize; int sy3 = ic.screenY(y+height) - halfSize; int sx2 = sx1 + (sx3 - sx1)/2; int sy2 = sy1 + (sy3 - sy1)/2; int sw2 = (int)(0.14645*(sx3-sx1)); int sh2 = (int)(0.14645*(sy3-sy1)); if (sx>=sx1+sw2&&sx<=sx1+sw2+size&&sy>=sy1+sh2&&sy<=sy1+sh2+size) return 0; if (sx>=sx2&&sx<=sx2+size&&sy>=sy1&&sy<=sy1+size) return 1; if (sx>=sx3-sw2&&sx<=sx3-sw2+size&&sy>=sy1+sh2&&sy<=sy1+sh2+size) return 2; if (sx>=sx3&&sx<=sx3+size&&sy>=sy2&&sy<=sy2+size) return 3; if (sx>=sx3-sw2&&sx<=sx3-sw2+size&&sy>=sy3-sh2&&sy<=sy3-sh2+size) return 4; if (sx>=sx2&&sx<=sx2+size&&sy>=sy3&&sy<=sy3+size) return 5; if (sx>=sx1+sw2&&sx<=sx1+sw2+size&&sy>=sy3-sh2&&sy<=sy3-sh2+size) return 6; if (sx>=sx1&&sx<=sx1+size&&sy>=sy2&&sy<=sy2+size) return 7; return -1; } public ImageProcessor getMask() { if (cachedMask!=null && cachedMask.getPixels()!=null) return cachedMask; ImageProcessor mask = new ByteProcessor(width, height); double a=width/2.0, b=height/2.0; double a2=a*a, b2=b*b; a -= 0.5; b -= 0.5; double xx, yy; int offset; byte[] pixels = (byte[])mask.getPixels(); for (int y=0; y<height; y++) { offset = y*width; for (int x=0; x<width; x++) { xx = x - a; yy = y - b; if ((xx*xx/a2+yy*yy/b2)<=1.0) pixels[offset+x] = -1; } } cachedMask = mask; return mask; } /** Returns the perimeter length. */ public double getLength() { double pw=1.0, ph=1.0; if (imp!=null) { Calibration cal = imp.getCalibration(); pw = cal.pixelWidth; ph = cal.pixelHeight; } return Math.PI*(width*pw+height*ph)/2.0; } /** Returns Feret's diameter, the greatest distance between any two points along the ROI boundary. */ public double getFeretsDiameter() { double pw=1.0, ph=1.0; if (imp!=null) { Calibration cal = imp.getCalibration(); pw = cal.pixelWidth; ph = cal.pixelHeight; } return width*pw>=height*ph?width*pw:height*ph; } }
|
OvalRoi |
|