How to fix this problem Collect coordinates to point polygon - android

I have problem about my gps and plot polygon
I collect GPS every second from
Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
and put it to realm database
(So I things do I not good idea)
Maybe should accumulate every 10 meters
image below is result I got
my problems
Polygon look alike the PASTA instead of area.
My gps can jump over to another building(GPS is not stable)
help recommend me please.
ArrayList<LatLng> coordList = new ArrayList<LatLng>();
#Cleanup Realm realm = Realm.getDefaultInstance();
RealmResults<PolygonAreas> PlotPolygon = realm.where(PolygonAreas.class).findAll();
if (PlotPolygon.size() > 0) {
for (PolygonAreas Polypoint : PlotPolygon) {
coordList.add(new LatLng(Polypoint.getLatitude(), Polypoint.getLongitude()));
try {
Runnable addPolygon = new CellTowerMarkerGoogle.AddPolygon(mMap, new PolygonOptions()
.addAll(coordList).fillColor(0x7F80b370).strokeColor(0x7F80b370)
);
getActivity().runOnUiThread(addPolygon);
} catch (Exception e) {
log.debug("Exception : " + e);
}
}
}
public static class AddPolygon implements Runnable{
private GoogleMap map;
private PolygonOptions options;
public AddPolygon(GoogleMap map,PolygonOptions options){
this.map = map;
this.options = options;
}
#Override
public void run() { map.addPolygon(options);}
}

I found problem
Because my logic incorrect variable addPolygon
every back again it's create new Object polygon(.addAll)
It causes the creation of overloaded objects.
How can I fix it?
I have to destroy the polygon object and recreate it every time.
The value will be updated all the time. I have to destroy and create new polygons every time to update.

Related

Picking the right Zoom level for different cities in GoogleMaps

I have an activity implementing OnMapReadyCallback to display some markers.
Before opening the map i provide a target city which i'd like to look at closer on the map basically by calling :
LatLng currentCity = new LatLng(cityLat,cityLng)
CameraUpdate location = CameraUpdateFactory.newLatLngZoom(currentCity,13);
googleMap.animateCamera(location);
The main problem here is that the zoom level is just an arbitrary number which works fine for some city and bad for others (Too zoomed in, Not enough zoomed in).
What i would like to achieve is to determine the zoom level dynamically depending on the city in the same way Google Maps does.
I know that the bigger the ViewPort of the city is, the smaller the zoom needs to be but i can't find a method to get the ViewPort for a given city and then changing the zoom level accordingly
EDIT : I was thinking about using a Geocoder to get a list of adress using the latitude and longitude of the city using
List<Address> addresses = mGeocoder.getFromLocation(Lat,Lon,maxLimit);
and then iterating over this list to find out the outermost adresses avaible for that city, in order to build a LatLngBounds to pass at setLatLngBoundsForCameraTarget() method.
The main problem with this approach is that, once again, the "maxLimit" is arbitrary and needs to be quite big for a big city, eventually returning a really big List
You can retrieve a view port for the city from the Geocoding API reverse geocoding response.
You should execute HTTP request to retrieve city view port from your activity. Once you receive the response you can construct the LatLngBounds instance and move camera accordingly.
Sample reverse geocoding request that gets city from coordinates is the following
https://maps.googleapis.com/maps/api/geocode/json?latlng=47.376887%2C8.541694&result_type=locality&key=YOUR_API_KEY
I wrote a small example for Map activity that receives lat and lng from the intent, executes the reverse geocoding HTTP request using the Volley library and moves camera to show the city view port.
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
private float lat;
private float lng;
private String name;
private RequestQueue mRequestQueue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent i = getIntent();
this.lat = i.getFloatExtra("lat", 0);
this.lng = i.getFloatExtra("lng", 0);
this.name = i.getStringExtra("name");
mRequestQueue = Volley.newRequestQueue(this);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng pos = new LatLng(this.lat, this.lng);
mMap.addMarker(new MarkerOptions().position(pos).title(this.name));
mMap.moveCamera(CameraUpdateFactory.newLatLng(pos));
this.fetchReverseGeocodeJson();
}
private void fetchReverseGeocodeJson() {
// Pass second argument as "null" for GET requests
JsonObjectRequest req = new JsonObjectRequest(Request.Method.GET,
"https://maps.googleapis.com/maps/api/geocode/json?latlng=" + this.lat + "%2C" + this.lng + "&result_type=locality&key=AIzaSyBrPt88vvoPDDn_imh-RzCXl5Ha2F2LYig",
null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
String status = response.getString("status");
if (status.equals("OK")) {
JSONArray results = response.getJSONArray("results");
JSONObject item = results.getJSONObject(0);
JSONObject geom = item.getJSONObject("geometry");
JSONObject bounds = geom.getJSONObject("viewport");
JSONObject ne = bounds.getJSONObject("northeast");
JSONObject sw = bounds.getJSONObject("southwest");
LatLngBounds mapbounds = new LatLngBounds(new LatLng(sw.getDouble("lat"),sw.getDouble("lng")),
new LatLng(ne.getDouble("lat"), ne.getDouble("lng")));
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(mapbounds, 0));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e("Error: ", error.getMessage());
}
}
);
/* Add your Requests to the RequestQueue to execute */
mRequestQueue.add(req);
}
}
You can find a complete sample project at github:
https://github.com/xomena-so/so44735477
Hope this helps!

