在 osmdroid 奖励包中在多边形上绘制网格
Draw grid over polygon in osmdroid bonus pack
我搜索了所有互联网,但没有找到问题的答案。我正在使用 osmdroid
,我想在多边形上添加网格,如图所示。我在 Whosebug 中找到了一个类似的 question 但这个问题没有答案。所以请告诉我这可能吗?
是的,这是可能的。
有一些可能的解决方案。
1) 假设有人好心制作了满足您需求的kml文件,可以直接使用osmbonuspack导入kml文件。
2) 以编程方式自行制作。所以你有几个任务。
a) 将多边形作为叠加层
b) 将网格作为叠加层
c) 按顺序将它们添加到地图视图中。这应该使网格位于多边形之上。
现在进入细节。制作多边形很简单,所以不会在这里介绍。
制作网格也不难。您需要知道网格的边界,然后在从北边界到南边界的某个间隔处放置来自东、西边界的线。然后对南北线做相反的事情。日期变更线、赤道和两极都有特殊情况,请记住这一点。
在这种情况下计算行间隔比较简单,您可以通过两种方式解决。使用以十进制度为单位的固定间隔或根据缩放级别进行计算。后面的部分更难,但通常会提供更好的可视化效果(当您放大时,网格会重新绘制并在该缩放级别看起来更合适)。
重要说明,对于 osmbonuspack 和 osmdroid,如果您提供的覆盖线超出视图范围(如果关闭硬件加速),您可能 运行 出现内存不足错误。如果启用了硬件加速,则如果起点和终点都离开屏幕一定距离,则线条可能根本不会显示。长话短说,对于相对较小的距离,你应该没问题,否则,你必须在地图平移和缩放时在视图边界处进行裁剪。
我用 osmbonuspack 做了类似的事情来显示 lat/lon 网格线,这些网格线会在您放大和平移时进行调整(这意味着间隔会根据缩放级别进行调整)。如果这是一项要求,那么您也许可以重用代码,该代码主要计算绘制网格的每条线的距离和位置。
现在,如果您只想将网格绘制为图案(对网格线位置没有限制),应该有一个简单的替代方法,使用 "shader":
fillPaint.setShader(patternBMPshader);
完整示例:http://code.tutsplus.com/tutorials/android-sdk-drawing-with-pattern-fills--mobile-19527
坏消息,没有 getter 的多边形填充涂料。好消息,该属性是受保护的,而不是私有的。
所以你可以子类化多边形,并添加 getter:
Paint getFillPaint(){
return mFillPaint;
}
@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();
但是如果您尝试移动多边形,您可能会感到困惑 - 位图不想移动:
为避免这种情况,您应该计算着色器的偏移量:
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);
}
}
结果:
我搜索了所有互联网,但没有找到问题的答案。我正在使用 osmdroid
,我想在多边形上添加网格,如图所示。我在 Whosebug 中找到了一个类似的 question 但这个问题没有答案。所以请告诉我这可能吗?
是的,这是可能的。
有一些可能的解决方案。 1) 假设有人好心制作了满足您需求的kml文件,可以直接使用osmbonuspack导入kml文件。
2) 以编程方式自行制作。所以你有几个任务。
a) 将多边形作为叠加层 b) 将网格作为叠加层 c) 按顺序将它们添加到地图视图中。这应该使网格位于多边形之上。
现在进入细节。制作多边形很简单,所以不会在这里介绍。
制作网格也不难。您需要知道网格的边界,然后在从北边界到南边界的某个间隔处放置来自东、西边界的线。然后对南北线做相反的事情。日期变更线、赤道和两极都有特殊情况,请记住这一点。
在这种情况下计算行间隔比较简单,您可以通过两种方式解决。使用以十进制度为单位的固定间隔或根据缩放级别进行计算。后面的部分更难,但通常会提供更好的可视化效果(当您放大时,网格会重新绘制并在该缩放级别看起来更合适)。
重要说明,对于 osmbonuspack 和 osmdroid,如果您提供的覆盖线超出视图范围(如果关闭硬件加速),您可能 运行 出现内存不足错误。如果启用了硬件加速,则如果起点和终点都离开屏幕一定距离,则线条可能根本不会显示。长话短说,对于相对较小的距离,你应该没问题,否则,你必须在地图平移和缩放时在视图边界处进行裁剪。
我用 osmbonuspack 做了类似的事情来显示 lat/lon 网格线,这些网格线会在您放大和平移时进行调整(这意味着间隔会根据缩放级别进行调整)。如果这是一项要求,那么您也许可以重用代码,该代码主要计算绘制网格的每条线的距离和位置。
现在,如果您只想将网格绘制为图案(对网格线位置没有限制),应该有一个简单的替代方法,使用 "shader":
fillPaint.setShader(patternBMPshader);
完整示例:http://code.tutsplus.com/tutorials/android-sdk-drawing-with-pattern-fills--mobile-19527
坏消息,没有 getter 的多边形填充涂料。好消息,该属性是受保护的,而不是私有的。 所以你可以子类化多边形,并添加 getter:
Paint getFillPaint(){
return mFillPaint;
}
@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();
但是如果您尝试移动多边形,您可能会感到困惑 - 位图不想移动:
为避免这种情况,您应该计算着色器的偏移量:
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);
}
}
结果: