Wrong distances when creating random locations - android

I am trying to create random locations nearby my location. What i want is to create random latitude/longitude pairs inside a 200 meters circle surrounding my location. After asking this question: generate random locations nearby my location this is what i have come up with.
in onLocationChanged, this is what i do:
private void updateWithNewLocation(Location location) {
if (location != null) {
this.myItemizedOverlay.clear();
this.nonPlayerItemizedOverlay.clear();
this.mapOverlays.clear();
// Update my map location.
Double latitude = location.getLatitude() * 1E6;
Double longitude = location.getLongitude() * 1E6;
GeoPoint geoPoint = new GeoPoint(latitude.intValue(),
longitude.intValue());
CustomOverlayItem pcOverlayItem = new CustomOverlayItem(geoPoint,
"", "", "");
this.mapController.animateTo(geoPoint);
this.myItemizedOverlay.setLocation(location);
this.myItemizedOverlay.addOverlay(pcOverlayItem);
this.mapOverlays.add(this.myItemizedOverlay);
// Everytime i get a new location i generate random non player
// characters near my location
int numberOfNonPlayers = new Random().nextInt(5);
for (int i = 0; i < numberOfNonPlayers; i++) {
int radius = (int) this.myMapView.getProjection()
.metersToEquatorPixels(200);
double lowerLimit = -1;
double upperLimit = 1;
Double newLatitude = location.getLatitude()
* 1E6
+ (radius * (lowerLimit + (Math.random() * ((upperLimit - lowerLimit) + 1))));
Double newLongitude = location.getLongitude()
* 1E6
+ (radius * (lowerLimit + (Math.random() * ((upperLimit - lowerLimit) + 1))));
GeoPoint geoPoint2 = new GeoPoint(newLatitude.intValue(),
newLongitude.intValue());
CustomOverlayItem npcOverlayItem = new CustomOverlayItem(
geoPoint2, "", "", "");
Location newLocation = new Location("npc " + i);
newLocation.setLatitude(newLatitude);
newLocation.setLongitude(newLongitude);
this.nonPlayerItemizedOverlay = new NonPlayerItemizedOverlay(
this.nonPlayerDrawable, this.myMapView);
this.nonPlayerItemizedOverlay.setLocation(newLocation);
this.nonPlayerItemizedOverlay.addOverlay(npcOverlayItem);
this.mapOverlays.add(this.nonPlayerItemizedOverlay);
}
}
}
And this is my NonPlayerItemizedOverlay class:
public class NonPlayerItemizedOverlay extends BaseItemizedOverlay {
public NonPlayerItemizedOverlay(Drawable defaultMarker, MapView mapView) {
super(defaultMarker, mapView);
// TODO Auto-generated constructor stub
}
private Location location;
public static int metersToRadius(float meters, MapView map, double latitude) {
return (int) (map.getProjection().metersToEquatorPixels(meters) * (1 / Math
.cos(Math.toRadians(latitude))));
}
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
super.draw(canvas, mapView, shadow);
if (shadow == false) {
Projection projection = mapView.getProjection();
// Get the current location
Double latitude = location.getLatitude();
Double longitude = location.getLongitude();
GeoPoint geoPoint = new GeoPoint(latitude.intValue(),
longitude.intValue());
// Convert the location to screen pixels
Point point = new Point();
projection.toPixels(geoPoint, point);
// int radius = metersToRadius(30, mapView, latitude);
int radius = (int) mapView.getProjection()
.metersToEquatorPixels(50);
RectF oval = new RectF(point.x - radius, point.y - radius, point.x
+ radius, point.y + radius);
// Setup the paint
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(2.0f);
paint.setColor(0xffE62020);
paint.setStyle(Style.STROKE);
canvas.drawOval(oval, paint);
paint.setColor(0x18E62020);
paint.setStyle(Style.FILL);
canvas.drawOval(oval, paint);
}
}
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
And my MyItemizedOverlay class:
public class MyItemizedOverlay extends BaseItemizedOverlay {
public MyItemizedOverlay(Drawable defaultMarker, MapView mapView) {
super(defaultMarker, mapView);
// TODO Auto-generated constructor stub
}
private Location location;
public static int metersToRadius(float meters, MapView map, double latitude) {
return (int) (map.getProjection().metersToEquatorPixels(meters) * (1 / Math
.cos(Math.toRadians(latitude))));
}
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
super.draw(canvas, mapView, shadow);
if (shadow == false) {
Projection projection = mapView.getProjection();
// Get the current location
Double latitude = location.getLatitude() * 1E6;
Double longitude = location.getLongitude() * 1E6;
GeoPoint geoPoint = new GeoPoint(latitude.intValue(),
longitude.intValue());
// Convert the location to screen pixels
Point point = new Point();
projection.toPixels(geoPoint, point);
// int radius = metersToRadius(100, mapView, latitude);
int radius = (int) mapView.getProjection().metersToEquatorPixels(
200);
RectF oval = new RectF(point.x - radius, point.y - radius, point.x
+ radius, point.y + radius);
// Setup the paint
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(2.0f);
paint.setColor(0xff6666ff);
paint.setStyle(Style.STROKE);
canvas.drawOval(oval, paint);
paint.setColor(0x186666ff);
paint.setStyle(Style.FILL);
canvas.drawOval(oval, paint);
}
}
public Location getLocation() {
return location;
}
public void setLocation(Location location) {
this.location = location;
}
The thing is that something weird is happening because all the random locations are too near of my location center, it seems that the formula does not cover the whole radius and i think that distances are not in real meters.
Any idea of what could be wrong with my formula?
Thanks in advance