Cannot create route from one point to another ArcGIS Android

I've been trying very hard to create a route between two points(startPoint, endPoint). But i am getting the following error:
Location "Location 1" in "Stops" is unlocated. Location "Location 2" in "Stops" is unlocated. Need at least 2 valid stops. "Stops" does not contain valid input for any route.
I've posted this question on gis.stackexchange.com and geonet.esri.com and didn't get a reply except one which was not helpful.
My Code:
private final String routeTaskURL = "http://sampleserver3.arcgisonline.com/ArcGIS/rest/services/Network/USA/NAServer/Route";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMapView = (MapView) findViewById(R.id.map);
mMapView.enableWrapAround(true);
new Thread(new Runnable() {
#Override
public void run() {
try {
UserCredentials userCredentials = new UserCredentials();
userCredentials.setUserToken(token, clientID);
RouteTask routeTask = RouteTask.createOnlineRouteTask(routeTaskURL, userCredentials);
RouteParameters routeParameters = routeTask.retrieveDefaultRouteTaskParameters();
NAFeaturesAsFeature naFeatures = new NAFeaturesAsFeature();
Point startPoint = new Point(36.793653, -119.866896);
Point stopPoint = new Point(36.795488, -119.853345);
StopGraphic startPnt = new StopGraphic(startPoint);
StopGraphic stopPnt = new StopGraphic(stopPoint);
naFeatures.setFeatures(new Graphic[] {startPnt, stopPnt});
routeParameters.setStops(naFeatures);
RouteResult mResults = routeTask.solve(routeParameters);
List<Route> routes = mResults.getRoutes();
System.out.println(mResults.getRoutes());
Route mRoute = routes.get(0);
Geometry geometry = mRoute.getRouteGraphic().getGeometry();
Graphic symbolGraphic = new Graphic(geometry, new SimpleLineSymbol(Color.BLUE, 3));
mGraphicsLayer.addGraphic(symbolGraphic);
System.out.println(mResults.getStops());
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
I've searched the internet. Many developers were/are facing this problem. I've tried all the solutions but none of them worked. I got routeTaskURL from the ArcGIS Routing Sample app. The link which is given in the documentation of ArcGIS maps gives me the 403 error if i open it in the browser.
Note: "token" and "clientID" is declared in the first step and they both are taken from the ArcGIS developers console where i registered my application.
Any Suggestions?
Your X and Y values are switched. Change to this:
Point startPoint = new Point(-119.866896, 36.793653);
Point stopPoint = new Point(-119.853345, 36.795488);
See the Point class documentation to learn that the constructor parameters are (x, y), not (y, x). The route service you're using has a default spatial reference of 4326, which is unprojected longitude and latitude. -119.866896 and -119.853345 are not valid latitude (y) values, but they are valid longitude (x) values.

Controlling markers Deployment.?

I am building an android app in which i have to do tracking of a user from one date/time to another and deploy makers using polylines one by one?
In response from a server i am receiving multiple lat/langs in a list. Now i want to deploy them one by one like a video is being played i know how to add markers i just want to control there deployment.E.g Marker A is deployed after 2 secs marker B should be deployed and joining with marker A with a poly-line and so do markers C,D. etc. How should i be able to achieve that. Timer, Threads? Any help or references,algos, would be great although i have searched such examples i couldn't find it yet.
Thanks in advance
You can use Handler to perform this task.
I am posting an example for you, I have not run it but I hope It will run successfully:
private final Handler mHandler = new Handler(Looper.getMainLooper());
private List<LatLng> mLatLngs;
private PutMarkerRunnable mRunnable;
private int mNoOfMarkersPlaced = -1;
private void showMarkers(List<LatLng> latLngs) {
mLatLngs = latLngs;
mHandler.post(mRunnable);
}
private class PutMarkerRunnable implements Runnable {
#Override
public void run() {
// write code to add marker
map.addMarker();
mNoOfMarkersPlaced++;
if (mNoOfMarkersPlaced != mLatLngs.size()) {
// scheduling next marker to be placed after 3 seconds
mHandler.postDelayed(mRunnable, 3000);
}
}
}
Ok thanks community.. But i have been finally able to do this through. Mark it correct because this really worked for me!
First we animate our camera using..
CameraPosition cameraPosition =
new CameraPosition.Builder()
.target(new LatLng(0,0))
.bearing(45)
.tilt(90)
.zoom(googleMap.getCameraPosition().zoom)
.build();
googleMap.animateCamera(
CameraUpdateFactory.newCameraPosition(cameraPosition),
ANIMATE_SPEEED_TURN,
new CancelableCallback() {
#Override
public void onFinish() {
}
#Override
public void onCancel() {
}
}
);/**
*
* Callback that highlights the current marker and keeps animating to the next marker, providing a "next marker" is still available.
* If we've reached the end-marker the animation stops.
*
*/
CancelableCallback simpleAnimationCancelableCallback =
new CancelableCallback(){
#Override
public void onCancel() {
}
#Override
public void onFinish() {
if(++currentPt < markers.size()){
CameraPosition cameraPosition =
new CameraPosition.Builder()
.target(targetLatLng)
.tilt(currentPt<markers.size()-1 ? 90 : 0)
//.bearing((float)heading)
.zoom(googleMap.getCameraPosition().zoom)
.build();
googleMap.animateCamera(
CameraUpdateFactory.newCameraPosition(cameraPosition),
3000,
simpleAnimationCancelableCallback);
highLightMarker(currentPt);
}
}
};
A bearing can be calculated between 2 android.location.Location objects. As we’re working with com.google.android.gms.maps.model.LatLng objects here, we first need to convert them into Location objects.
private Location convertLatLngToLocation(LatLng latLng) {
Location location = new Location("someLoc");
location.setLatitude(latLng.latitude);
location.setLongitude(latLng.longitude);
return location;
}
Once we have 2 Location objects, we can calculate the bearing between the 2. This is what we need to put on the Camera when transitioning to the target (the endLocation).
private float bearingBetweenLatLngs(LatLng beginLatLng,LatLng endLatLng) {
Location beginLocation = convertLatLngToLocation(beginLatLng);
Location endLocation = convertLatLngToLocation(endLatLng);
return beginLocation.bearingTo(endLocation);
}
We’ll use that number to calculate the coordinates of the intermediate point. Once we have those coordinates, we set our tracking marker to that new position.
long elapsed = SystemClock.uptimeMillis() - start;
double t = interpolator.getInterpolation((float)elapsed/ANIMATE_SPEEED);
double lat = t * endLatLng.latitude + (1-t) * beginLatLng.latitude;
double lng = t * endLatLng.longitude + (1-t) * beginLatLng.longitude;
LatLng intermediatePosition = new LatLng(lat, lng);
trackingMarker.setPosition(intermediatePosition);
We’ll also update our polyline with the new marker position, creating a trailing effect on the polyline.
private void updatePolyLine(LatLng latLng) {
List<LatLng> points = polyLine.getPoints();
points.add(latLng);
polyLine.setPoints(points);
}

RoadManager for osmdroid error

I am following a tutorial here https://code.google.com/p/osmbonuspack/wiki/Tutorial_1 but I have encountered an error that it doesn't show the correct route correctly. It just shows a straight line from Point A to Point B.
What I want to achieve is to show the correct route from these points. I'm guessing the error is that it doesn't recognize any nodes to go through.
A similar question has been also asked and I am assuming I have the same problem if I haven't explained my question well.
Similar question can be found here: OSMDroid Routing problems when following a tutorial
Here is a part of my code using RoadManager
Here is a part of the code.
try {
//get current longlat
gpsLocator.getLocation();
cur_loc_lat =gpsLocator.getLatitude();
cur_loc_long =gpsLocator.getLongitude();
} catch (Exception e) {
// TODO: handle exception
}
//--- Create Another Overlay for multi marker
anotherOverlayItemArray = new ArrayList<OverlayItem>();
anotherOverlayItemArray.add(new OverlayItem(
"UST", "UST", new GeoPoint( testlat, testlong)));
//--- Create Another Overlay for multi marker
anotherOverlayItemArray.add(new OverlayItem(
locDefine[0], "UST", new GeoPoint( sel_latitude, sel_longitude)));
ItemizedIconOverlay<OverlayItem> anotherItemizedIconOverlay
= new ItemizedIconOverlay<OverlayItem>(
TomWalks.this, anotherOverlayItemArray, myOnItemGestureListener);
myOpenMapView.getOverlays().add(anotherItemizedIconOverlay);
//---
//Add Scale Bar
ScaleBarOverlay myScaleBarOverlay = new ScaleBarOverlay(TomWalks.this);
myOpenMapView.getOverlays().add(myScaleBarOverlay);
try {
//1 Routing via road manager
RoadManager roadManager = new MapQuestRoadManager();
roadManager.addRequestOption("routeType=pedestrian");
/*
roadManager.addRequestOption("units=m");
roadManager.addRequestOption("narrativeType=text");
roadManager.addRequestOption("shapeFormat=raw");
roadManager.addRequestOption("direction=0");
*/
//Then, retrieve the road between your start and end point:
ArrayList<GeoPoint> waypoints = new ArrayList<GeoPoint>();
waypoints.add(new GeoPoint(testlat, testlong));
waypoints.add(new GeoPoint(sel_latitude,sel_longitude)); //end point
Road road = roadManager.getRoad(waypoints);
// then, build an overlay with the route shape:
PathOverlay roadOverlay = RoadManager.buildRoadOverlay(road, myOpenMapView.getContext());
roadOverlay.setColor(Color.GREEN);
//Add Route Overlays into map
myOpenMapView.getOverlays().add(roadOverlay);
myOpenMapView.invalidate();//refesh map
final ArrayList<ExtendedOverlayItem> roadItems =
new ArrayList<ExtendedOverlayItem>();
ItemizedOverlayWithBubble<ExtendedOverlayItem> roadNodes =
new ItemizedOverlayWithBubble<ExtendedOverlayItem>(TomWalks.this, roadItems, myOpenMapView);
myOpenMapView.getOverlays().add(roadNodes);
myOpenMapView.invalidate();//refesh map
int nodesize=road.mNodes.size();
double length = road.mLength;
Drawable marker = getResources().getDrawable(R.drawable.marker_node);
Toast.makeText(TomWalks.this, " Distance : " + length + " Nodes : "+nodesize ,Toast.LENGTH_SHORT).show();
for (int i=0; i<road.mNodes.size(); i++)
{
RoadNode node = road.mNodes.get(i);
ExtendedOverlayItem nodeMarker = new ExtendedOverlayItem("Step "+i, "", node.mLocation, TomWalks.this);
nodeMarker.setMarkerHotspot(OverlayItem.HotspotPlace.CENTER);
nodeMarker.setMarker(marker);
roadNodes.addItem(nodeMarker);
nodeMarker.setDescription(node.mInstructions);
nodeMarker.setSubDescription(road.getLengthDurationText(node.mLength, node.mDuration));
Drawable icon = getResources().getDrawable(R.drawable.marker_node);
nodeMarker.setImage(icon);
}//end for
myOpenMapView.getOverlays().add(roadNodes);
myOpenMapView.invalidate();//refesh map
} catch (Exception e) {
// TODO: handle exception
Toast.makeText(TomWalks.this,e.getMessage(),Toast.LENGTH_SHORT).show();
}
myMapController.setCenter(new GeoPoint( sel_latitude, sel_longitude));
} catch (Exception e) {
// TODO: handle exception
}
}
}
}//===================================================================================================
Let's try to provide a complete answer to this quite frequent question.
Basically, when you get the "straight line", it means that the RoadManager got an error.
So, first of all, in your code, you should check the result of getRoad, this way:
if (road.mStatus != Road.STATUS_OK){
//handle error... warn the user, etc.
}
Now, where this error is coming from?
=> You must search in the logcat. You should find the full url that has been sent, and probably a stacktrace about the error.
I strongly recommend that you copy/paste this full url in a browser , and check the result.
Here are the typical errors, by decreasing probability:
1) You didnt' read carefully the "Important note" at the beginning of the Tutorial_0, and you are trying to do a Network call in the main thread, with an SDK >= 3.0.
=> Read this "Important note".
2) You asked for a route that is not possible (really not possible, or because of weird positions, or because of setting unsupported options).
=> This is easy to check by copy/pasting the full url in a web browser, and looking at the answer.
3) Your device has no network connectivity.
4) The routing service changed its API (this happened, more than once...).
=> Could be checked by copy/pasting the full url in a browser.
In this case, raise an Issue in OSMBonusPack project, so that we can take it into account ASAP.
5) The routing service is down.
=> Easy to check by copy/pasting the full url in a browser.
I think it is better to use AsyncTasks in this case:
/**
* Async task to get the road in a separate thread.
*/
private class UpdateRoadTask extends AsyncTask<Object, Void, Road> {
protected Road doInBackground(Object... params) {
#SuppressWarnings("unchecked")
ArrayList<GeoPoint> waypoints = (ArrayList<GeoPoint>)params[0];
RoadManager roadManager = new OSRMRoadManager();
return roadManager.getRoad(waypoints);
}
#Override
protected void onPostExecute(Road result) {
road = result;
// showing distance and duration of the road
Toast.makeText(getActivity(), "distance="+road.mLength, Toast.LENGTH_LONG).show();
Toast.makeText(getActivity(), "durée="+road.mDuration, Toast.LENGTH_LONG).show();
if(road.mStatus != Road.STATUS_OK)
Toast.makeText(getActivity(), "Error when loading the road - status="+road.mStatus, Toast.LENGTH_SHORT).show();
Polyline roadOverlay = RoadManager.buildRoadOverlay(road,getActivity());
map.getOverlays().add(roadOverlay);
map.invalidate();
//updateUIWithRoad(result);
}
}
then call it new UpdateRoadTask().execute(waypoints);
new Thread(new Runnable()
{
public void run()
{
RoadManager roadManager = new OSRMRoadManager();
ArrayList<GeoPoint> waypoints = new ArrayList<GeoPoint>();
GeoPoint startPoint = new GeoPoint(source_lat, source_longi);
waypoints.add(startPoint);
GeoPoint endPoint = new GeoPoint(desti_lat,desti_longi);
waypoints.add(endPoint);
try
{
road = roadManager.getRoad(waypoints);
}
catch (Exception e)
{
e.printStackTrace();
}
runOnUiThread(new Runnable()
{
public void run()
{
if (road.mStatus != Road.STATUS_OK)
{
//handle error... warn the user, etc.
}
Polyline roadOverlay = RoadManager.buildRoadOverlay(road, Color.RED, 8, context);
map.getOverlays().add(roadOverlay);
}
});
}
}).start();
And i am use two jar files 1)slf4j-android-1.5.8.jar and 2)osmdroid-android-4.2.jar and osmbonuspack library.
A strange error I found regarding this is as follows:
Firstly I mention following line of code for taking directions for the vehicle "BIKE"
((OSRMRoadManager) roadManager).setMean(OSRMRoadManager.MEAN_BY_BIKE);
Now when it was first called it follows the following URL:
https://routing.openstreetmap.de/routed-car/route/v1/driving/68.8889678000,23.2151582000;73.1808008000,22.3110728000?alternatives=false&overview=full&steps=true
Now when calling the second time{same MEAN_BY_BIKE}, it is following this URL:
:https://routing.openstreetmap.de/routed-bike/route/v1/driving/68.8889678000,23.2151582000;73.1808008000,22.3110728000?alternatives=false&overview=full&steps=true
So the issue is that no response is for the "routed-bike" and it is calling automatically itself when called for second time.
So as a solution I changed my code to the following:
((OSRMRoadManager) roadManager).setMean(OSRMRoadManager.MEAN_BY_CAR);
You can check your LogCat for the same.

