Find intersection by 2 vectors on the globe - android

I am trying to calculate intersection GPS coordinate by 2 vectors.
Vector#1 is created by (longitude#1, latitude#1) and (longitude#2, latitude#2).
Vector#2 is created by (longitude#3, latitude#3) and (longitude#4, latitude#4).
My main point is finding intersection by above 2 vectors. I've tried to calculate intersection on X,Y/longitude, latitude/ coordinate system. But it was not accurate location.
Can you help you for my issue ?
findIntersection(double long1, double lati1, double long2, double lati2, double long3, double lati3, double long4, double lati4) {
//...find intersection.
return intersectionLong, intersectionLati;
}

See this website: http://www.movable-type.co.uk/scripts/latlong.html
There is a section called Intersection of two paths given start points and bearings which is what you want.

Related

Converting GPS to ENU

I want to create android application "Points of interest". I've read many different tutorials, and I do not understand why I need to convert GPS coordinates to ECEF and then to ENU. Can you explain, please?
Thanks!
Geospatial coordinate systems are a big topic, but the main choice between systems such as ECEF and ENU is about whether you want to describe a large region of the Earth's surface or just a small region.
When Android provides a geolocation via the LocationListener API, it typically does this using latitude/longitude/altitude which is ideal for representing any point over the Earth's surface, but is a "polar" or "geodetic" coordinate system that isn't ideal for plotting 2D locations. Standard techniques allow this coordinate system to be converted into ECEF, which is another coordinate system which is suitable for the whole globe, but is "cartesian" so can be rotated and scaled using much simpler mathematical operations than the original latitude/longitude/altitude coordinates.
Earth-Centred Earth Fixed (ECEF) uses a coordinate system with its origin at the Earth's centre, so that any point on the ground will have coordinate values that are typically in the millions of metres. This is great for describing satellite orbits, or locations that span multiple continents, but not very convenient for 2D plots of points of interest within a town or city.
If you want to draw a 2D map of a small region of the Earth's surface, then the East-North-Up coordinate system may be much more convenient. To use this, you need a reference location (such as the centre of a particular city) about which the local East/North/Up directions can be defined. Those then provide a set of x/y/z axes, where the x & y axes might be directly converted into the 2D screen coordinates. Obviously, as the region of interest grows larger (e.g. more than 100km), the effects of the Earth's curvature become more noticeable, and an ENU coordinate system will be less useful. See wikipedia for more info.
Moving from an ECEF to ENU coordinate system can be done by a simple set of matrix additions & multiplications which can be computed from the ECEF location of the centre of the map, and the unit vectors in the east/north/up directions.
You can do it this way on Java
public List<Double> convertGpsToECEF(double lat, double longi, float alt) {
double a=6378.1;
double b=6356.8;
double N;
double e= 1-(Math.pow(b, 2)/Math.pow(a, 2));
N= a/(Math.sqrt(1.0-(e*Math.pow(Math.sin(Math.toRadians(lat)), 2))));
double cosLatRad=Math.cos(Math.toRadians(lat));
double cosLongiRad=Math.cos(Math.toRadians(longi));
double sinLatRad=Math.sin(Math.toRadians(lat));
double sinLongiRad=Math.sin(Math.toRadians(longi));
double x =(N+0.001*alt)*cosLatRad*cosLongiRad;
double y =(N+0.001*alt)*cosLatRad*sinLongiRad;
double z =((Math.pow(b, 2)/Math.pow(a, 2))*N+0.001*alt)*sinLatRad;
List<Double> ecef= new ArrayList<>();
ecef.add(x);
ecef.add(y);
ecef.add(z);
return ecef;
}
public List<Double> convertECEFtoENU(List<Double> ecefUser, List<Double> ecefPOI, double lat, double longi){
double cosLatRad=Math.cos(Math.toRadians(lat));
double cosLongiRad=Math.cos(Math.toRadians(longi));
double sinLatRad=Math.sin(Math.toRadians(lat));
double sinLongiRad=Math.sin(Math.toRadians(longi));
List<Double> vector = new ArrayList<>();
vector.add(ecefUser.get(0)-ecefPOI.get(0));
vector.add(ecefUser.get(1)-ecefPOI.get(1));
vector.add(ecefUser.get(2)-ecefPOI.get(2));
double e= vector.get(0)*(-sinLongiRad)+vector.get(0)*(cosLongiRad);
double n= vector.get(0)*(-sinLatRad)*(cosLongiRad)+vector.get(1)*(-sinLatRad)*(sinLongiRad)+vector.get(2)*cosLatRad;
double u= vector.get(0)*(cosLatRad)*(cosLongiRad)+vector.get(1)*(cosLatRad)*(sinLongiRad)+vector.get(2)*sinLatRad;
List<Double> enu= new ArrayList<>();
enu.add(e);
enu.add(n);
enu.add(u);
return enu;
}