For questions regarding map projections and coordinate calculations, this SE site could be helpful: http://gis.stackexchange.com (Geographic Information Systems).

To be sure use the distanceTo() formula of location class.You can do it this way:
double distance = a.distanceTo(b);
where a and b are Location objects.

Related

MapView display route between a lot of GeoPoints

I have an app where an user is given a lot of points (100 or even more) and he has to physically go to those points and "check in". They have to go to those points in a certain order, so I need to display a route in the MapView which passes through all those points.
I've read a lot about getting the route between two points, but I can't find anything about drawing a complex route with a lot of points. Is this behavior possible?
public class RouteOverlay extends Overlay {
private GeoPoint gp1;
private GeoPoint gp2;
private int color;
public RouteOverlay(GeoPoint gp1, GeoPoint gp2, int color) {
this.gp1 = gp1;
this.gp2 = gp2;
this.color = color;
}
Now all that's left now for our Overlay is to override the draw() method and draw the line as we need it:
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
Projection projection = mapView.getProjection();
Paint paint = new Paint();
Point point = new Point();
projection.toPixels(gp1, point);
paint.setColor(color);
Point point2 = new Point();
projection.toPixels(gp2, point2);
paint.setStrokeWidth(5);
paint.setAlpha(120);
canvas.drawLine(point.x, point.y, point2.x, point2.y, paint);
super.draw(canvas, mapView, shadow);
}
Back in the Activity, just iterate over the GeoPoints that you got from google maps and add each of them to the MapView:
private void drawPath(List geoPoints, int color) {
List overlays = mapView.getOverlays();
for (int i = 1; i < geoPoints.size(); i++) {
overlays.add(new RouteOverlay(geoPoints.get(i - 1), geoPoints.get(i), color));
}
}
Try something like this
if(DataSources.ActivitiesList.length >0)
{
String address = "http://maps.google.com/maps?daddr=" + DataSources.ActivitiesList[0].SiteLatitude.toString() + "," + DataSources.ActivitiesList[0].SiteLongitude.toString();
for (int i= 1 ;i < DataSources.ActivitiesList.length ; i++)
{
if(DataSources.ActivitiesList[i].SiteLatitude != null)
address += "+to:" + DataSources.ActivitiesList[i].SiteLatitude + "," + DataSources.ActivitiesList[i].SiteLongitude;
}
Intent intent = new Intent(android.content.Intent.ACTION_VIEW, Uri.parse(address));
startActivity(intent);
break;
}

Android google maps show geo points which are closest to current location

