在实时纬度和经度之间绘制路线
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 项获取的两个地理点之间绘制标记和路线?