/*
* Copyright (c) 2012 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
*/
package uk.ac.diamond.scisoft.analysis.crystallography;
import java.util.Arrays;
import javax.vecmath.Vector3d;
/**
* UnitCell class as specified by lengths and angles of cell
*/
public class UnitCell extends LatticeCell {
private double[] lengths;
private double[] angles;
protected UnitCell() {
}
/**
* Cubic unit cell
* @param length
*/
public UnitCell(double length) {
this(new double[] { length, length, length });
}
/**
* Cuboid unit cell or general unit cell
*
* @param parameters can be lengths (for cuboid) or both lengths and angles
*/
public UnitCell(double[] parameters) {
super();
if (parameters.length >= 6) {
setLengths(Arrays.copyOf(parameters, 3));
setAngles(Arrays.copyOfRange(parameters, 3, 6));
makeBasisVectors();
} else if (parameters.length == 3) {
setLengths(parameters.clone());
setAngles(new double[] { 90, 90, 90 });
a = new Vector3d(lengths[0], 0, 0);
b = new Vector3d(0, lengths[1], 0);
c = new Vector3d(0, 0, lengths[2]);
} else {
throw new IllegalArgumentException("Insufficient number of parameters: need at least three");
}
}
/**
* @param lengths
* @param angles (in degrees)
*/
public UnitCell(double[] lengths, double[] angles) {
super();
setLengths(lengths);
setAngles(angles);
makeBasisVectors();
}
private void makeBasisVectors() {
double alpha = Math.toRadians(angles[0]);
double beta = Math.toRadians(angles[1]);
double gamma = Math.toRadians(angles[2]);
a = new Vector3d(lengths[0], 0, 0);
b = new Vector3d(lengths[1] * Math.cos(gamma), lengths[1] * Math.sin(gamma), 0);
double sinBcosA = (Math.cos(alpha) - Math.cos(beta) * Math.cos(gamma)) / Math.sin(gamma);
double sinA = sinBcosA / Math.sin(beta);
sinA = 1.0 - sinA * sinA;
if (sinA < 0.0)
sinA = 0.0; // for numerical errors
c = new Vector3d(lengths[2] * Math.cos(beta), lengths[2] * sinBcosA,
lengths[2] * Math.sin(beta) * Math.sqrt(sinA));
}
/**
* @param oa
* @param ob
* @param oc
*/
public UnitCell(double[] oa, double[] ob, double[] oc) {
super();
a = new Vector3d(oa[0], oa[1], oa[2]);
b = new Vector3d(ob[0], ob[1], ob[2]);
c = new Vector3d(oc[0], oc[1], oc[2]);
setLengths(new double[] { a.length(), b.length(), c.length() });
setAngles(new double[] { 90, 90, 90 });
}
/**
* @param lengths of unit cell
*/
public void setLengths(double[] lengths) {
this.lengths = lengths;
}
/**
* @return lengths of unit cell
*/
public double[] getLengths() {
return lengths;
}
/**
* @param angles (in degrees)
*/
public void setAngles(double[] angles) {
this.angles = angles;
}
/**
* @return angles (in degrees) of unit cell
*/
public double[] getAngles() {
return angles;
}
protected void calculateAll() {
if (lengths == null)
lengths = new double[3];
lengths[0] = a.length();
lengths[1] = b.length();
lengths[2] = c.length();
if (angles == null)
angles = new double[3];
angles[0] = Math.toDegrees(b.angle(c));
angles[1] = Math.toDegrees(c.angle(a));
angles[2] = Math.toDegrees(a.angle(b));
}
@Override
public void setA(Vector3d a) {
super.setA(a);
lengths[0] = a.length();
angles[1] = Math.toDegrees(c.angle(a));
angles[2] = Math.toDegrees(a.angle(b));
}
@Override
public void setB(Vector3d b) {
super.setB(b);
lengths[1] = b.length();
angles[0] = Math.toDegrees(b.angle(c));
angles[2] = Math.toDegrees(a.angle(b));
}
@Override
public void setC(Vector3d c) {
super.setC(c);
lengths[2] = c.length();
angles[0] = Math.toDegrees(b.angle(c));
angles[1] = Math.toDegrees(c.angle(a));
}
}