在osmdroid奖金包中绘制多边形网格

时间:2016-01-20 18:16:44

标签: android osmdroid offlineapps maping

我搜索了所有网络,但我找不到问题的答案。我正在使用osmdroid,我想在图像中显示多边形网格。我在stackoverflow中发现了一个类似的question,但这个问题没有答案。那么请告诉我可能吗?

enter image description here

3 个答案:

答案 0 :(得分:1)

@Mker提出了一个很好的开始:BitmapShader

以下是示例代码:

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);
    }
}

用法:

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();

但是如果你试图移动多边形,你可能会感到困惑 - 位图不想移动:

description

要避免这种情况,您应该计算着色器的偏移量:

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);
    }
}

结果:

enter image description here

Full source code

答案 1 :(得分:0)

是的,这是可能的。

有一些潜在的解决方案。 1)假设有人做得足以制作满足您需求的kml文件,可以使用osmbonuspack直接导入kml文件。

2)以编程方式自己创建。所以你有一些任务。

a)将多边形作为叠加层 b)将网格作为叠加层 c)按顺序将它们添加到地图视图中。这应该使网格位于多边形的顶部。

现在谈谈细节。制作多边形是微不足道的,所以不要在这里覆盖它。

使网格也不太难。您需要知道网格的边界,然后从北边界到南边界以一定间隔放置东,西边界线。然后在南北线做相反的事情。在日期线,赤道和两极都有特殊情况,所以请记住这一点。

在这种情况下计算行间隔有点简单,您可以通过两种方式解决它。使用十进制度的固定间隔或根据缩放级别计算。后面的部分更难,但通常会提供更好的可视化效果(当您放大时,网格重绘并在该缩放级别看起来更合适)。

重要提示,使用osmbonuspack和osmdroid,如果给出超出视图边界的覆盖线(如果硬件加速关闭),则可能会遇到内存不足错误。如果启用了硬件加速,则如果起点和终点都在屏幕外一定的余量,则可能根本不显示线条。长话短说,对于相对较小的距离,你应该没问题,否则,你必须在地图平移和缩放的视图边界处剪辑。

我用osmbonuspack做了类似的事情来显示lat / lon网格线,当你放大和平移时调整它们(意味着间隔根据缩放级别调整)。如果这是一项要求,那么您可能只需重复使用代码,该代码主要计算绘制网格每一行的距离和位置。

答案 2 :(得分:0)

现在,如果你只想将网格绘制为一个模式(没有关于网格线位置的约束),那么使用“着色器”应该有一个简单的替代方法:

fillPaint.setShader(patternBMPshader);

完整示例:http://code.tutsplus.com/tutorials/android-sdk-drawing-with-pattern-fills--mobile-19527

坏消息,没有Polygon填充漆的吸气剂。好消息是,属性受到保护,而不是私有。 所以你可以继承Polygon,并添加getter:

Paint getFillPaint(){
  return mFillPaint;
}