【问题标题】:how to rotate marker(bus) according to direction?如何根据方向旋转标记(总线)?
【发布时间】:2017-08-30 15:49:09
【问题描述】:

从下面的代码中,我在地图上添加标记,每 15 秒刷新一次并从数据库中获取新的纬度和经度。标记(巴士图像)成功添加到地图上,并从一个位置顺利移动到另一个位置,就像汽车在路上行驶一样。现在我想要根据方向旋转总线标记。我怎样才能做到这一点?我没有得到 toRotation 和 st 的价值是什么?

public Runnable runLocation = new Runnable() {
        @Override
        public void run() {
            gps = new GPSTracker(MapActivity.this);
            MyLocation1.clear();
            if (gps.CanGetLocation()) {
                double latitude = gps.getLatitude();
                double longitude = gps.getLongitude();
                LatLng mylocation = new LatLng(latitude, longitude);
                if (marker != null) {
                    marker.remove();
                }
                if (circle != null) {
                    circle.remove();
                }
                if (busMarker != null){
                    lastBusPos = busMarker.getPosition();
                }

                marker = mMap.addMarker(new MarkerOptions()
                        .icon(BitmapDescriptorFactory.fromResource(R.drawable.location))
                        .title("My Location")
                        .position(mylocation));

                circle = mMap.addCircle(new CircleOptions()
                        .center(mylocation)
                        .radius(1000)
                        .strokeColor(0x10000000)
                        .fillColor(0x10000000));
            } else {
                // gps.showSettingsAlert();
            }

            String tag_json_obj = "json_obj_req";
            String url = AppConfig.RouteData + "i=1&" + "y=1";

            JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

                @Override
                public void onResponse(JSONObject response) {
                    try {

                        JSONObject jObj = new JSONObject(String.valueOf(response));
                        JSONArray json_user = jObj.getJSONArray("Message");
                        for (int i = 0; i < json_user.length(); i++) {

                            try {

                                JSONObject obj = json_user.getJSONObject(i);

                                final Double currLat = obj.getDouble("actual_lat");
                                final Double currLong = obj.getDouble("actual_long");
                                final LatLng hcmus = new LatLng(currLat, currLong);


                                List<LatLng> latList = new ArrayList<LatLng>();
                                latList.add(hcmus);

                                if (mMarkers.size() != json_user.length()) {
                                    busMarker = mMap.addMarker(new MarkerOptions()
                                            .icon(BitmapDescriptorFactory.fromResource(R.drawable.bus))
                                            .title("Bus No" + obj.getString("bus_id"))
                                            .position(hcmus));
                                    mMarkers.add(busMarker);
                                } else {
                                    //busMarker.setPosition(hcmus);
                                    animateMarker(hcmus, false);
                                    rotateMarker(busMarker, 45.0f, 45.0f);
                                }

                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }, new Response.ErrorListener() {

                @Override
                public void onErrorResponse(VolleyError error) {
                    Toast.makeText(MapActivity.this, "Sorry something went wrong..Try again", Toast.LENGTH_SHORT).show();
                }
            });

            // Adding request to request queue
            AppController.getInstance().addToRequestQueue(jsonObjReq, tag_json_obj);

            MapActivity.this.handler.postDelayed(MapActivity.this.runLocation, 15000);
        }

    };

    /*-------------------------------Animation----------------------------*/
    public void rotateMarker(final Marker marker, final float toRotation, final float st) {
        final Handler handler = new Handler();
        final long start = SystemClock.uptimeMillis();
        final float startRotation = st;
        final long duration = 1555;

        final Interpolator interpolator = new LinearInterpolator();

        handler.post(new Runnable() {
            @Override
            public void run() {
                long elapsed = SystemClock.uptimeMillis() - start;
                float t = interpolator.getInterpolation((float) elapsed / duration);

                float rot = t * toRotation + (1 - t) * startRotation;

                marker.setRotation(-rot > 180 ? rot / 2 : rot);
                if (t < 1.0) {
                    // Post again 16ms later.
                    handler.postDelayed(this, 16);
                }
            }
        });
    }

    public void animateMarker(final LatLng toPosition,final boolean hideMarke) {
        final Handler handler = new Handler();
        final long start = SystemClock.uptimeMillis();
        Projection proj = mMap.getProjection();
        Point startPoint = proj.toScreenLocation(lastBusPos);
        final LatLng startLatLng = proj.fromScreenLocation(startPoint);
        final long duration = 5000;

        final Interpolator interpolator = new LinearInterpolator();

        handler.post(new Runnable() {
            @Override
            public void run() {
                long elapsed = SystemClock.uptimeMillis() - start;
                float t = interpolator.getInterpolation((float) elapsed
                        / duration);
                double lng = t * toPosition.longitude + (1 - t)
                        * startLatLng.longitude;
                double lat = t * toPosition.latitude + (1 - t)
                        * startLatLng.latitude;
                busMarker.setPosition(new LatLng(lat, lng));

                if (t < 1.0) {
                    // Post again 16ms later.
                    handler.postDelayed(this, 16);
                } else {
                    if (hideMarke) {
                        busMarker.setVisible(false);
                    } else {
                        busMarker.setVisible(true);
                    }
                }
            }
        });
    }

    /*--------------------------------------------------------------------*/

【问题讨论】:

    标签: java android google-maps


    【解决方案1】:

    您可以参考这个related thread。使用Location 对象的bearing,然后将其设置为CameraPosition

    如果您使用 GPS 定位用户,那么 Location 对象您 进入onLocationChanged 包含bearing

    如果您只有两个坐标(例如,您只有坐标 来自网络位置提供商),您可以使用Location.bearingTo() 计算两个坐标的方位:

    Location prevLoc = ... ;
    Location newLoc = ... ;
    float bearing = prevLoc.bearingTo(newLoc) ;
    

    如果你有一个方位,你可以设置标记的旋转使用 MarkerOptions.rotation():

    mMap.addMarker(new MarkerOptions()
                        .position(markerLatLng)
                        .icon(BitmapDescriptorFactory.fromResource(R.drawable.map_marker))
                        .anchor(0.5f, 0.5f)
                        .rotation(bearing)
                        .flat(true));
    

    您必须将anchor 设置为您要旋转的点 周围,​​也是你想要在你设定的位置的点 到标记。 (0.5, 0.5) 是图像的中心。

    以下是一些可能也有帮助的帖子:

    【讨论】:

      【解决方案2】:

      试试下面的代码。 这很容易实现。

      这里 latLng1=您的旧位置 & latLng2=您的新位置。

      Step=1

       private double getBearingBetweenTwoPoints1(LatLng latLng1, LatLng latLng2) {
      
              double lat1 = degreesToRadians(latLng1.latitude);
              double long1 = degreesToRadians(latLng1.longitude);
              double lat2 = degreesToRadians(latLng2.latitude);
              double long2 = degreesToRadians(latLng2.longitude);
      
      
              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 radiansBearing = Math.atan2(y, x);
      
      
              return radiansToDegrees(radiansBearing);
          }
      

      步骤=2

      private double degreesToRadians(double degrees) {
              return degrees * Math.PI / 180.0;
          }
      

      Step=3

      private double radiansToDegrees(double radians) {
          return radians * 180.0 / Math.PI;
      }
      

      Step=4设置标记旋转。

       mPositionMarker.setRotation((float) getBearingBetweenTwoPoints1(new LatLng(lastLocLati, lastLocLongi), new LatLng(lati, longi)));
      

      【讨论】:

      • 您的代码可以完美地改变方向,但我需要同时改变位置。当我在这条 .setRotation 线之后设置位置时,标记移动并成功改变方向,但是当它到达第二个点时,它再次将其方向改变为图标的原始方向。
      【解决方案3】:

      这是使用轴承同时移动和旋转标记的代码 -

         public void animateMarker(final Marker marker, final LatLng toPosition, final boolean hideMarker) {
          boolean contains = mMap.getProjection()
                  .getVisibleRegion()
                  .latLngBounds
                  .contains(toPosition);
      
          if(!contains){
              mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(toPosition, 60));
           // MOVE CAMERA
          }
          final Handler handler = new Handler();
          final long start = SystemClock.uptimeMillis();
          Projection proj = mMap.getProjection();
          Point startPoint = proj.toScreenLocation(marker.getPosition());
          final LatLng startLatLng = proj.fromScreenLocation(startPoint);
          final long duration = 500;
          final float toRotation = (float) bearingBetweenLocations(marker.getPosition(), toPosition);
          final float startRotation = marker.getRotation();
          final Interpolator interpolator = new LinearInterpolator();
          handler.post(new Runnable() {
              @Override
              public void run() {
                  long elapsed = SystemClock.uptimeMillis() - start;
                  float t = interpolator.getInterpolation((float) elapsed
                          / duration);
                  //rotate marker
                  float rot = t * toRotation + (1 - t) * startRotation;
                  float bearing = -rot > 180 ? rot / 2 : rot;
                  marker.setRotation(bearing);
                  //move marker
                  double lng = t * toPosition.longitude + (1 - t)
                          * startLatLng.longitude;
                  double lat = t * toPosition.latitude + (1 - t)
                          * startLatLng.latitude;
                  marker.setPosition(new LatLng(lat, lng));
                  if (t < 1.0) {
                      // Post again 16ms later.
                      handler.postDelayed(this, 16);
                  } else {
                      if (hideMarker) {
                          marker.setVisible(false);
                      } else {
                          marker.setVisible(true);
                      }
                  }
              }
          });
      }
      
      
      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;
      }
      

      【讨论】:

        猜你喜欢
        • 2015-01-21
        • 1970-01-01
        • 2014-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多