@@ -0,0 +1,2327 @@
+%0Apackage org.bonej.ops;%0A%0Aimport net.imagej.ops.AbstractOp;%0Aimport net.imagej.ops.Op;%0Aimport net.imglib2.type.numeric.real.DoubleType;%0A%0Aimport org.apache.commons.math3.random.UnitSphereRandomVectorGenerator;%0Aimport org.scijava.ItemIO;%0Aimport org.scijava.plugin.Parameter;%0Aimport org.scijava.plugin.Plugin;%0Aimport org.scijava.vecmath.AxisAngle4d;%0Aimport org.scijava.vecmath.Quat4d;%0Aimport org.scijava.vecmath.Vector3d;%0A%0A/**%0A * Rotates a vector around an axis by the given radians.%0A * %3Cp%3E%0A * The rotations are done by quaternions so there's no risk of gimbal lock as%0A * with rotation matrices.%0A * %3C/p%3E%0A * %0A * @author Richard Domander%0A */%0A@Plugin(type = Op.class)%0Apublic class RotateAboutAxis extends AbstractOp %7B%0A%0A%09@Parameter(type = ItemIO.BOTH)%0A%09private Vector3d vector;%0A%0A%09/**%0A%09 * An axis around which the vector is rotated. The axis should be a unit%0A%09 * vector, if not it'll be normalized. If left null, it's generated randomly.%0A%09 */%0A%09@Parameter(type = ItemIO.BOTH, required = false)%0A%09private Vector3d axis;%0A%0A%09/** The rotation angle in radians. If left null, it's generated randomly. */%0A%09// A ItemIO.BOTH needs to be a mutable object, i.e. a Double won't do.%0A%09@Parameter(type = ItemIO.BOTH, required = false)%0A%09private DoubleType angle;%0A%0A%09/**%0A%09 * Generates four normally distributed values that describe a unit quaternion.%0A%09 * These can be used to create uniformally distributed rotations.%0A%09 */%0A%09private static final UnitSphereRandomVectorGenerator qGenerator =%0A%09%09new UnitSphereRandomVectorGenerator(4);%0A%0A%09@Override%0A%09public void run() %7B%0A%09%09final Quat4d q = populateParameters();%0A%09%09rotate(vector, q);%0A%09%7D%0A%0A%09private static void rotate(final Vector3d v, final Quat4d q) %7B%0A%09%09final Quat4d p = new Quat4d();%0A%09%09p.set(v.getX(), v.getY(), v.getZ(), 0);%0A%09%09final Quat4d r = new Quat4d(q);%0A%09%09r.mul(p);%0A%09%09r.mulInverse(q);%0A%09%09v.set(r.x, r.y, r.z);%0A%09%7D%0A%0A%09private Quat4d populateParameters() %7B%0A%09%09final Quat4d q = new Quat4d();%0A%09%09q.set(qGenerator.nextVector());%0A%09%09final AxisAngle4d axisAngle = new AxisAngle4d();%0A%09%09axisAngle.set(q);%0A%09%09if (axis == null) %7B%0A%09%09%09axis = new Vector3d(axisAngle.x, axisAngle.y, axisAngle.z);%0A%09%09%7D%0A%09%09else %7B%0A%09%09%09axis.normalize();%0A%09%09%7D%0A%09%09if (angle == null) %7B%0A%09%09%09angle = new DoubleType(axisAngle.angle);%0A%09%09%7D%0A%09%09axisAngle.set(axis.getX(), axis.getY(), axis.getZ(), angle.get());%0A%09%09q.set(axisAngle);%0A%09%09q.normalize();%0A%09%09return q;%0A%09%7D%0A%7D%0A

Implement rotate op