Map push pins - limit on a screen / concurrentModificationException

So I am extending an ItemizedOverlay, and using a rest query to make an async http request to web service where I can get the coordinates of lots of push pins.
Once the handler gets the async http request I do the following (maybe not the best solution - ie. clearing all records all the time). But I am open to suggestions (hence the post)..
Basically here is the code flow (I have a list view & map view on a flipper and want to keep them in sync - hence the arrayAdapter;
locationRecords.clear(); // ArrayList<LocationRecord>
updateScreen(jArray); // jSONArray jArray
arrayAdapter.notifyDataSetChanged();
updateOverlay();
private synchronized void updateOverlay() {
// Clear the previous overlay of map push pins (don't want to keep adding new overlays)
Iterator<Overlay> listofOverlays = mapView.getOverlays().iterator();
while (listofOverlays.hasNext()) {
Overlay tempOverlay = listofOverlays.next();
if (tempOverlay.getClass().equals(MunzeeOverlay.class)) {
mapView.getOverlays().remove(tempOverlay);
}
this.notify();
}
MyOverlay overlay = new MyOverlay(MapTools.getGreenMarker(mContext),mapView);
Iterator<LocationRecord> mapList = locationRecords.iterator();
while (mapList.hasNext()) {
overlay.addOverlay(mapList.next().getOverlayItem());
}
mapView.getOverlays().add(overlay);
}
protected void updateScreen(JSONArray jArray) {
if ( jArray != null ) {
for ( int i = 0; i < jArray.length(); i++ ) {
try {
JSONObject myArray = jArray.getJSONObject(i);
locationRecords.add(new LocationRecord(myArray,mContext));
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
My thought is on the myOverlay that I can do a check when I addOverlay w/ an equiv check and make sure it is not already there, that way i would not need to delete the overlay on the map?
I also am seeing some ConcurrentModificationExceptions in updateOverlay (I suppose that could have to do w/ clearing the locationRecords & updatingScreen not in a synchronized manner.. Sooo..
1) Any suggestions for improving map pin performance, and not seeming to freeze the map while it is updating the overlay
2) Any suggestions on fixing the ConcurrentModificationExceptions?
Have one overlay with N pins. Near as I can tell, you have N overlays with one pin each. This is bad.
When your data arrives, call populate() on the one-and-only overlay to have Android reload all of the markers -- you do not need to clear anything yourself.

Categories

Resources