Skip to content
Permalink
Browse files

Merge pull request #1483 from osmdroid/feature/#1458

feature/#1458 - new method `PolyOverlayWithIW.usePath`
  • Loading branch information
monsieurtanuki committed Jan 13, 2020
2 parents e966ede + 6fddad6 commit c688ce8cf300e4d083186a48b7fbefb766e90673
@@ -127,7 +127,8 @@ private void touch_up() {
case PolylineAsPath:
final boolean asPath = drawingMode == Mode.PolylineAsPath;
final int color = Color.argb(100, 100, 100, 100);
final Polyline line = new Polyline(map, asPath);
final Polyline line = new Polyline(map);
line.usePath(true);
line.setInfoWindow(
new BasicInfoWindow(org.osmdroid.library.R.layout.bonuspack_bubble, map));
line.getOutlinePaint().setColor(color);
@@ -5,6 +5,9 @@
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.Region;
import android.view.MotionEvent;

import org.osmdroid.util.BoundingBox;
import org.osmdroid.util.Distance;
@@ -33,8 +36,8 @@
private List<MilestoneManager> mMilestoneManagers = new ArrayList<>();
private GeoPoint mInfoWindowLocation;

private final LineDrawer mLineDrawer;
protected final Path mPath;
private LineDrawer mLineDrawer;
protected Path mPath;
protected float mDensity = 1.0f;

/**
@@ -58,25 +61,48 @@
private final PointL mDowngradeOffset = new PointL();
private float[] mDowngradeSegments;

/**
* @since 6.2.0
* Used to be in {@link Polyline}
*/
private float mDensityMultiplier = 1.0f;
private final boolean mClosePath;

protected PolyOverlayWithIW(final MapView pMapView, final boolean pUsePath, final boolean pClosePath) {
super();
mClosePath = pClosePath;
if (pMapView != null) {
setInfoWindow(pMapView.getRepository().getDefaultPolylineInfoWindow());
mDensity = pMapView.getContext().getResources().getDisplayMetrics().density;
}
if (pUsePath) {
mPath = new Path();
mLineDrawer = null;
mOutline = new LinearRing(mPath, pClosePath);
} else {
mPath = null;
mLineDrawer = new LineDrawer(256);
mOutline = new LinearRing(mLineDrawer, pClosePath);
////mOutline.clearPath();
mLineDrawer.setPaint(mOutlinePaint);
}
usePath(pUsePath);
}

/**
* @since 6.2.0
* Use Path or not for the display
* drawPath can be notoriously slower than drawLines, therefore when relevant "Polygon"s
* would be better off if displayed with drawLines.
* On the other hand, drawPath sometimes looks better, therefore when relevant "Polyline"s
* would be better off if displayed with drawPath
*/
public void usePath(final boolean pUsePath) {
final ArrayList<GeoPoint> previousPoints = mOutline == null ? null : mOutline.getPoints();
if (pUsePath) {
mPath = new Path();
mLineDrawer = null;
mOutline = new LinearRing(mPath, mClosePath);
} else {
mPath = null;
mLineDrawer = new LineDrawer(256);
mOutline = new LinearRing(mLineDrawer, mClosePath);
mLineDrawer.setPaint(mOutlinePaint);
}
if (previousPoints != null) {
setPoints(previousPoints);
}
}

public void setVisible(boolean visible){
setEnabled(visible);
}
@@ -513,4 +539,86 @@ private void displayDowngrade(final Canvas pCanvas, final Projection pProjection
}
pCanvas.drawLines(mDowngradeSegments, 0, index, paint);
}

/**
* @since 6.2.0
*/
protected abstract boolean click(final MapView pMapView, final GeoPoint pEventPos);

/**
* @since 6.2.0
* Used to be in {@link Polyline}
*/
public void setDensityMultiplier(final float pDensityMultiplier) {
mDensityMultiplier = pDensityMultiplier;
}

/**
* Used to be if {@link Polygon}
* Important note: this function returns correct results only if the Poly has been drawn before,
* and if the MapView positioning has not changed.
* @return true if the Poly contains the event position.
*/
public boolean contains(final MotionEvent pEvent){
if (mPath.isEmpty()) {
return false;
}
final RectF bounds = new RectF(); //bounds of the Path
mPath.computeBounds(bounds, true);
final Region region = new Region();
//Path has been computed in #draw (we assume that if it can be clicked, it has been drawn before).
region.setPath(mPath, new Region((int)bounds.left, (int)bounds.top,
(int) (bounds.right), (int) (bounds.bottom)));
return region.contains((int)pEvent.getX(), (int)pEvent.getY());
}

/**
* @since 6.2.0
* Used to be in {@link Polyline}
* Detection is done is screen coordinates.
* @param pTolerance in pixels
* @return true if the Poly is close enough to the point.
*/
public boolean isCloseTo(final GeoPoint pPoint, final double pTolerance, final MapView pMapView) {
return getCloseTo(pPoint, pTolerance, pMapView) != null;
}

/**
* @since 6.2.0
* Used to be in {@link Polyline}
* Detection is done is screen coordinates.
* @param pTolerance in pixels
* @return the first GeoPoint of the Poly close enough to the point
*/
public GeoPoint getCloseTo(final GeoPoint pPoint, final double pTolerance, final MapView pMapView) {
return mOutline.getCloseTo(pPoint, pTolerance, pMapView.getProjection(), mClosePath);
}

