/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2014, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotools.process.spatialstatistics.core;
import java.util.logging.Logger;
import org.geotools.util.logging.Logging;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Point;
/**
* Utility class for spatial statistics
*
* @author Minpa Lee, MangoSystem
*
* @source $URL$
*/
public class SSUtils {
protected static final Logger LOGGER = Logging.getLogger(SSUtils.class);
public enum StatEnum {
LEFT, // area under the curve to the left
RIGHT, // area under the curve to the right
BOTH // two-tailed test
}
/** Default tolerance for double comparisons: 1.0e-8 = 0.00000001 */
public static final double DOUBLE_COMPARE_TOLERANCE = 0.00000001d;
/** Default tolerance for float comparisons: 1.0e-4 = 0.0001 */
public static final float FLOAT_COMPARE_TOLERANCE = 0.0001f;
public static double zProb(double x, StatEnum type) {
// Calculates the area under the curve of the standard normal distribution.
// NOTES: Source - Algorithm AS 66: Applied Statistics, Vol. 22(3), 1973
double pvalue = 0.0d;
double x0 = 0.398942280444;
double x1 = 0.39990348504;
double x2 = 5.75885480458;
double x3 = -29.8213557808;
double x4 = 2.62433121679;
double x5 = 48.6959930692;
double x6 = 5.92885724438;
double x7 = 0.398942280385;
double x8 = -3.8052e-08;
double x9 = 1.00000615302;
double x10 = 3.98064794e-04;
double x11 = 1.98615381364;
double x12 = -0.151679116635;
double x13 = 5.29330324926;
double x14 = 4.8385912808;
double x15 = -15.1508972451;
double x16 = 0.742380924027;
double x17 = 30.789933034;
double x18 = 3.99019417011;
double lt = 7.0;
double con = 1.28;
boolean pos = x >= 0;
double z = Math.abs(x);
if (z > lt) {
pvalue = 0.0d;
} else {
double y = 0.5 * z * z;
if (z <= con) {
pvalue = 0.5 - z * (x0 - x1 * y / (y + x2 + x3 / (y + x4 + x5 / (y + x6))));
} else {
pvalue = x7
* Math.exp(-y)
/ (z + x8 + x9
/ (z + x10 + x11
/ (z + x12 + x13
/ (z + x14 + x15 / (z + x16 + x17 / (z + x18))))));
}
}
switch (type) {
case LEFT:
if (pos)
pvalue = 1.0 - pvalue;
break;
case RIGHT:
if (!pos)
pvalue = 1.0 - pvalue;
break;
default:
pvalue = 2.0 * pvalue;
break;
}
return pvalue;
}
public static double convert2Degree(double radians) {
return radians * (180.0 / Math.PI);
}
public static double convert2Radians(double degree) {
return Math.PI / 180.0 * degree;
}
public static double getAngle(double numerator, double denominator) {
double ratio = 0.0;
if (denominator == 0.0) {
ratio = Math.PI / 2.0;
} else if (numerator == 0.0) {
ratio = Math.PI;
} else {
ratio = Math.abs(Math.atan(numerator / denominator));
}
double angle = 0.0;
if (numerator >= 0) {
if (denominator >= 0) {
angle = ratio;
} else {
angle = Math.PI - ratio;
}
} else {
if (denominator < 0) {
angle = Math.PI + ratio;
} else {
angle = (2.0 * Math.PI) - ratio;
}
}
return angle;
}
public static double getAngle(Point firstPoint, Point lastPoint) {
return getAngle(firstPoint.getCoordinate(), lastPoint.getCoordinate());
}
public static double getAngle(Coordinate firstPoint, Coordinate lastPoint) {
double numerator = lastPoint.x - firstPoint.x;
double denominator = lastPoint.y - firstPoint.y;
return getAngle(numerator, denominator);
}
public static double getEuclideanDistance(double x1, double y1, double x2, double y2) {
double dx = x1 - x2;
double dy = y1 - y2;
return Math.sqrt((dx * dx) + (dy * dy));
}
public static double getManhattanDistance(double x1, double y1, double x2, double y2) {
// it is |x1 - x2| + |y1 - y2|.
double dx = Math.abs(x1 - x2);
double dy = Math.abs(y1 - y2);
return dx + dy;
}
public static boolean compareDouble(double a, double b, double rTol) {
final double aTol = 0.00000001;
if (Math.abs(a - b) < aTol + (rTol * Math.abs(b))) {
return true;
}
return false;
}
public static boolean compareDouble(double a, double b) {
return compareDouble(a, b, DOUBLE_COMPARE_TOLERANCE);
}
public static boolean compareFloat(float a, float b, float rTol) {
final float aTol = 0.0001f;
if (Math.abs(a - b) < aTol + (rTol * Math.abs(b))) {
return true;
}
return false;
}
public static boolean compareFloat(float a, float b) {
return compareFloat(a, b, FLOAT_COMPARE_TOLERANCE);
}
}