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-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 
007 * Visit http://imagingbook.com for additional details.
008 *******************************************************************************/
009
010package imagingbook.pub.geometry.mappings.linear;
011
012import java.awt.geom.Point2D;
013
014public class AffineMapping extends ProjectiveMapping {
015        
016        /**
017         * Creates the identity mapping.
018         */
019        public AffineMapping() {
020                super();
021        }
022   
023        public AffineMapping (
024                        double a11, double a12, double a13, 
025                        double a21, double a22, double a23, 
026                        boolean inv) {
027                super(
028                                a11, a12, a13, 
029                                a21, a22, a23, 
030                                0, 0, inv);
031        }
032        
033        public AffineMapping(LinearMapping lm) {
034                super(lm);
035                a20 = 0;
036                a21 = 0;
037                a22 = 1;
038        }
039        
040        public AffineMapping(Point2D A1, Point2D A2, Point2D A3, Point2D B1, Point2D B2, Point2D B3) {
041                super();
042                double ax1 = A1.getX(), ax2 = A2.getX(), ax3 = A3.getX();
043                double ay1 = A1.getY(), ay2 = A2.getY(), ay3 = A3.getY();
044                double bx1 = B1.getX(), bx2 = B2.getX(), bx3 = B3.getX();
045                double by1 = B1.getY(), by2 = B2.getY(), by3 = B3.getY();
046                
047                double S = ax1*(ay3-ay2) + ax2*(ay1-ay3) + ax3*(ay2-ay1); // TODO: check S for zero value and throw exception!
048                a00 = (ay1*(bx2-bx3) + ay2*(bx3-bx1) + ay3*(bx1-bx2)) / S;
049                a01 = (ax1*(bx3-bx2) + ax2*(bx1-bx3) + ax3*(bx2-bx1)) / S;
050                a10 = (ay1*(by2-by3) + ay2*(by3-by1) + ay3*(by1-by2)) / S;
051                a11 = (ax1*(by3-by2) + ax2*(by1-by3) + ax3*(by2-by1)) / S;
052                a02 = 
053                                (ax1*(ay3*bx2-ay2*bx3) + ax2*(ay1*bx3-ay3*bx1) + ax3*(ay2*bx1-ay1*bx2)) / S;
054                a12 = 
055                                (ax1*(ay3*by2-ay2*by3) + ax2*(ay1*by3-ay3*by1) + ax3*(ay2*by1-ay1*by2)) / S;
056        }
057        
058        public AffineMapping(Point2D[] A, Point2D[] B) {
059                this(A[0], A[1], A[2], B[0], B[1], B[2]);
060        }
061        
062        public AffineMapping concat(AffineMapping B) {  // TODO: more general arguments?
063                AffineMapping A = new AffineMapping(this);
064                A.concatDestructive(B);
065                return A;
066        }
067        
068        @Override
069        public AffineMapping invert() {
070                AffineMapping pm = new AffineMapping(this);
071                pm.invertDestructive();
072                return pm;
073        }
074        
075        @Override
076        public AffineMapping duplicate() {
077                return (AffineMapping) this.clone();
078        }
079        
080        // warp parameter support (used in Lucas-Kanade-matcher) --------------------------
081        
082        @Override
083        public int getWarpParameterCount() {
084                return 6;
085        }
086        
087        @Override
088        public double[] getWarpParameters() {
089                double[] p = new double[] {
090                        a00 - 1, 
091                        a01,
092                        a10,
093                        a11 - 1,
094                        a02,
095                        a12 };
096                return p;
097        }
098
099        @Override
100        public void setWarpParameters(double[] p) {
101                a00 = p[0] + 1;
102                a01 = p[1];
103                a10 = p[2];
104                a11 = p[3] + 1;
105                a02 = p[4];
106                a12 = p[5];
107        }
108        
109        @Override
110        public double[][] getWarpJacobian(double[] xy) {
111                final double x = xy[0];
112                final double y = xy[1];
113                return new double[][]
114                                {{x, y, 0, 0, 1, 0},
115                                 {0, 0, x, y, 0, 1}};
116        }
117        
118}
119
120
121
122