src/com/wherehoo/WHGeo.java
/**
     * Calculates a heading between <tt>origin</tt> point 
     * and a point on <tt>end_line</tt> that is closest to <tt>origin</tt>.
     * @param origin the starting point
     * @param end_line the line segment described by two points on Earth.
     * @return Heading from <tt>origin</tt> point to a point on the<tt> end_line</tt> 
     * that is closest to<tt> origin</tt> point. This closest point is either one of end points of <tt>end_line</tt>,
     * or a point at the intersection of <tt>end_line</tt> and a line that is perpendicular to it
     * and passes through <tt>origin point</tt>.
     */
Calculates a heading between origin point
and a point on end_line that is closest to origin.
@param origin the starting point
@param end_line the line segment described by two points on Earth.
@return Heading from origin point to a point on the end_line
that is closest to origin point. This closest point is either one of end points of end_line,
or a point at the intersection of end_line and a line that is perpendicular to it
and passes through origin point.
Calculates a heading between origin point and a point on end_line that is closest to origin . @param origin the starting point @param end_line the line segment described by two points on Earth . @return Heading from origin point to a point on the end_line that is closest to origin point . This closest point is either one of end points of end_line or a point at the intersection of end_line and a line that is perpendicular to it and passes through origin point .
public static double heading(Point2D.Double origin, Line2D.Double line_end){
	Point2D.Double p1;
	Point2D.Double p2;
	double headingP1P2;
	double headingP1O;
	double headingP2P1;
	double headingP2O;
	double angleOP1P2;
	double angleOP2P1;
	if (line_end.getX1()>line_end.getX2()){
	    p1= new Point2D.Double(line_end.getX1(),line_end.getY1());
	    p2= new Point2D.Double(line_end.getX2(),line_end.getY2());
	}
	else {
	    p2= new Point2D.Double(line_end.getX1(),line_end.getY1());
	    p1= new Point2D.Double(line_end.getX2(),line_end.getY2());
	}
	headingP1P2= WHGeo.heading(p1,p2);
	headingP1O = WHGeo.heading(p1,origin);
	headingP2P1= WHGeo.heading(p2,p1);
	headingP2O = WHGeo.heading(p2,origin);
	angleOP1P2 = Math.abs(headingP1P2-headingP1O);
	if (angleOP1P2>180)
	    angleOP1P2=360-angleOP1P2;
	angleOP2P1 = Math.abs(headingP2P1-headingP2O);
	if (angleOP2P1>180)
	    angleOP2P1=360-angleOP2P1;
	if((angleOP1P2>90)||(angleOP2P1>90)){
	    double d1=WHGeo.distance(origin,p1);
	    double d2=WHGeo.distance(origin,p2);
	    if(d1<d2)
		return WHGeo.heading(origin,p1);
	    else 
		return WHGeo.heading(origin,p2);
	}
	else {
	    if (headingP1P2<headingP1O)
		return (((headingP1P2-90)+360)%360);
	    else
		return (((headingP1P2+90)+360)%360);
	}
    }
public static double heading ( Point2D . Double origin , Line2D . Double line_end ) { Point2D . Double p1 ; Point2D . Double p2 ; double headingP1P2 ; double headingP1O ; double headingP2P1 ; double headingP2O ; double angleOP1P2 ; double angleOP2P1 ; if ( line_end . getX1 ( ) > line_end . getX2 ( ) ) { p1 = new Point2D . Double ( line_end . getX1 ( ) , line_end . getY1 ( ) ) ; p2 = new Point2D . Double ( line_end . getX2 ( ) , line_end . getY2 ( ) ) ; } else { p2 = new Point2D . Double ( line_end . getX1 ( ) , line_end . getY1 ( ) ) ; p1 = new Point2D . Double ( line_end . getX2 ( ) , line_end . getY2 ( ) ) ; } headingP1P2 = WHGeo . heading ( p1 , p2 ) ; headingP1O = WHGeo . heading ( p1 , origin ) ; headingP2P1 = WHGeo . heading ( p2 , p1 ) ; headingP2O = WHGeo . heading ( p2 , origin ) ; angleOP1P2 = Math . abs ( headingP1P2 - headingP1O ) ; if ( angleOP1P2 > 180 ) angleOP1P2 = 360 - angleOP1P2 ; angleOP2P1 = Math . abs ( headingP2P1 - headingP2O ) ; if ( angleOP2P1 > 180 ) angleOP2P1 = 360 - angleOP2P1 ; if ( ( angleOP1P2 > 90 ) || ( angleOP2P1 > 90 ) ) { double d1 = WHGeo . distance ( origin , p1 ) ; double d2 = WHGeo . distance ( origin , p2 ) ; if ( d1 < d2 ) return WHGeo . heading ( origin , p1 ) ; else return WHGeo . heading ( origin , p2 ) ; } else { if ( headingP1P2 < headingP1O ) return ( ( ( headingP1P2 - 90 ) + 360 ) % 360 ) ; else return ( ( ( headingP1P2 + 90 ) + 360 ) % 360 ) ; } }
Calculates a heading between <tt>origin</tt> point
 and a point on <tt>end_line</tt> that is closest to <tt>origin</tt>.
Calculates a heading between <tt > origin< / tt > point and a point on <tt > end_line< / tt > that is closest to <tt > origin< / tt > .
//some helper variables
 //calculate them
 //p1 will be upper point, and p2 will be lower point
 //check if either of these angles is obtuse
 //return the heading of the closer point
 //return heading that is perpendicular to P1P2 line
 //determine if the origin is above or below the line
