/*-
*******************************************************************************
* 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.impl.function;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.dawnsci.analysis.api.roi.IRectangularROI;
import org.eclipse.january.dataset.DTypeUtils;
import org.eclipse.january.dataset.Dataset;
import org.eclipse.january.dataset.DatasetFactory;
import org.eclipse.january.dataset.DatasetUtils;
import org.eclipse.january.dataset.IDataset;
import org.eclipse.january.dataset.Maths;
/**
* Map a 2D dataset from Cartesian to rotated Cartesian coordinates and return that remapped dataset from a rotated
* rectangle return a dataset and an unclipped unit version (for clipping compensation)
*/
public class MapToRotatedCartesian implements DatasetToDatasetFunction {
int ox, oy;
int h, w;
private double cp;
private double sp;
/**
* Set up mapping of rotated 2D dataset
*
* @param x
* top left x (in pixel coordinates)
* @param y
* top left y
* @param width
* @param height
* @param angle in degrees
* (clockwise from positive x axis)
*/
public MapToRotatedCartesian(int x, int y, int width, int height, double angle) {
ox = x;
oy = y;
h = height;
w = width;
double phi = Math.toRadians(angle);
cp = Math.cos(phi);
sp = Math.sin(phi);
}
/**
* @param x
* @param y
* @param width
* @param height
* @param angle
* @param isDegrees
*/
public MapToRotatedCartesian(int x, int y, int width, int height, double angle, boolean isDegrees) {
this(x, y, width, height, isDegrees ? Math.toRadians(angle) : angle);
}
/**
* @param roi
*/
public MapToRotatedCartesian(IRectangularROI roi) {
this((int) roi.getPointX(), (int) roi.getPointY(), (int) roi.getLength(0), (int) roi.getLength(1), roi.getAngleDegrees());
}
/**
* @param i
* @param j
* @return position of indexed point on grid
*/
public int[] getPoint(int i, int j) {
return new int[] {(int) (oy + j * sp + i * cp), (int) (ox + j * cp - i * sp)};
}
/**
* @param pos
* @return position of point on grid
*/
public int[] getPoint(int[] pos) {
return getPoint(pos[0], pos[1]);
}
/**
* The class implements mapping of a Cartesian grid sampled data (pixels) to another Cartesian grid
*
* @param datasets
* input 2D dataset
* @return two 2D dataset where rows label tilted rows and columns label tilted columns
*/
@Override
public List<Dataset> value(IDataset... datasets) {
if (datasets.length == 0)
return null;
List<Dataset> result = new ArrayList<Dataset>();
for (IDataset ids : datasets) {
if (ids.getRank() != 2)
return null;
Dataset ds = DatasetUtils.convertToDataset(ids);
int[] os = new int[] { h, w };
// work out cosine and sine
Dataset newmap = DatasetFactory.zeros(os, DTypeUtils.getBestFloatDType(ds.getDType()));
Dataset unitmap = DatasetFactory.zeros(newmap);
double cx, cy;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
unitmap.set(1.0, y, x);
// back transformation from tilted to original coordinates
cx = ox + x * cp - y * sp;
cy = oy + x * sp + y * cp;
newmap.set(Maths.interpolate(ds, cy, cx), y, x);
}
}
result.add(newmap);
result.add(unitmap);
}
return result;
}
}