-1
$\begingroup$

This is a practical question, so if you find something missing, please assume a real life scenario.

The question is related to GPS and the Earth.

lat1: my latitude, GPS position I'm standing at (degrees)
lon1: my longitude, GPS position I'm standing at (degrees)
dir1: my direction I'm facing (from north, 0-360°, positive clockwise)
lat2: latitude of object
lon2: longitude of object
view: my viewport

I'm a person with position lat1, lon1, facing dir1. My viewport is 180°. Object is located at lat2, lon2.

How do I calculate that object is within my viewport?

Edit: viewport is assumed to be 180° and has a 1km radius.

  • 0
    This problem really begs for vector maths, if you can convert the positions and facing to 3D vectors there are some simple operations to determine this (and a lot of other good stuff).2011-07-24

2 Answers 2

1

Read up on vectors if you are not already into the subject.

Translation from coordinates to unit vectors (vectors of length 1), where the origin is centre of the Earth, X-axis points to N0,E0, Y-axis points to N0,E90 and Z-axis points to the North pole:

posX=cos(lon)*cos(lat) posY=sin(lon)*cos(lat) posZ=sin(lat)  faceNorthX=-cos(lon)*sin(lat) faceNorthY=-sin(lon)*sin(lat) faceNorthZ=cos(lat)  faceEastX=-sin(lon) faceEastY=cos(lon) faceEastZ=0  faceDir=faceNorth*cos(dir)+faceEast*sin(dir) 

Now if

dotProduct(faceDir1,pos2-pos1) 

is positive, then you are according to your definition facing pos2 from pos1.

More general

dotProduct(vector1,vector2) / (length(vector1) * length(vector1)) 

is cosine of the angle between the vectors.

This is useful for calculating the surface distance between two points, since the vectors generated so far are all unit vectors the expression can be simplified a bit for this use.

surfaceDistance=Earth.radius*arccos(dotProduct(pos1,pos2)) 

The direct distance is simply

directDistance=Earth.radius*length(pos2-pos1) 
0

Ok folks, this is what I could come up with in 4 hours LOL. Could any of you please check that this is correct? Probably I'll write a bunch of unit tests anyway, but I'm so confused...

public class GpsPosition {  private double              mLatitude; private double              mLongitude; private double              mDirection;  public boolean isInViewport(GpsPosition otherPos) {     double otherDir = directionTowards(otherPos);     double range = VIEWPORT_DEGREE / 2;     double minRange = mDirection - range;     double maxRange = mDirection + range;      if (minRange < 0) {         minRange = 360 + minRange;         if (otherDir >= minRange) {             return true;         } else if (otherDir <= maxRange) {             return true;         } else {             return false;         }     } else if (maxRange > 360) {         maxRange = maxRange - 360;         if (otherDir <= maxRange) {             return true;         } else if (otherDir >= minRange) {             return true;         } else {             return false;         }     } else if (minRange >= 0 && maxRange <= 360) {         if (otherDir <= maxRange && otherDir >= minRange) {             return true;         } else {             return false;         }     } else {         throw new AssertionError("I'm sorry, Dave, I'm afraid I can't do that.");     }  }  double directionTowards(GpsPosition otherPos) {     GpsPosition northPole = new GpsPosition(90,0,0);     double a = distanceTo(otherPos);     double b = distanceTo(northPole);     double c = otherPos.distanceTo(northPole);      //Laws of cosines     double gamma = Math.acos((a*a + b*b - c*c)/(2*a*b));      boolean negative = (otherPos.mLongitude - mLongitude) < 0;//potential bug at 180° longitude, ignore for now     if (negative) {         gamma = 360 - gamma;     }     return gamma;  }  double distanceTo(GpsPosition otherPos) {      double R = EARTH_PERIMETER; //6371.0 km     double lat1 = mLatitude;     double lon1 = mLongitude;     double lat2 = otherPos.mLatitude;     double lon2 = otherPos.mLongitude;       double dLat = Math.toRadians(lat2-lat1);     double dLon = Math.toRadians(lon2-lon1);     lat1 = Math.toRadians(lat1);     lat2 = Math.toRadians(lat2);      //Haversine formula     double a = Math.sin(dLat/2) * Math.sin(dLat/2) +             Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);      double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));      double d = R * c;     return d; } } 
  • 1
    @bizs009: As a rule of thumb, I think that posts on a non-programming site should not require the reader to understand a programming language (or even pseudocode). I certainly do not, and as a result I have no clue what your answer says (eBusiness's post is essentially intelligible, although the wordy variable names still throw me off). If you are able to implement an answer in code, surely you are also able to [describe it using mathematics](http://meta.math.stackexchange.com/questions/107/faq-for-math-stackexchange/117#117), and I think math is the better option in terms of accessibility.2011-07-24