001/*******************************************************************************
002 * This software is provided as a supplement to the authors' textbooks on digital
003 * image processing published by Springer-Verlag in various languages and editions.
004 * Permission to use and distribute this software is granted under the BSD 2-Clause
005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause).
006 * Copyright (c) 2006-2023 Wilhelm Burger, Mark J. Burge. All rights reserved.
007 * Visit https://imagingbook.com for additional details.
008 ******************************************************************************/
009
010package imagingbook.common.geometry.mappings.linear;
011
012import imagingbook.common.geometry.basic.Pnt2d;
013
014/**
015 * <p>
016 * This class represents a pure 2D translation (as a special case of affine transformation). Instances are immutable and
017 * it can be assumed that every instance of this class is indeed a translation. See Secs. 21.1.3 and 21.3.1 of [1] for
018 * details.
019 * </p>
020 * <p>
021 * [1] W. Burger, M.J. Burge, <em>Digital Image Processing &ndash; An Algorithmic Introduction</em>, 3rd ed, Springer
022 * (2022).
023 * </p>
024 *
025 * @author WB
026 */
027public class Translation2D extends AffineMapping2D {
028
029        /**
030         * Constructor, creates a new 2D translation mapping.
031         * @param tx translation in x
032         * @param ty translation in y
033         */
034        public Translation2D(double tx, double ty) {
035                super(1, 0, tx, 0, 1, ty);
036        }
037        
038        /**
039         * Constructor, creates a new 2D translation mapping.
040         * @param txy translation in x/y (2-element array)
041         */
042        public Translation2D(double[] txy) {
043                this(txy[0], txy[1]);
044        }
045
046        /** 
047         * Constructor, reates a new translation instance from a given translation.
048         * @param m a 2D translation mapping
049         */
050        public Translation2D(Translation2D m) {
051                this(m.a02, m.a12);
052        }
053
054        /**
055         * Creates a new translation that maps between the first point to the second point specified.
056         *
057         * @param p the first point
058         * @param q the second point
059         * @return a new translation instance
060         */
061        public static Translation2D fromPoints(Pnt2d p, Pnt2d q) {
062                return new Translation2D(q.getX() - p.getX(), q.getY() - p.getY());
063        }
064        
065        // ----------------------------------------------------------
066
067        @Override
068        public Translation2D duplicate() {
069                return new Translation2D(this);
070        }
071
072        /**
073         * Concatenates this translation A with another translation B and returns a new translation C, such that C(x) =
074         * B(A(x)).
075         *
076         * @param B the second translation
077         * @return the concatenated translations
078         */
079        public Translation2D concat(Translation2D B) {
080                return new Translation2D(this.a02 + B.a02, this.a12 + B.a12);
081        }
082        
083        @Override
084        public Translation2D getInverse() {
085                return new Translation2D(-this.a02, -this.a12);
086        }
087
088        @Override
089        public double[][] getJacobian(Pnt2d xy) {
090                // this mapping has a constant Jacobian (indep. of xy)
091                return new double[][]
092                        {{1, 0},
093                         {0, 1}};
094        }
095}