package ij.gui;
import java.awt.*;
import java.awt.image.*;
import ij.*;
import ij.plugin.frame.Recorder;
import ij.process.FloatPolygon;
import ij.measure.Calibration;
public class RotatedRectRoi extends PolygonRoi {
private double xstart, ystart;
private static double DefaultRectWidth = 50;
private double rectWidth = DefaultRectWidth;
public RotatedRectRoi(double x1, double y1, double x2, double y2, double rectWidth) {
super(new float[5], new float[5], 5, FREEROI);
this.rectWidth = rectWidth;
makeRectangle(x1, y1, x2, y2);
state = NORMAL;
bounds = null;
}
public RotatedRectRoi(int sx, int sy, ImagePlus imp) {
super(sx, sy, imp);
type = FREEROI;
xstart = ic.offScreenXD(sx);
ystart = ic.offScreenYD(sy);
ImageWindow win = imp.getWindow();
int pixels = win!=null?(int)(win.getSize().height/win.getCanvas().getMagnification()):imp.getHeight();
if (IJ.debugMode) IJ.log("RotatedRectRoi: "+(int)rectWidth+" "+pixels);
if (rectWidth>pixels)
rectWidth = pixels/3;
setDrawOffset(false);
bounds = null;
}
public void draw(Graphics g) {
super.draw(g);
if (!overlay && ic!=null) {
double mag = ic.getMagnification();
int size2 = HANDLE_SIZE/2;
for (int i=0; i<4; i++) {
if (i==3) handleColor = strokeColor!=null?strokeColor:ROIColor;
else
handleColor=Color.white;
drawHandle(g, hxs(i)-size2, hys(i)-size2);
}
}
}
private int hxs(int index) {
int indexPlus1 = index<3?index+1:0;
return xp2[index]+(xp2[indexPlus1]-xp2[index])/2;
}
private int hys(int index) {
int indexPlus1 = index<3?index+1:0;
return yp2[index]+(yp2[indexPlus1]-yp2[index])/2;
}
private double hx(int index) {
int indexPlus1 = index<3?index+1:0;
return xpf[index]+(xpf[indexPlus1]-xpf[index])/2+x;
}
private double hy(int index) {
int indexPlus1 = index<3?index+1:0;
return ypf[index]+(ypf[indexPlus1]-ypf[index])/2+y;
}
protected void grow(int sx, int sy) {
double x1 = xstart;
double y1 = ystart;
double x2 = ic.offScreenXD(sx);
double y2 = ic.offScreenYD(sy);
makeRectangle(x1, y1, x2, y2);
imp.draw();
}
void makeRectangle(double x1, double y1, double x2, double y2) {
double length = Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
double angle = Math.atan ((x2-x1)/(y2-y1));
double wsa = (rectWidth/2.0)*Math.sin((Math.PI/2.0)+angle);
double wca = (rectWidth/2.0)*Math.cos((Math.PI/2)+angle);
nPoints = 5;
xpf[3] = (float)(x1-wsa);
ypf[3] = (float)(y1-wca);
xpf[0] = (float)(x1+wsa);
ypf[0] = (float)(y1+wca);
xpf[1] = (float)(x2+wsa);
ypf[1] = (float)(y2+wca);
xpf[2] = (float)(x2-wsa);
ypf[2] = (float)(y2-wca);
xpf[4] = xpf[0];
ypf[4] = ypf[0];
makePolygonRelative();
cachedMask = null;
DefaultRectWidth = rectWidth;
}
void makePolygonRelative() {
FloatPolygon poly = new FloatPolygon(xpf, ypf, nPoints);
Rectangle r = poly.getBounds();
x = r.x;
y = r.y;
width = r.width;
height = r.height;
bounds = null;
for (int i=0; i<nPoints; i++) {
xpf[i] = xpf[i]-x;
ypf[i] = ypf[i]-y;
}
}
protected void handleMouseUp(int screenX, int screenY) {
nPoints = 4;
state = NORMAL;
if (Recorder.record) {
double[] p = getParams();
if (Recorder.scriptMode())
Recorder.recordCall("imp.setRoi(new RotatedRectRoi("+(int)p[0]+","+(int)p[1]+","+(int)p[2]+","+(int)p[3]+","+(int)p[4]+"));");
else
Recorder.record("makeRotatedRectangle", (int)p[0], (int)p[1], (int)p[2], (int)p[3], (int)p[4]);
}
}
protected void moveHandle(int sx, int sy) {
double ox = ic.offScreenXD(sx);
double oy = ic.offScreenYD(sy);
double x1 = hx(3);
double y1 = hy(3);
double x2 = hx(1);
double y2 = hy(1);
switch(activeHandle) {
case 0:
double dx = hx(2) - ox;
double dy = hy(2) - oy;
rectWidth = Math.sqrt(dx*dx+dy*dy);
break;
case 1:
x2 = ox;
y2 = oy;
break;
case 2:
dx = hx(0) - ox;
dy = hy(0) - oy;
rectWidth = Math.sqrt(dx*dx+dy*dy);
break;
case 3:
x1 = ox;
y1 = oy;
break;
}
makeRectangle(x1, y1, x2, y2);
imp.draw();
}
public int isHandle(int sx, int sy) {
int size = HANDLE_SIZE+5;
int halfSize = size/2;
int index = -1;
for (int i=0; i<4; i++) {
int sx2 = (int)Math.round(hxs(i)-halfSize), sy2=(int)Math.round(hys(i)-halfSize);
if (sx>=sx2 && sx<=sx2+size && sy>=sy2 && sy<=sy2+size) {
index = i;
break;
}
}
return index;
}
public double[] getParams() {
double[] params = new double[5];
params[0] = hx(3);
params[1] = hy(3);
params[2] = hx(1);
params[3] = hy(1);
params[4] = rectWidth;
return params;
}
public boolean subPixelResolution() {
return true;
}
}