简体   繁体   中英

Draw grid over polygon in osmdroid bonus pack

I have searched all internet but I don't find answer to my problem .I'm using osmdroid and I want to add grid over polygon as shown in image. I found one similar question in stackoverflow but this question doesn't have answer. So please tell me is that possible?

在此处输入图片说明

@Mker gave a good point to start: BitmapShader .

Here is a sample code:

public class GridPolygon extends Polygon {

    private BitmapShader bitmapShader;

    public GridPolygon(Context ctx) {
        super(ctx);
    }

    public void setPatternBMP(@NonNull final Bitmap patternBMP) {
        bitmapShader = new BitmapShader(patternBMP, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        mFillPaint.setShader(bitmapShader);
    }
}

Usage:

final GridPolygon polygon = new GridPolygon(context);
polygon.setPoints(geoData);
polygon.setFillColor(fillColor);
polygon.setStrokeColor(strokeColor);
polygon.setStrokeWidth(strokeWidth);
polygon.setPatternBMP(BitmapFactory.decodeResource(getResources(), R.drawable.pattern));
map.getOverlays().add(polygon);
map.invalidate();

But you might be confused if you tried to move the polygon - the bitmap doesn't want to move:

描述

To avoid this you should calculate the offset for your shader:

public class GridPolygon extends Polygon {

    private BitmapShader bitmapShader;
    private IGeoPoint lastCenterGeoPoint;
    private int xOffset = 0;
    private int yOffset = 0;

    public GridPolygon(Context ctx) {
        super(ctx);
    }

    public void setPatternBMP(@NonNull final Bitmap patternBMP) {
        bitmapShader = new BitmapShader(patternBMP, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        mFillPaint.setShader(bitmapShader);
    }

    protected void recalculateMatrix(@NonNull final MapView mapView) {
        //final int mapSize = TileSystem.MapSize(mapView.getZoomLevel());

        final Projection projection = mapView.getProjection();
        final IGeoPoint geoPoint = mapView.getMapCenter();
        if (lastCenterGeoPoint == null) lastCenterGeoPoint = geoPoint;

        final Point point = projection.toPixels(geoPoint, null);
        final Point lastCenterPoint = projection.toPixels(lastCenterGeoPoint, null);

        xOffset += lastCenterPoint.x - point.x;
        yOffset += lastCenterPoint.y - point.y;

        xOffset %= 100; // 100 is pixel size of shader image
        yOffset %= 100;

        final Matrix matrix = new Matrix();
        matrix.reset();
        matrix.setScale(1,1);
        matrix.preTranslate(xOffset, yOffset);
        //matrix.setTranslate(xOffset, yOffset);
        bitmapShader.setLocalMatrix(matrix);

        mFillPaint.setShader(bitmapShader);

        lastCenterGeoPoint = geoPoint;
    }

    @Override
    protected void draw(Canvas canvas, MapView mapView, boolean shadow) {
        recalculateMatrix(mapView);
        super.draw(canvas, mapView, shadow);
    }
}

Result:

在此处输入图片说明

Full source code .

Yes it's possible.

There's a few potential solutions. 1) Assuming someone was nice enough to make a kml file that meets your needs, the kml file can be directly imported using osmbonuspack.

2) Make it yourself programatically. So you have a few tasks.

a) Make the polygon as an overlay b) Make the grid as an overlay c) Add them to the map view in that order. This should make the grid be on top of the polygon.

Now on to the details. Making the polygon is trivial so won't cover this here.

Making the grid isn't too hard either. You need to know the bounds of the grid, then place lines from the east, west bounds at some interval from the north bounds to the south bounds. Then do the opposite for north south lines. There's special cases at the date line, equator, and poles so keep that in mind.

Calculating the line interval in this case is somewhat simple and you can tackle it two ways. Use a fixed interval in degrees decimal or calculate based on zoom level. The later part is harder but generally gives a better visualization (when you zoom in, the grid redraws and looks more appropriate at that zoom level).

Important note, with osmbonuspack and osmdroid, you may run into out of memory errors if you give the overlay lines that are way outside of the bounds of the view (if hardware acceleration is off). If hardware acceleration is on, then lines may not show at all if both the start and end points are off screen by a certain margin. Long story short, for relatively small distances, you should be fine, otherwise, you have to clip at the view bounds on map panning and zooming.

I've done similar things with osmbonuspack for displaying lat/lon grid lines that adjust as you zoom in and pan (meaning the interval adjusts based on on zoom level). If that's a requirement, then you might be able to just reuse the code, which essentially calculates about how far away and where to draw each line of the grid.

Now, if you just want to draw the grid as a pattern (no constraint about grid lines positions), there should be a simple alternative by using a "shader":

fillPaint.setShader(patternBMPshader);

Full example: http://code.tutsplus.com/tutorials/android-sdk-drawing-with-pattern-fills--mobile-19527

Bad news, there is no getter of the Polygon fill paint. Good news, the attribute is protected, not private. So you can subclass Polygon, and add the getter:

Paint getFillPaint(){
  return mFillPaint;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM