java - How to move marker along polyline using google map -


i trying move marker according polyline , animation. similar below image:

taken mapbox

mapbox giving kind of demo. want achieve same using google maps. right marker not rotating along path. here have tried:

private void onready(list<latlng> polyz) {        (int = 0; < polyz.size() - 1; i++) {         latlng src = polyz.get(i);         latlng dest = polyz.get(i + 1);         polyline line = map.addpolyline(new polylineoptions()             .add(new latlng(src.latitude, src.longitude),                 new latlng(dest.latitude, dest.longitude))             .width(2).color(color.red).geodesic(true));        }       latlngbounds.builder builder = new latlngbounds.builder();       builder.include(polyz.get(0));       builder.include(polyz.get(polyz.size()-1));       map.movecamera(cameraupdatefactory.newlatlngbounds(builder.build(), 48));       map.animatecamera(cameraupdatefactory.zoomto(7), 1000, null);       bitmapdescriptor icon = bitmapdescriptorfactory.fromresource(r.drawable.car);       marker = map.addmarker(new markeroptions()           .position(polyz.get(0))           .title("curr")           .snippet("move"));       marker.seticon(icon);      } 

and animation:

    private void animatemarker(googlemap mymap, final marker marker, final list<latlng> directionpoint,       final boolean hidemarker) {     final handler handler = new handler();     final long start = systemclock.uptimemillis();     projection proj = mymap.getprojection();     final long duration = 600000;      final interpolator interpolator = new linearinterpolator();      handler.post(new runnable() {       int = 0;        @override       public void run() {         long elapsed = systemclock.uptimemillis() - start;         float t = interpolator.getinterpolation((float) elapsed             / duration);         location location=new location(string.valueof(directionpoint.get(i)));         location newlocation=new location(string.valueof(directionpoint.get(i+1)));         marker.setanchor(0.5f, 0.5f);         marker.setrotation(location.bearingto(newlocation)  - 45);         if (i < directionpoint.size()) {           marker.setposition(directionpoint.get(i));         }         i++;          if (t < 1.0) {           // post again 16ms later.           handler.postdelayed(this, 16);         } else {           if (hidemarker) {             marker.setvisible(false);           } else {             marker.setvisible(true);           }         }       }     });   } 

you can use task approach based on custom marker animation: animate separately car movement , car turns throughout direction points. need 2 kinds of animation:

1) animation car movement;

2) animation car turn;

which calls each other on end (car movement animation on end calls car turn animation , vice versa: car turn animation on end calls car movement animation , points of car path).

for example on fig.:

enter image description here

1) animation car movement p0 p1;

2) animation car turn on p1;

3) animation car movement p1 p2

and on.

car movement animation can implemented method this:

