2

When I click on polyline I want time (custom object) to be displayed at that particular lat long position.

Code to achieve polyline

PolylineOptions lineOptions = new PolylineOptions().width(7).color(Color.BLACK).geodesic(true);

for (int i = 0; i < points.size(); i++) {
    LatLng latLng1 = new LatLng(Double.parseDouble(points.get(i).getmLatitude()), Double.parseDouble(points.get(i).getmLongitude()));
    lineOptions.add(latLng1);
}

if (mPolyline != null) {
    mPolyline.remove();
}

mPolyline = mMap.addPolyline(lineOptions);
mPolyline.setClickable(true);

for (int i = 0; i < points.size(); i++) {
//setting tags to be used on ployline click                   
mPolyline.setTag(points.get(i).getTime());
}

List<PatternItem> pattern = Arrays.asList(
        new Gap(15), new Dash(15), new Gap(15));
mPolyline.setPattern(pattern);
mPolyline.setJointType(JointType.ROUND);

Now when I click on polyline I get only one tag which is same for all. I want unique tags(custom objects) for every polyline position which relate to lat long

mMap.setOnPolylineClickListener(new GoogleMap.OnPolylineClickListener() {
    @Override
    public void onPolylineClick(Polyline polyline) {
        Toast.makeText(mContext, (String) polyline.getTag(), Toast.LENGTH_SHORT).show();
    }
});

Thanks for contributing :)

EDIT

 mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
    @Override
    public void onMapClick(LatLng latLng) {
        boolean isOnRoute = PolyUtil.isLocationOnPath(latLng, lineOptions.getPoints(), false, 25);

        if (isOnRoute) {              
            for (LocationVo mCoordinates : points) {
              double distanceInMeters =  SphericalUtil.computeDistanceBetween(latLng, mCoordinates.getmLatLong());
                boolean isWithin50m = distanceInMeters < 50;
                if (isWithin50m) {
                    Toast.makeText(mContext, mCoordinates.getTime(), Toast.LENGTH_SHORT).show();
                    break;
                }
            }
        }
    }
});

Not all my polylines match with the conditions and show no toast on click

lelloman
  • 13,883
  • 5
  • 63
  • 85
coderBox
  • 140
  • 1
  • 12
  • 2
    You can't get there with tag - you're better off using the `onMapClickListener` and compute the closest point and if within tolerance display time from `points`. See android-maps-utils for `PolyLine.isLocationOnPath` and `SphericalUtil.computeDistanceBetween`. Unfortunately, the polyLineListener does not give the click point otherwise you could do the compute there. –  Dec 30 '18 at 00:11
  • @Andy It's been a while 18 days to be exact to get back to this, I was able to show time on polyline click by following your comment THANKS!! I have a problem though,I compare distance I get from SphericalUtil.computeDistanceBetween to be less than 50 meters and not all my polyline clicks show time please check I have edited my question – coderBox Jan 16 '19 at 11:35

1 Answers1

1

With a tolerance of 25 meters you are defining a corridor along each path segment 25 meters on either side. So as implemented, all this tells you is the click point is somewhere in the corridor centered on the path - or effectively they've clicked on the polyline with some room for error.

The problem you are having is in your assumption that you'll always be within 50 meters of a point - this is incorrect and also not what you want as best as I can tell. By definition, once isOnRoute is true, you always want to find a point since by definition they've clicked on the polyline; this is done (inefficiently) by simply calculating all distances from click-point to all polyline points and determining the shortest distance (a simple loop with a min logic); then use this point for your toast.

Now if you really wanted to limit what are considered "successful" clicks, where a successful click is both "on the polyline" and "near a point" then your distance check would be added using some acceptable value - this would be in effect defining a "box" around each point with dimensions 50 meters (25 x 2)-by-whatever your distance check is. Note this is not the same as just checking a radius circle around each point unless the radius of the desired circle is equivalent to the polyline tolerance.

(One other trivial point - your mixing measurement systems when using false for geodesic and then computing spherical distance - but should not be an issue with your implementation.) (If helpful I'll add a picture later.)

Summary of modification: "check if user clicks along the polyline" AND "determine closest point along line" AND "display some toast for that point".

So make this modification after isOnRoute is true:

        LocationVo closestPoint = null;
        double minDist = -1;
        for (LocationVo mCoordinates : points) {
          double distanceInMeters =  SphericalUtil.computeDistanceBetween(latLng, mCoordinates.getmLatLong());
          if (minDist < 0 || distanceInMeters < minDist) {
             minDist = distanceInMeters;
             closestPoint = mCoordinates;
          }
        }
        if (closestPoint != null) {
            Toast.makeText(mContext, closestPoint.getTime(), Toast.LENGTH_SHORT).show();
        }

To implement the "box" discussed above around each point modify the one condition:

          if ((distanceInMeters < MAX_DISTANCE_FROM_POINT) && (minDist < 0 || distanceInMeters < minDist)) {

Note this means in some cases you will not get a toast even if they clicked along the polyline.