Skip to content
Permalink
Browse files

feature/#1409 - downgrade mode for PolyOverlayWithIW when the project…

…ed poly is too small

The downgrade management works with 2 methods:
* `PolyOverlayWithIW.setDowngradeMaximumPixelSize(int)` - if the poly projected at the screen is too small (width or height lower than this value), either we don't display the poly or we display a rectangle instead
* `PolyOverlayWithIW.setDowngradeDisplay(boolean)` - should we display the rectangle when the poly is too small?

It can be tested in `SampleShapeFile`.

Deleted class:
* `PathOverlay`, which was deprecated 4 years ago

Impacted classes:
* `BoundBoxTest`: unrelated refactoring
* `Counters`: added a more flexible access to counter features with methods `reset(String)`, `increment(String)` and `get(String)`
* `CustomPaintingSurface`: used the new method `PolyOverlayWithIW.getBounds`; unrelated performance refactoring
* `DefaultOverlayManager`: unrelated display optimization for MapSnapshots
* `LinearRing`: now computing the bounding box ASAP, in method `computeProjected`, which simplifies method `getCenter`; created another version of `getBestOffset`; created method `getCloserValue`; created methods `getBoundingBox` and `clear`
* `LineDrawer`: optimized the display
* `MilestoneLineDisplayer`: fixed a minor unrelated bug, where the last point was added as (X0,Y0), but without a correspnding (X1,Y1)
* `OsmMapShapeConverter`: used method `PolyOverlayWithIW.getActualPoints` instead of deprecated `Polygon.getPoints()`
* `Polygon`: deprecated method `getPoints()`, to be replaced by `PolyOverlayWithIW.getActualPoints`; moved methods `setPoints` and `addPoint` to `PolyOverlayWithIW`
* `Polyline`: deprecated method `getPoints()`, to be replaced by `PolyOverlayWithIW.getActualPoints`; moved methods `setPoints` and `addPoint` to `PolyOverlayWithIW`
* `PolyOverlayWithIW`: added in the `draw` the downgrade management; created methods `setDowngradeMaximumPixelSize`, `setDowngradeDisplay`, `isWorthDisplaying` and `displayDowngrade` for the downgrade management; moved `Polygon` and `Polyline` methods here - `getBounds`, `setPoints`, `addPoint` and `getActualPoints`
* `Projection`: computed `mProjectedMapSize` regardless of the tile size; created method `getWorldMapSize()`
* `SampleOsmPath`: removed the "deprecated 4 years ago" `PathOverlay` sample; refactored
* `SampleShapeFile`: set up the display (downgrade and style)
* `ShapeConverter`: used the new method `PolyOverlayWithIW.getBounds`
* `TileSystem`: deprecated now useless member `projectionZoomLevel`
  • Loading branch information
monsieurtanuki committed Dec 22, 2019
1 parent 3d58deb commit fc18077c58d45893a9d3b2c487ba51b5f40a919a
Showing with 405 additions and 496 deletions.
  1. +7 −31 OpenStreetMapViewer/src/main/java/org/osmdroid/samplefragments/data/SampleOsmPath.java
  2. +13 −2 OpenStreetMapViewer/src/main/java/org/osmdroid/samplefragments/data/SampleShapeFile.java
  3. +13 −18 OpenStreetMapViewer/src/main/java/org/osmdroid/samplefragments/drawing/CustomPaintingSurface.java
  4. +39 −0 osmdroid-android/src/main/java/org/osmdroid/tileprovider/util/Counters.java
  5. +2 −0 osmdroid-android/src/main/java/org/osmdroid/util/TileSystem.java
  6. +13 −6 osmdroid-android/src/main/java/org/osmdroid/views/Projection.java
  7. +2 −1 osmdroid-android/src/main/java/org/osmdroid/views/overlay/DefaultOverlayManager.java
  8. +36 −4 osmdroid-android/src/main/java/org/osmdroid/views/overlay/LineDrawer.java
  9. +81 −72 osmdroid-android/src/main/java/org/osmdroid/views/overlay/LinearRing.java
  10. +0 −272 osmdroid-android/src/main/java/org/osmdroid/views/overlay/PathOverlay.java
  11. +163 −4 osmdroid-android/src/main/java/org/osmdroid/views/overlay/PolyOverlayWithIW.java
  12. +6 −28 osmdroid-android/src/main/java/org/osmdroid/views/overlay/Polygon.java
  13. +4 −38 osmdroid-android/src/main/java/org/osmdroid/views/overlay/Polyline.java
  14. +13 −3 osmdroid-android/src/main/java/org/osmdroid/views/overlay/milestones/MilestoneLineDisplayer.java
  15. +10 −10 osmdroid-android/src/test/java/org/osmdroid/util/BoundBoxTest.java
  16. +1 −1 osmdroid-geopackage/src/main/java/org/osmdroid/gpkg/overlay/OsmMapShapeConverter.java
  17. +2 −6 osmdroid-shape/src/main/java/org/osmdroid/shape/ShapeConverter.java
