android - 找出折线重叠的部分 GoogleMap
问题描述
我想在 a 上显示几条折线,GoogleMap
其中一些可能会重叠,如下图所示。(它们可能不会完美重叠)。
我的目标是获得一个多段线列表,这些多段线与初始多段线集穿过相同的道路,但约束条件是它们不重叠。
对于前一种情况,我可能会得到这样的结果:
关于如何实现这一目标的一些想法?
解决方案
最简单的方法(如果你没有那么多折线)是使用Google Maps Roads API部分Snap to Road这
返回给定 GPS 坐标集的最佳拟合道路几何图形。该服务需要沿路线收集多达 100 个 GPS 点,并返回一组类似的数据,这些点捕捉到车辆行驶的最可能的道路。
就像在这个例子中:
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mGoogleMap;
private MapFragment mapFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mapFragment = (MapFragment) getFragmentManager()
.findFragmentById(R.id.map_fragment);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
List<LatLng> sourcePoints = new ArrayList<>();
sourcePoints.add(new LatLng(<COORDINATES_OF_POLYLINE>));
...
sourcePoints.add(new LatLng(<COORDINATES_OF_POLYLINE>));
PolylineOptions polyLineOptions = new PolylineOptions();
polyLineOptions.addAll(sourcePoints);
polyLineOptions.width(5);
polyLineOptions.color(Color.BLUE);
mGoogleMap.addPolyline(polyLineOptions);
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(sourcePoints.get(0), 15));
List<LatLng> snappedPoints = new ArrayList<>();
new GetSnappedPointsAsyncTask().execute(sourcePoints, null, snappedPoints);
}
private String buildRequestUrl(List<LatLng> trackPoints) {
StringBuilder url = new StringBuilder();
url.append("https://roads.googleapis.com/v1/snapToRoads?path=");
for (LatLng trackPoint : trackPoints) {
url.append(String.format("%8.5f", trackPoint.latitude));
url.append(",");
url.append(String.format("%8.5f", trackPoint.longitude));
url.append("|");
}
url.delete(url.length() - 1, url.length());
url.append("&interpolate=true");
url.append(String.format("&key=%s", <your_Google_Maps_API_key>);
return url.toString();
}
private class GetSnappedPointsAsyncTask extends AsyncTask<List<LatLng>, Void, List<LatLng>> {
protected void onPreExecute() {
super.onPreExecute();
}
protected List<LatLng> doInBackground(List<LatLng>... params) {
List<LatLng> snappedPoints = new ArrayList<>();
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(buildRequestUrl(params[0]));
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder jsonStringBuilder = new StringBuilder();
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line+"\n");
jsonStringBuilder.append(line);
jsonStringBuilder.append("\n");
}
JSONObject jsonObject = new JSONObject(jsonStringBuilder.toString());
JSONArray snappedPointsArr = jsonObject.getJSONArray("snappedPoints");
for (int i = 0; i < snappedPointsArr.length(); i++) {
JSONObject snappedPointLocation = ((JSONObject) (snappedPointsArr.get(i))).getJSONObject("location");
double lattitude = snappedPointLocation.getDouble("latitude");
double longitude = snappedPointLocation.getDouble("longitude");
snappedPoints.add(new LatLng(lattitude, longitude));
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return snappedPoints;
}
@Override
protected void onPostExecute(List<LatLng> result) {
super.onPostExecute(result);
PolylineOptions polyLineOptions = new PolylineOptions();
polyLineOptions.addAll(result);
polyLineOptions.width(5);
polyLineOptions.color(Color.RED);
mGoogleMap.addPolyline(polyLineOptions);
LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(result.get(0));
builder.include(result.get(result.size()-1));
LatLngBounds bounds = builder.build();
mGoogleMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 10));
}
}
}
(为此,您需要在 Google Cloud Console 中为您的项目添加 Google Maps Roads API 支持)
使用 Snap To Road 处理所有“初始”多段线后,它们都应该完全重叠,您可以使用Polyline的 Z-Index 属性来管理多段线的 Z 顺序。
另一种方法是“手动”检测折线的重叠。在这种情况下,您应该:
- 决定如何确定应该显示在其他折线之上的“主”折线(最长或具有最大数量的点或其他东西);
- 对于“非主”折线的每个点,检查它是否在“主”折线上(您可以使用PolyUtil库的isLocationOnPath()方法)并根据检查结果选择线段的颜色:如果点在“主” " 路径(在以米为单位的指定公差内)您不应显示“非主”折线段或以其他方式显示所选颜色。
推荐阅读
- json - 从 Bash 或 Ruby 创建一个有效的 JSON 字符串?
- c# - .Net Core [FromBody] JArray 到 ICollection
- java - 如何实现 StringBuilder 以避免不可变字符串分配问题?
- postgresql - 使用 fetchtype LAZY 和 @ManyToOne 从 Spring 存储库传输错误的 UUID(主键)
- ibm-cloud - IBM 认知实验室登录
- android - How to create handler with callbacks that run on a different thread?
- python - 从日期列表中使用 Pandas (DateOffset) 创建日历
- css - 如何将 DIV 与其容器底部对齐?
- python - 蟒蛇:名称错误:名称
- ionic3 - 如何在ionic3中调用没有表单数据的POST API?