How to get latitude and longitude at given bearing and given distance from a point

Let say I have point A(28.513393, 77.072276) and bearing is 45 degree then get point B(?,?) at distance 5 Km from point A at given bearing.
In order to calculate the position of point B you can use the
Google Maps Android API Utility Library. The utility library has a class SphericalUtil that allows to calculate distances, areas and headings via spherical geometry.
The method of SphericalUtil that should be used is the computeOffset. According to the documentation
public static LatLng computeOffset(LatLng from,
double distance,
double heading)
Returns the LatLng resulting from moving a distance from an origin in the specified heading (expressed in degrees clockwise from north).
source: http://googlemaps.github.io/android-maps-utils/javadoc/
So, the code snippet in your example is
LatLng pointA = new LatLng(28.513393, 77.072276);
double distance = 5000.0; //expressed in meters
double heading = 45.0 //expressed in degrees clockwise from north
LatLng pointB = SphericalUtil.computeOffset(pointA, distance, heading);
For more details follow setup guide of the utility library:
https://developers.google.com/maps/documentation/android-api/utility/setup
I hope this helps!

How to get straight distance between two location in android?

First read Question carefully ...
I need straight distance, not by walking,car,or etc.
Take a look to this image which given below,
Google provide us distance by car and driving.
But I don't want it, I want straight distance between two location (latitude - longitude).
Which is displayed as as RED LINE.
NOTE : I don't want to put red line on Google map, just want the Distance in Units(mile,km,etc.)
ANDROID
double distance
Location locationA = new Location(“point A”)
locationA.setLatitude(latA);
locationA.setLongitude(lngA);
Location locationB = new Location(“point B”);
locationB.setLatitude(latB);
LocationB.setLongitude(lngB);
distance = locationA.distanceTo(locationB);
MATHEMATICALY
a = distance in degrees //meterConversion = 1609;
b = 90 - latitude of point 1
c = 90 - latitude of point 2
l = longitude of point 1 - longitude of point 2
Cos(a) = Cos(b)Cos(c) + Sin(b)Sin(c)Sin(l)
d = circumference of Earth * a / 360 // circumference of Earth = 3958.7558657440545D km
The Haversine function is used to find the distance between two points on a sphere.
It's fairly straightforward to extend this to finding the straight line distance between two points on the Earth. The Earth is not a perfect sphere, but this is still a good approximation using a standard measurement (called WGS84) for the radius at the equator.
As CommonsWare has said, you can do this very simply by using distanceBetween(), which uses the Haversine function and the WGS84 radius.
For better understanding of implementation/math, take a look at this sample code in Python.
Distance you find with following code.
You just need to get two geoPoint's latitude and longitude.
and use that in following calculation to get distance.
R = 6371; // km
d = Math.acos(Math.sin(lat1)*Math.sin(lat2) +
Math.cos(lat1)*Math.cos(lat2) *
Math.cos(lon2-lon1)) * R;
That will be return distance after all calculation.
R is the radius of surface in KM, need to use in calculation and you try this. I hope it is useful for you.

Latitude / Longitude and meters

