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.nonlinear;
011
012import imagingbook.pub.geometry.mappings.Mapping;
013
014public class SphereMapping extends Mapping {
015        double xc;                              // center of sphere
016        double yc;
017        double rad;                             // radius of sphere
018        double refIdx = 1.8;    // refraction index
019   
020        SphereMapping (double xc, double yc, double rad, boolean inv) {
021                this.xc = xc;
022                this.yc = yc;
023                this.rad = rad;
024                this.isInverseFlag = inv;
025        }
026        
027        public static SphereMapping makeInverseMapping(double xc, double yc, double rad){
028                return new SphereMapping(xc, yc, rad, true);
029        }
030
031        public double[] applyTo (double[] xy){
032                double dx = xy[0]-xc;
033                double dy = xy[1]-yc;
034                double dx2 = dx*dx;
035                double dy2 = dy*dy;
036                double rad2 = rad*rad;
037                
038                double r2 = dx*dx + dy*dy;
039                
040                if (r2 > 0 && r2 < rad2) {
041                        double z2 = rad2 - r2; 
042                        double z = Math.sqrt(z2);
043
044                        double xAlpha = Math.asin(dx / Math.sqrt(dx2 + z2));
045                        double xBeta = xAlpha - xAlpha * (1 / refIdx);
046                        double x1 = xy[0] - z * Math.tan(xBeta);
047
048                        double yAlpha = Math.asin(dy / Math.sqrt(dy2 + z2));
049                        double yBeta = yAlpha - yAlpha * (1 / refIdx);
050                        double y1 = xy[1] - z * Math.tan(yBeta);
051                        //pnt.setLocation(x1, y1);
052                        return new double[] {x1, y1};
053                } 
054                // otherwise leave point unchanged
055                return xy.clone();
056        }
057}
058
059
060
061