Is there any way If I have like 100 geo points added in my MapActivity and I want to show only these which are like 1000m away from my current location. The other ones should not be visible on the map.
Any suggestions?
Ok, here is the example. You can subclass Overlay class and override draw method. Whenever the Overlay is invalidated, you should check if your points are within 1000m from your location. Off course, you should know your location within your overlay class. The flowing is the example:
public class MyMapOverlay extends Overlay {
Bitmap bmp;
Context context;
public MyMapOverlay()
{
bmp = BitmapFactory.decodeResource(MyApplication.getContext().getResources(), R.drawable.myplace);
}
#Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when)
{
super.draw(canvas, mapView, shadow);
Point screenPts = new Point();
for(int i = 0;i<points.size(); i++)
{
GeoPoint point = points.get(i);
Location locationA = new Location("point " + String.valueOf(i));
locationA.setLatitude(point.getLatitudeE6());
locationA.setLongitude(point.getLongitudeE6());
float distance = myLocation.distanceTo(locationA);
if(distance < 1000.0)
{
mapView.getProjection().toPixels(p, screenPts);
canvas.drawBitmap(bmp, screenPts.x-bmp.getWidth()/2, screenPts.y-bmp.getHeight(), null);
}
}
return true;
}
With some help of the first answer I find this solution :
if(location != null){
Location locA = new Location("gps");
GeoPoint myLoc = new GeoPoint((int)(location.getLatitude() * 1E6), (int)(location.getLongitude() * 1E6));
mapController.animateTo(myLoc);
String sqlbars = "SELECT DISTINCT id, latitude, longitude, address, " +
" (SELECT category FROM bars_categories WHERE bar_id=bars.id) AS category " +
" FROM bars WHERE is_active=1";
Cursor curBars = dbHelper.executeSQLQuery(sqlbars);
if(curBars != null){
if(curBars.getCount() > 0){
for(curBars.move(0);curBars.moveToNext();curBars.isAfterLast()){
double latitude = curBars.getDouble(curBars.getColumnIndex("latitude"));
double longitude = curBars.getDouble(curBars.getColumnIndex("longitude"));
final List<Overlay> mapOverlays = mapView.getOverlays();
Drawable drawable = SofiaLiveNearbyActivity.this.getResources().getDrawable(R.drawable.pin_map_icon);
int markerWidth = drawable.getIntrinsicWidth();
int markerHeight = drawable.getIntrinsicHeight();
drawable.setBounds(0, markerHeight, markerWidth, 0);
final HelloItemizedOverlay itemizedoverlay = new HelloItemizedOverlay(drawable, SofiaLiveNearbyActivity.this);
GeoPoint point = new GeoPoint((int)(latitude * 1E6),(int)(longitude *1E6));
OverlayItem overlayitem = new OverlayItem(point, "Type: "+category+"\n----------------\nAddress: "+address, id);
locA.setLatitude(latitude);
locA.setLongitude(longitude);
float distance = location.distanceTo(locA);
if(distance < 1000.0){
itemizedoverlay.addOverlay(overlayitem);
mapOverlays.add(itemizedoverlay);
}
}
}
curBars.close();
}
and it worked.

How to draw route using multiple geopoints?

I am implementing an android application for Map activity.
I am using Location listener for getting location updates. After updating location i am saving those updated latitude and longitude values in database.
I am able draw Route path From Source to destination using source latitude, longitude and destination latitude, longitude values. But using multiple latitude and longitude values of database at a time i want to draw the route path. I am using my RoutePath.java class to draw the route path for multiple latitudes and longitudes.Using those list of latitudes and longitudes i am able to draw the path, but it shows point to point stright line not shows the route path. See the below image...
If you observe carefully some points are on the route and some points are outside of route path. See again below image with full zooming...
Please help me if anyone knows the solution for this problem...
RoutePath.java:
public class RoutePath extends Overlay {
private int _pathColor;
private final List<GeoPoint> _points;
private boolean _drawStartEnd;
public RoutePath(List<GeoPoint> points) {
this(points, Color.RED, true);
}
public RoutePath(List<GeoPoint> points, int pathColor,
boolean drawStartEnd) {
_points = points;
_pathColor = pathColor;
_drawStartEnd = drawStartEnd;
}
private void drawOval(Canvas canvas, Paint paint, Point point) {
Paint ovalPaint = new Paint(paint);
ovalPaint.setStyle(Paint.Style.FILL_AND_STROKE);
ovalPaint.setStrokeWidth(2);
int _radius = 6;
RectF oval = new RectF(point.x - _radius, point.y - _radius, point.x
+ _radius, point.y + _radius);
canvas.drawOval(oval, ovalPaint);
}
public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
long when) {
Projection projection = mapView.getProjection();
if (shadow == false && _points != null) {
Point startPoint = null, endPoint = null;
Path path = new Path();
// We are creating the path
for (int i = 0; i < _points.size(); i++) {
GeoPoint gPointA = _points.get(i);
Point pointA = new Point();
projection.toPixels(gPointA, pointA);
if (i == 0) { // This is the start point
startPoint = pointA;
path.moveTo(pointA.x, pointA.y);
} else {
if (i == _points.size() - 1)// This is the end point
endPoint = pointA;
path.lineTo(pointA.x, pointA.y);
}
}
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(_pathColor);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
paint.setAlpha(90);
if (getDrawStartEnd()) {
if (startPoint != null) {
drawOval(canvas, paint, startPoint);
}
if (endPoint != null) {
drawOval(canvas, paint, endPoint);
}
}
if (!path.isEmpty())
canvas.drawPath(path, paint);
}
return super.draw(canvas, mapView, shadow, when);
}
public boolean getDrawStartEnd() {
return _drawStartEnd;
}
public void setDrawStartEnd(boolean markStartEnd) {
_drawStartEnd = markStartEnd;
}
}
You got Straight line because the the GeoPoints are like that only..... means if you have a complete route paths then it will show according to your Geopoints....It all depends on GeoPoints.!

How to make anything when my geolocation is changed?

I want to make some action, i.e. show dialog with text 'im here' every time when my geolocation will be changed.
I'm using MyLocationOverlay to draw a dot on my location on the Google Maps's mapview.
How can I achieve that?
Below is the location listener class -
private MyOverLay draw = new MyOverLay();
class MyLocationListener_gps implements LocationListener {
public void onLocationChanged(Location location) {
clat = location.getLatitude();
clon = location.getLongitude();
GeoPoint geoPoint = new GeoPoint((int) (clat * 1E6),
(int) (clon * 1E6));
mapView.getController().animateTo(geoPoint);
draw = new MyOverLay(geoPoint);
mapView.getOverlays().add(draw);
}
}
Here is code overlay class-
class MyOverLay extends Overlay {
private GeoPoint gp1;
private int mRadius = 3;
public MyOverLay() {
}
public MyOverLay(GeoPoint gp1) {
this.gp1 = gp1;
}
#Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
long when) {
Projection projection = mapView.getProjection();
if (shadow == false) {
Paint paint = new Paint();
paint.setAntiAlias(true);
Point point = new Point();
projection.toPixels(gp1, point);
paint.setColor(Color.BLUE);
RectF oval = new RectF(point.x - mRadius, point.y - mRadius,
point.x + mRadius, point.y + mRadius);
canvas.drawOval(oval, paint);
}
return super.draw(canvas, mapView, shadow, when);
}
}
It will draw a blue dot as u move and ur co-ordinates chnage.
Override the onLocationChanged method:
// Create an overlay to show current location
mMyLocationOverlay = new MyLocationOverlay(this, mMapView) {
#Override
public void onLocationChanged(android.location.Location location) {
String text = "New coordinates: " + location.getLatitude() + ", " + location.getLatitude();
Toast toast = Toast.makeText(getApplicationContext(), text, Toast.LENGTH_SHORT);
toast.show();
super.onLocationChanged(location);
}
};
mMyLocationOverlay.runOnFirstFix(new Runnable() { public void run() {
mMapView.getController().animateTo(mMyLocationOverlay.getMyLocation());
}});
mMapView.getOverlays().add(mMyLocationOverlay);

