Generating random position near me with markers - android

I want to integrate this code into mine, but don't know how to get it to work.
I got problem with the return statement and then how to create a mark with randomly generated position?
Can you please tell me how to get the getRandomLocation() method working in creating markers?
public Location getRandomLocation() {
Location location = new Location("");
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
int radius = 10;
double x0 = latLng.latitude;
double y0 = latLng.longitude;
Random random = new Random();
// Convert radius from meters to degrees
double radiusInDegrees = radius / 111000f;
double u = random.nextDouble();
double v = random.nextDouble();
double w = radiusInDegrees * Math.sqrt(u);
double t = 2 * Math.PI * v;
double x = w * Math.cos(t);
double y = w * Math.sin(t);
// Adjust the x-coordinate for the shrinking of the east-west distances
double new_x = x / Math.cos(y0);
double foundLatitude = new_x + x0;
double foundLongitude = y + y0;
LatLng randomLatLng = new LatLng(foundLatitude, foundLongitude);
Location loc = new Location("");
loc.setLatitude(randomLatLng.latitude);
loc.setLongitude(randomLatLng.longitude);
//dont know what to return
return ;
}
public final void addMarker(GoogleMap mMap) {
//dont know how to get working the getRandomLocation())
mMap.addMarker( new MarkerOptions()
// .position(new LatLng(48.349723, 18.052405))
.position(getRandomLocation())
.title("krokodĂ­l")
.icon(BitmapDescriptorFactory.fromBitmap(resizeMapIcons("krokodil", 100, 100))));
mMap.addMarker(new MarkerOptions()
// .position(new LatLng(48.310025, 18.038878))
.position(getRandomLocation())
.icon(BitmapDescriptorFactory.fromBitmap(resizeMapIcons("fretka", 100, 100)))
.title("fretk"));
mMap.addMarker (new MarkerOptions()
.title("hroch")
.icon(BitmapDescriptorFactory.fromBitmap(resizeMapIcons("hroch", 100, 100)))
// .title()
//.snippet(mObj.getNumber(Configs.MONSTERS_MONSTER_POINTS) + " points")
// .position(new LatLng(48.318569, 18.055767)));
.position(getRandomLocation()));
}

