Closed GoogleCodeExporter closed 9 years ago
You must check first if the event is related to your overlay. And this is not
done yet for polylines.
The key point is to detect if the hit point is close to the polyline. The
method used for polygon can not be used here. So you have to check segment
after segment if the point is close enough.
If you implement that, I would be interested to add it in the lib.
Original comment by mathieu....@gmail.com
on 7 Aug 2014 at 7:24
I came up with a solution which could be optimized a lot but works.
Probably it won't work very smoothly where there are a lot of Polylines.
I have overrode the Polyline adding the following methods:
//Method to be called to check if a point is on the line
public boolean isOnLine(IGeoPoint point) {
boolean toRtn = false;
ArrayList<GeoPoint> mPoints = (ArrayList<GeoPoint>) getPoints();
for (int i = 0; i < getNumberOfPoints() - 1; i++) {
GeoPoint a = mPoints.get(i);
GeoPoint b = mPoints.get(i + 1);
//the simpliest way i found is to hardcode a tolerance but it could be made so it varies with the zoom level
toRtn = toRtn || (linePointDist(a, b, point, true) <= 0.0005);
}
return toRtn;
}
// Compute the dot product AB x AC
private double dot(IGeoPoint A, IGeoPoint B, IGeoPoint C) {
double[] AB = new double[2];
double[] BC = new double[2];
AB[0] = B.getLongitude() - A.getLongitude();
AB[1] = B.getLatitude() - A.getLatitude();
BC[0] = C.getLongitude() - B.getLongitude();
BC[1] = C.getLatitude() - B.getLatitude();
double dot = AB[0] * BC[0] + AB[1] * BC[1];
return dot;
}
// Compute the cross product AB x AC
private double cross(IGeoPoint A, IGeoPoint B, IGeoPoint C) {
double[] AB = new double[2];
double[] AC = new double[2];
AB[0] = B.getLongitude() - A.getLongitude();
AB[1] = B.getLatitude() - A.getLatitude();
AC[0] = C.getLongitude() - A.getLongitude();
AC[1] = C.getLatitude() - A.getLatitude();
double cross = AB[0] * AC[1] - AB[1] * AC[0];
return cross;
}
// Compute the distance from A to B
private double distance(IGeoPoint A, IGeoPoint B) {
double d1 = A.getLongitude() - B.getLongitude();
double d2 = A.getLatitude() - B.getLatitude();
return Math.sqrt(d1 * d1 + d2 * d2);
}
// Compute the distance from AB to C
// if isSegment is true, AB is a segment, not a line.
private double linePointDist(IGeoPoint A, IGeoPoint B, IGeoPoint C,
boolean isSegment) {
double dist = cross(A, B, C) / distance(A, B);
if (isSegment) {
double dot1 = dot(A, B, C);
if (dot1 > 0)
return distance(B, C);
double dot2 = dot(B, A, C);
if (dot2 > 0)
return distance(A, C);
}
return Math.abs(dist);
}
Original comment by armellin...@gmail.com
on 8 Aug 2014 at 3:21
Thanks a lot, that's a good starting point.
I integrated directly in the Polyline class, with some perfs improvements.
The source is now commited.
Simple usage:
polyline.setInfoWindow(new DefaultInfoWindow(R.layout.bonuspack_bubble, map));
polyline.setTitle("My Route");
However, this solution has 2 issues:
1) As you mentionned, no handling of zoom level
2) In geodesic mode, additional points not taken into account
It would be probably better to work in the projected (screen) coord system, but
this is not straightforward. I let the issue opened for now.
Original comment by mathieu....@gmail.com
on 11 Aug 2014 at 4:02
Solution solving issues 1 and 2 just commited. Touch detection done in screen
coords, taking into account polyline stroke width.
Original comment by mathieu....@gmail.com
on 22 Aug 2014 at 12:55
Feature now fully integrated in v4.9.
Michelle, thanks for the contribution!
Original comment by mathieu....@gmail.com
on 15 Sep 2014 at 3:52
Original issue reported on code.google.com by
armellin...@gmail.com
on 7 Aug 2014 at 3:07