I'm using jjoe64's awesome GraphView for Android. At the moment I'm trying to determine 2 things:
Is it possible, once plotted, to get a DataPoint's x,y location values?
Also, is it possible to get that location in the onTap call?
I'm trying to show a custom view just above the data point (tapped or otherwise); hence the reason I need it's coordinates. I know how to get the x,y position of a user touch, but the issue is I also need the value from the datapoint.
From what I can tell the DataPoint and DataPointInterface do not have an accessible x,y location value - only x,y double values (non-location related).
I was hoping for something like:
DataPoint p = series.getPoint(n);
int x = p.getXLocation();
int y = p.getYLocation();
Where n is either the exact position in the series (like getting something from an ArrayList) or n represents the non-location x value given to the DataPoint upon creation (new DataPoint(double x, double y)).
Has anyone else using this library solved this? Any help would be much appreciated. Thank you!
I ended up subclassing BaseSeries and basically doing a complete replication of LineGraphSeries with the exception of making some of those protected functions public. This gave me the ability to keep track of datapoints and their PointF's in a Map, then look up PointF's based on their corresponding datapoint.
views.setOnDataPointTapListener(new OnDataPointTapListener() {
#Override
public void onTap(Series series, DataPointInterface dataPoint) {
Toast.makeText(graph.getContext(), "Data : On Data Point clicked: "+dataPoint, Toast.LENGTH_SHORT).show();
}
});
I found this to show data-points.Its quite easy as you can see.
Related
I am building an Android app that will render a map. Using the phone location and a specific destination, I need to display the route on the map, and re-draw the route when the user's phone is moving. Sorry for the long post, I am trying to make this as explicit as possible.
I have to use Azure Maps, and the user has to follow the original route, so I need to re-draw the route when the user is following it. Basically I just need to make the original route start from the phone location everytime the user moves.
I am getting the latitude and longitude of the phone every three seconds, and when the user picks a destination location, I am calling the Azure API for the route, which returns a JSON array that contains points(latitude and longitude) from origin to destination. I save these points in an ArrayList and draw the route using a LineString and a LineLayer. My problem is that I don't want to call the Azure Api for the route every three seconds or even everytime the phone moves, because the call is really slow, and it puts to much pressure on my backend server.
Considering that the JSON array is sorted from origin to destination, I tried to compute the absolute difference between the phone location and the points from the array, and save the point for which the difference is smaller than a threshold, because it's the closest point from the route to the phone actual location. Every three seconds I am computing this difference and save the point as the start from the new route, and re-draw the route. The code for the difference is this:
private void getStartIndices() {
//r_points is the ArrayList with the points from the route
if(r_points != null)
{
for (int i = 0; i < r_points.length() - 1; i++) {
try {
JSONObject point = r_points.getJSONObject(i);
if( abs(mCurrentLocation.getLongitude() - point.getDouble("longitude")) < 0.00001 && abs(mCurrentLocation.getLatitude() - point.getDouble("latitude")) < 0.00001 )
{
Log.e(TAG, i + " They both change");
returnable = i;
}
else{
if( abs(mCurrentLocation.getLongitude() - point.getDouble("longitude")) < 0.000004 )
{
Log.e(TAG,i + "The longitude is changing");
returnable = i;
}
else{
if(abs(mCurrentLocation.getLatitude() - point.getDouble("latitude")) < 0.000004 )
{
Log.e(TAG,i + " The latitude is changing");
returnable = i;
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
This works but not accurate enough and it has some really bad bugs that I can't solve.
My question is: Is there any better way to do this, I really need to make as few calls as possible and I also need to make this redraw as accurate as possible.
The standard way to accomplish this is to loop through each line segment (pair of points in the line) and calculate the nearest point on that segment from your point. Then as you go through, find which segment has the closest point. Here is an algorithm that does this: https://softwareengineering.stackexchange.com/questions/270655/efficient-method-for-finding-closest-point-to-a-line-segment-from-a-set-of-point
However, this algorithm is based on pixel coordinates. If you use longitude/latitude coordinates, there will be some inaccuracies since the latitude and longitude scales are different (they aren't a flat 2D coordinate system, but part of a spherical coordinate system). An easy way to handle this is to convert your positions to pixel coordinates using the built in mercatorPositionsToPixels method in the MapMath namespace of the Azure Maps Android SDK. This will convert the longitude/latitude positions into pixel coordinates base don the Mercator map projection, and will result in much higher accuracy calculations. The zoom level specifies the resolution. Set this to 22, and that should work always (unless you want to start getting into microscopic accuracy).
/**
* Converts an array of positions into an array of global Mercator pixel coordinates at a specified zoom level.
* #param positions Array of positions.
* #param zoom Zoom level.
* #returns Array of global Mercator pixels.
*/
public static Pixel[] mercatorPositionsToPixels(#NonNull Position[] positions, double zoom)
Convert all the points of your line using this method, and store those since it sounds like your base line isn't changing. Then on each GPS ping, convert the GPS position to a Mercator pixel and use that nearest point on line algorithm to find the nearest point out of all the line segments. This will give you a point that could be between other points, but is on the path which is likely much more inline with what you are looking for.
In terms of performance, unless your line has millions of points in it, these calculations will run really fast. I used the same algorithm in JavaScript at a much higher frequency and it runs fine.
Update: the calculated coordinate will be in pixel units, you will need to convert it back to a position using the mercatorPixelsToPositions method.
I have List of Points where each of them have properties latitude and longitude, How I need to sort a list of points nearest to a given point.
One of the solutions go over the list using for() loop and compare each point with the given point(given current location).
I'm using RxJava2 in android , I see methods toSortedList() which works with Comparator which I thing isn't the way to achieve the solution,
Is there any way using compareTo() method and have the solution.
.map(new Function<List<Point>, List<Point>>() {
#Override
public List<StoreModel> apply(List<Point> storeModels) throws Exception {
//...sort list
return storeModels;
}
})
as #Gabe Sechan mention, Comparator is the standard way, you can compare it to an external value, that does not really matter, as Comparator just need to know about giving 2 items what's the quantitative comparison between them.
so toSortedList() with Comparator it can be something like this:
somePointsObservable.toSortedList((p1, p2) ->
calculateDistance(givenPoint, p1) - calculateDistance(givenPoint, p2));
where calculateDistance calculates the distance between 2 points, and
givenPoint is the current given location you are comparing against.
My App uses the Firebase Database to display a list of Event.
From the moment the App starts, I get the User current Location and it's updated if it changes.
What I would like to do is to display the List of Event based on the User current Location, going from the closest event to the most distant.
I have implemented Geofire in my App and get all the events withing the given Radius but unfortunately they are not filtered based on the closest to the most distant.
As far as I know, Geofire doesn't support this filtering yet (but do not hesitate to correct me if I'm wrong).
However, in my Adapter, I get a List of Model that I could filter on the fly, each Models have a coordinates property with value.
So does anyone know how to filter based on Coordinates String or Locations objects?
Cheers
What you can do is:
1) Add the distance property (double field) to your Event object;
2) Calculate distance from user:
double distance = GeoUtils.distance(userLoc.getLatitude(), userLoc.getLongitude(), eventLatitude, eventLongitude);
event.setDistanceInMeters(distance);
3) After you finish the Geofire call order your collection of events:
Collections.sort(eventsList, new Comparator<Event>() {
#Override
public int compare(Eventt1, Eventt2) {
return Double.valueOf(t1.getDistanceInMeters()).compareTo(t2.getDistanceInMeters());
}
});
4) ....;
5) PROFIT;
i have punch of GPS coordinates (latitude longitude) i want to create groups each one will contain coordinates that in the same radius , iam using this code to get distance between 2 points:-
float radius = (float) 1000.0;
float distance = loc.distanceTo(loc2);
if (distance < radius)
Toast.makeText(getApplicationContext(), "inside", Toast.LENGTH_LONG).show();
}
but with this code i need to compare each coordinate with the rest to check which one is closest ,which seem insufficient , is there any other way?
thanks in advance
The other way is to use a geo spatial index, like quad tree.
In that case you would first calculate which quad cells are within the radius, and then you only consider the points inside that cells.
But this is some programming, search and understanding effort, so use such an index when a brute force search over all points is to slow.
I am developing an application that shows the distance between the user and multiple locations (such as foursquare in the image below) on android, I am using eclipse and would like to know how to calculate the distance between various points. Thank you!
Image:
http://i.stack.imgur.com/rsWmO.jpg
There are probably many ways to get this done, here's an option.
You could use the distanceTo() method. If you want more than one distance, simply use a loop to repeat it until you've calculated the distances between all the Locations you have at hand.
If you're using Google Maps, you can use a Distance Matrix
https://developers.google.com/maps/documentation/distancematrix/
https://developers.google.com/maps/documentation/javascript/distancematrix
Here I am providing you some sample code for Distance calculation. I have done like this in my project. Here distanceTo() method will return you the distance in double.
private Location currentLocation, distanceLocation;
double distance = 0;
//set your current location
currentLocation.setLatitude(currentLat);
currentLocation.setLongitude(currentLong);
//set your destination location
distanceLocation = new Location("");
distanceLocation.setLatitude(destinatioLat);
distanceLocation.setLongitude(destinationLong);
distance = currentLocation.distanceTo(distanceLocation)/1000;
Same for more then one location you can use Array for storing distance. Its on you how you want to use it as per your requirement.
Hope this will help you.