I have a array of about 7000 locations, each one was recorded using the location manager on android, when loading these locations I filter out any that are further then 1km from the previous or have an accuracy higher then 50 using this:
if (c.moveToFirst())
do {
lat = c.getString(0);
lng = c.getString(1);
ac = c.getString(2);
alt = c.getString(3);
if (l1 != null) {
l2 = new Location("MAP");
l2.setLatitude(Double.parseDouble(lat));
l2.setLongitude(Double.parseDouble(lng));
l2.setAltitude(Double.parseDouble(alt));
l2.setAccuracy(Float.parseFloat(ac));
if (l1.distanceTo(l2) < 1000
&& l2.getAccuracy() < 51) {
opts.add(new LatLng(Double.parseDouble(lat),
Double.parseDouble(lng)));
list.add(l2);
l1 = l2;
}
} else {
l1 = new Location("MAP");
l1.setLatitude(Double.parseDouble(lat));
l1.setLongitude(Double.parseDouble(lng));
l1.setAccuracy(Float.parseFloat(ac));
l1.setAltitude(Double.parseDouble(alt));
if (l1.getAccuracy() > 50)
l1 = null;
}
} while (c.moveToNext());
So that removes the possibilities for these random lines assuming its working as it should.
When it is working correctly it should come up like this:
However, when I zoom in a little more or move around sometimes I get these random lines:
Im adding the lines like this:
Location[] locations = Arrays.copyOfRange(mLocations, a, b);
if (mStartLine != null)
mStartLine.remove();
if (mMiddleLine != null)
mMiddleLine.remove();
if (mEndLine != null)
mEndLine.remove();
if (mMarker != null) {
mMarker.remove();
mMarker = null;
}
PolylineOptions so = new PolylineOptions();
PolylineOptions mo = new PolylineOptions();
PolylineOptions eo = new PolylineOptions();
so.color(Color.GREEN);
eo.color(Color.GREEN);
mo.color(Color.BLACK);
if (locations.length < 2) {
if (locations.length == 0)
return;
// Add just a dot instead.
MarkerOptions m = new MarkerOptions();
m.position(new LatLng(locations[0].getLatitude(), locations[0]
.getLongitude()));
mMarker = mMap.addMarker(m);
return;
}
so.add(new LatLng(locations[0].getLatitude(), locations[0].getLongitude()));
so.add(new LatLng(locations[1].getLatitude(), locations[1].getLongitude()));
mStartLine = mMap.addPolyline(so);
for(int i = 1; i < (locations.length - 1); i++){
mo.add(new LatLng(locations[i].getLatitude(), locations[i].getLongitude()));
}
mMiddleLine = mMap.addPolyline(mo);
eo.add(new LatLng(locations[locations.length - 2].getLatitude(), locations[locations.length - 2].getLongitude()));
eo.add(new LatLng(locations[locations.length - 1].getLatitude(), locations[locations.length - 1].getLongitude()));
mEndLine = mMap.addPolyline(eo);
The bar at the bottom is a selector to only show that span of locations (Because when you have something like 7000 locations showing then it gets pretty crazy and you get StackOverflowError's)
There appears to be a bug open for it: https://code.google.com/p/gmaps-api-issues/issues/detail?id=5313
EDIT
It appears if you filter vertices that are closer than 1 meter to each other the the bug is resolved. I will write some code to fix this later tonight and put it here.
UPDATE
This bug was handled in Google issue tracker
https://issuetracker.google.com/issues/35821816
It was fixed in Google Play Services - 9.2.56
https://developers.google.com/maps/documentation/android-api/releases#june_27_2016
Here is an approach that fixed this issue for us. Not necessarily the ideal solution, but it works. At certain zoom levels you may see a polyline extend beyond where it should be (like the pictures show above). If you keep changing your zoom level the extension would disappear and then reappear. This happened to us everytime when two coordinates were exactly the same. e.g.
Lets say you have 3 coordinates A,B,C. Bus starts from A and goes to B, the bus then turns around and comes to C. If A and C are the exact same coordinates you would see this polyline extension problem.
After a few approaches we settled on offseting the latitude of point C by .00001. That has fixed all our issues.
Related
This seems like a duplicate question but it is not. Please read before you mark it as duplicate
I was trying to get distance between two LatLng, so first i generated it's PolylineOptions,
Now the problem is - The output is not understandable.
It's different from other questions because it uses PolylineOptions.
Calculating Code
#Override
public void onParserTaskComplete(PolylineOptions points, int count) {
if (points != null) {
float totalDistance = 0;
for (int i = 1; i < points.getPoints().size(); i++) {
Location currLocation = new Location("this");
currLocation.setLatitude(points.getPoints().get(i).latitude);
currLocation.setLongitude(points.getPoints().get(i).longitude);
Location lastLocation = new Location("this");
currLocation.setLatitude(points.getPoints().get(i - 1).latitude);
currLocation.setLongitude(points.getPoints().get(i - 1).longitude);
totalDistance += lastLocation.distanceTo(currLocation);
}
items.get(count).setDistance(String.valueOf(totalDistance));
adapter.notifyDataSetChanged();
} else {
items.get(count).setDistance("");
adapter.notifyDataSetChanged();
}
}
According to Google Maps the distance should be around 5.5KM
but output is coming like 8783711.0
Question - How do i convert this value to KM?
You duplicated currLocation and don't set values for lastLocation.
This is correct way:
Location currLocation = new Location("this");
currLocation.setLatitude(points.getPoints().get(i).latitude);
currLocation.setLongitude(points.getPoints().get(i).longitude);
Location lastLocation = new Location("this");
// here you used currLocation
lastLocation.setLatitude(points.getPoints().get(i - 1).latitude);
lastLocation.setLongitude(points.getPoints().get(i - 1).longitude);
I have a huge list in an XML tag like so:
<coor> -123.3858,41.34119,0
-123.3856,41.34109,0
-123.3852,41.34121,0
-123.3848,41.34139,0</coor>
and need it like this:
new LatLng(-123.3858,41.34119),
new LatLng(-123.3856,41.34109),
new LatLng(-123.3852,41.34121),
new LatLng(-123.3848,41.34139),
to work with google maps v2 android.
I've done a string replace on the coordinates and am getting the correct results like so:
String ll = "),new LatLng(";
coor = coor.replaceAll(",0", ll);
replacing the ,0 for the new LatLng(... I am not figuring out how to change the large string of latlng text into latlng locations to put into my polygon:
PolygonOptions perimeteres = new PolygonOptions().add(coor);
Is there way to do this? Or do I need to separate each out and make them individual latlng?
EDIT::::
String[] splitData = coor.split(",0");
for (String eachSplit : splitData) {
if (!eachSplit.endsWith(",0")) {
//Log.e("EACH",eachSplit);
Log.v("e","new LatLon("+eachSplit+");");
}
}
This is getting me a little closer...
You are going completely in the wrong direction, this
String ll = "),new LatLng(";
coor = coor.replaceAll(",0", ll);
is not the same as
new LatLng(-123.3858,41.34119)
the first gives you a string which does nothing for you, the second is an object which is what you need.
Edit
you need to remove the 0 from the coordinates then you do a string split on the , so you have an array of latitudes and longitudes.
then create a List<LatLng> which is what you need to create a polygon of points
and loop through your points
for(int j=0;j<locationAry.length;j++){
if(j%2 == 0){
lon = Float.parseFloat(locationAry[j+1]);
lat = Float.parseFloat(locationAry[j]);
}
}
i am currently trying to implement an ActionBar-Button that on usage sets all my markers on my GoogleMap-object visible or invisible. My problem is that i don't know how i can get a reference to all my markers once they have been created and are shown on my map. Im looking for a solution where i stash all my marker-objects into an array, that i can access in other parts of my code aswell. is this approach reasonable?
here is what i am thinking of:
private Marker[] mMarkerArray = null;
for (int i = 0; i < MainActivity.customers.size(); i++) {
LatLng location = new LatLng(mData.lat, mData.lng);
Marker marker = mMap.addMarker(new MarkerOptions().position(location)
.title(mData.title)
.snippet(mData.snippet));
mMarkerArray.add(marker);
}
and set all my markers invisible on within another method:
for (int i = 0; i < mMarkerArray.length;; i++) {
mMarkerArray[i].setVisible(false);
}
it refuses to add the markers to a Marker[]-array. how can i achieve it?
mMarkerArray.add(marker) doesnt work
i figured out an answer that also regards my customerList having customers without coordinates --> (0,0;0,0). inspired by this blog.
initialize ArrayList:
private ArrayList<Marker> mMarkerArray = new ArrayList<Marker>();
add marker to my map and to the mMarkerArray:
for (int i = 0; i < MainActivity.customers.size(); i++) {
Customer customer = MainActivity.customers.get(i);
if (customer.getLon() != 0.0) {
if (!customer.isProspect()) {
Data mData= new Data(customer.getLat(),customer.getLon(),customer.getName(),
customer.getOrt());
LatLng location = new LatLng(mData.lat, mData.lng);
Marker marker = mMap.addMarker(new MarkerOptions().position(location)
.title(mData.title)
.snippet(mData.snippet));
mMarkerArray.add(marker);
}}}
set all markers not-visible
for (Marker marker : mMarkerArray) {
marker.setVisible(false);
//marker.remove(); <-- works too!
}
Replace
private Marker[] mMarkerArray = null;
with
private List<Marker> mMarkerArray = new ArrayList<Marker>();
and you should be fine.
If you use Android Maps Extensions, you can simply iterate over all markers using
for (Marker marker : googleMap.getMarkers()) {
marker.setVisible(false);
}
without having your own List of all Markers.
You can keep a Collection of OverlayItem within your Activity or Fragment and then call MapView.getOverlays().clear() to make them "invisible" and then add them back to make them visible again. Call MapView.invalidate() after each action to cause the map to be repainted.
I am making an android app that will list specific places that are not on google places. I have all the latitude and longitudes and place names and they will not be changing. I can display them in my custom list and it works fine the problem is I want to sort them all by distance from your(the users) location and display the distance next to them.
I have tried lots of different ways but have become a bit stuck. I would like to say that I am new to programming and sort of stumbling my way through this app, If anyone could help it would be really appreciated.
So the question im asking is how can/should I sort locations by distance so I can add them to my custom list.
// create array to hold place names to be looped through later
String[] placenames = { "place1", "place2",
"place3", "place4" };
// // create arrays to hold all the latitudes and longitudes
double[] latArray = new double[] { 51.39649, 51.659775, 51.585433,
51.659775 };
double[] lngArray = new double[] { 0.836523, 0.539901, 0.555385,
0.539901, };
// hard code my location for test purposes only
Location MyLocation = new Location("My location");
MyLocation.setLatitude(51.659775);
MyLocation.setLongitude(0.539901);
for (int i = 0; i < placenames.length;) {
// Place location object
Location PlaceName = new Location(placenames[i]);
PlaceName.setLatitude(latArray[i]);
PlaceName.setLongitude(lngArray[i]);
i++;
// calculate distance in meters
float distanceInMeters = PlaceName.distanceTo(MyLocation);
// convert to double
double DistanceInMiles = distanceInMeters * 0.000621371;
dimint = (int) DistanceInMiles;
// format numbers to two decimal places
DecimalFormat df = new DecimalFormat("#.##");
dim = df.format(DistanceInMiles);
//make treemap and then sortedmap to sort places by distance
TreeMap<Integer, String> treemap = new TreeMap<Integer, String>();
SortedMap<Integer, String> treemapsorted = new TreeMap<Integer,String>();
treemap.put(dimint, PlaceName.getProvider());
treemapsorted = treemap.subMap(0, 5);
// Toast for test purpose to see if sort is working
Toast tst = Toast.makeText(this, treemapsorted.entrySet()
.toString(), Toast.LENGTH_SHORT);
tst.show();
CustomList place_data[] = new CustomList[] {
// This is the problem part
new CustomList(R.drawable.picture1, treemapsorted.get(dimint)),
};
CustomListAdapter adapter = new CustomListAdapter(this,
R.layout.listview_item_row, place_data);
listView1 = (ListView) findViewById(R.id.listView1);
listView1.setAdapter(adapter);
;
}
I just reviewed your code and found lots of problems:
Use i++ in your for loop statement instead of in the loop body, like this:
for (int i = 0; i < placenames.length; i++) {
}
You calculate the distance in miles, cast this to int (I would use Math.round() here) and then create a string with DecimalFormat which you don't use.
You create a TreeMap in every loop iteration. Move the creation in front of the loop and add items to it in the loop body.
TreeMap is not the right class for this task. I tested your code and the Map contained only 3 items after the loop. The reason is, that a TreeMap contains key value pairs, where the key has to be unique. Adding an element with a key (distance in your case), which is already in the map, results in overwriting that element. So instead of a TreeMap I recommend using an ArrayList. You need to create a class with all the variables you need, like distance and place name. This class needs to implement the interface Comparable<Class>. You will then have to implement the method public int compareTo(T other) in which you compare the distance with the distance of the other object. Then you can sort the ArrayList using Collections.sort(arrayList). In the for loop body you should add items to that ArrayList, then sort it, then iterate over the ArrayList items and add them to your ListView.
My Problem is I have 4 Location's Latitude and Longitude into my local database, I am fetching those data and use for draw route path in android but problem is first to second location route is not display on mapview other second to third and third to fourth route path is display on mapview. Sorry for bad English communication.
i am getting code from following link for draw route path.
MapRoute Example
and call drawing class using following function:-
public void drawpath(){
mDb.open();
Cursor cr = mDb.getAllTitles();
cr.moveToFirst();
if (cr.getCount() > 0) {
for (int i = 0; i <= cr.getCount()/2; i++) {
fromlat = Double.parseDouble(cr.getString(1));
fromlng = Double.parseDouble(cr.getString(2));
cr.moveToNext();
tolat = Double.parseDouble(cr.getString(1));
tolng = Double.parseDouble(cr.getString(2));
String url = RoadProvider
.getUrl(fromlat, fromlng, tolat, tolng);
InputStream is = getConnection(url);
mRoad = RoadProvider.getRoute(is);
MapOverlay mapOverlay = new MapOverlay(mRoad, mapView);
List<Overlay> listOfOverlays = mapView.getOverlays();
listOfOverlays.add(mapOverlay);
mapView.invalidate();
}
}
cr.close();
mDb.close();
}
Intent intent = new Intent(android.content.Intent.ACTION_VIEW,
Uri.parse("http://maps.google.com/maps?saddr=20.344,34.34&daddr=20.5666,45.345"));
startActivity(intent);
It is happening because you are using cr.getCount()/2.
When you will have even number of count then it will work not work fine
For example if you have 4 number of rows then you cr.getCount()/2 = 2
so your loop will continue from 0 to 2 means 3 times.
Actually it should be continue 2 times as your coding.
Now lat take a odd numbers say 5 so cr.getCount()/2 = 2 because i is the integer value so your loop will work total 3 times.
So you have different mechanism.
Like try to add all the lat and long in the arraylist and then after loop complete.
Make a loop of the size of that arrayList and create a path.May be for that you required two additional variable to store the previous lat and long.