/**
* Used to be in both {@link Polyline} and {@link Polygon}
* Default listener for a single tap event on a Poly:
* set the infowindow at the tapped position, and open the infowindow (if any).
* @return true if tapped
*/
@Override
public boolean onSingleTapConfirmed(final MotionEvent pEvent, final MapView pMapView){
final Projection projection = pMapView.getProjection();
final GeoPoint eventPos = (GeoPoint) projection.fromPixels((int)pEvent.getX(), (int)pEvent.getY());
final GeoPoint geoPoint;
if (mPath != null) {
final boolean tapped = contains(pEvent);
if (tapped) {
geoPoint = eventPos;
} else {
geoPoint = null;
}
} else {
final double tolerance = mOutlinePaint.getStrokeWidth() * mDensity * mDensityMultiplier;
geoPoint = getCloseTo(eventPos, tolerance, pMapView);
}
if (geoPoint != null) {
return click(pMapView, geoPoint);
}
return false;
}
}
@@ -3,15 +3,11 @@

import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Region;
import android.view.MotionEvent;

import org.osmdroid.api.IGeoPoint;
import org.osmdroid.util.BoundingBox;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.Projection;

import java.util.ArrayList;
import java.util.List;
@@ -193,47 +189,6 @@ public void setHoles(List<? extends List<GeoPoint>> holes){
points.add(new GeoPoint(northLat, east.getLongitude()));
return points;
}



/** Important note: this function returns correct results only if the Polygon has been drawn before,
* and if the MapView positioning has not changed.
* @param event
* @return true if the Polygon contains the event position.
*/
public boolean contains(MotionEvent event){
if (mPath.isEmpty())
return false;
RectF bounds = new RectF(); //bounds of the Path
mPath.computeBounds(bounds, true);
Region region = new Region();
//Path has been computed in #draw (we assume that if it can be clicked, it has been drawn before).
region.setPath(mPath, new Region((int)bounds.left, (int)bounds.top,
(int) (bounds.right), (int) (bounds.bottom)));
return region.contains((int)event.getX(), (int)event.getY());
}

/**
* Default listener for a single tap event on a Polygon:
* set the infowindow at the tapped position, and open the infowindow (if any).
* @param event
* @param mapView
* @return true if tapped
*/
@Override public boolean onSingleTapConfirmed(final MotionEvent event, final MapView mapView){
Projection pj = mapView.getProjection();
GeoPoint eventPos = (GeoPoint)pj.fromPixels((int)event.getX(), (int)event.getY());
boolean tapped = contains(event);
if (tapped) {
if (mOnClickListener == null) {
return onClickDefault(this, mapView, eventPos);
} else {
return mOnClickListener.onClick(this, mapView, eventPos);
}
} else
return tapped;
}

@Override public void onDetach(MapView mapView) {
super.onDetach(mapView);
@@ -264,4 +219,16 @@ public boolean onClickDefault(Polygon polygon, MapView mapView, GeoPoint eventPo
public void setOnClickListener(OnClickListener listener) {
mOnClickListener = listener;
}

/**
* @since 6.2.0
*/
@Override
protected boolean click(final MapView pMapView, final GeoPoint pEventPos) {
if (mOnClickListener == null) {
return onClickDefault(this, pMapView, pEventPos);
} else {
return mOnClickListener.onClick(this, pMapView, pEventPos);
}
}
}
@@ -2,11 +2,9 @@

import android.graphics.Color;
import android.graphics.Paint;
import android.view.MotionEvent;

import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.Projection;

import java.util.ArrayList;

@@ -25,12 +23,6 @@
protected OnClickListener mOnClickListener;
private float mDensity = 1.0f;
private float mDensityMultiplier = 1.0f;
/**
* If MapView is not provided, infowindow popup will not function unless you set it yourself.
*/
@@ -121,49 +113,6 @@ public void setOnClickListener(OnClickListener listener) {
mOnClickListener = listener;
}
public void setDensityMultiplier(float multiplier) {
mDensityMultiplier = multiplier;
}
/**
* Detection is done is screen coordinates.
*
* @param point
* @param tolerance in pixels
* @return true if the Polyline is close enough to the point.
*/
public boolean isCloseTo(GeoPoint point, double tolerance, MapView mapView) {
return getCloseTo(point, tolerance, mapView) != null;
}
/**
* @since 6.0.3
* Detection is done is screen coordinates.
*
* @param point
* @param tolerance in pixels
* @return the first GeoPoint of the Polyline close enough to the point
*/
public GeoPoint getCloseTo(GeoPoint point, double tolerance, MapView mapView) {
return mOutline.getCloseTo(point, tolerance, mapView.getProjection(), false);
}
@Override
public boolean onSingleTapConfirmed(final MotionEvent event, final MapView mapView) {
final Projection pj = mapView.getProjection();
GeoPoint eventPos = (GeoPoint) pj.fromPixels((int) event.getX(), (int) event.getY());
double tolerance = mOutlinePaint.getStrokeWidth() * mDensity * mDensityMultiplier;
final GeoPoint closest = getCloseTo(eventPos, tolerance, mapView);
if (closest != null) {
if (mOnClickListener == null) {
return onClickDefault(this, mapView, closest);
} else {
return mOnClickListener.onClick(this, mapView, closest);
}
} else
return false;
}
/** Internal method used to ensure that the infowindow will have a default position in all cases,
* so that the user can call showInfoWindow even if no tap occured before.
* Currently, set the position on the "middle" point of the polyline.
@@ -194,4 +143,15 @@ public void onDetach(MapView mapView) {
public double getDistance() {
return mOutline.getDistance();
}
/**
* @since 6.2.0
*/
@Override
protected boolean click(final MapView pMapView, final GeoPoint pEventPos) {
if (mOnClickListener == null) {
return onClickDefault(this, pMapView, pEventPos);
}
return mOnClickListener.onClick(this, pMapView, pEventPos);
}
}

0 comments on commit c688ce8

Please sign in to comment.
You can’t perform that action at this time.