private void animatecarmove(final marker marker, final latlng beginlatlng, final latlng endlatlng, final long duration) {         final handler handler = new handler();         final long starttime = systemclock.uptimemillis();          final interpolator interpolator = new linearinterpolator();          // set car bearing current part of path         float angledeg = (float)(180 * getangle(beginlatlng, endlatlng) / math.pi);         matrix matrix = new matrix();         matrix.postrotate(angledeg);         marker.seticon(bitmapdescriptorfactory.frombitmap(bitmap.createbitmap(mmarkericon, 0, 0, mmarkericon.getwidth(), mmarkericon.getheight(), matrix, true)));          handler.post(new runnable() {             @override             public void run() {                 // calculate phase of animation                 long elapsed = systemclock.uptimemillis() - starttime;                 float t = interpolator.getinterpolation((float) elapsed / duration);                 // calculate new position marker                 double lat = (endlatlng.latitude - beginlatlng.latitude) * t + beginlatlng.latitude;                 double lngdelta = endlatlng.longitude - beginlatlng.longitude;                  if (math.abs(lngdelta) > 180) {                     lngdelta -= math.signum(lngdelta) * 360;                 }                 double lng = lngdelta * t + beginlatlng.longitude;                  marker.setposition(new latlng(lat, lng));                  // if not end of line segment of path                  if (t < 1.0) {                     // call next marker position                     handler.postdelayed(this, 16);                 } else {                     // call turn animation                     nextturnanimation();                 }             }         });     } 

where

mmarkericon is:

bitmap mmarkericon; ... mmarkericon = bitmapfactory.decoderesource(getresources(), r.drawable.the_car);  // car icon in file the_car.png in drawable folder 

and car icon should north oriented:

enter image description here

for correct rotation apply

nextturnanimation() - method called on end of car movement animation start car turn animation:

private void nextturnanimation() {         mindexcurrentpoint++;          if (mindexcurrentpoint < mpathpolygonpoints.size() - 1) {             latlng prevlatlng = mpathpolygonpoints.get(mindexcurrentpoint - 1);             latlng currlatlng = mpathpolygonpoints.get(mindexcurrentpoint);             latlng nextlatlng = mpathpolygonpoints.get(mindexcurrentpoint + 1);              float beginangle = (float)(180 * getangle(prevlatlng, currlatlng) / math.pi);             float endangle = (float)(180 * getangle(currlatlng, nextlatlng) / math.pi);              animatecarturn(mcarmarker, beginangle, endangle, turn_animation_duration);         }     } 

in turn car turn animation method can this:

private void animatecarturn(final marker marker, final float startangle, final float endangle, final long duration) {         final handler handler = new handler();         final long starttime = systemclock.uptimemillis();         final interpolator interpolator = new linearinterpolator();          final float dandgle = endangle - startangle;          matrix matrix = new matrix();         matrix.postrotate(startangle);         bitmap rotatedbitmap = bitmap.createbitmap(mmarkericon, 0, 0, mmarkericon.getwidth(), mmarkericon.getheight(), matrix, true);         marker.seticon(bitmapdescriptorfactory.frombitmap(rotatedbitmap));          handler.post(new runnable() {             @override             public void run() {                  long elapsed = systemclock.uptimemillis() - starttime;                 float t = interpolator.getinterpolation((float) elapsed / duration);                  matrix m = new matrix();                 m.postrotate(startangle + dandgle * t);                 marker.seticon(bitmapdescriptorfactory.frombitmap(bitmap.createbitmap(mmarkericon, 0, 0, mmarkericon.getwidth(), mmarkericon.getheight(), m, true)));                  if (t < 1.0) {                     handler.postdelayed(this, 16);                 } else {                     nextmoveanimation();                 }             }         });     } 

where nextmoveanimation() is:

private void nextmoveanimation() {         if (mindexcurrentpoint <  mpathpolygonpoints.size() - 1) {             animatecarmove(mcarmarker, mpathpolygonpoints.get(mindexcurrentpoint), mpathpolygonpoints.get(mindexcurrentpoint+1), move_animation_duration);         }     } 

the mpathpolygonpoints (geopoints of car trip) is:

private list<latlng> mpathpolygonpoints; 

and mindexcurrentpoint variable index of current point on path (it should 0 @ start of animation , incremented on each turn of path in nextturnanimation() method).

turn_animation_duration - duration (in ms) animation car turn on path geopoint;

move_animation_duration - duration (in ms) animation car movement along line segment of path;

to bearing can use method that:

private double getangle(latlng beginlatlng, latlng endlatlng) {         double f1 = math.pi * beginlatlng.latitude / 180;         double f2 = math.pi * endlatlng.latitude / 180;         double dl = math.pi * (endlatlng.longitude - beginlatlng.longitude) / 180;         return math.atan2(math.sin(dl) * math.cos(f2) , math.cos(f1) * math.sin(f2) - math.sin(f1) * math.cos(f2) * math.cos(dl));;     } 

finally can start animations call animatecarmove() once:

animatecarmove(mcarmarker, mpathpolygonpoints.get(0), mpathpolygonpoints.get(1), move_animation_duration); 

other steps of animation called automatically each point of car path.

and should take account "special cases" like:

1) changing sign of of turn angle (e.g. bearing changes -120 150 degrees);

2) possibilities interrupt of animation user;

3) calculate animation duration on path segment length (e.g. 1 sec 1 km of segment length instead of fixed move_animation_duration)

4) tune value 16 in handler.postdelayed(this, 16); line better performance;

5) , on.


Comments

Popular posts from this blog

asynchronous - C# WinSCP .NET assembly: How to upload multiple files asynchronously -

aws api gateway - SerializationException in posting new Records via Dynamodb Proxy Service in API -

asp.net - Problems sending emails from forum -