use of net.jafama.DoubleWrapper in project elki by elki-project.
the class SphericalCosineEarthModel method latLngRadToECEF.
@Override
public double[] latLngRadToECEF(double lat, double lng) {
// Then to sine and cosines:
// To return cosine
final DoubleWrapper tmp = new DoubleWrapper();
final double slat = FastMath.sinAndCos(lat, tmp), clat = tmp.value;
final double slng = FastMath.sinAndCos(lng, tmp), clng = tmp.value;
return new double[] { EARTH_RADIUS * clat * clng, EARTH_RADIUS * clat * slng, EARTH_RADIUS * slat };
}
use of net.jafama.DoubleWrapper in project elki by elki-project.
the class SVGUtil method svgCircleSegment.
/**
* Create a circle segment.
*
* @param svgp Plot to draw to
* @param centerx Center X position
* @param centery Center Y position
* @param angleStart Starting angle
* @param angleDelta Angle delta
* @param innerRadius inner radius
* @param outerRadius outer radius
* @return SVG element representing this circle segment
*/
public static Element svgCircleSegment(SVGPlot svgp, double centerx, double centery, double angleStart, double angleDelta, double innerRadius, double outerRadius) {
// To return cosine
final DoubleWrapper tmp = new DoubleWrapper();
double sin1st = FastMath.sinAndCos(angleStart, tmp);
double cos1st = tmp.value;
double sin2nd = FastMath.sinAndCos(angleStart + angleDelta, tmp);
double cos2nd = tmp.value;
double inner1stx = centerx + (innerRadius * sin1st);
double inner1sty = centery - (innerRadius * cos1st);
double outer1stx = centerx + (outerRadius * sin1st);
double outer1sty = centery - (outerRadius * cos1st);
double inner2ndx = centerx + (innerRadius * sin2nd);
double inner2ndy = centery - (innerRadius * cos2nd);
double outer2ndx = centerx + (outerRadius * sin2nd);
double outer2ndy = centery - (outerRadius * cos2nd);
double largeArc = 0;
if (angleDelta >= Math.PI) {
largeArc = 1;
}
SVGPath path = new SVGPath(inner1stx, inner1sty);
path.lineTo(outer1stx, outer1sty);
path.ellipticalArc(outerRadius, outerRadius, 0, largeArc, 1, outer2ndx, outer2ndy);
path.lineTo(inner2ndx, inner2ndy);
if (innerRadius > 0) {
path.ellipticalArc(innerRadius, innerRadius, 0, largeArc, 0, inner1stx, inner1sty);
}
return path.makeElement(svgp);
}
use of net.jafama.DoubleWrapper in project elki by elki-project.
the class SphereUtil method latlngMinDistRad.
/**
* Point to rectangle minimum distance.
*
* Complexity:
* <ul>
* <li>Trivial cases (on longitude slice): no trigonometric functions.</li>
* <li>Corner case: 3/4 trig + 4-5 trig, 1 sqrt</li>
* <li>Cross-track case: 4+2 trig</li>
* </ul>
*
* <b>Important:</b> Rectangles must be in -pi:+pi, and must have min <
* max, so they cannot cross the date line.
*
* Reference:
* <p>
* Erich Schubert, Arthur Zimek and Hans-Peter Kriegel<br />
* Geodetic Distance Queries on R-Trees for Indexing Geographic Data<br />
* 13th Int. Symposium on Advances in Spatial and Temporal Databases
* </p>
*
* @param plat Latitude of query point.
* @param plng Longitude of query point.
* @param rminlat Min latitude of rectangle.
* @param rminlng Min longitude of rectangle.
* @param rmaxlat Max latitude of rectangle.
* @param rmaxlng Max longitude of rectangle.
* @return Distance on unit sphere.
*/
@//
Reference(//
authors = "Erich Schubert, Arthur Zimek and Hans-Peter Kriegel", //
title = "Geodetic Distance Queries on R-Trees for Indexing Geographic Data", //
booktitle = "13th Int. Symposium on Advances in Spatial and Temporal Databases", url = "http://dx.doi.org/10.1007/978-3-642-40235-7_9")
public static double latlngMinDistRad(double plat, double plng, double rminlat, double rminlng, double rmaxlat, double rmaxlng) {
// Degenerate rectangles:
if ((rminlat >= rmaxlat) && (rminlng >= rmaxlng)) {
return cosineOrHaversineRad(rminlat, rminlng, plat, plng);
}
// The simplest case is when the query point is in the same "slice":
if (rminlng <= plng && plng <= rmaxlng) {
return // Inside
(rminlat <= plat && plat <= rmaxlat) ? // Inside
0 : // S, N
(plat < rminlat) ? rminlat - plat : plat - rmaxlat;
}
// Determine whether going east or west is shorter.
double lngE = rminlng - plng, lngW = plng - rmaxlng;
// Ensure delta to be in 0 to 2pi.
lngE = lngE >= 0 ? lngE : lngE + TWOPI;
lngW = lngW >= 0 ? lngW : lngW + TWOPI;
// Case distinction east or west:
final double lngD = (lngE <= lngW) ? lngE : lngW;
final double rlng = (lngE <= lngW) ? rminlng : rmaxlng;
// To return cosine
final DoubleWrapper tmp = new DoubleWrapper();
final double slngD = sinAndCos(lngD, tmp), clngD = tmp.value;
final double tlatQ = tan(plat);
if (lngD >= HALFPI) {
// XTD disappears at 90°
return cosineOrHaversineRad(//
plat, //
plng, // N/S
tlatQ >= tan((rmaxlat + rminlat) * .5) * clngD ? rmaxlat : rminlat, rlng);
}
if (tlatQ >= tan(rmaxlat) * clngD) {
// North corner
return cosineOrHaversineRad(plat, plng, rmaxlat, rlng);
}
if (tlatQ <= tan(rminlat) * clngD) {
// South corner
return cosineOrHaversineRad(plat, plng, rminlat, rlng);
}
// Cross-track-distance to longitude line.
return asin(cos(plat) * slngD);
}
use of net.jafama.DoubleWrapper in project elki by elki-project.
the class SphereUtil method ellipsoidVincentyFormulaRad.
/**
* Compute the approximate great-circle distance of two points.
*
* Reference:
* <p>
* T. Vincenty<br />
* Direct and inverse solutions of geodesics on the ellipsoid with application
* of nested equations<br />
* Survey review 23 176, 1975
* </p>
*
* @param f Ellipsoid flattening
* @param lat1 Latitude of first point in degree
* @param lon1 Longitude of first point in degree
* @param lat2 Latitude of second point in degree
* @param lon2 Longitude of second point in degree
* @return Distance for a minor axis of 1.
*/
@//
Reference(//
authors = "T. Vincenty", //
title = "Direct and inverse solutions of geodesics on the ellipsoid with application of nested equations", booktitle = "Survey review 23 176, 1975", url = "http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf")
public static double ellipsoidVincentyFormulaRad(double f, double lat1, double lon1, double lat2, double lon2) {
final double dlon = (lon2 >= lon1) ? (lon2 - lon1) : (lon1 - lon2);
// = 1 - (a-b)/a = b/a
final double onemf = 1 - f;
// Second eccentricity squared
// = a/b
final double a_b = 1. / onemf;
// (a^2-b^2)/(b^2)
final double ecc2 = (a_b + 1) * (a_b - 1);
// Reduced latitudes:
final double u1 = atan(onemf * tan(lat1));
final double u2 = atan(onemf * tan(lat2));
// Trigonometric values
// To return cosine
final DoubleWrapper tmp = new DoubleWrapper();
final double su1 = sinAndCos(u1, tmp), cu1 = tmp.value;
final double su2 = sinAndCos(u2, tmp), cu2 = tmp.value;
// Eqn (13) - initial value
double lambda = dlon;
for (int i = 0; ; i++) {
final double slon = sinAndCos(lambda, tmp), clon = tmp.value;
// Eqn (14) - \sin \sigma
final double term1 = cu2 * slon, term2 = cu1 * su2 - su1 * cu2 * clon;
final double ssig = sqrt(term1 * term1 + term2 * term2);
// Eqn (15) - \cos \sigma
final double csig = su1 * su2 + cu1 * cu2 * clon;
// Two identical points?
if (!(ssig > 0)) {
return 0.;
}
// Eqn (16) - \sigma from \tan \sigma
final double sigma = atan2(ssig, csig);
// Eqn (17) - \sin \alpha, and this way \cos^2 \alpha
final double salp = cu1 * cu2 * slon / ssig;
final double c2alp = (1. + salp) * (1. - salp);
// Eqn (18) - \cos 2 \sigma_m
final double ctwosigm = (Math.abs(c2alp) > 0) ? csig - 2.0 * su1 * su2 / c2alp : 0.;
final double c2twosigm = ctwosigm * ctwosigm;
// Eqn (10) - C
final double cc = f * .0625 * c2alp * (4.0 + f * (4.0 - 3.0 * c2alp));
// Eqn (11) - new \lambda
final double prevlambda = lambda;
lambda = dlon + //
(1.0 - cc) * f * salp * (sigma + cc * ssig * (ctwosigm + cc * csig * (-1.0 + 2.0 * c2twosigm)));
// Check for convergence:
if (Math.abs(prevlambda - lambda) < PRECISION || i >= MAX_ITER) {
// TODO: what is the proper result to return on MAX_ITER (antipodal
// points)?
// Definition of u^2, rewritten to use second eccentricity.
final double usq = c2alp * ecc2;
// Eqn (3) - A
final double aa = 1.0 + usq / 16384.0 * (4096.0 + usq * (-768.0 + usq * (320.0 - 175.0 * usq)));
// Eqn (4) - B
final double bb = usq / 1024.0 * (256.0 + usq * (-128.0 + usq * (74.0 - 47.0 * usq)));
// Eqn (6) - \Delta \sigma
final double dsig = bb * ssig * (ctwosigm + .25 * bb * (//
csig * (-1.0 + 2.0 * c2twosigm) - ONE_SIXTH * bb * ctwosigm * (-3.0 + 4.0 * ssig * ssig) * (-3.0 + 4.0 * c2twosigm)));
// Eqn (19) - s
return aa * (sigma - dsig);
}
}
}
use of net.jafama.DoubleWrapper in project elki by elki-project.
the class SphereUtil method sphericalVincentyFormulaRad.
/**
* Compute the approximate great-circle distance of two points.
*
* Uses Vincenty's Formula for the spherical case, which does not require
* iterations.
*
* Complexity: 7 trigonometric functions, 1 sqrt.
*
* Reference:
* <p>
* T. Vincenty<br />
* Direct and inverse solutions of geodesics on the ellipsoid with application
* of nested equations<br />
* Survey review 23 176, 1975
* </p>
*
* @param lat1 Latitude of first point in degree
* @param lon1 Longitude of first point in degree
* @param lat2 Latitude of second point in degree
* @param lon2 Longitude of second point in degree
* @return Distance on unit sphere
*/
@//
Reference(//
authors = "T. Vincenty", //
title = "Direct and inverse solutions of geodesics on the ellipsoid with application of nested equations", //
booktitle = "Survey review 23 176, 1975", url = "http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf")
public static double sphericalVincentyFormulaRad(double lat1, double lon1, double lat2, double lon2) {
// Half delta longitude.
final double dlnh = (lon1 > lon2) ? (lon1 - lon2) : (lon2 - lon1);
// Spherical special case of Vincenty's formula - no iterations needed
// To return cosine
final DoubleWrapper tmp = new DoubleWrapper();
final double slat1 = sinAndCos(lat1, tmp), clat1 = tmp.value;
final double slat2 = sinAndCos(lat2, tmp), clat2 = tmp.value;
final double slond = sinAndCos(dlnh, tmp), clond = tmp.value;
final double a = clat2 * slond;
final double b = (clat1 * slat2) - (slat1 * clat2 * clond);
return atan2(sqrt(a * a + b * b), slat1 * slat2 + clat1 * clat2 * clond);
}
Aggregations