这是我自己的将标记捕捉到折线的实现(基于 GPS 位置):
首先,使用折线点创建距离较小的LatLng 列表(我使用的是splitPathIntoPoints 函数中指定的一米距离):
for (int i = 0; i < polylinePoints.size(); i++) {
LatLng src = new LatLng(Double.parseDouble(polylinePoints.get(i).get("lat")), Double.parseDouble(polylinePoints.get(i).get("lng")));
if (polylinePoints.size() > i + 1) {
LatLng dest = new LatLng(Double.parseDouble(polylinePoints.get(i + 1).get("lat")), Double.parseDouble(polylinePoints.get(i + 1).get("lng")));
List<LatLng> splitPoints = splitPathIntoPoints(src, dest);
mSplitPoints.addAll(splitPoints);
} else {
break;
}
}
splitPathIntoPoints 的代码:
public static List<LatLng> splitPathIntoPoints(LatLng source, LatLng destination) {
Float distance = findDistance(source, destination);
List<LatLng> splitPoints = new ArrayList<>();
splitPoints.add(source);
splitPoints.add(destination);
while (distance > 1) {
int polypathSize = splitPoints.size();
List<LatLng> tempPoints = new ArrayList<>();
tempPoints.addAll(splitPoints);
int injectionIndex = 1;
for (int i = 0; i < (polypathSize - 1); i++) {
LatLng a1 = tempPoints.get(i);
LatLng a2 = tempPoints.get(i + 1);
splitPoints.add(injectionIndex, findMidPoint(a1, a2));
injectionIndex += 2;
}
distance = findDistance(splitPoints.get(0), splitPoints.get(1));
}
return splitPoints;
}
findDistance 的代码:
public static Float findDistance(LatLng source, LatLng destination) {
Location srcLoc = new Location("srcLoc");
srcLoc.setLatitude(source.latitude);
srcLoc.setLongitude(source.longitude);
Location destLoc = new Location("destLoc");
destLoc.setLatitude(destination.latitude);
destLoc.setLongitude(destination.longitude);
return srcLoc.distanceTo(destLoc);
}
findMidPoint 的代码:
public static LatLng findMidPoint(LatLng source, LatLng destination) {
double x1 = toRad(source.latitude);
double y1 = toRad(source.longitude);
double x2 = toRad(destination.latitude);
double y2 = toRad(destination.longitude);
double Bx = Math.cos(x2) * Math.cos(y2 - y1);
double By = Math.cos(x2) * Math.sin(y2 - y1);
double x3 = toDeg(Math.atan2(Math.sin(x1) + Math.sin(x2), Math.sqrt((Math.cos(x1) + Bx) * (Math.cos(x1) + Bx) + By * By)));
double y3 = y1 + Math.atan2(By, Math.cos(x1) + Bx);
y3 = toDeg((y3 + 540) % 360 - 180);
return new LatLng(x3, y3);
}
一旦mSplitPoints 填充了彼此相距 1 米的较小折线点,下面的函数会根据我当前的 GPS 位置在折线上找到捕捉的位置。请注意,mMinorIndexTravelled 是我班级中的一个私有字段,初始值设置为零。
public static LatLng snapToPolyline(LatLng currentLocation) {
LatLng snappedLatLng = null;
Location current = new Location("current");
current.setLatitude(currentLocation.latitude);
current.setLongitude(currentLocation.longitude);
Integer minConfirmCount = 0;
float currentMinDistance = 0, previousMinDistance = 0;
List<Float> distances = new ArrayList<>();
for (LatLng point: mSplitPoints.subList(mMinorIndexTravelled, mSplitPoints.size() - 1)) {
Location pointLoc = new Location("pointLoc");
pointLoc.setLatitude(point.latitude);
pointLoc.setLongitude(point.longitude);
distances.add(current.distanceTo(pointLoc));
previousMinDistance = currentMinDistance;
currentMinDistance = Collections.min(distances);
if (currentMinDistance == previousMinDistance) {
minConfirmCount++;
if (minConfirmCount > 10) {
mMinorIndexTravelled = distances.indexOf(currentMinDistance) + mMinorIndexTravelled;
snappedLatLng = mSplitPoints.get(mMinorIndexTravelled);
break;
}
}
}
return snappedLatLng;
}