I am building an android application that gets the users current position and find nearby attractions. When I select an attraction a route is drawn to it from the current position but when I do this a second time the first route stays there, I want it to disappear. Below is the code I use to draw the line. Each time a direction is drawn this is called. I have tried to use line.remove each time before method is called but this removes both lines then. Any suggestions?
for (int i = 0; i < pontos.size() - 1; i++) {
LatLng src = pontos.get(i);
LatLng dest = pontos.get(i + 1);
try{
//here is where it will draw the polyline in your map
line = mMap.addPolyline(new PolylineOptions()
.add(new LatLng(src.latitude, src.longitude),
new LatLng(dest.latitude, dest.longitude))
.width(2).color(Color.RED).geodesic(true));
Save your Polylines in an array so you can remove them before other ones are added:
List<Polyline> mPolylines = new ArrayList<>();
private void someMethod() {
// Remove polylines from map
for (Polyline polyline : mPolylines) {
polyline.remove();
}
// Clear polyline array
mPolylines.clear();
for (int i = 0; i < pontos.size() - 1; i++) {
LatLng src = pontos.get(i);
LatLng dest = pontos.get(i + 1);
mPolylines.add(mMap.addPolyline(new PolylineOptions()
.add(new LatLng(src.latitude, src.longitude),
new LatLng(dest.latitude, dest.longitude))
.width(2).color(Color.RED).geodesic(true)));
}
}
Related
I have 4 LatLng. For making a rectangle polygon, they should be in a list in either clockwise or anti-clockwise direction, so that when i add these LatLng in addPolygon(new LatLng) in google map it will create a rectangle shape.
But in my case, they might be in clockwise or anti-clockwise or in different form. One example is -> 1st LatLng followed by 3rd LatLng followed by 2nd LatLng followed by 4th LatLng. In this case, It will not create rectangle polygon on google map.
So I have to arrange it in clockwise or anti clockwise, so that the shape form must be rectangle, When i Put this LatLng list in addPolygon() in google map.
Suppose:
val rectOptions = PolygonOptions()
.add(
LatLng(37.35, -122.0),
LatLng(37.45, -122.0),
LatLng(37.45, -122.2),
LatLng(37.35, -122.2)
)
If I put rectOptions in AddPolygon() in mMap.addPolygon(rectOptions)
it will Create a rectangular shape on google map. In my case:
val rectOptions = PolygonOptions()
.add(
LatLng(37.45, -122.0),
LatLng(37.45, -122.2),
LatLng(37.35, -122.0),
LatLng(37.35, -122.2)
)
This will not create rectangular shape. So I have to arrange these LatLng so that they form rectangular shape.
In general your task is Convex hull construction and can be solved by one of Convex hull algorithms, e.g. like Gift wrapping (aka Jarvis) algorithm in this implementation.
Note that most of Convex hull algorithms implementations is for flat (x,y) point coordinates, not for LatLng location coordinates, so easiest way is to convert LatLng to flat (x,y) points with Projection.toScreenLocation() method and than, after Convex hull algorithm apply, convert it back to LatLng with Projection.fromScreenLocation() method.
Also remember, that the Projection object will only return valid values after the map has passed the layout process (i.e. it has valid width and height set) and you can get it in OnCameraIdleListener or use approach, described by andr in this answer.
So full demo source code can be like that:
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mGoogleMap;
private SupportMapFragment mMapSupportedFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMapSupportedFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map_fragment);
mMapSupportedFragment.getMapAsync(MainActivity.this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
mGoogleMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
#Override
public void onCameraIdle() {
ArrayList<LatLng> sourcePoints = new ArrayList<>();
sourcePoints.add(new LatLng(37.35, -122.0));
sourcePoints.add(new LatLng(37.45, -122.2));
sourcePoints.add(new LatLng(37.40, -122.1));
sourcePoints.add(new LatLng(37.35, -122.2));
sourcePoints.add(new LatLng(37.45, -122.0));
Projection projection = mGoogleMap.getProjection();
ArrayList<Point> screenPoints = new ArrayList<>(sourcePoints.size());
for (LatLng location : sourcePoints) {
Point p = projection.toScreenLocation(location);
screenPoints.add(p);
}
ArrayList<Point> convexHullPoints = convexHull(screenPoints);
ArrayList<LatLng> convexHullLocationPoints = new ArrayList(convexHullPoints.size());
for (Point screenPoint : convexHullPoints) {
LatLng location = projection.fromScreenLocation(screenPoint);
convexHullLocationPoints.add(location);
}
PolygonOptions polygonOptions = new PolygonOptions();
for (LatLng latLng : convexHullLocationPoints) {
polygonOptions.add(latLng);
}
mGoogleMap.clear();
Polygon polygon = mGoogleMap.addPolygon(polygonOptions.strokeColor(Color.argb(255, 49, 101, 187)).fillColor(Color.argb(100, 49, 101, 187)));
}
});
}
private boolean CCW(Point p, Point q, Point r) {
return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y) > 0;
}
public ArrayList<Point> convexHull(ArrayList<Point> points)
{
int n = points.size();
if (n <= 3) return points;
ArrayList<Integer> next = new ArrayList<>();
// find the leftmost point
int leftMost = 0;
for (int i = 1; i < n; i++)
if (points.get(i).x < points.get(leftMost).x)
leftMost = i;
int p = leftMost, q;
next.add(p);
// iterate till p becomes leftMost
do {
q = (p + 1) % n;
for (int i = 0; i < n; i++)
if (CCW(points.get(p), points.get(i), points.get(q)))
q = i;
next.add(q);
p = q;
} while (p != leftMost);
ArrayList<Point> convexHullPoints = new ArrayList();
for (int i = 0; i < next.size() - 1; i++) {
int ix = next.get(i);
convexHullPoints.add(points.get(ix));
}
return convexHullPoints;
}
}
Also you can find more simple algorithm if you need to "sort" points only for rectangles (e.g. you need to test which 3 points form a right angle and add it from first to third and then add fourth point and so on).
I have about 200 Polylines on my Map.
Now i try to find out witch Polyline the User have Click.
But polyline.getId() give me every Time a new random number like PL65 next start of the App PL144 and so on.
Is there any Way to know witch Polyline the user have click ?
I must show for every Polyline a Text with rules.
PolylineOptions spss7 = new PolylineOptions()
.add(new LatLng(52.260803, 8.16152))
.add(new LatLng(52.259113, 8.162186))
.add(new LatLng(52.258438, 8.158634))
.color(Color.GREEN)
.geodesic(true);
Polyline psps7 = googleMap.addPolyline(spss7);
psps7.setClickable(true);
PolylineOptions spss8 = new PolylineOptions()
.add(new LatLng(52.3524987, 7.709607499999999))
.add(new LatLng(52.3524921, 7.7098328))
.add(new LatLng(52.3534915, 7.710031300000001))
.color(Color.GREEN)
.geodesic(true);
Polyline psps8 = googleMap.addPolyline(spss8);
psps8.setClickable(true);
}
googleMap.setOnPolylineClickListener(new GoogleMap.OnPolylineClickListener(){
public void onPolylineClick(Polyline polyline) {
int strokeColor = polyline.getColor() ^ 0x0000CC00;
polyline.setColor(strokeColor);
Toast.makeText(getActivity(), "Polyline klick: "+polyline.getId(), Toast.LENGTH_LONG).show();
}
You can use the polyline tag to identify the polyline.
PolylineOptions spss7 = new PolylineOptions()
.add(new LatLng(52.260803, 8.16152))
.add(new LatLng(52.259113, 8.162186))
.add(new LatLng(52.258438, 8.158634))
.color(Color.GREEN)
.geodesic(true);
Polyline psps7 = googleMap.addPolyline(spss7);
psps7.setClickable(true);
psps7.setTag(new String("psps7"));
PolylineOptions spss8 = new PolylineOptions()
.add(new LatLng(52.3524987, 7.709607499999999))
.add(new LatLng(52.3524921, 7.7098328))
.add(new LatLng(52.3534915, 7.710031300000001))
.color(Color.GREEN)
.geodesic(true);
Polyline psps8 = googleMap.addPolyline(spss8);
psps8.setClickable(true);
psps8.setTag(new String("psps8"));
}
googleMap.setOnPolylineClickListener(new GoogleMap.OnPolylineClickListener(){
public void onPolylineClick(Polyline polyline) {
int strokeColor = polyline.getColor() ^ 0x0000CC00;
polyline.setColor(strokeColor);
Toast.makeText(getActivity(), "Polyline klick: " +
(String)polyline.getTag(), Toast.LENGTH_LONG).show();
}
We set the tag for the 2 polylines in this example then in the onClickListener we get the tag and cast it back to a string.
I have searched in google and find this answer where i can remove all polyLine of a Map.
But I want to remove only a particular line from the poly Line. For Example I want to remove the line from 2nd to 3rd LatLng in the given code. I want to change color of a particular line of a polyLine or make it transparent. And I also want to add a clickListener to PolyLine
PolylineOptions rectOptions = new PolylineOptions()
.add(new LatLng(37.35, -122.0))
.add(new LatLng(37.45, -122.0)) // North of the previous point, but at the same longitude
.add(new LatLng(37.45, -122.2)) // Same latitude, and 30km to the west
.add(new LatLng(37.35, -122.2)) // Same longitude, and 16km to the south
.add(new LatLng(37.35, -122.0)).width(5).color(Color.RED);; // Closes the polyline.
Polyline polyline = myMap.addPolyline(rectOptions);
Main goal is to remove/make it transparent a particular line of a PolyLine on click or tap.
PolylineOptions line= new PolylineOptions().add(HAMBURG,// these are latlong
KIEL,
KIEL2,
KIEL3
new LatLng(40.748963847316034,
-73.96807193756104)
)
.width(5).color(Color.RED);
Polyline polyline= googleMap.addPolyline(line);
And i want to remov line between KIEL1 and KIEL2
You'll have to manually remove points from the polyline.
EDIT:
Step by step:
Create a List of polylines:
List<Polyline> mPolylines = new ArrayList<Polyline>();
Add PolylineOptions to the map:
Polyline polyline1 = myMap.addPolyline(rectOptions1);
Polyline polyline2 = myMap.addPolyline(rectOptions2);
Polyline polyline3 = myMap.addPolyline(rectOptions3);
Then save the added polylines to your array
mPolylines.add(polyline1);
mPolylines.add(polyline2);
mPolylines.add(polyline3);
Now at any time you can trim the polyline like so:
// Get polyline1
List<LatLng> points = mPolylines.get(0).getPoints();
// Set the bounds of points to remove (inclusive)
int startPoint = 1, endPoint = 2; // will remove kiel1 and kiel2
// Remove the points
for (int i=startPoint; i<=endPoint; i++) {
points.remove(i);
}
// Added this line as getPoints returns a copy
mPolylines.get(0).setPoints(points);
Now in theory this should work fine. I found that the points don't actually change after setPoints.
I even tried:
Polyline polyline = mPolylines.get(0);
// Get copy of the points
List<LatLng> points = polyline.getPoints();
mPolylines.get(0).remove();
mPolylines.remove(0);
for (int i=3000; i<7000; i++) {
points.remove(i);
}
// Create a PolylineOptions object with the new points
PolylineOptions polylineOptions = new PolylineOptions().addAll(points);
mPolylines.add(0, mMap.addPolyline(polylineOptions));
And to my surprise a new Polyline was added (I can tell by the changed stroke width and color), but it still used the old points, even though points.size() returned the correct (trimmed) count.
I'm not sure why this is so, perhaps some error in my code. You can try these methods yourself and see if you are any luckier.
I have an array with positions. I wanted to parse this array to show polyline in google maps.
Here is an example:
how can I parse this array?
double [][] pos = {
{3.7067858,-14.4728779},
{3.7067858,-14.4728779},
{3.7067858,-14.4728779},
{3.7067858,-14.4728779},
{3.7067858,-14.4728779},
{3.7067858,-14.4728779},
{3.7067858,-14.4728779}};
PolylineOptions rectOptions = new PolylineOptions()
for (int i = 0; i < 1; i++){
.add(new LatLng(pos[i][i]))
i++;
}
Polyline polyline = mMap.addPolyline(rectOptions);
Building on Evan's answer, you can build your LatLng objects within your loop.
double[][] pos = { {3.7067858,-14.4728779}, ... };
PolylineOptions rectOptions = new PolylineOptions()
for (int i = 0; i < pos.length; i++){
rectOptions.add(new LatLng(pos[i][0], pos[i][1]));
}
Polyline polyline = mMap.addPolyline(rectOptions);
As a side note, a 2D array of doubles is fine for point lists. It is how LineStrings are defined in the GeoJSON specification.
First of all a 2d array for position data doesn't make much sense what you should do is have an array of LatLng's:
LatLng[] pos = {new LatLng(3.7067858,-14.4728779), ..., ...};
PolylineOptions rectOptions = new PolylineOptions();
for (LatLng l : pos){
rectOptions.add(l);
}
Polyline polyline = mMap.addPolyline(rectOptions);
I have a list full of LatLng points to create a polygon in google maps android v2, but I cannot figure out how to add this list to the .add area correctly. Here is my list full of points:
list.add(new LatLng(la,lo));
Here is the polygon via Google Dev
Polygon polygon = map.addPolygon(new PolygonOptions()
.add(*******HOW TO ITTERATE LIST************).strokeColor(Color.RED)
.fillColor(Color.BLUE));
How do you go about adding the points?
PolygonOptions opts=new PolygonOptions();
for (LatLng location : list) {
opts.add(location);
}
Polygon polygon = map.addPolygon(opts.strokeColor(Color.RED).fillColor(Color.BLUE));
This assumes that list is something like an ArrayList<LatLng>.
I had the same issue and I find this without need for iteration.
PolygonOptions polOpt =
new PolygonOptions().addAll(latlngs).strokeColor(Color.RED).fillColor(Color.BLUE);
Polygon polygon = mMap.addPolygon(polOpt);
It may help someone. I did the same its working.
ArrayList<LatLng> locations = new ArrayList();
Adding the latLng value in list.
locations .add(new LatLng(2, 2));
locations .add(new LatLng(4, 2));
locations .add(new LatLng(4, 4));
locations .add(new LatLng(2, 4));
locations .add(new LatLng(2, 2))
Creating the GeoFence on the map
PolylineOptions options = new PolylineOptions().width(5).color(Color.RED).geodesic(true);
for (int z = 0; z < locations.size(); z++) {
LatLng point = locations.get(z);
options.add(point);
}
mMap.addPolyline(options);
CameraPosition cameraPosition;
cameraPosition = new CameraPosition.Builder().target(new LatLng(50.8404969, -0.1504184)).zoom(15).build();
mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));