How do you draw a line from previous point to current point in Android Google Maps?

I am trying to create a GPS tracking app, and is stuck on how I can draw a line from the previous point to current point. I've tried using an Overlay, but it does not display... I am not THAT good on Java, so please speak to me like I'm 4 years old...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initMapView();
initMyLocation();
TabHost.TabSpec spec;
TabHost th = (TabHost)findViewById(R.id.tabhost);
th.setup();
spec = th.newTabSpec("tag1");
spec.setContent(R.id.mapTab);
spec.setIndicator("Map");
th.addTab(spec);
spec = th.newTabSpec("tag2");
spec.setContent(R.id.logTab);
spec.setIndicator("Log");
th.addTab(spec);
spec = th.newTabSpec("tag3");
spec.setContent(R.id.detailsTab);
spec.setIndicator("Details");
th.addTab(spec);
}
#Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
//Map and Controls
private void initMapView() {
map = (MapView) findViewById(R.id.mvMain);
controller = map.getController();
map.setSatellite(true);
//map.setStreetView(true);
map.setBuiltInZoomControls(true);
}
//Creates an Overlay that marks current position
private void initMyLocation() {
final MyLocationOverlay overlay = new MyLocationOverlay(this, map);
overlay.enableMyLocation();
overlay.enableCompass();
overlay.runOnFirstFix(new Runnable() {
public void run() {
controller.setZoom(17);
controller.animateTo(overlay.getMyLocation());
map.getOverlays().add(overlay);
}
});
}
//Experiment
public class detailsTab extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.id.detailsTab);
LocationManager locationManager;
String context = Context.LOCATION_SERVICE;
locationManager = (LocationManager)getSystemService(context);
String provider = LocationManager.GPS_PROVIDER;
Location location = locationManager.getLastKnownLocation(provider);
updateWithNewLocation(location);
}
private void updateWithNewLocation(Location location) {
String latLongString;
TextView myLocationText;
myLocationText = (TextView)findViewById(R.id.detailsText);
if(location != null){
double lat = location.getLatitude();
double lng = location.getLongitude();
latLongString = "Lat:" + lat + "\nLong" + lng;
}
else {
latLongString = "No Location Found";
}
myLocationText.setText("Your current position is: \n" + latLongString);
}
}
public class NewOverlay extends Overlay {
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
Projection projection = mapView.getProjection();
Double lat = lati *1E6;
Double lng = longi *1E6;
GeoPoint geoPoint = new GeoPoint(lat.intValue(), lng.intValue());
if (shadow == false) {
Point myPoint = new Point();
projection.toPixels(geoPoint, myPoint);
//Creating and setting up the paint brush
Paint paint = new Paint();
paint.setARGB(250, 255, 0, 0);
paint.setAntiAlias(true);
paint.setFakeBoldText(true);
//Create circle
int rad = 25;
RectF oval = new RectF(myPoint.x-rad, myPoint.y-rad, myPoint.x+rad, myPoint.y+rad);
canvas.drawOval(oval, paint);
canvas.drawText("Red Circle", myPoint.x+rad, myPoint.y, paint);
}
}
}
}
I do that this way, inside draw() method,
int x1 = -1, y1 = -1, x2 = -1, y2 = -1;
Paint paint = new Paint();
paint.setColor(Color.rgb(0x7b, 0x7b, 0xff));
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
if(mPoints!=null || mPoints.size()<2)
{
for (int i = 0; i < mPoints.size(); i++) {
Point point = new Point();
mv.getProjection().toPixels(mPoints.get(i), point);
Point loc = new Point();
mv.getProjection().toPixels(new GeoPoint((int) (location.getLatitude()*1.0E6),(int) (location.getLongitude()*1.0E6)), loc);
x2 = point.x;
y2 = point.y;
if (i == 0)
{
x2 = loc.x;
y2 = loc.y;
}
if (i > 0) {
canvas.drawLine(x1, y1, x2, y2, paint);
}
x1 = x2;
y1 = y2;
}
}
This code will draw for me a whole route, mPoints is an array of GeoPoint that I want to draw them. This should be useful for you.
public void draw(Canvas canvas, MapView mapv, boolean shadow){
super.draw(canvas, mapv, shadow);
Projection projection = mapv.getProjection();
Path p = new Path();
for (int i = 0; i < geoPointsArray.size(); i++) {
if (i == geoPointsArray.size() - 1) {
break;
}
Point from = new Point();
Point to = new Point();
projection.toPixels(geoPointsArray.get(i), from);
projection.toPixels(geoPointsArray.get(i + 1), to);
p.moveTo(from.x, from.y);
p.lineTo(to.x, to.y);
}
Paint mPaint = new Paint();
mPaint.setStyle(Style.STROKE);
mPaint.setColor(Color.GREEN);
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(5);
canvas.drawPath(p, mPaint);
mapv.invalidate();
super.draw(canvas, mapv, shadow);
}//draw()
we can use the above method to draw route as we move place to place. where geoPointsArray is array of locations received. And in your onCreate() you need to call mapv.invalidate(); to draw route continously

Categories

Resources