package endrov.IJ.roi; 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; } /** @deprecated */ 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) { double asp; 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=x+width, y2=y+height, xc=x+width/2, yc=y+height/2; int w2 = (int)(0.14645*width); int h2 = (int)(0.14645*height); if (width > 7 && height > 7) { asp = (double)width/(double)height; asp_bk = asp; } else { asp = asp_bk; } 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=1; x=x2=xc; } if(y>=y2) { height=1; y=y2=yc; } } if(constrain) { if(activeHandle==1 || activeHandle==5) width=height; else height=width; if(x>=x2) { width=1; x=x2=xc; } if(y>=y2) { height=1; y=y2=yc; } switch(activeHandle){ case 0: x=x2-width; y=y2-height; break; case 1: x=xc-width/2; y=y2-height; break; case 2: y=y2-height; break; case 3: y=yc-height/2; break; case 5: x=xc-width/2; break; case 6: x=x2-width; break; case 7: y=yc-height/2; x=x2-width; break; } if(center){ x=xc-width/2; y=yc-height/2; } } if(aspect && !constrain) { if(activeHandle==1 || activeHandle==5) width=(int)Math.rint((double)height*asp); else height=(int)Math.rint((double)width/asp); switch(activeHandle){ case 0: x=x2-width; y=y2-height; break; case 1: x=xc-width/2; y=y2-height; break; case 2: y=y2-height; break; case 3: y=yc-height/2; break; case 5: x=xc-width/2; break; case 6: x=x2-width; break; case 7: y=yc-height/2; x=x2-width; break; } if(center){ x=xc-width/2; y=yc-height/2; } // Attempt to preserve aspect ratio when roi very small: if (width<8) { if(width<1) width = 1; height=(int)Math.rint((double)width/asp_bk); } if (height<8) { if(height<1) height =1; width=(int)Math.rint((double)height*asp_bk); } } updateClipRect(); imp.draw(clipX, clipY, clipWidth, clipHeight); oldX=x; oldY=y; oldWidth=width; oldHeight=height; cachedMask = null; } public void draw(Graphics g) { Color color = strokeColor!=null? strokeColor:ROIColor; if (fillColor!=null) color = fillColor; g.setColor(color); mag = 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 = screenX(x); int sy1 = screenY(y); int sx2 = sx1+sw/2; int sy2 = sy1+sh/2; int sx3 = sx1+sw; int sy3 = sy1+sh; Graphics2D g2d = (Graphics2D)g; if (stroke!=null) g2d.setStroke(getScaledStroke()); if (fillColor!=null) g.fillOval(sx1, sy1, sw, sh); else g.drawOval(sx1, sy1, sw, sh); if (state!=CONSTRUCTING && clipboard==null && !overlay) { 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) { int saveWidth = ip.getLineWidth(); if (getStrokeWidth()>1f) ip.setLineWidth((int)Math.round(getStrokeWidth())); ip.drawPolygon(p); ip.setLineWidth(saveWidth); } if (Line.getWidth()>1 || getStrokeWidth()>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=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