How do you clone your own Location, and then add some extra metres towards a desired direction?
Right now my android app can get the azimut, and my GPS location, and I hardcoded the desired distanct for an example, 10 metres.
Then my app should create a new Location, exactly 10 metres ahead where im facing.
So if my position is: longitude 17.537200603552526, latitude 25.70358496181195
and i want to it to move 8 metres directly towards north, and 2 metres directly towards east.
Would the new longitude and latitude look like:
current longitude + 0.00008 , current latitude + 0.00002
Heres some of my code to calculate the gradient and the new location:
public double[] calculateXYLength(double[] vals, double distance)
{
double x = vals[0];
double y = vals[1];
if (vals[0] < 0)
{
x = x * -1;
}
if (vals[1] < 0)
{
y = y * -1;
}
// Log.d("lengths", "K = " + distance + " / (" + x + " + " + y + " )" );
double k = distance / (x + y);
// Log.d("lengths", "vals[0]: " + vals[0] + " vals[1]: " + vals[1]);
// Log.d("lengths", "x: " + (vals[0] * k) + " y: " + (vals[1] * k) +
// " k: " + k);
return new double[] { (vals[0] * k), (vals[1] * k) };
}
Notice the vals is the gradient i already calculated, and the result i'm returning i'm going to use to add to my new location point.
Location newPosition = currentPosition
newPosition.setLongitude(myPosition.getLongitude() + val[0]);
newPosition.setLatitude(myPosition.getLatitude() + val[1]);
But the thing is, I don't get the desired distance between these two locations.. And I can't figure out why. How do I add the desired distance on the latitude/longitude?
Thanks,
Johan
The measures of longitude and latitude are degrees not meters, I think that is the problem.
1 degree = 111.12 km
Related
I have three gps locations as double lat and lng. I have three radius that correspond to each of the lat and lng values. The radius form circles around the locations. I want to determine the one point where all three circles overlap.
My starting point:
(x−lat_1)^2+(y−lng_1)^2=r_1^2
(x−lat_2)^2+(y−lng_2)^2=r_2^2
(x−lat_3)^2+(y−lng_3)^2=r_3^2
But here I am stuck - not only is that system of equations over-determined, it is also unclear, how to mix up degrees, minutes and seconds with a radius in meters.
What could a function(pseudocode is enough) look like that receives three locations and three radius and outputs one coordinate showing the overlapping.
Speaking of which, there needs to be some tolerance, as neither the radius nor the locations are too precise.
Take a look at this question:
Find intersecting point of three circles programmatically
I'm posting here the code that does what you need:
private static final double EPSILON = 0.000001;
private boolean calculateThreeCircleIntersection(double x0, double y0, double r0,
double x1, double y1, double r1,
double x2, double y2, double r2)
{
double a, dx, dy, d, h, rx, ry;
double point2_x, point2_y;
/* dx and dy are the vertical and horizontal distances between
* the circle centers.
*/
dx = x1 - x0;
dy = y1 - y0;
/* Determine the straight-line distance between the centers. */
d = Math.sqrt((dy*dy) + (dx*dx));
/* Check for solvability. */
if (d > (r0 + r1))
{
/* no solution. circles do not intersect. */
return false;
}
if (d < Math.abs(r0 - r1))
{
/* no solution. one circle is contained in the other */
return false;
}
/* 'point 2' is the point where the line through the circle
* intersection points crosses the line between the circle
* centers.
*/
/* Determine the distance from point 0 to point 2. */
a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;
/* Determine the coordinates of point 2. */
point2_x = x0 + (dx * a/d);
point2_y = y0 + (dy * a/d);
/* Determine the distance from point 2 to either of the
* intersection points.
*/
h = Math.sqrt((r0*r0) - (a*a));
/* Now determine the offsets of the intersection points from
* point 2.
*/
rx = -dy * (h/d);
ry = dx * (h/d);
/* Determine the absolute intersection points. */
double intersectionPoint1_x = point2_x + rx;
double intersectionPoint2_x = point2_x - rx;
double intersectionPoint1_y = point2_y + ry;
double intersectionPoint2_y = point2_y - ry;
Log.d("INTERSECTION Circle1 AND Circle2:", "(" + intersectionPoint1_x + "," + intersectionPoint1_y + ")" + " AND (" + intersectionPoint2_x + "," + intersectionPoint2_y + ")");
/* Lets determine if circle 3 intersects at either of the above intersection points. */
dx = intersectionPoint1_x - x2;
dy = intersectionPoint1_y - y2;
double d1 = Math.sqrt((dy*dy) + (dx*dx));
dx = intersectionPoint2_x - x2;
dy = intersectionPoint2_y - y2;
double d2 = Math.sqrt((dy*dy) + (dx*dx));
if(Math.abs(d1 - r2) < EPSILON) {
Log.d("INTERSECTION Circle1 AND Circle2 AND Circle3:", "(" + intersectionPoint1_x + "," + intersectionPoint1_y + ")");
}
else if(Math.abs(d2 - r2) < EPSILON) {
Log.d("INTERSECTION Circle1 AND Circle2 AND Circle3:", "(" + intersectionPoint2_x + "," + intersectionPoint2_y + ")"); //here was an error
}
else {
Log.d("INTERSECTION Circle1 AND Circle2 AND Circle3:", "NONE");
}
return true;
}
Usage:
calculateThreeCircleIntersection(-2.0, 0.0, 2.0, // circle 1 (center_x, center_y, radius)
1.0, 0.0, 1.0, // circle 2 (center_x, center_y, radius)
0.0, 4.0, 4.0);// circle 3 (center_x, center_y, radius)
As you said, you probably need to do some unit conversion here. There is some complicated formula that calculates distance between two geolocations, so you need to reverse it to get meters from radian based distance.
Here you may find implementations of this calculation and try to reverse it:
Calculate distance between two latitude-longitude points? (Haversine formula)
I have a list of places in my database, they all have a latitude / longitude.
In my app, I got the user location and I want to fetch all places which are 100 meters away from him.
To do it, I add 100 meters to his latitude, and longitude
I tried to do something like this:
double radius = 100; // 100 meters
double limitLatitudeNorth = latitude + radius;
double limitLatitudeSouth = latitude - radius;
double limitLongitudeWest = longitude - radius;
double limitLongitudeEast = longitude + radius;
StringBuffer query = "latitude < '" + limitLatitudeNorth + "' AND latitude > '" + limitLatitudeSouth + "' AND longitude < '" + limitLongitudeWest + "' AND longitude > '" + limitLongitudeEast + "'";
But of course, laitude and longitude are not meters, so I don't know how make the sum.
What is the formula? I heard that it depends of the position in the globe. Let's say I'm in France.
A lot of apps do that (ie: LINE) I thought I will easily find a code for that, but I didn't: (
Any idea?
You need to check the distance between one point in your DB and the users current location. You can use Location.distanceBetween().
The Method returns an array of results with distance, bearing etc. The distance between the two locations is always in results[0].
I've written a small check. It calculates the distance and returns true, if the distance is smaller than your radius.
private boolean checkDistance(double currentLocLat, double currentLocLong, double placeLocLat, double placeLocLong) {
float radius = 100F;
float[] results = new float[3];
Location.distanceBetween(currentLocLat, currentLocLong, placeLocLat, placeLocLong, results);
return (results[0] <= radius);
}
I have a list of places in my database, they all have a latitude / longitude.
In my app, I got the user location and I want to fetch all places which are 100 meters away from him.
To do it, I add 100 meters to his latitude, and longitude
I tried to do something like this:
double radius = 100; // 100 meters
double limitLatitudeNorth = latitude + radius;
double limitLatitudeSouth = latitude - radius;
double limitLongitudeWest = longitude - radius;
double limitLongitudeEast = longitude + radius;
StringBuffer query = "latitude < '" + limitLatitudeNorth + "' AND latitude > '" + limitLatitudeSouth + "' AND longitude < '" + limitLongitudeWest + "' AND longitude > '" + limitLongitudeEast + "'";
But of course, laitude and longitude are not meters, so I don't know how make the sum.
What is the formula? I heard that it depends of the position in the globe. Let's say I'm in France.
A lot of apps do that (ie: LINE) I thought I will easily find a code for that, but I didn't: (
Any idea?
You can use the distanceTo method inside Location class. Do the following:
Location location = new Location();
location.setLatitude(latitude);
location.setLongitude(longitude);
Location locationFromDB = new Location();
locationFromDB.setLatitude(latitudeFromDB);
locationFromDB.setLongitude(longitudeFromDB);
float dist = location.distanceTo(locationFromDB);
if(dist<100f){
//do here your magic
}
For distances in latitude (which trace a great circle through the poles) then 1 minute of arc = 1 nautical mile = 1852 metres (approx). Thus 1 degree = 111.12 km
For changes in longitude you need to multiply this factor by the cosine of the latitude. So at the equator the distance change is the same as for changes in latitude, at the poles (cos 90 degrees = 0) the lines of equal longitude all converge to a point.
I need to animate the drawing of a line graph. I'll receive an array of values (probably between 0 and 10) and that has to go on a graph over time. I want the line graph to be drawn, and the drawing should be visible; animated.
I've looked at Anders Ericsson's tutorial here: http://www.jayway.com/2012/08/29/creating-custom-android-views-part-3-animating-your-custom-views-smoothly/#comment-105813
The code here: https://github.com/andersericsson/ViewTutorialPart3
But I can't seem to swing it to work my way.
Is there another solution out there?
The solution I ended up using involved some algebra in the class where I extended View.
The function gets the array of scores (values between 0 and 10) from the activity and uses the values two-by-two as start and end points to a line (note that the end point of one line is the start point of the next line).
It calculates the length of the line and how many segments will be in the line; also how far to move in the x direction and how for to move in the y direction.
Then it calculates the x and y values of the end of the first segment in the line and draws that segment.
Then the xDirection and yDirection is added to the x and y points respectively and the line is drawn again, which now includes the first and second segment of the line. This is done for every segment in the line, and then the final line from point A to point B is drawn.
But it's not complete - the entire for loop in the setData function should be placed in a recursive function, because postInvalidateDelayed() doesn't pause the for loop from executing.
However, nothing is drawn on the canvas at all, hence the link to my other question currently on SO: Why are no lines drawn on my (custom View) canvas?
But for this question, I think that the solution I ended up using is probably not so bad. Comments?
public void setData(float[] scorePoints, float max, int totalScores){
Log.d(TAG, "Get stuff from activity");
scores = scorePoints;
numberOfScores = totalScores;
Log.d(TAG, "Number of scores = " + numberOfScores);
maxScore = max;
Log.d(TAG, "Max score = " + maxScore);
segmentToDraw = (float) 10;
//get the width of the area to draw
width = Math.abs(getWidth() - getPaddingLeft() - getPaddingRight());
//get the height of the area to draw
height = getHeight() - getPaddingTop() - getPaddingBottom();
Log.d(TAG, "Drawable area in view = " + width + " x " + height);
/*
* Now we start filling an array of points.
* The onDraw function will drawLines of groupings of four points in a given array.
*
* For the first segment, we'll draw from the x and y of the first point (which will be in the 1st and 2nd spots in our array)
* to the x and y of the first segment (which will be in the 3rd and 4th spots in our array).
* And then the 3rd and 4th spots in our array will be replaced by a new x and y
* marking the end of the second segment to be drawn from our first point.
*
* This will happen until the x and y is not smaller than the x and y of the final point of the line, any more.
* Then the 3rd and 4th spots in our array will be replaced by the x and y of the final point of the line.
*
* If there are more points to draw, the 5th and 6th spots in our array will also be created and filled with
* the x and y of the final point of the line because it'll be the first two values (x and y) for drawing the next line.
*
* So, yes, there will be duplicates in our array of points to draw, but a grouping of four spots will be used to draw one line,
* and the end point of the first line is the starting point of the second line, so we need it twice.
*/
points.add(getXPos(scores[0]));
points.add(getYPos(scores[0]));
points.add((float) 0);
points.add((float) 0);
x = points.get(0);
y = points.get(1);
startPoint = scores[0];
endPoint = scores[1];
for(int i=0; i<scores.length-1; i++){
String thePoints = "";
if(i>0){
startPoint = scores[i];
endPoint = scores[i+1];
x = points.get(i*4);
y = points.get((i*4) + 1);
}
startPointX = getXPos(startPoint);
startPointY = getYPos(startPoint);
endPointX = getXPos(endPoint);
endPointY = getYPos(endPoint);
distanceOfLine = (float) Math.sqrt(Math.pow((endPointX - startPointX), 2) + Math.pow((endPointY - startPointY), 2));
Log.d(TAG, "Distance of line = " + distanceOfLine);
//get number of segments in line
numberOfSegmentsInLine = (int) (distanceOfLine/segmentToDraw);
Log.d(TAG, "Number of segments in line = " + numberOfSegmentsInLine);
//get distance to move in Y direction
yDirection = (float) ((endPointY - startPointY)/ (float) numberOfSegmentsInLine);
Log.d(TAG, "Move " + yDirection + " in Y direction");
//get distance to move in X direction
xDirection = (float) ((endPointX - startPointX)/ (float) numberOfSegmentsInLine);
Log.d(TAG, "Move " + xDirection + " in X direction");
//loop for each segment
for(int j=0; j<numberOfSegmentsInLine; j++){
x += xDirection;
y += yDirection;
points.set(points.size()-2, Float.valueOf(x));
points.set(points.size()-1, Float.valueOf(y));
Log.d(TAG, "Line : " + (i+1) + " Segment : " + j);
Log.d(TAG, "X = "+ (x+xDirection) + " Y = " + (y+yDirection));
Log.d(TAG, "Call invalidate now!");
//invalidate();
//postInvalidateDelayed(delayMilliseconds);
}
//draw final line
points.set(points.size()-2, endPointX);
points.set(points.size()-1, endPointY);
invalidate();
//postInvalidateDelayed(delayMilliseconds);
if(i<scores.length-2){
points.add(endPointX);
points.add(endPointY);
points.add((float) 0);
points.add((float) 0);
}
for(int k =0; k<points.size(); k++){
thePoints = thePoints + " : " + points.get(k);
}
Log.d(TAG, "Points array = " + thePoints);
}
}
#Override
public void onDraw(Canvas canvas){
//setWillNotDraw(true);
Log.d(TAG, "DRAW DAMNIT!!!");
Log.d(TAG, "Width = " + (int) width + " Height = " + (int)height);
paint = new Paint();
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(4);
paint.setColor(Color.RED);
//paint.setAntiAlias(true);
//paint.setShadowLayer(4, 2, 2, 0x81000000);
Bitmap bitmap = Bitmap.createBitmap((int)width, (int)height, Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
String drawPointsGo = "";
float[] drawPoints = new float[points.size()];
for(int i=0; i<points.size(); i++){
Float f = points.get(i);
drawPoints[i] = (float) (f != null ? f : 0.0);
drawPointsGo = drawPointsGo + " : " + drawPoints[i];
}
Log.d(TAG, "Draw Points: " + drawPointsGo);
canvas.drawLines(drawPoints, paint);
}
Try looking into CountDownTimer or Runnable so that onTick() or when it's time to post you can update your line by drawing a few more pixels. This would let you draw one line after the other but would give the effect of animation.
Here is the general direction to try:
Make sure you are comfortable with Canvas drawing.
Then you will want to create a new View (subclass it) and override the onDraw method.
This method should only draw the graph partially, based on the elapsed time since the start of the animation.
Ok, so I am trying to write a code which returns back the values of all the 4 corner position of the map according to current view able area. For example, a user access Google maps through his device, he focuses on a particular area and hits a button and gets back the position (latitude and longitude) of all the four corners.
For this I have the center coordinate and now all I want span of the current viewable area and get the top left and bottom right corner coordinates. for this I used,
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x; // returns 480
int height = size.y; // returns 800
Now I want to convert them into latitude and longitude values so that I can use simple math such as:
topLeftLat= centerLat + lat/2;
topLeftLon= centerLon - lng/2;
bottomRightLat= centerLat - lat/2;
bottomRightLon = CenterLon + lng/2;
This would give me the corner cordinates.
lat and lng being the converted sceen resolution in latitude and longtiude values.
This took 5 minutes search on google so I don't know why I'm giving you this ... learning to research is the biggest part of being a developer.
GeoPoint mapCenter = myMap.getMapCenter();
float centerLatitude = (float)(mapCenter.getLatitudeE6())/1000000;
float centerLongitude = (float)(mapCenter.getLongitudeE6())/1000000;
float latitudeSpan = (float)(myMap.getLatitudeSpan())/1000000;
float longitudeSpan = (float)(myMap.getLongitudeSpan()/1000000);
GeoPoint mapTopLeft = myMap.getProjection().fromPixels(0, 0);
float topLatitude = (float)(mapTopLeft.getLatitudeE6())/1000000;
float leftLongitude = (float)(mapTopLeft.getLongitudeE6())/1000000;
GeoPoint mapBottomRight
= myMap.getProjection().fromPixels(myMap.getWidth(), myMap.getHeight());
float bottomLatitude = (float)(mapBottomRight.getLatitudeE6())/1000000;
float rightLongitude = (float)(mapBottomRight.getLongitudeE6())/1000000;
String info =
"Center: " + centerLatitude + "/" + centerLongitude + "\n"
+ "Top Left: " + topLatitude + "/" + leftLongitude + "\n"
+ "Bottom Right: " + bottomLatitude + "/" + rightLongitude + "\n"
+ "latitudeSpan: " + latitudeSpan + "\n"
+ "longitudeSpan: " + longitudeSpan + "\n";
Toast.makeText(AndroidMapActivity.this,
info,
Toast.LENGTH_LONG).show();
}};
The full tutorial is available at Android-er: Get the the coordinates (Latitude and Longitude) currently displayed on MapView