Marker rotation in the Google Maps API v2

I followed this answer and it works great. stack overflow

But the problems that I am currently facing are as follows:

  • When I stop anywhere, it is not stable. I get a random value even when I am not moving.
  • when I turn it counterclockwise, which is wrong. It should be done in short turns.

This is the code I'm using:

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;
    }

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);

                    CameraPosition camPos = CameraPosition
                            .builder(mMap.getCameraPosition())
                            .bearing(bearing)
                            .target(marker.getPosition())
                            .build();
                    mMap.animateCamera(CameraUpdateFactory.newCameraPosition(camPos));

                    if (t < 1.0) {
                        // Post again 16ms later.
                        handler.postDelayed(this, 16);
                    } else {
                        isMarkerRotating = false;
                    }
                }
            });
        }
    }

AT onLocationChanged()

float toRotation = (float) bearingBetweenLocations(toLatLng(oldLocation), toLatLng(newLocation));
rotateMarker(my_marker, toRotation);
+4
source share
1 answer

So, finally found my own answer, which I will post here so that others may find it useful.

, onLocationChanged, , . .

 double oldLat = oldLocation.getLatitude();
 double oldLng = oldLocation.getLongitude();

 double newLat = newLocation.getLatitude();
 double newLng = newLocation.getLongitude();

 if (oldLat != newLat && oldLng != newLng){
      updateMyLocation(toLatLng(oldLocation), toLatLng(mCurrentLocation));
 }

. . ( ).

float rotation = (float) SphericalUtil.computeHeading(old, new);
rotateMarker(bus_marker, new, rotation);

private void rotateMarker(final Marker marker, final LatLng destination, final float rotation) {

    if (marker != null) {

        final LatLng startPosition = marker.getPosition();
        final float startRotation = marker.getRotation();

        final LatLngInterpolator latLngInterpolator = new LatLngInterpolator.Spherical();
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
        valueAnimator.setDuration(3000); // duration 3 second
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {

                try {
                    float v = animation.getAnimatedFraction();
                    LatLng newPosition = latLngInterpolator.interpolate(v, startPosition, destination);
                    float bearing = computeRotation(v, startRotation, rotation);

                    marker.setRotation(bearing);
                    marker.setPosition(newPosition);

                }
                catch (Exception e){
                    e.printStackTrace();
                }
            }
        });
        valueAnimator.start();
    }
}
private static float computeRotation(float fraction, float start, float end) {
    float normalizeEnd = end - start; // rotate start to 0
    float normalizedEndAbs = (normalizeEnd + 360) % 360;

    float direction = (normalizedEndAbs > 180) ? -1 : 1; // -1 = anticlockwise, 1 = clockwise
    float rotation;
    if (direction > 0) {
        rotation = normalizedEndAbs;
    } else {
        rotation = normalizedEndAbs - 360;
    }

    float result = fraction * rotation + start;
    return (result + 360) % 360;
}
+3

Source: https://habr.com/ru/post/1664034/


All Articles