在实时纬度和经度之间绘制路线

Posted

技术标签:

【中文标题】在实时纬度和经度之间绘制路线【英文标题】:draw route line between real time latitude and longitude 【发布时间】:2020-07-27 01:44:23 【问题描述】:

现在我正在获取纬度和经度 n 次,如果我用手机移动标记也会根据纬度和经度移动,但如果手机改变位置,我需要绘制路线。 示例 我有 T1、T2、T4、T5 时间纬度经度点我需要绘制从 T1 到 T2 和 T2 到 T3 和 T3 到 T4 的路线等等,我无法实时绘制行。

MainActivity

public class MainActivity extends AppCompatActivity implements OnMapReadyCallback 

private static final int MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 5445;

private GoogleMap googleMap;
private FusedLocationProviderClient fusedLocationProviderClient;
private Marker currentLocationMarker;
private Location currentLocation;
private boolean firstTimeFlag = true;

private final View.OnClickListener clickListener = view -> 
    if (view.getId() == R.id.currentLocationImageButton && googleMap != null && currentLocation != null)
        animateCamera(currentLocation);
;

private final LocationCallback mLocationCallback = new LocationCallback() 

    @Override
    public void onLocationResult(LocationResult locationResult) 
        super.onLocationResult(locationResult);
        if (locationResult.getLastLocation() == null)
            return;
        currentLocation = locationResult.getLastLocation();
        if (firstTimeFlag && googleMap != null) 
            animateCamera(currentLocation);
            firstTimeFlag = false;
        
        showMarker(currentLocation);
    
;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    SupportMapFragment supportMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapFragment);
    supportMapFragment.getMapAsync(this);
    findViewById(R.id.currentLocationImageButton).setOnClickListener(clickListener);
    mydb = new DatabaseHelper(this);



@Override
public void onMapReady(GoogleMap googleMap) 
    this.googleMap = googleMap;




private void startCurrentLocationUpdates() 
    LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(3000);
//locationRequest.setFastestInterval(1000);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
        if (ActivityCompat.checkSelfPermission(this, 
android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && 
ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != 
PackageManager.PERMISSION_GRANTED) 
            ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]Manifest.permission.ACCESS_FINE_LOCATION,
                    MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
            return;
        
    
    fusedLocationProviderClient.requestLocationUpdates(locationRequest, mLocationCallback, 
Looper.myLooper());


private boolean isGooglePlayServicesAvailable() 
    GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
    int status = googleApiAvailability.isGooglePlayServicesAvailable(this);
    if (ConnectionResult.SUCCESS == status)
        return true;
    else 
        if (googleApiAvailability.isUserResolvableError(status))
            Toast.makeText(this, "Please Install google play services to use this application", Toast.LENGTH_LONG).show();
    
    return false;


@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) 
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION) 
        if (grantResults[0] == PackageManager.PERMISSION_DENIED)
            Toast.makeText(this, "Permission denied by uses", Toast.LENGTH_SHORT).show();
        else if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
            startCurrentLocationUpdates();
    


private void animateCamera(@NonNull Location location) 
    LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());

googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(getCameraPositionWithBearing(latLng)));
    addLines(latLng);

    AddData(location);


@NonNull
private CameraPosition getCameraPositionWithBearing(LatLng latLng) 
    addLines(latLng);
    return new CameraPosition.Builder().target(latLng).zoom(16).build();


private void showMarker(@NonNull Location currentLocation) 
    LatLng latLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
    BitmapDescriptor icon = 
BitmapDescriptorFactory.fromResource(R.drawable.ic_person_pin_circle_black_24dp);
    addLines(latLng);
    viewAll();
    if (currentLocationMarker == null)

        currentLocationMarker = googleMap.addMarker(new 
MarkerOptions().icon(BitmapDescriptorFactory.defaultMarker()).flat(true).position(latLng));
    else
        MarkerAnimation.animateMarkerToGB(currentLocationMarker, latLng, new LatLngInterpolator.Spherical());



@Override
protected void onStop() 
    super.onStop();
    if (fusedLocationProviderClient != null)
        fusedLocationProviderClient.removeLocationUpdates(mLocationCallback);


@Override
protected void onResume() 
    super.onResume();
    if (isGooglePlayServicesAvailable()) 
        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
        startCurrentLocationUpdates();

    


@Override
protected void onDestroy() 
    super.onDestroy();
    fusedLocationProviderClient = null;
    googleMap = null;


private void addLines(LatLng latLng) 

    LatLng TIMES_SQUARE = new LatLng(latLng.latitude, latLng.longitude);
    LatLng ***LYN_BRIDGE = new LatLng(latLng.latitude, latLng.longitude);
    LatLng LOWER_MANHATTAN = new LatLng(latLng.latitude, latLng.longitude);
    Log.i("===Lat", String.valueOf(latLng.latitude));
    Log.i("===Longt", String.valueOf(latLng.longitude));
    String polyLine = "q`epCakwfP_@EMvBEv@iSmBq@GeGg@C]mBS@KTiDRyCiBS";
    List<LatLng> polyLineList = Collections.singletonList(TIMES_SQUARE);

    LatLngBounds.Builder builder = new LatLngBounds.Builder();

    for (LatLng latLng1 : polyLineList) 
        builder.include(latLng1);


        googleMap.addPolyline((new PolylineOptions())
//.add(TIMES_SQUARE, LOWER_MANHATTAN,TIMES_SQUARE).width(5).color(Color.RED)
//.add( new LatLng(14.2354843, 76.2484165), new LatLng(14.2251, 76.3980)).width(5).color(Color.RED)
                .add(new LatLng(latLng.latitude, latLng.longitude), new LatLng(latLng.latitude, latLng.longitude)).addAll(polyLineList).width(5).color(Color.BLUE)
                .geodesic(true));

        PolylineOptions polylineOptions = new PolylineOptions();
        polylineOptions.color(Color.BLACK);
        polylineOptions.width(5);
        polylineOptions.startCap(new SquareCap());
        polylineOptions.endCap(new SquareCap());
        polylineOptions.jointType(ROUND);
        polylineOptions.addAll(polyLineList);
        Polyline greyPolyLine = googleMap.addPolyline(polylineOptions);
    
    ;
    // move camera to zoom on map
    // googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LOWER_MANHATTAN,13));