According to the logic of your code, you need to return randomLatLng.
Change the line:
public Location getRandomLocation() {
to:
public LatLng getRandomLocation() {
and make the return statement something like:
return randomLatLng;
The method MarkerOptions.position() needs an object of type LatLng, that is what your IDE showing you as an error.

Related

Draw Heart Shape Polygon on Google Map

I am trying to create heart shape polygon on Google Map using current location. I am able to identify some LatLngs and tried to create heart shape but as expected curves are not showing.
Can you please help me out to create exact heart shape polygon using current location.
Here is code which I am using to create heart shape.
private static final int FRONT = 0;
private static final int RIGHT = 90;
private static final int LEFT = 270;
private void drawHeartPolygon(LatLng currentLatLng) {
LatLng destLatLang = GetDestinationPoint(currentLatLng, FRONT, 0.050F);
frontAngleCalculation(currentLatLng, destLatLang, 0.050F);
}
private void frontAngleCalculation(LatLng latLng, LatLng destLatLang, float distance) {
PolygonOptions rectOptions = new PolygonOptions();
LatLng centerLocation = GetDestinationPoint(latLng, FRONT, (distance + (distance/4)/2)/2);
LatLng rightLocation = GetDestinationPoint(centerLocation, RIGHT, distance/2);
LatLng leftLocation = GetDestinationPoint(centerLocation, LEFT, distance/2);
LatLng centerLeftLocation = GetDestinationPoint(destLatLang, LEFT, distance/4);
LatLng centerLeftTopLocation = GetDestinationPoint(centerLeftLocation, FRONT, (distance/4)/2);
LatLng centerRightLocation = GetDestinationPoint(destLatLang, RIGHT, distance/4);
LatLng centerRightTopLocation = GetDestinationPoint(centerRightLocation, FRONT, (distance/4)/2);
rectOptions.add(new LatLng(latLng.latitude, latLng.longitude),
leftLocation,
centerLeftTopLocation,
new LatLng(destLatLang.latitude, destLatLang.longitude),
centerRightTopLocation,
rightLocation);
Log.d(TAG, "Current Location : "+latLng);
rectOptions.strokeColor(Color.RED);
// Get back the mutable Polygon
Polygon polygon = mMap.addPolygon(rectOptions);
List<PatternItem> pattern = Arrays.<PatternItem>asList(
new Dot(), new Gap(20), new Dash(30), new Gap(20));
polygon.setStrokePattern(pattern);
polygon.setStrokeWidth(POLYGON_STROKE_WIDTH_PX);
polygon.setStrokeColor(strokeColor);
}
public static LatLng GetDestinationPoint(LatLng startLoc, float bearing, float depth) {
LatLng newLocation = null;
double radius = 6371.0; // earth's mean radius in km
double lat1 = Math.toRadians(startLoc.latitude);
double lng1 = Math.toRadians(startLoc.longitude);
double brng = Math.toRadians(bearing);
double lat2 = Math.asin(Math.sin(lat1) * Math.cos(depth / radius) + Math.cos(lat1) * Math.sin(depth / radius) * Math.cos(brng));
double lng2 = lng1 + Math.atan2(Math.sin(brng) * Math.sin(depth / radius) * Math.cos(lat1), Math.cos(depth / radius) - Math.sin(lat1) * Math.sin(lat2));
lng2 = (lng2 + Math.PI) % (2 * Math.PI) - Math.PI;
// normalize to -180...+180
if (lat2 == 0 || lng2 == 0) {
newLocation = new LatLng(0.0, 0.0);
} else {
newLocation = new LatLng(Math.toDegrees(lat2), Math.toDegrees(lng2));
}
return newLocation;
}
#Override
public void onMapReady(GoogleMap googleMap) {
Log.d(TAG, "onMapReady");
mMap = googleMap;
LatLng latLng = new LatLng(latitude, longitude);
mMap.addMarker(new MarkerOptions().position(latLng).draggable(true));
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.setMaxZoomPreference(22.0f);
mMap.setMinZoomPreference(17.0f);
drawHeartPolygon(new LatLng(latitude, longitude));
}
Here is screenshot which shows heart shape which I achieved but not as per expectation.
Please give me reference or hint which will draw heart shape polygon with curves.
I don't know whether you'll like this answer or not but this will work as your requirement and is easy as hell but different.
Just place a marker:
LatLng latLng1 = new LatLng(13.014849, 80.224343);
mMap.addMarker(new MarkerOptions().position(latLng1).title("Name").snippet("snippet").flat(true).icon(BitmapDescriptorFactory.fromResource(R.drawable.marker1)));
CameraPosition cameraPosition = new CameraPosition.Builder().target(latLng1).zoom(12).build();
mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
Here, marker1.png is an image created through photoshop which will provide the same result.
Result:
Marker1.png:
As you can see marker1 here is a whole image containing the marker + the heart but you can also create two markers on same LatLng: 1st is the red marker and 2nd is the Heart. Using this way, infowindow will open only on clicking the red marker instead of the provided result as you can disable the heart's infowindow or you can use heart's infowindow for some other info.
As I said earlier this solution is different and isn't similar to custom shaped polygon but is super easy to achieve.

Generate random LatLng given device location and radius

I am trying to generate random points on the map near a given location. I have a circle shape which surrounds the user location with a radius of 100, and I would like to generate random LatLng coordinates within this circle area. I have come up with the following function so far, but the point markers are still appearing outside the circle range.
double lat = location.getLatitude();
double lon = location.getLongitude();
for (int i = 0; i < markers.size(); i++) {
Marker mrk = markers.get(i);
Random random = new Random();
double radiusInDegrees =mCircle.getRadius();
double u = random.nextDouble();
double v = random.nextDouble();
double w = radiusInDegrees * Math.sqrt(u);
double t = 2 * Math.PI * v;
double x = w * Math.cos(t);
double y = w * Math.sin(t);
// Adjust the x-coordinate for the shrinking of the east-west distances
double new_x = x / Math.cos(lat);
double newLongitude = new_x + lon;
double newLatitude = y + lat;
mrk.setPosition(new LatLng(newLatitude,newLongitude));
}
with the help of this
https://gis.stackexchange.com/a/68275
I am able to make a function which generate random LatLng point within certain radius, where radius is in meter.
public LatLng getRandomLocation(LatLng point, int radius) {
List<LatLng> randomPoints = new ArrayList<>();
List<Float> randomDistances = new ArrayList<>();
Location myLocation = new Location("");
myLocation.setLatitude(point.latitude);
myLocation.setLongitude(point.longitude);
//This is to generate 10 random points
for(int i = 0; i<10; i++) {
double x0 = point.latitude;
double y0 = point.longitude;
Random random = new Random();
// Convert radius from meters to degrees
double radiusInDegrees = radius / 111000f;
double u = random.nextDouble();
double v = random.nextDouble();
double w = radiusInDegrees * Math.sqrt(u);
double t = 2 * Math.PI * v;
double x = w * Math.cos(t);
double y = w * Math.sin(t);
// Adjust the x-coordinate for the shrinking of the east-west distances
double new_x = x / Math.cos(y0);
double foundLatitude = new_x + x0;
double foundLongitude = y + y0;
LatLng randomLatLng = new LatLng(foundLatitude, foundLongitude);
randomPoints.add(randomLatLng);
Location l1 = new Location("");
l1.setLatitude(randomLatLng.latitude);
l1.setLongitude(randomLatLng.longitude);
randomDistances.add(l1.distanceTo(myLocation));
}
//Get nearest point to the centre
int indexOfNearestPointToCentre = randomDistances.indexOf(Collections.min(randomDistances));
return randomPoints.get(indexOfNearestPointToCentre);
}
The purpose of for loop is just to ensure to get nearest random point, as I have seen points were getting out of circle as I am increasing the radius. You may remove loop.
This answer should help. It looks like what you have execpt for converting the radiusfrom meters to degrees.
// Convert radius from meters to degrees
double radiusInDegrees = radius / 111000f;
See link here.

Rotate marker as per user direction on Google Maps V2 Android

I want to rotate marker as per bearing or sensor value received from Accelerometer to show the user where actually he is moving. I have set marker icon and flat value to true but its not working as required.
mCurrentLocationMarker.position(new LatLng(
LocationUtils.sLatitude, LocationUtils.sLongitude));
mCurrentLocationMarker.icon(icon);
mCurrentLocationMarker.flat(true);
mCurrentLocationMarker.rotation(LocationUtils.sBearing);
if (currentMarker != null) {
currentMarker.setPosition(new LatLng(
LocationUtils.sLatitude,
LocationUtils.sLongitude));
} else {
currentMarker = mGoogleMap
.addMarker(mCurrentLocationMarker);
}
animateCameraTo(true);
I have used this as marker.
I don't know why its not rotating as per user's direction. If anyone has any idea please kindly help me where i am making mistake.
LocationUtils.sBearing is the value of Bearing which i received from onLocationChanged or accelerometer.
Basically I want to make my marker same as google maps marker which shows user in which direction they are moving or turning.
This is an old question and it appears the API has changed since then.
I'm assuming you are able to get the devices bearing. If not here is a handy tutorial.
First thing is to create a marker we can use for bearing updates.
private Marker marker;
// Create this marker only once; probably in your onMapReady() method
marker = mGoogleMap.addMarker(new MarkerOptions()
.position(new LatLng(myLatitude, myLongitude))
.flat(true));
Note the .flat(true) portion. The ensures our marker is north aligned so that our bearings will work correctly even if the user rotates the map.
Now when you get your bearing updates you can do the following
marker.setRotation(bearing);
// or if following the linked tutorial
// marker.setRotation((float) azimuth);
This assumes your marker icon has the forward direction at the top. If your marker is rotated like the one pictured, you will have to adjust the bearing to compensate before setting it to the marker. Just a simple setRotation(bearing - 45) should do it.
Im posting this answer because people like me who are searching for a solution related to the above question might find it useful.
So here how i did it.
As #colin said you must enable .flat(true) to rotate markers.
1.For bearing angle i have used the following code.
Here latLng1 - my old location && latLng2 - my new location
private double bearingBetweenLocations(LatLng latLng1,LatLng latLng2) {
double PI = 3.14159;
double lat1 = latLng1.latitude * PI / 180;
double long1 = latLng1.longitude * PI / 180;
double lat2 = latLng2.latitude * PI / 180;
double long2 = latLng2.longitude * PI / 180;
double dLon = (long2 - long1);
double y = Math.sin(dLon) * Math.cos(lat2);
double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
* Math.cos(lat2) * Math.cos(dLon);
double brng = Math.atan2(y, x);
brng = Math.toDegrees(brng);
brng = (brng + 360) % 360;
return brng;
}
2.To rotate marker using above bearing angle i have used this code
Here isMarkerRotating is a boolean value. Add isMarkerRotating = false in OnCreate method
private void rotateMarker(final Marker marker, final float toRotation) {
if(!isMarkerRotating) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final float startRotation = marker.getRotation();
final long duration = 2000;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
#Override
public void run() {
isMarkerRotating = true;
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed / duration);
float rot = t * toRotation + (1 - t) * startRotation;
float bearing = -rot > 180 ? rot / 2 : rot;
marker.setRotation(bearing);
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
isMarkerRotating = false;
}
}
});
}
}
3.using above code
LatLng oldLocation, newLocaation;
float bearing = (float) bearingBetweenLocations(oldLocation, newLocaation);
rotateMarker(start_marker, bearing);
In Kotlin by using Google SphericalUtil class we can get bearing by passing source and destination LatLngs like:
fun calculateBearing(lat1: Double, lng1: Double, lat2: Double, lng2: Double): Float {
val sourceLatLng = LatLng(lat1, lng1)
val destinationLatLng = LatLng(lat2, lng2)
return SphericalUtil.computeHeading(sourceLatLng, destinationLatLng).toFloat()
}
Then set this result 'bearing` to the marker like
Val bearing = calculateBearing(lat1, lng1, lat2, lng2)
marker.rotation(bearing)
Reference: https://developers.google.com/maps/documentation/android-sdk/utility/#spherical

