package com.algobase.share.geo;

import android.location.Location;
import java.util.Vector;

public class Geometry {

  static final int EARTH_RADIUS = 6371000;

  public static double polarDistance(double lon1, double lat1, 
                                     double lon2, double lat2)
  { final double EARTH_RADIUS = 6371000;
    final double f = Math.PI/180;
    lon1 *= f;
    lat1 *= f;
    lon2 *= f;
    lat2 *= f;
    double d = Math.sin(lat1) * Math.sin(lat2) +
                      Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon1-lon2);
    if (d > +1) d = +1;
    if (d < -1) d = -1;
    return Math.acos(d) * EARTH_RADIUS;
  }
 

/*
  public static double distance_to_line(Location a, Location b, Location c)
  { // distance from c to line (great-circle) through a and b
    // Funktioniert NICHT  (evtl. negative Werte)
    double d_ac = a.distanceTo(c);
    double b_ac = a.bearingTo(c);
    double b_ab = a.bearingTo(b);
    return Math.asin(Math.sin(d_ac/EARTH_RADIUS) * Math.sin(b_ac-b_ab))
           *EARTH_RADIUS;
  }
*/

  public static double distance_to_line(Location A, Location B, Location C)
  { // distance from C to line (great-circle) through A and B
    // Approximation: Hoehe im Dreieck (A,B,C) in der Ebene

    double a = B.distanceTo(C);
    double b = C.distanceTo(A);
    double c = A.distanceTo(B);

    double s = (a+b+c)/2;
    double area = Math.sqrt(s*(s-a)*(s-b)*(s-c));

    return 2*area/c;
  }



  public static int DouglasPeucker(Location[] path, Location[] result, 
                                                    double delta)
  {
    return DouglasPeucker(path,path.length,result,delta);
   }


  public static int DouglasPeucker(final Location[] path, int n, 
                                   Location[] result, double delta)
  {
    DouglasPeucker dp = new DouglasPeucker(delta) {

         @Override
         public double distance_to_line(int i, int j, int k) {
            return Geometry.distance_to_line(path[i],path[j],path[k]);
         }

     };

    int[] index = new int[n];
    int num = dp.run(index,n);
    for(int i=0; i<num; i++) result[i] = path[index[i]];
    return num;
  }



  public static int DouglasPeucker(final Location[] path, 
                                   Vector<Location> result, double delta)
  {
    DouglasPeucker dp = new DouglasPeucker(delta) {

         @Override
         public double distance_to_line(int i, int j, int k) {
            return Geometry.distance_to_line(path[i],path[j],path[k]);
         }

     };

    int n = path.length;
    int[] index = new int[n];
    int num = dp.run(index,n);
    for(int i=0; i<num; i++) result.add(path[index[i]]);
    return num;
  }

}