标记动画

public class MarkerAnimation 
public static void animateMarkerToGB(final Marker marker, final LatLng finalPosition, final LatLngInterpolator latLngInterpolator) 
    final LatLng startPosition = marker.getPosition();
    final Handler handler = new Handler();
    final long start = SystemClock.uptimeMillis();
    final Interpolator interpolator = new AccelerateDecelerateInterpolator();
    final float durationInMs = 3000;

    handler.post(new Runnable() 
        long elapsed;
        float t;
        float v;

        @Override
        public void run() 
            // Calculate progress using interpolator
            elapsed = SystemClock.uptimeMillis() - start;
            t = elapsed / durationInMs;
            v = interpolator.getInterpolation(t);

            marker.setPosition(latLngInterpolator.interpolate(v, startPosition, finalPosition));

            // Repeat till progress is complete.
            if (t < 1) 

                // Post again 16ms later.
//handler.postDelayed(this, 16);
                handler.postDelayed(this, 16);
            
        
    );


LatLngInterpolator 接口

public interface LatLngInterpolator 

LatLng interpolate(float fraction, LatLng a, LatLng b);

class Spherical implements LatLngInterpolator 

    /* From github.com/googlemaps/android-maps-utils */
    @Override
    public LatLng interpolate(float fraction, LatLng from, LatLng to) 
        // http://en.wikipedia.org/wiki/Slerp
        double fromLat = toRadians(from.latitude);
        double fromLng = toRadians(from.longitude);
        double toLat = toRadians(to.latitude);
        double toLng = toRadians(to.longitude);
        double cosFromLat = cos(fromLat);
        double cosToLat = cos(toLat);

        // Computes Spherical interpolation coefficients.
        double angle = computeAngleBetween(fromLat, fromLng, toLat, toLng);
        double sinAngle = sin(angle);
        if (sinAngle < 1E-6) 
            return from;
        
        double a = sin((1 - fraction) * angle) / sinAngle;
        double b = sin(fraction * angle) / sinAngle;

        // Converts from polar to vector and interpolate.
        double x = a * cosFromLat * cos(fromLng) + b * cosToLat * cos(toLng);
        double y = a * cosFromLat * sin(fromLng) + b * cosToLat * sin(toLng);
        double z = a * sin(fromLat) + b * sin(toLat);

        // Converts interpolated vector back to polar.
        double lat = atan2(z, sqrt(x * x + y * y));
        double lng = atan2(y, x);
        return new LatLng(toDegrees(lat), toDegrees(lng));
    

    private double computeAngleBetween(double fromLat, double fromLng, double toLat, double toLng) 
        // Haversine's formula
        double dLat = fromLat - toLat;
        double dLng = fromLng - toLng;
        return 2 * asin(sqrt(pow(sin(dLat / 2), 2) +
                cos(fromLat) * cos(toLat) * pow(sin(dLng / 2), 2)));
    


【问题讨论】:

“帮我找到解决办法。” 目前有什么问题?您似乎有代码可以观察设备位置的变化,并且您似乎有代码可以在 Google 地图上绘制折线,所以大部分内容似乎都被覆盖了。你有什么需要帮助的?仅通过查看预先存在的代码可能很难判断。 @Markus Kauppinen 线条未绘制,无法绘制线条 您的addLines 循环似乎只使用latLng 点来表示所有没有连线的点。 @Andy 我需要添加什么 您需要构建一个列表 - remove() 并在添加点时重绘 - 我不知道如何继续添加到先前绘制的折线。 【参考方案1】:

考虑用此方法替换您的 addLines 方法,该方法会在每次更新时维护并重绘折线:

private List<LatLng> polyLineList = new ArrayList<>();
private Polyline greyPolyLine;

private void addToLine(LatLng pt)

    polyLineList.add(pt);

    if (greyPolyLine != null)
    
        greyPolyLine.remove();
    
    PolylineOptions polylineOptions = new PolylineOptions();
    polylineOptions.color(Color.BLACK);
    polylineOptions.width(5);
    polylineOptions.startCap(new SquareCap());
    polylineOptions.endCap(new SquareCap());
    polylineOptions.jointType(ROUND);
    polylineOptions.addAll(polyLineList);
    greyPolyLine = googleMap.addPolyline(polylineOptions);

addLine 只是在每次调用时绘制一个点 - 单个点不太可能是可见的。

可能只需要在 showMarker 方法中调用它 - 不知道您为什么在相机方法中调用 addLines

【讨论】:

我有一个疑问,当前位置不合适..? 如何创建方向箭头折线

以上是关于在实时纬度和经度之间绘制路线的主要内容,如果未能解决你的问题,请参考以下文章

如何获取地图上两点之间的路线方向以绘制行车路线?

如何在从 ListView 项获取的两个地理点之间绘制标记和路线?

如何使用 Google API 查找航点上的纬度和经度

使用谷歌地图v3验证两点(纬度或地址)服务器端之间的路线距离

在路线中以固定时间间隔确定中间纬度/经度

检查两条路线(以纬度和经度表示)是不是彼此相对