/*-
*******************************************************************************
* Copyright (c) 2011, 2014 Diamond Light Source Ltd.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Peter Chang - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.dawnsci.analysis.dataset.roi;
import java.io.Serializable;
public class GridROI extends RectangularROI implements Serializable {
double xSpacing = 50;
double ySpacing = 50;
boolean midPointOn = true;
boolean gridLinesOn = false;
private GridPreferences gridPref = new GridPreferences();
@SuppressWarnings("unused")
private GridROI() {
super();
}
@SuppressWarnings("unused")
private GridROI(double width, double angle) {
super(width, angle);
}
@SuppressWarnings("unused")
private GridROI(double width, double height, double angle) {
super(width, height, angle);
}
/**
* If using this constructor, you should set x and y spacing and GridPreferences
* at some point.
*
* @param ptx
* @param pty
* @param width
* @param height
* @param angle
*/
public GridROI(double ptx, double pty, double width, double height, double angle) {
super(ptx, pty, width, height, angle);
}
@SuppressWarnings("unused")
private GridROI(double ptx, double pty, double width, double height, double angle, boolean clip) {
super(ptx, pty, width, height, angle, clip);
}
private GridROI(double ptx, double pty, double width, double height, double angle, double xSpacing, double ySpacing) {
super(ptx, pty, width, height, angle, false);
this.xSpacing = xSpacing;
this.ySpacing = ySpacing;
}
public GridROI(double ptx, double pty, double width, double height, double angle, double xSpacing, double ySpacing,
boolean gridLinesOn, boolean midPointOn) {
this(ptx, pty, width, height, angle, xSpacing, ySpacing);
this.gridLinesOn = gridLinesOn;
this.midPointOn = midPointOn;
}
public GridROI(double ptx, double pty, double width, double height, double angle, double xSpacing, double ySpacing,
boolean gridLinesOn, boolean midPointOn, GridPreferences gridPref) {
this(ptx, pty, width, height, angle, xSpacing, ySpacing);
this.gridLinesOn = gridLinesOn;
this.midPointOn = midPointOn;
this.gridPref = gridPref;
}
public GridROI(GridPreferences gridPrefs) {
this.gridPref = gridPrefs;
}
@Override
public GridROI copy() {
GridROI c = new GridROI(spt[0], spt[1], len[0], len[1], getAngle(), xSpacing,
ySpacing, gridLinesOn, midPointOn, gridPref);
c.name = name;
c.plot = plot;
return c;
}
/**
* @return Returns the spacing of X and Y grid
*/
public double[] getSpacing() {
return new double[] { xSpacing, ySpacing };
}
/**
* @return integer lengths
*/
public int[] getIntSpacing() {
return new int[] { (int) xSpacing, (int) ySpacing };
}
/**
* Work out where all the grid points (middle of grid box) are
*
* @return grid points
*/
public double[][] getGridPoints() {
final double[] len = getLengths();
final double[] spt = getPointRef();
int xGrids = (int) ((len[0] / xSpacing) + 0.5);
int yGrids = (int) ((len[1] / ySpacing) + 0.5);
double[] xLocs = new double[xGrids];
double[] yLocs = new double[yGrids];
if (xGrids != 0 && yGrids != 0) {
xLocs[0] = spt[0] + xSpacing / 2.0;
yLocs[0] = spt[1] + ySpacing / 2.0;
for (int i = 1; i < xGrids; i++) {
xLocs[i] = xLocs[0] + xSpacing * i;
}
for (int i = 1; i < yGrids; i++) {
yLocs[i] = yLocs[0] + ySpacing * i;
}
}
double[][] gp = new double[2][];
gp[0] = xLocs;
gp[1] = yLocs;
return gp;
}
public double[][] getGridLines() {
double[][] gp = getGridPoints();
int xGrids = gp[0].length;
int yGrids = gp[1].length;
double[][] gl = new double[2][];
if (getSpacing()[0] * xGrids >= getLengths()[0]) {
xGrids--;
if (xGrids < 0) {
xGrids = 0;
}
gl[0] = new double[xGrids];
} else {
gl[0] = gp[0];
}
if (getSpacing()[1] * yGrids >= getLengths()[1]) {
yGrids--;
if (yGrids < 0) {
yGrids = 0;
}
gl[1] = new double[yGrids];
} else {
gl[1] = gp[1];
}
for (int i = 0; i < xGrids; i++) {
gl[0][i] = gp[0][i] + xSpacing / 2.0;
}
for (int i = 0; i < yGrids; i++) {
gl[1][i] = gp[1][i] + ySpacing / 2.0;
}
return gl;
}
/**
* @return Returns the value for x-axis resolution
*/
public double getxSpacing() {
return xSpacing;
}
/**
* @return Returns the value for y-axis resolution
*/
public double getySpacing() {
return ySpacing;
}
/**
* @param xSpacing
* Sets grid resolution for x-axis
* @param ySpacing
* Sets grid resolution for y-axis
*/
public void setxySpacing(double xSpacing, double ySpacing) {
this.xSpacing = xSpacing;
this.ySpacing = ySpacing;
}
public void setxSpacing(double xSpacing) {
this.xSpacing = xSpacing;
}
public void setySpacing(double ySpacing) {
this.ySpacing = ySpacing;
}
/**
* @return Returns true if midpoints are enabled, false otherwise
*/
public boolean isMidPointOn() {
return midPointOn;
}
/**
* @param midPointOn
* Turns on display of midpoints
*/
public void setMidPointOn(boolean midPointOn) {
this.midPointOn = midPointOn;
}
/**
* @return Returns true if gridpoints are enabled, false otherwise
*/
public boolean isGridLineOn() {
return gridLinesOn;
}
/**
* @param gridLinesOn
* Turns on display of gridpoints
*/
public void setGridLineOn(boolean gridLinesOn) {
this.gridLinesOn = gridLinesOn;
}
public int getNumberOfPoints() {
int[] dimensions = getDimensions();
return dimensions[0] * dimensions[1];
}
public int[] getDimensions() {
double[][] gp = getGridPoints();
return new int[] { gp[0].length, gp[1].length };
}
/**
* returns an array of (x, y) tuples that represent the physical amount the motors
* have to be driven relative to the current position (when taking the image) to drive
* every point on the grid into the beam.
*
* @return the tuples
*/
public double[][] getPhysicalGridPoints() {
double[][] gp = getGridPoints();
double[][] xyTuples = new double[getNumberOfPoints()][2];
double cang = Math.cos(getAngle());
double sang = Math.sin(getAngle());
final double[] spt = getPointRef();
double[] beam = getBeamCentre();
double[] ppmm = new double[] { gridPref.getResolutionX(), gridPref.getResolutionY() };
int i = 0;
for (double x : gp[0]) {
for (double y : gp[1]) {
double[] tuple = xyTuples[i];
tuple[0] = spt[0] + (x - spt[0]) * cang - (y - spt[1]) * sang;
tuple[0] -= beam[0];
tuple[0] /= ppmm[0];
tuple[1] = spt[1] + (y - spt[1]) * cang + (x - spt[0]) * sang;
tuple[1] -= beam[1];
tuple[1] /= ppmm[1];
i++;
}
}
return xyTuples;
}
/**
* beam centre on camera image
* @return x and y pixels for beam centre
*/
public double[] getBeamCentre() {
return new double[] { gridPref.getBeamlinePosX(), gridPref.getBeamlinePosY() };
}
/**
* pixel size in x and y in m
* @return pixel size in x and y in m
*/
public double[] getPixelSizeM() {
return new double[] { 0.001/gridPref.getResolutionX(), 0.001/gridPref.getResolutionY() };
}
@Override
public String toString() {
return super.toString() + String.format(", spacing=[%g, %g]", xSpacing, ySpacing);
}
public GridPreferences getGridPreferences() {
return gridPref;
}
public void setGridPreferences(GridPreferences gridPref) {
this.gridPref = gridPref;
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + (gridLinesOn ? 1231 : 1237);
result = prime * result + ((gridPref == null) ? 0 : gridPref.hashCode());
result = prime * result + (midPointOn ? 1231 : 1237);
long temp;
temp = Double.doubleToLongBits(xSpacing);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(ySpacing);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
GridROI other = (GridROI) obj;
if (gridLinesOn != other.gridLinesOn)
return false;
if (gridPref == null) {
if (other.gridPref != null)
return false;
} else if (!gridPref.equals(other.gridPref))
return false;
if (midPointOn != other.midPointOn)
return false;
if (Double.doubleToLongBits(xSpacing) != Double.doubleToLongBits(other.xSpacing))
return false;
if (Double.doubleToLongBits(ySpacing) != Double.doubleToLongBits(other.ySpacing))
return false;
return true;
}
}