/** * Pretty-print the matrix content of an affine transform. * * @param transform * the transform to print. * @return a string representation of the specified transform. */ public static final String toString( final AffineTransform3D transform ) { return String.format( "(% 7.2f, % 7.2f, % 7.2f, % 7.2f\n" + " % 7.2f, % 7.2f, % 7.2f, % 7.2f\n" + " % 7.2f, % 7.2f, % 7.2f, % 7.2f)", transform.get( 0, 0 ), transform.get( 0, 1 ), transform.get( 0, 2 ), transform.get( 0, 3 ), transform.get( 1, 0 ), transform.get( 1, 1 ), transform.get( 1, 2 ), transform.get( 1, 3 ), transform.get( 2, 0 ), transform.get( 2, 1 ), transform.get( 2, 2 ), +transform.get( 2, 3 ) ); } }
/** * Can be used by derived classes in the {@link #draw(Graphics2D)} method to * get the current transform from 2D source coordinates to screen * coordinates. * * @param transform */ protected void getCurrentTransform2D( final AffineTransform2D transform ) { info.getViewerTransform( tmp ); tmp.concatenate( sourceTransform ); transform.set( tmp.get( 0, 0 ), tmp.get( 0, 1 ), tmp.get( 0, 3 ), tmp.get( 1, 0 ), tmp.get( 1, 1 ), tmp.get( 1, 3 ) ); }
@Override public void scroll( final double wheelRotation, final boolean isHorizontal, final int x, final int y ) { synchronized ( affine ) { final double dZ = speed * -wheelRotation; // TODO (optionally) correct for zoom affine.set( affine.get( 2, 3 ) - dZ, 2, 3 ); notifyListener(); } } }
@Override public void click( final int x, final int y ) { synchronized ( affine ) { affine.set( affine.get( 2, 3 ) + speed, 2, 3 ); notifyListener(); } } }
private void scale( final double s, final double x, final double y ) { // center shift affine.set( affine.get( 0, 3 ) - x, 0, 3 ); affine.set( affine.get( 1, 3 ) - y, 1, 3 ); // scale affine.scale( s ); // center un-shift affine.set( affine.get( 0, 3 ) + x, 0, 3 ); affine.set( affine.get( 1, 3 ) + y, 1, 3 ); }
private void scale( final double s, final double x, final double y ) { // center shift affine.set( affine.get( 0, 3 ) - x, 0, 3 ); affine.set( affine.get( 1, 3 ) - y, 1, 3 ); // scale affine.scale( s ); // center un-shift affine.set( affine.get( 0, 3 ) + x, 0, 3 ); affine.set( affine.get( 1, 3 ) + y, 1, 3 ); }
private void scale( final double s, final double x, final double y ) { // center shift affine.set( affine.get( 0, 3 ) - x, 0, 3 ); affine.set( affine.get( 1, 3 ) - y, 1, 3 ); // scale affine.scale( s ); // center un-shift affine.set( affine.get( 0, 3 ) + x, 0, 3 ); affine.set( affine.get( 1, 3 ) + y, 1, 3 ); }
/** * Rotate by d radians around axis. Keep screen coordinates ( * {@link #centerX}, {@link #centerY}) fixed. */ private void rotate( final int axis, final double d ) { // center shift affine.set( affine.get( 0, 3 ) - centerX, 0, 3 ); affine.set( affine.get( 1, 3 ) - centerY, 1, 3 ); // rotate affine.rotate( axis, d ); // center un-shift affine.set( affine.get( 0, 3 ) + centerX, 0, 3 ); affine.set( affine.get( 1, 3 ) + centerY, 1, 3 ); }
/** * Rotate by d radians around axis. Keep screen coordinates ( * {@link #centerX}, {@link #centerY}) fixed. */ private void rotate( final int axis, final double d ) { // center shift affine.set( affine.get( 0, 3 ) - centerX, 0, 3 ); affine.set( affine.get( 1, 3 ) - centerY, 1, 3 ); // rotate affine.rotate( axis, d ); // center un-shift affine.set( affine.get( 0, 3 ) + centerX, 0, 3 ); affine.set( affine.get( 1, 3 ) + centerY, 1, 3 ); }
/** * Rotate by d radians around axis. Keep screen coordinates ( * {@link #centerX}, {@link #centerY}) fixed. */ private void rotate( final int axisNo, final double d ) { // center shift affine.set( affine.get( 0, 3 ) - centerX, 0, 3 ); affine.set( affine.get( 1, 3 ) - centerY, 1, 3 ); // rotate affine.rotate( axisNo, d ); // center un-shift affine.set( affine.get( 0, 3 ) + centerX, 0, 3 ); affine.set( affine.get( 1, 3 ) + centerY, 1, 3 ); }
@Override public void scroll( final double wheelRotation, final boolean isHorizontal, final int x, final int y ) { synchronized ( affine ) { final double theta = speed * wheelRotation * Math.PI / 180.0; // center shift affine.set( affine.get( 0, 3 ) - x, 0, 3 ); affine.set( affine.get( 1, 3 ) - y, 1, 3 ); affine.rotate( 2, theta ); // center un-shift affine.set( affine.get( 0, 3 ) + x, 0, 3 ); affine.set( affine.get( 1, 3 ) + y, 1, 3 ); notifyListener(); } } }
@Override public void setCanvasSize( final int width, final int height, final boolean updateTransform ) { if ( updateTransform ) { synchronized ( affine ) { affine.set( affine.get( 0, 3 ) - canvasW / 2, 0, 3 ); affine.set( affine.get( 1, 3 ) - canvasH / 2, 1, 3 ); affine.scale( ( double ) width / canvasW ); affine.set( affine.get( 0, 3 ) + width / 2, 0, 3 ); affine.set( affine.get( 1, 3 ) + height / 2, 1, 3 ); notifyListener(); } } canvasW = width; canvasH = height; centerX = width / 2; centerY = height / 2; }
@Override public AffineTransform3D get( final double t ) { final AffineTransform3D transform = new AffineTransform3D(); transform.set( transformStart ); final double sx = transform.get( 0, 3 ); final double sy = transform.get( 1, 3 ); final double sz = transform.get( 2, 3 ); final double tx = targetTranslation[ 0 ]; final double ty = targetTranslation[ 1 ]; final double tz = targetTranslation[ 2 ]; transform.set( sx + t * ( tx - sx ), 0, 3 ); transform.set( sy + t * ( ty - sy ), 1, 3 ); transform.set( sz + t * ( tz - sz ), 2, 3 ); return transform; } }
@Override public void setCanvasSize( final int width, final int height, final boolean updateTransform ) { if ( updateTransform ) { synchronized ( affine ) { affine.set( affine.get( 0, 3 ) - canvasW / 2, 0, 3 ); affine.set( affine.get( 1, 3 ) - canvasH / 2, 1, 3 ); affine.scale( ( double ) width / canvasW ); affine.set( affine.get( 0, 3 ) + width / 2, 0, 3 ); affine.set( affine.get( 1, 3 ) + height / 2, 1, 3 ); update(); } } canvasW = width; canvasH = height; centerX = width / 2; centerY = height / 2; }
@Override public void setCanvasSize( final int width, final int height, final boolean updateTransform ) { if ( width == 0 || height == 0 ) { // NB: We are probably in some intermediate layout scenario. // Attempting to trigger a transform update with 0 size will result // in the exception "Matrix is singular" from imglib2-realtrasform. return; } if ( updateTransform ) { synchronized ( affine ) { affine.set( affine.get( 0, 3 ) - canvasW / 2, 0, 3 ); affine.set( affine.get( 1, 3 ) - canvasH / 2, 1, 3 ); affine.scale( ( double ) width / canvasW ); affine.set( affine.get( 0, 3 ) + width / 2, 0, 3 ); affine.set( affine.get( 1, 3 ) + height / 2, 1, 3 ); notifyListener(); } } canvasW = width; canvasH = height; centerX = width / 2; centerY = height / 2; }
@Override public void drag( final int x, final int y ) { synchronized ( affine ) { final double dX = oX - x; final double dY = oY - y; affine.set( affineDragStart ); // center shift affine.set( affine.get( 0, 3 ) - oX, 0, 3 ); affine.set( affine.get( 1, 3 ) - oY, 1, 3 ); final double v = step * speed; affine.rotate( 0, -dY * v ); affine.rotate( 1, dX * v ); // center un-shift affine.set( affine.get( 0, 3 ) + oX, 0, 3 ); affine.set( affine.get( 1, 3 ) + oY, 1, 3 ); notifyListener(); } }
public static Pair< double[], AffineTransform3D > scaling( final Dimensions dim, final AffineTransform3D transformationModel ) { final AffineTransform3D transform = transformationModel.copy(); final AffineTransform3D mapBack = TransformationTools.computeMapBackModel( dim, new AffineTransform3D(), // identity TransformationTools.getModel( transform ), // current model new RigidModel3D() ); // what to use // reset translation mapBack.set( 0.0, 0, 3 ); mapBack.set( 0.0, 1, 3 ); mapBack.set( 0.0, 2, 3 ); //System.out.println( "MapBack: " + TransformationTools.printAffine3D( mapBack ) ); final AffineTransform3D atOrigin = transform.preConcatenate( mapBack ); //System.out.println( "At origin: " + TransformationTools.printAffine3D( atOrigin ) ); // there seems to be a bug in Transform3D, it does mix up the y/z dimensions sometimes // TransformationTools.getScaling( atOrigin, scale ); // the scale is approximately now the diagonal entries in the matrix // and we are only interested in the absolute value since it could be mirrored, in which case the scaling is negative return new ValuePair<>( new double[]{ Math.abs( atOrigin.get( 0, 0 ) ), Math.abs( atOrigin.get( 1, 1 ) ), Math.abs( atOrigin.get( 2, 2 ) ) }, mapBack ); }
@Override public AffineTransform3D get( final double t ) { final AffineTransform3D transform = new AffineTransform3D(); transform.set( transformStart ); // center shift transform.set( transform.get( 0, 3 ) - cX, 0, 3 ); transform.set( transform.get( 1, 3 ) - cY, 1, 3 ); // rotate final double[] qAddCurrent = new double[4]; final AffineTransform3D tAddCurrent = new AffineTransform3D(); LinAlgHelpers.quaternionPower( qAddEnd, t, qAddCurrent ); final double[][] m = new double[3][4]; LinAlgHelpers.quaternionToR( qAddCurrent, m ); tAddCurrent.set( m ); transform.preConcatenate( tAddCurrent ); // center un-shift transform.set( transform.get( 0, 3 ) + cX, 0, 3 ); transform.set( transform.get( 1, 3 ) + cY, 1, 3 ); return transform; } }