How to check if a point is within one or more circles on google map?

I am new to programming android and having a problem with an map application I am working on. The app allows for circles to be place on the map through a click and if the current location is inside the circle a message is displayed, also if outside the circle a different message is displayed. The problem is during the onStart check of the circles it only detects inside or outside of the last created circle instead of all available ones. I am not sure what is causing this problem. Code Snippet follows:
// Opening the sharedPreferences object
sharedPreferences = getSharedPreferences("location", 0);
// Getting number of locations already stored
locationCount = sharedPreferences.getInt("locationCount", 0);
// Getting stored zoom level if exists else return 0
//String zoom = sharedPreferences.getString("zoom", "0");
// If locations are already saved
if(locationCount!=0){
String lat = "";
String lng = "";
// Iterating through all the locations stored
for(int i=0;i<locationCount;i++){
// Getting the latitude of the i-th location
lat = sharedPreferences.getString("lat"+i,"0");
// Getting the longitude of the i-th location
lng = sharedPreferences.getString("lng"+i,"0");
double latitude = Double.parseDouble(lat);
double longitude = Double.parseDouble(lng);
startCircle = googleMap.addCircle(new CircleOptions().center(new LatLng (latitude, longitude)).radius(CIRCLE_RADIUS).fillColor(0x55888888));
}
}
public void onStart(){
super.onStart();
//Create a criteria object to retrieve provider
Criteria criteria = new Criteria();
// Set accuracy of criteria to address level
criteria.setAccuracy(Criteria.ACCURACY_FINE);
//Get the name of the best provider
String provider = locationManager.getBestProvider(criteria, true);
//Get Current Location
Location myLocation = locationManager.getLastKnownLocation(provider);
double lat = myLocation.getLatitude();
double lon = myLocation.getLongitude();
LatLng latlng = new LatLng(lat,lon);
if(startCircle == null){
return;
}
else{
float[] distance = new float[2];
marker = googleMap.addMarker(new MarkerOptions().position(latlng).visible(false));
myLocation.distanceBetween( marker.getPosition().latitude, marker.getPosition().longitude,
startCircle.getCenter().latitude, startCircle.getCenter().longitude, distance);
if( distance[0] < startCircle.getRadius()){
Toast.makeText(getBaseContext(), "Inside", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getBaseContext(), "Outside", Toast.LENGTH_LONG).show();
}
}
}
The problem is during the onStart check of the circles it only detects inside or outside of the last created circle instead of all available ones. I am not sure what is causing this problem.
the problem is when you create a circle you are overwriting the last circle created so the startCircle is always the last one created. You will need to keep a list of all the circles you plot on the map;
to look how to check if a point is inside an object I would check out this link as it prooved very useful to me when I needed to do this
How can I determine whether a 2D Point is within a Polygon?
in Javascript I used:
google.maps.geometry.poly.containsLocation(pos, selectedPolygon);
This method available in google-maps API 3, (Sounds like you can't)
But try to write some math function based on circle area.
it really easy. Calculate distance between 2 coordinates:
public static float distFrom2LocationsInMeter() {
double lat1 = ...;
double lng1 = ...;
double lat2 = ...;
double lng2 =...;
//lat1 /= 1000000; // sometimes Android returns location in 10^6 form
//lng1 /= 1000000;
//lat2 /= 1000000;
// lng2 /= 1000000;
double earthRadius = 3958.75;
double dLat = Math.toRadians(lat2-lat1);
double dLng = Math.toRadians(lng2-lng1);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
Math.sin(dLng/2) * Math.sin(dLng/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;
int meterConversion = 1609;
return Float.valueOf((float)(dist * meterConversion ));
}
After just check your radius:
if R > distFrom2LocationsInMeter() // you inside
if R < distFrom2LocationsInMeter() // you outside
Toast.makeText(MapActivity.this,String.valueOf(isInside(latitude_location_place, longitude_location_place,0.002,map.getMyLocation().getLatitude(),map.getMyLocation().getLongitude())) , Toast.LENGTH_SHORT).show();
public boolean isInside(double circle_x, double circle_y,
double rad, double x, double y) {
map.addCircle(new CircleOptions()
.center(new LatLng(circle_x, circle_y))
.radius(200)
//its about 20 meter
// you most set rad=0.002 for 20 meter
.strokeColor(Color.RED)
.fillColor(R.color.color_circle));
map.addMarker(new MarkerOptions().position(new LatLng(x, y)));
if ((x - circle_x) * (x - circle_x) +
(y - circle_y) * (y - circle_y) <= rad*rad)
return true;
else
return false;
}
Example:
Toast.makeText(MapActivity.this,String.valueOf(isInside(latitude_location_place, longitude_location_place,0.002,map.getMyLocation().getLatitude(),map.getMyLocation().getLongitude())) , Toast.LENGTH_SHORT).show();
public boolean isInside(double circle_x, double circle_y,
double rad, double x, double y) {
map.addCircle(new CircleOptions()
.center(new LatLng(circle_x, circle_y))
.radius(200)
//its about 20 meter
// you most set rad=0.002 for 20 meter
.strokeColor(Color.RED)
.fillColor(R.color.color_circle));
map.addMarker(new MarkerOptions().position(new LatLng(x, y)));
if ((x - circle_x) * (x - circle_x) +
(y - circle_y) * (y - circle_y) <= rad*rad)
return true;
else
return false;
}

Android Google Maps: How to get the area which is currently shown in screen device?

Is there a way to get the coordinates of the current area, which is shown at the device?
Background is, we want to show "nearby" places, which are stored in our own database. So let's say, the user looks at following clip of a map:
How do we get the longitude/latitude of the screen (or the point in the middle of the screen and a radius which covers everything?). Please keep in mind, center of the map is not usually the current position, since the user can move the center of the card!
Use map.getProjection().getVisibleRegion(). From VisibleRegion you can get LatLngBounds, which is easy to work with. You may also try directly with the region, which might be trapezoid.
I found the solution for Google Map API v2 from few of responses:
stackoverflow#1 and
stackoverflow#2
So, need implements Activity from GoogleMap.OnCameraChangeListener interface
private static final int REQUEST_CODE_GOOGLE_PLAY_SERVECES_ERROR = -1;
private static final double EARTH_RADIOUS = 3958.75; // Earth radius;
private static final int METER_CONVERSION = 1609;
private GoogleMap mGoogleMap;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_layout);
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mContext);
if (status != ConnectionResult.SUCCESS)
{
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, activity,
REQUEST_CODE_GOOGLE_PLAY_SERVECES_ERROR);
dialog.show();
mGoogleMap = null;
}
else
{
mGoogleMap = ((SupportMapFragment) getFragmentManager().findFragmentById(
R.id.fragment_shops_layout_maps_fragment)).getMap();
mGoogleMap.setOnCameraChangeListener(this);
}
}
The listener, that working when map scaled. Determin as LatLng the positions of bottom left, bottom right, top left and top right sides of map, that showing on screen. By greatest side of screen and two points we can get radius from center of map.
#Override
public void onCameraChange(CameraPosition cameraPosition)
{
// Listener of zooming;
float zoomLevel = cameraPosition.zoom;
VisibleRegion visibleRegion = mGoogleMap.getProjection().getVisibleRegion();
LatLng nearLeft = visibleRegion.nearLeft;
LatLng nearRight = visibleRegion.nearRight;
LatLng farLeft = visibleRegion.farLeft;
LatLng farRight = visibleRegion.farRight;
double dist_w = distanceFrom(nearLeft.latitude, nearLeft.longitude, nearRight.latitude, nearRight.longitude);
double dist_h = distanceFrom(farLeft.latitude, farLeft.longitude, farRight.latitude, farRight.longitude);
Log.d("DISTANCE: ", "DISTANCE WIDTH: " + dist_w + " DISTANCE HEIGHT: " + dist_h);
}
Return distance between 2 points, stored as 2 pair location at meters;
public double distanceFrom(double lat1, double lng1, double lat2, double lng2)
{
// Return distance between 2 points, stored as 2 pair location;
double dLat = Math.toRadians(lat2 - lat1);
double dLng = Math.toRadians(lng2 - lng1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(Math.toRadians(lat1))
* Math.cos(Math.toRadians(lat2)) * Math.sin(dLng / 2) * Math.sin(dLng / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double dist = EARTH_RADIOUS * c;
return new Double(dist * METER_CONVERSION).floatValue();
}
If you want get radius of area, that showed on screen just need devided by 2.
I hope will useful !
This calculates the radio in km based on the map width:
public double calculateVisibleRadius() {
float[] distanceWidth = new float[1];
VisibleRegion visibleRegion = map.getProjection().getVisibleRegion();
LatLng farRight = visibleRegion.farRight;
LatLng farLeft = visibleRegion.farLeft;
LatLng nearRight = visibleRegion.nearRight;
LatLng nearLeft = visibleRegion.nearLeft;
//calculate the distance between left <-> right of map on screen
Location.distanceBetween( (farLeft.latitude + nearLeft.latitude) / 2, farLeft.longitude, (farRight.latitude + nearRight.latitude) / 2, farRight.longitude, distanceWidth );
// visible radius is / 2 and /1000 in Km:
return distanceWidth[0] / 2 / 1000 ;
}

Categories

Resources