I have a small algorithmic problem.
I am developing an Android application. I get GPS coordinates. For example: latitude: 23.23907, longitude: 50.45786.
So I get a point. I want to compute bounds details on this point plus or minus 5 meters. I.e.:
[23.23907 - 5 meters ; 23.23907 + 5 meters]
[50.45786 - 5 meters ; 50.45786 + 5 meters]
How to make this calculation?
Thank you very much!
The haversine formula can be simplified a great deal when you work in north-south and east-west directions only.
If Earth's circumference is C, the point at d kilometers to south of a given point is 360*d/C degrees to the south. The point at d kilometers to east is 360*d/(C*cos(latitude)) degrees to the east. The cosine in the denominator comes from the fact that the length of the longitude at a given latitude shorter than the equator by that much.
So if the Earth's circumference is 40075.04 km, to move 5 m to the north/south you would add/subtract 0.0000449 from the latitude and use the same longitude. To move 5 m to the west/east you would use the same latitude and add/subtract 0.0000449/cos(latitude) to the longitude. Don't forget about the edge cases though: near poles you have to clamp latitude to 90°, and near longitude 180° you'll have too add or subtract 360° to keep the longitude in the correct range.
With your numbers the range turns out to be approximately:
latitude: [23.23903 ; 23.23911]
longitude: [50.45781 ; 50.45791]
Update: Note that this still assumes that the Earth is a perfect sphere, which it's not. The GPS system for example models the Earth as an ellipsoid where the equator is at 6378.137km and the poles are at 6356.7523142km from the center of the Earth. The difference is about 1/300th and matters a great deal for many applications, but in this case it's within the margin of error.
Correcting the formula for the longitude should be simple since the parallels are still circles: you would just have to swap cos(latitude) for the correct coefficient. Calculating the correct latitude is harder because the meridians are not circles but ellipses, and the arc length of an ellipse cannot be calculated using elementary functions, so you must use approximations.
I would like to add a very important comment:
The cosine is to be calculated on the latitude in radians and not in degrees.
conversion: radians = PI / 180 * degrees

Get screen coordinates by specific location and longitude (android)

I have an application of augmented reality in which I have stored information such us metro, gas stations, places of interest, etc. with the corresponding latitude and longitude.
Now, according to the orientation of the device, I would show a marker for each site in the camera view of the device. Similar to Layar and Wikitude.
It takes three days searching without stopping and have not found anyone to explain how to solve this problem.
Since information on this topic is very sparse, and I recently solved this problem on the iPhone, I thought I would share my method for anyone that can make it work with Android (there's nothing really specific to iPhone in this answer except for the Math functions sin, cos, and fmod, which can be found in java.lang.Math). These are the steps I took:
Obtain your own lat/lon and your current compass heading (lat1, lon1 and heading). On the iPhone, CLLocation returns these in degrees, but for these calculations they MUST be in radians (i.e. multiply by PI/180)
Obtain lat/lon of Points of Interest (POI) in radians (lat2 and lon2).
Calculate the distance between lat1/lon1 and lat2/lon2 using formula found here: http://www.movable-type.co.uk/scripts/latlong.html
Calculate angle to lat2/lon2 in relation to north. This is also described in the link above but I had a little bit of trouble getting this to work, here is C code for this:
double latDelta = (lat2 - lat1);
double lonDelta = (lon2 - lon1);
double y = sin(lonDelta) * cos(lat2);
double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2)* cos(lonDelta);
double angle = atan2(y, x); //not finished here yet
double headingDeg = compass.currentHeading;
double angleDeg = angle * 180/PI;
double heading = headingDeg*PI/180;
angle = fmod(angleDeg + 360, 360) * PI/180; //normalize to 0 to 360 (instead of -180 to 180), then convert back to radians
angleDeg = angle * 180/PI;
Using standard trigonometry, I calculate x and y. Remember, these coordinates are in 3D space, so we are not finished here yet because you still have to map them to 2D:
x = sin(angle-heading) * distance;
z = cos(angle-heading) * distance; //typically, z faces into the screen, but in our 2D map, it is a y-coordinate, as if you are looking from the bottom down on the world, like Google Maps
Finally, using the projection formula, you can calculate screen x ( I didn't do y because it was not necessary for my project, but you would need to get accelerator data and figure out if the device is perpendicular to the ground). The projection formula is found here (scroll to the very bottom): http://membres.multimania.fr/amycoders/tutorials/3dbasics.html
double screenX = (x * 256) / z
Now you can use this x coordinate to move an image or a marker on your screen. Remember a few points:
Everything must be in radians
The angle from you to the POI relative to North is angleBeteweenPoints - currentHeading
(For some reason I can't properly format the code on this computer, so if anyone wants to edit this answer, feel free).

Categories

Resources