- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我目前正在玩 TileProver
在 Android Maps API v2 中遇到以下问题:我手动绘制到位图中的图形在较高的缩放级别上会明显倾斜:
让我解释一下我在这里做什么。我有多个 LatLng 点,我为 map 上的每个点画了一个圆圈,所以当你放大时 - 点保持在相同的地理位置。正如您在屏幕截图中看到的那样,圆圈在较低的缩放级别上看起来很好,但是当您开始放大时 - 圆圈会发生倾斜。
它是这样实现的:
package trickyandroid.com.locationtracking;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.Log;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Tile;
import com.google.android.gms.maps.model.TileProvider;
import com.google.maps.android.geometry.Point;
import com.google.maps.android.projection.SphericalMercatorProjection;
import java.io.ByteArrayOutputStream;
/**
* Created by paveld on 8/8/14.
*/
public class CustomTileProvider implements TileProvider {
private final int TILE_SIZE = 256;
private int density = 1;
private int tileSizeScaled;
private Paint circlePaint;
private SphericalMercatorProjection projection;
private Point[] points;
public CustomTileProvider(Context context) {
density = 3; //hardcoded for now, but should be driven by DisplayMetrics.density
tileSizeScaled = TILE_SIZE * density;
projection = new SphericalMercatorProjection(TILE_SIZE);
points = generatePoints();
circlePaint = new Paint();
circlePaint.setAntiAlias(true);
circlePaint.setColor(0xFF000000);
circlePaint.setStyle(Paint.Style.FILL);
}
private Point[] generatePoints() {
Point[] points = new Point[6];
points[0] = projection.toPoint(new LatLng(47.603861, -122.333393));
points[1] = projection.toPoint(new LatLng(47.600389, -122.326741));
points[2] = projection.toPoint(new LatLng(47.598942, -122.318973));
points[3] = projection.toPoint(new LatLng(47.599000, -122.311549));
points[4] = projection.toPoint(new LatLng(47.601373, -122.301721));
points[5] = projection.toPoint(new LatLng(47.609764, -122.311850));
return points;
}
@Override
public Tile getTile(int x, int y, int zoom) {
Bitmap bitmap = Bitmap.createBitmap(tileSizeScaled, tileSizeScaled, Bitmap.Config.ARGB_8888);
float scale = (float) (Math.pow(2, zoom) * density);
Matrix m = new Matrix();
m.setScale(scale, scale);
m.postTranslate(-x * tileSizeScaled, -y * tileSizeScaled);
Canvas c = new Canvas(bitmap);
c.setMatrix(m);
for (Point p : points) {
c.drawCircle((float) p.x, (float) p.y, 20 / scale, circlePaint);
}
return bitmapToTile(bitmap);
}
private Tile bitmapToTile(Bitmap bmp) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] bitmapdata = stream.toByteArray();
return new Tile(tileSizeScaled, tileSizeScaled, bitmapdata);
}
}
逻辑告诉我发生这种情况是因为我只将 LatLng 转换为 1 个图 block (256x256,即缩放级别 0)的屏幕位置,然后为了将此屏幕点转换为其他缩放级别,我需要缩放我的位图并将其转换到适当的位置。同时,由于位图被缩放,我需要补偿圆半径,所以我用比例因子除以半径。所以在缩放级别 19 我的比例因子已经是 1572864 这是巨大的。就像用巨大的放大镜看这个圆圈。这就是为什么我有这种效果。
所以我认为解决方案是避免位图缩放并仅缩放/转换屏幕坐标。在这种情况下,我的圆半径将始终相同并且不会缩小。
不幸的是,矩阵数学不是我最强的技能,所以我的问题是 - 如何缩放/转换任意缩放级别的点集,并为缩放级别“0”计算点集?
最简单的方法是为每个缩放级别设置不同的 Projection 实例,但由于 GeoPoint -> ScreenPoint 转换是非常昂贵的操作,我会保留这种方法作为备份并使用一些简单的数学来转换已经存在的屏幕点。
注意请注意,我需要专门自定义 TileProvider
,因为在应用程序中我将绘制比圆圈更复杂的图 block 。如此简单的 Marker
类在这里对我不起作用
更新尽管我想出了如何平移单个点并避免位图缩放:
c.drawCircle((float) p.x * scale - (x * tileSizeScaled), (float) p.y * scale - (y * tileSizeScaled), 20, circlePaint);
我仍然不知道如何使用 Path
对象执行此操作。我不能像你对单个点那样转换/缩放路径,所以我仍然必须缩放我的位图,这会再次导致绘图伪影(笔画宽度在更高的缩放级别上倾斜):
这是一个代码 fragment :
package trickyandroid.com.locationtracking;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Tile;
import com.google.android.gms.maps.model.TileProvider;
import com.google.maps.android.geometry.Point;
import com.google.maps.android.projection.SphericalMercatorProjection;
import java.io.ByteArrayOutputStream;
/**
* Created by paveld on 8/8/14.
*/
public class CustomTileProvider implements TileProvider {
private final int TILE_SIZE = 256;
private int density = 1;
private int tileSizeScaled;
private SphericalMercatorProjection projection;
private Point[] points;
private Path path;
private Paint pathPaint;
public CustomTileProvider(Context context) {
density = 3; //hardcoded for now, but should be driven by DisplayMetrics.density
tileSizeScaled = TILE_SIZE * density;
projection = new SphericalMercatorProjection(TILE_SIZE);
points = generatePoints();
path = generatePath(points);
pathPaint = new Paint();
pathPaint.setAntiAlias(true);
pathPaint.setColor(0xFF000000);
pathPaint.setStyle(Paint.Style.STROKE);
pathPaint.setStrokeCap(Paint.Cap.ROUND);
pathPaint.setStrokeJoin(Paint.Join.ROUND);
}
private Path generatePath(Point[] points) {
Path path = new Path();
path.moveTo((float) points[0].x, (float) points[0].y);
for (int i = 1; i < points.length; i++) {
path.lineTo((float) points[i].x, (float) points[i].y);
}
return path;
}
private Point[] generatePoints() {
Point[] points = new Point[10];
points[0] = projection.toPoint(new LatLng(47.603861, -122.333393));
points[1] = projection.toPoint(new LatLng(47.600389, -122.326741));
points[2] = projection.toPoint(new LatLng(47.598942, -122.318973));
points[3] = projection.toPoint(new LatLng(47.599000, -122.311549));
points[4] = projection.toPoint(new LatLng(47.601373, -122.301721));
points[5] = projection.toPoint(new LatLng(47.609764, -122.311850));
points[6] = projection.toPoint(new LatLng(47.599221, -122.311531));
points[7] = projection.toPoint(new LatLng(47.599663, -122.312410));
points[8] = projection.toPoint(new LatLng(47.598823, -122.312614));
points[9] = projection.toPoint(new LatLng(47.599959, -122.310651));
return points;
}
@Override
public Tile getTile(int x, int y, int zoom) {
Bitmap bitmap = Bitmap.createBitmap(tileSizeScaled, tileSizeScaled, Bitmap.Config.ARGB_8888);
float scale = (float) (Math.pow(2, zoom) * density);
Canvas c = new Canvas(bitmap);
Matrix m = new Matrix();
m.setScale(scale, scale);
m.postTranslate(-x * tileSizeScaled, -y * tileSizeScaled);
c.setMatrix(m);
pathPaint.setStrokeWidth(6 * density / scale);
c.drawPath(path, pathPaint);
return bitmapToTile(bitmap);
}
private Tile bitmapToTile(Bitmap bmp) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] bitmapdata = stream.toByteArray();
return new Tile(tileSizeScaled, tileSizeScaled, bitmapdata);
}
}
最佳答案
我看到您正在使用 google 的 tileview,您可以尝试考虑 mogarius 的库,它是一个
在 github 上开源的库
我以前从未尝试过,但它开箱即用地支持你需要的大部分功能(标记\点
和动态路径绘制),这样可以节省你制作
的时间用于放大和缩小的矩阵计算。
还有一个演示video对于他所做的一些用法,以及很棒的 javadoc他出版了。
关于android - TileProvider 图形在更高的缩放级别上倾斜,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25251831/
我有一个 DIV #page,如果我在顶部添加边距,突然出现一个滚动条,即使该元素不大于主体。我怎样才能去掉滚动条? (参见 Fiddle) 我的 HTML I am a div siz
function getClosestValue(standardArray, targetVal) { standardArray = standardArray.sort(function(a,
我有 318x424 的书籍封面图片,我想做的是指定一张图片,并在其下方添加一个文本链接。初始 src 是 about:blank,这样如果响应式设计不显示框架,它就不会占用用户带宽。 框架的 HTM
我被这个问题困了两天了,还是没搞定。 基本上,我有一个二维数组,其中包含某些数字(在给定范围内)之间的关系: 0 = 顺序无关紧要 1 = 第一个数字(左栏中的数字)应该是第一个 2 = 第二个数字(
只有当我在更高的 API 上进行调试时,我才会强制关闭脚本:16,但是当涉及到 API 时它工作正常:10。这可能是我的项目设置问题吗? 这是对服务器的简单请求,以获取 fragment 中的类别列表
给定下表books id | listorder ----+----------- 3 | 1 2 | 2 1 | 3 4 |
我想要那个密码切换功能,好像TextInputLayout有这个功能,而不是 TextInputEditText .但是正如您在下面的代码中看到的,即使我将高度设置为 wrap_content和 ap
似乎从 读取给出空列表,它主要发生在延迟较高的网络上的主机上。是否有更强大的与远程主机交互的方式? use Net::SSH2; # my $ssh = Net::SSH2->new(); # ..
为了在 Play 商店中发布我的应用程序,我必须将 TargetSdkVersion 从 23 更改为 26。在我更改它之前,该应用程序运行良好!现在应用程序在启动时崩溃。我想通了,问题出在这两行:
我尝试了很多解决方案,但找不到一个。我有 3 个不同的列,其中包含不同类型的文本,我需要它们具有相同的高度。但它们是这样不同的:colums有人可以帮忙吗? 代码: .col-sm-2{
我尝试将一个 div 相对于其具有负顶值的父级定位。这工作正常,现在的问题是这个 div,即使它有一个负的 top 值也会使父 div 更大。 我该怎么做才能让父 div 不那么大? Here's a
这是一个一般性问题,可能适用于任何给定的语言,如 C、C++、Java 等。 我认为无论以何种方式实现它,都不会比使用 2 个循环更高效,后者的效率为 n^2。 for(i=0;i O(1) ),要么
我需要查找所有有订单的家庭。我根本不关心订单的数据,只关心它的存在。 (使用 SQL Server) 这样说是不是更有效率: SELECT HouseholdID, LastName, FirstNa
我有一个 UINavigationController,在屏幕顶部有一个 UINavigationBar,在底部有一个 UIToolbar。我想让工具栏高一点。这是我的代码: CGRect toolb
我正在使用自定义字体。该字体在我的 Windows PC 上完美运行,但在我的 Mac (Yosemite OSX) 上运行不佳。正如您在图片中看到的,Mac 上的字体比 Windows 上的字体稍大
我正在尝试使用 FaSTLane 将我的应用程序作为 alpha 版本部署到 Play 商店,但出现此错误: Google Api 错误:multiApkShadowedActiveApk:任何设备都
我在这里找不到神奇的调味料。看起来 API 不支持它,所以我想我正在寻找一些 CSS 来使 slider 更大。 我得到的是左边的,但我想把它设计成右边的样子?任何 CSS 技巧或以前有人这样做过。
如果我运行这段代码: float a=1.123456789; printf("The float value is %f\n",a); double b=1.123456789876543 prin
我正在尝试使用 strip binary 来剥离我的目标文件。我在 gcc-7 上构建了最新的 binutils,但我的代码库使用 gcc-4.9.2。Binutils 是为 64 位架构构建的,我的
有没有办法让 iPhone 应用的“内容”区域感知到更大的导航栏? 类似这些问题: iOS: Adding a fixed image just below the navigation bar iO
我是一名优秀的程序员,十分优秀!