Main.java Source code

Java tutorial

Introduction

Here is the source code for Main.java

Source

//package com.java2s;
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.

import android.location.Location;

public class Main {
    static final double DEG_TO_RAD = 0.017453292519943295769236907684886;
    static final double EARTH_RADIUS_IN_METERS = 6372797.560856;

    public static double distanceFromLineInMeters(Location C, Location A, Location B) {
        double dA = arcInRadians(C, A);
        double dB = arcInRadians(C, B);
        double dAB = arcInRadians(A, B);

        if (dA == 0)
            return 0;
        if (dB == 0)
            return 0;
        if (dAB == 0)
            return dA;

        return EARTH_RADIUS_IN_METERS * distanceFromArc(dA, dB, dAB);
    }

    static double arcInRadians(Location A, Location B) {
        double latitudeArc = (A.getLatitude() - B.getLatitude()) * DEG_TO_RAD;
        double longitudeArc = (A.getLongitude() - B.getLongitude()) * DEG_TO_RAD;
        double latitudeH = Math.sin(latitudeArc * 0.5);
        latitudeH *= latitudeH;
        double lontitudeH = Math.sin(longitudeArc * 0.5);
        lontitudeH *= lontitudeH;
        double tmp = Math.cos(A.getLatitude() * DEG_TO_RAD) * Math.cos(B.getLatitude() * DEG_TO_RAD);
        return 2.0 * Math.asin(Math.sqrt(latitudeH + tmp * lontitudeH));
    }

    static double distanceFromArc(double dA, double dB, double dAB) {
        // In spherical trinagle ABC
        // a is length of arc BC, that is dB
        // b is length of arc AC, that is dA
        // c is length of arc AB, that is dAB
        // We rename parameters so following formulas are more clear:
        double a = dB;
        double b = dA;
        double c = dAB;

        // First, we calculate angles alpha and beta in spherical triangle ABC
        // and based on them we decide how to calculate the distance:
        if (Math.sin(b) * Math.sin(c) == 0.0 || Math.sin(c) * Math.sin(a) == 0.0) {
            // It probably means that one of distance is n*pi, which gives around 20000km for n = 1,
            // unlikely for Denmark, so we should be fine.
            return -1.0;
        }

        double alpha = Math.acos((Math.cos(a) - Math.cos(b) * Math.cos(c)) / (Math.sin(b) * Math.sin(c)));
        double beta = Math.acos((Math.cos(b) - Math.cos(c) * Math.cos(a)) / (Math.sin(c) * Math.sin(a)));

        // It is possible that both sinuses are too small so we can get nan when dividing with them
        if (Double.isNaN(alpha) || Double.isNaN(beta)) {
            // double cosa = cos(a);
            // double cosbc = cos(b) * cos(c);
            // double minus1 = cosa - cosbc;
            // double sinbc = sin(b) * sin(c);
            // double div1 = minus1 / sinbc;
            //
            // double cosb = cos(b);
            // double cosca = cos(a) * cos(c);
            // double minus2 = cosb - cosca;
            // double sinca = sin(a) * sin(c);
            // double div2 = minus2 / sinca;

            return -1.0;
        }

        // If alpha or beta are zero or pi, it means that C is on the same circle as arc AB,
        // we just need to figure out if it is between AB:
        if (alpha == 0.0 || beta == 0.0) {
            return (dA + dB > dAB) ? Math.min(dA, dB) : 0.0;
        }

        // If alpha is obtuse and beta is acute angle, then
        // distance is equal to dA:
        if (alpha > Math.PI / 2 && beta < Math.PI / 2)
            return dA;

        // Analogously, if beta is obtuse and alpha is acute angle, then
        // distance is equal to dB:
        if (beta > Math.PI / 2 && alpha < Math.PI / 2)
            return dB;

        // If both alpha and beta are acute or both obtuse or one of them (or both) are right,
        // distance is the height of the spherical triangle ABC:

        // Again, unlikely, since it would render at least pi/2*EARTH_RADIUS_IN_METERS, which is too much.
        if (Math.cos(a) == 0.0)
            return -1;

        double x = Math.atan(-1.0 / Math.tan(c) + (Math.cos(b) / (Math.cos(a) * Math.sin(c))));

        // Similar to previous edge cases...
        if (Math.cos(x) == 0.0)
            return -1.0;

        return Math.acos(Math.cos(a) / Math.cos(x));
    }
}