代码之家  ›  专栏  ›  技术社区  ›  David

在osmdroid奖励包中的多边形上绘制网格

  •  1
  • David  · 技术社区  · 8 年前

    我已经搜索了所有的互联网,但我没有找到问题的答案。我正在使用 osmdroid 我想在多边形上添加网格,如图所示。我发现了一个类似的 question 但这个问题没有答案。所以请告诉我这可能吗?

    enter image description here

    3 回复  |  直到 7 年前
        1
  •  3
  •   Mikalai Daronin    8 年前

    @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 .

        2
  •  0
  •   spy    8 年前

    是的,这是可能的。

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

    2) 通过编程自己制作。所以你有一些任务。

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

    现在来看细节。制作多边形很简单,所以这里不再赘述。

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

    在这种情况下,计算线间隔有些简单,您可以用两种方法来处理。使用固定的十进制度数间隔或基于缩放级别进行计算。后面的部分更难,但通常会提供更好的可视化效果(放大时,网格会重新绘制,在该缩放级别看起来更合适)。

    重要的是,使用osmbonuspack和osmdroid,如果给出的覆盖线超出了视图的边界(如果硬件加速关闭),则可能会出现内存不足的错误。如果硬件加速打开,那么如果起点和终点都偏离屏幕一定的距离,则可能根本不会显示线条。长话短说,对于相对较小的距离,你应该很好,否则,你必须在地图平移和缩放的视图边界处进行剪辑。

    我用osmbonuspack做了类似的事情,用于显示随着放大和平移而调整的横向/纵向网格线(这意味着间隔根据缩放级别进行调整)。如果这是一个需求,那么您可能只需要重用代码,它基本上计算出网格的每一条线的距离和位置。

        3
  •  0
  •   MKer    8 年前

    现在,如果您只想将栅格绘制为图案(没有关于栅格线位置的约束),应该有一个简单的替代方法,即使用“着色器”:

    fillPaint.setShader(patternBMPshader);
    

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

    坏消息是,没有多边形填充颜料的吸气剂。好消息是,属性是受保护的,不是私有的。 因此,您可以将Polygon子类化,并添加getter:

    Paint getFillPaint(){
      return mFillPaint;
    }