@@ -1,7 +1,6 @@
package org.osmdroid.samplefragments.data;

import org.osmdroid.R;
import org.osmdroid.api.IGeoPoint;
import org.osmdroid.events.MapListener;
import org.osmdroid.events.ScrollEvent;
import org.osmdroid.events.ZoomEvent;
@@ -10,7 +9,6 @@
import org.osmdroid.tileprovider.tilesource.OnlineTileSourceBase;
import org.osmdroid.tileprovider.tilesource.XYTileSource;
import org.osmdroid.views.overlay.ItemizedIconOverlay;
import org.osmdroid.views.overlay.PathOverlay;
import org.osmdroid.views.overlay.infowindow.BasicInfoWindow;
import org.osmdroid.views.overlay.Marker;
import org.osmdroid.views.overlay.Polygon;
@@ -20,8 +18,6 @@

import android.app.Activity;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.os.Bundle;
import android.util.Log;

@@ -40,14 +36,9 @@
public static final String TITLE = "OsmPath drawing";

private BoundingBox sCentralParkBoundingBox;
private Paint sPaint;

public SampleOsmPath() {
sCentralParkBoundingBox = new BoundingBox(40.796788, -73.949232, 40.768094, -73.981762);

sPaint = new Paint();
sPaint.setColor(Color.argb(175, 255, 0, 0));
sPaint.setStyle(Style.FILL);
}
@Override
public String getSampleTitle() {
@@ -57,8 +48,8 @@ public String getSampleTitle() {
@Override
public void onActivityCreated(Bundle savedInstanceState) {

mMapView.getController().setZoom(13);
mMapView.getController().setCenter(sCentralParkBoundingBox.getCenter());
mMapView.getController().setZoom(13.);
mMapView.getController().setCenter(sCentralParkBoundingBox.getCenterWithDateLine());

super.onActivityCreated(savedInstanceState);
}
@@ -70,14 +61,12 @@ protected void addOverlays() {
//we override this to force zoom to 22, even though mapnik dooesn't do that deep
OnlineTileSourceBase mapnik = new XYTileSource("Mapnik",
0, 22, 256, ".png", new String[] {
"http://a.tile.openstreetmap.org/",
"http://b.tile.openstreetmap.org/",
"http://c.tile.openstreetmap.org/" });
"https://a.tile.openstreetmap.org/",
"https://b.tile.openstreetmap.org/",
"https://c.tile.openstreetmap.org/" });
mMapView.getTileProvider().setTileSource(mapnik);


//mOsmPathOverlay = new OsmPathOverlay(context);
//mMapView.getOverlayManager().add(mOsmPathOverlay);
Polyline line = new Polyline(mMapView);
line.setTitle("Central Park, NYC");
line.setSubDescription(Polyline.class.getCanonicalName());
@@ -163,7 +152,7 @@ public boolean onClick(Polyline polyline, MapView mapView, GeoPoint eventPos) {

List<MyMapItem> list = new ArrayList<>();
list.add(new MyMapItem("title","description", new GeoPoint(51.7875, 6.135278)));
ItemizedIconOverlay<MyMapItem> layer = new ItemizedIconOverlay<MyMapItem>(list, getResources().getDrawable(R.drawable.shgpuci), new ItemizedIconOverlay.OnItemGestureListener<MyMapItem>() {
ItemizedIconOverlay<MyMapItem> layer = new ItemizedIconOverlay<>(list, getResources().getDrawable(R.drawable.shgpuci), new ItemizedIconOverlay.OnItemGestureListener<MyMapItem>() {
@Override
public boolean onItemSingleTapUp(int index, MyMapItem item) {
return false;
@@ -175,21 +164,8 @@ public boolean onItemLongPress(int index, MyMapItem item) {
}
}, getActivity());

PathOverlay path = new PathOverlay(Color.RED, 200f);

List<IGeoPoint> pathpoints = new ArrayList<>();


pathpoints.add(new GeoPoint(50.7865, 6.135278));
pathpoints.add(new GeoPoint(50.7865, 6.135288));
pathpoints.add(new GeoPoint(51.7864, 6.235288));
pathpoints.add(new GeoPoint(51.7864, 6.235288));
pathpoints.add(new GeoPoint(51.7865, 6.235278));

path.addPoints(pathpoints);
mMapView.getOverlayManager().add(path);
mMapView.getOverlayManager().add(layer);
mMapView.setMapListener(this);
mMapView.addMapListener(this);

}

@@ -1,6 +1,6 @@
package org.osmdroid.samplefragments.data;

import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
@@ -18,8 +18,8 @@
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.util.BoundingBox;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.overlay.FolderOverlay;
import org.osmdroid.views.overlay.Overlay;
import org.osmdroid.views.overlay.PolyOverlayWithIW;
import org.osmdroid.views.overlay.Polygon;

import java.io.File;
@@ -114,6 +114,17 @@ public void onSelectedFilePaths(String[] files) {
//files is the array of the paths of files selected by the Application User.
try {
List<Overlay> folder = ShapeConverter.convert(mMapView, new File(files[0]));
for (final Overlay item : folder) {
if (item instanceof PolyOverlayWithIW) {
final PolyOverlayWithIW poly = (PolyOverlayWithIW)item;
poly.setDowngradeMaximumPixelSize(20);
poly.setDowngradeDisplay(true);
final Paint paint = poly.getOutlinePaint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
}
}
mMapView.getOverlayManager().addAll(folder);
mMapView.invalidate();
} catch (Exception e) {
@@ -13,7 +13,6 @@
import android.view.View;
import android.widget.Toast;

import org.osmdroid.util.BoundingBox;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.Projection;
@@ -49,12 +48,11 @@ public void setMode(Mode mode) {
PolylineAsPath
}
protected boolean withArrows=false;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private MapView map;
private List<Point> pts = new ArrayList<>();
private Paint mPaint;
private final Paint mPaint;
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;

@@ -64,30 +62,27 @@ public void setMode(Mode mode) {
public CustomPaintingSurface(Context context, AttributeSet attrs) {
super(context,attrs);
mPath = new Path();
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFFFF0000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);
}


@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
final Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(bitmap);
}


@Override
protected void onDraw(Canvas canvas) {

mCanvas = new Canvas(mBitmap);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFFFF0000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(12);

canvas.drawPath(mPath, mPaint);
}
public void init(MapView mapView) {
@@ -169,7 +164,7 @@ public boolean onClick(Polyline polyline, MapView mapView, GeoPoint eventPos) {
));
line.setMilestoneManagers(managers);
}
line.setSubDescription(BoundingBox.fromGeoPoints(line.getPoints()).toString());
line.setSubDescription(line.getBounds().toString());
map.getOverlayManager().add(line);
lastPolygon=null;
break;
@@ -195,7 +190,7 @@ public boolean onClick(Polyline polyline, MapView mapView, GeoPoint eventPos) {
public boolean onClick(Polygon polygon, MapView mapView, GeoPoint eventPos) {
lastPolygon = polygon;
polygon.onClickDefault(polygon, mapView, eventPos);
Toast.makeText(mapView.getContext(), "polygon with " + polygon.getPoints().size() + "pts was tapped", Toast.LENGTH_LONG).show();
Toast.makeText(mapView.getContext(), "polygon with " + polygon.getActualPoints().size() + "pts was tapped", Toast.LENGTH_LONG).show();
return false;
}
});
@@ -2,6 +2,9 @@

import android.util.Log;

import java.util.HashMap;
import java.util.Map;

/**
* The counters class is a simple container for tracking various internal statistics for osmdroid,
* useful for troubleshooting osmdroid, finding memory leaks and more
@@ -23,6 +26,11 @@
public static int fileCacheOOM=0;
public static int fileCacheHit=0;

/**
* @since 6.2.0
*/
private static final Map<String, Integer> sMap = new HashMap<>();

public static void printToLogcat() {
Log.d(TAG, "countOOM " + countOOM);
Log.d(TAG, "tileDownloadErrors " + tileDownloadErrors);
@@ -39,4 +47,35 @@ public static void reset(){
fileCacheOOM=0;
fileCacheHit=0;
}

/**
* @since 6.2.0
*/
public static void reset(final String pTag) {
sMap.remove(pTag);
}

/**
* @since 6.2.0
*/
public static void increment(final String pTag) {
final Integer value = sMap.get(pTag);
if (value == null) {
sMap.put(pTag, 1);
} else {
sMap.put(pTag, value + 1);
}
}

/**
* @since 6.2.0
*/
public static int get(final String pTag) {
final Integer value = sMap.get(pTag);
if (value == null) {
return 0;
} else {
return value;
}
}
}
@@ -58,7 +58,9 @@
/**
* @since 6.0.2
* Used to be in the `TileSystem` class of another package
* @deprecated Just don't use it anymore
*/
@Deprecated
public static final int projectionZoomLevel = primaryKeyMaxZoomLevel + 1;

/**
@@ -32,11 +32,12 @@
public class Projection implements IProjection {

/**
* Size of the "projected" map: a virtual map with the largest zoom level
* WARNING: `mProjectedMapSize` MUST NOT be a static member,
* as it depends on {@link TileSystem#getTileSize()}
* The size in pixels of a VERY large map, the "projected" map.
* For optimization purpose, we may compute only once the projection of the GeoPoints
* on this large map, and then just divide in order to get the projection on a corresponding
* smaller map / smaller zoom
*/
public final double mProjectedMapSize = TileSystem.MapSize((double)TileSystem.projectionZoomLevel);
public static final double mProjectedMapSize = 1L << 60;
private long mOffsetX;
private long mOffsetY;
private long mScrollX;
@@ -444,8 +445,7 @@ public Matrix getScaleRotateCanvasMatrix() {
* @since 6.0.0
*/
public double getProjectedPowerDifference() {
final double zoomDifference = TileSystem.projectionZoomLevel - getZoomLevel();
return TileSystem.getFactor(zoomDifference);
return mProjectedMapSize / getWorldMapSize();
}

/**
@@ -860,4 +860,11 @@ public int getWidth() {
public int getHeight() {
return mIntrinsicScreenRectProjection.height();
}

/**
* @since 6.2.0
*/
public double getWorldMapSize() {
return mMercatorMapSize;
}
}
@@ -180,7 +180,8 @@ private void onDrawHelper(final Canvas c, final MapView pMapView, final Projecti
if (pMapView.getBoundingBox().overlaps(overlay.getBounds(), pMapView.getZoomLevelDouble()))
overlay.draw(c, pMapView, false);
} else {
overlay.draw(c, pProjection);
if (pProjection.getBoundingBox().overlaps(overlay.getBounds(), pProjection.getZoomLevel()))
overlay.draw(c, pProjection);
}
}
}
@@ -40,23 +40,29 @@ public void setIntegerAccepter(final IntegerAccepter pIntegerAccepter) {

@Override
public void flush() {
if(getSize() < 4) {
final int nbSegments = getSize() / 4;
if(nbSegments == 0) {
additionalFlush();
return;
}
final float[] lines = getLines();
final Paint paint = mPaintList.getPaint();
if (paint != null) { // monochromatic: that's enough
mCanvas.drawLines(lines, 0, getSize(), paint);
final int size = compact(lines, nbSegments * 4);
if (size > 0) {
mCanvas.drawLines(lines, 0, size, paint);
}
additionalFlush();
return;
}
final int size = getSize();
for (int i = 0; i < size ; i += 4) {
for (int i = 0; i < nbSegments * 4 ; i += 4) {
final float x0 = lines[i];
final float y0 = lines[i + 1];
final float x1 = lines[i + 2];
final float y1 = lines[i + 3];
if (x0 == x1 && y0 == y1) {
continue;
}
final int segmentIndex = mIntegerAccepter.getValue(i / 2);
mCanvas.drawLine(x0, y0, x1, y1, mPaintList.getPaint(segmentIndex, x0, y0, x1, y1));
}
@@ -68,4 +74,30 @@ private void additionalFlush() {
mIntegerAccepter.flush();
}
}

/**
* @since 6.2.0
* Compact a float[] containing (x0,y0,x1,y1) segment coordinate quadruplets
* by removing the single point cases (x0 == x1 && y0 == y1)
* @param pLines the input AND output array
* @param pSize the initial number of coordinates
* @return the number of relevant coordinates
*/
private static int compact(final float[] pLines, final int pSize) {
int dstIndex = 0;
for (int srcIndex = 0; srcIndex < pSize ; srcIndex += 4) {
final float x0 = pLines[srcIndex];
final float y0 = pLines[srcIndex + 1];
final float x1 = pLines[srcIndex + 2];
final float y1 = pLines[srcIndex + 3];
if (x0 == x1 && y0 == y1) {
continue;
}
if (srcIndex != dstIndex) {
System.arraycopy(pLines, srcIndex, pLines, dstIndex, 4);
}
dstIndex += 4;
}
return dstIndex;
}
}

0 comments on commit fc18077

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