Google Maps API v2 在 MapFragment 上绘制圆的一部分

2023-11-24

我需要画这样的东西,它将被绘制并且几乎没有透明度

它还需要可点击(onTouch 事件等)

enter image description here

我知道在 API v1 中你必须使用 Overlay 并使用画布和一些数学来扩展它。 在 Google Map API v2 中最简单的方法是什么?

PS:半径是可变的。

(供进一步参考) 编辑1:

我实现了 CanvasTileProvider 子类并重写其 onDraw() 方法:

@Override
void onDraw(Canvas canvas, TileProjection projection) {
    // TODO Auto-generated method stub

    LatLng tempLocation = moveByDistance(mSegmentLocation, mSegmentRadius, mSegmentAngle);

    DoublePoint segmentLocationPoint = new DoublePoint(0, 0);
    DoublePoint tempLocationPoint = new DoublePoint(0, 0);

    projection.latLngToPoint(mSegmentLocation, segmentLocationPoint);
    projection.latLngToPoint(tempLocationPoint, tempLocationPoint);

    float radiusInPoints = FloatMath.sqrt((float) (Math.pow(
            (segmentLocationPoint.x - tempLocationPoint.x), 2) + Math.pow(
            (segmentLocationPoint.y - tempLocationPoint.y), 2)));

    RectF segmentArea = new RectF();
    segmentArea.set((float)segmentLocationPoint.x - radiusInPoints, (float)segmentLocationPoint.y - radiusInPoints, 
            (float)segmentLocationPoint.x + radiusInPoints, (float)segmentLocationPoint.y + radiusInPoints);

    canvas.drawArc(segmentArea, getAdjustedAngle(mSegmentAngle), 
            getAdjustedAngle(mSegmentAngle + 60), true, getOuterCirclePaint());


}

另外,我从 MapActivity 添加了这个:

private void loadSegmentTiles() {

     TileProvider tileProvider; 
     TileOverlay tileOverlay = mMap.addTileOverlay(
         new TileOverlayOptions().tileProvider(new SegmentTileProvider(new LatLng(45.00000,15.000000), 250, 30)));

}

现在我想知道为什么我的弧不在地图上?


为了绘制圆段,如果这些段主要是静态的,我将注册一个 TileProvider。 (图块通常仅加载一次,然后缓存。)为了检查单击事件,您可以注册一个 onMapClickListener 并循环遍历您的段,以检查单击的 LatLng 是否位于您的某个段内。 (请参阅下面的更多细节。)

这是一个 TileProvider 示例,您可以对其进行子类化并仅实现 onDraw 方法。
一个重要的注意事项:子类必须是线程安全的! onDraw方法将被多个线程同时调用。因此,请避免在 onDraw 内更改任何全局变量!

/* imports should be obvious */ 
public abstract class CanvasTileProvider implements TileProvider {
private static int TILE_SIZE = 256;

private BitMapThreadLocal tlBitmap;

@SuppressWarnings("unused")
private static final String TAG = CanvasTileProvider.class.getSimpleName();

public CanvasTileProvider() {
    super();
    tlBitmap = new BitMapThreadLocal();
}

@Override
// Warning: Must be threadsafe. To still avoid creation of lot of bitmaps,
// I use a subclass of ThreadLocal !!!
public Tile getTile(int x, int y, int zoom) {
    TileProjection projection = new TileProjection(TILE_SIZE,
            x, y, zoom);

    byte[] data;
    Bitmap image = getNewBitmap();
    Canvas canvas = new Canvas(image);
    onDraw(canvas, projection);
    data = bitmapToByteArray(image);
    Tile tile = new Tile(TILE_SIZE, TILE_SIZE, data);
    return tile;
}

/** Must be implemented by a concrete TileProvider */
abstract void onDraw(Canvas canvas, TileProjection projection);

/**
 * Get an empty bitmap, which may however be reused from a previous call in
 * the same thread.
 * 
 * @return
 */
private Bitmap getNewBitmap() {
    Bitmap bitmap = tlBitmap.get();
    // Clear the previous bitmap
    bitmap.eraseColor(Color.TRANSPARENT);
    return bitmap;
}

private static byte[] bitmapToByteArray(Bitmap bm) {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    bm.compress(Bitmap.CompressFormat.PNG, 100, bos);
    byte[] data = bos.toByteArray();
    return data;
}

class BitMapThreadLocal extends ThreadLocal<Bitmap> {
    @Override
    protected Bitmap initialValue() {
        Bitmap image = Bitmap.createBitmap(TILE_SIZE, TILE_SIZE,
                Config.ARGB_8888);
        return image;
    }
}
}

使用传递到 onDraw 方法的投影首先获取图块的边界。如果没有段在边界内,则返回。否则将您的序列绘制到画布中。方法projection.latLngToPoint 可帮助您将LatLng 转换为画布的像素。

/** Converts between LatLng coordinates and the pixels inside a tile. */
public class TileProjection {

private int x;
private int y;
private int zoom;
private int TILE_SIZE;

private DoublePoint pixelOrigin_;
private double pixelsPerLonDegree_;
private double pixelsPerLonRadian_;

TileProjection(int tileSize, int x, int y, int zoom) {
    this.TILE_SIZE = tileSize;
    this.x = x;
    this.y = y;
    this.zoom = zoom;
    pixelOrigin_ = new DoublePoint(TILE_SIZE / 2, TILE_SIZE / 2);
    pixelsPerLonDegree_ = TILE_SIZE / 360d;
    pixelsPerLonRadian_ = TILE_SIZE / (2 * Math.PI);
}

/** Get the dimensions of the Tile in LatLng coordinates */
public LatLngBounds getTileBounds() {
    DoublePoint tileSW = new DoublePoint(x * TILE_SIZE, (y + 1) * TILE_SIZE);
    DoublePoint worldSW = pixelToWorldCoordinates(tileSW);
    LatLng SW = worldCoordToLatLng(worldSW);
    DoublePoint tileNE = new DoublePoint((x + 1) * TILE_SIZE, y * TILE_SIZE);
    DoublePoint worldNE = pixelToWorldCoordinates(tileNE);
    LatLng NE = worldCoordToLatLng(worldNE);
    return new LatLngBounds(SW, NE);
}

/**
 * Calculate the pixel coordinates inside a tile, relative to the left upper
 * corner (origin) of the tile.
 */
public void latLngToPoint(LatLng latLng, DoublePoint result) {
    latLngToWorldCoordinates(latLng, result);
    worldToPixelCoordinates(result, result);
    result.x -= x * TILE_SIZE;
    result.y -= y * TILE_SIZE;
}


private DoublePoint pixelToWorldCoordinates(DoublePoint pixelCoord) {
    int numTiles = 1 << zoom;
    DoublePoint worldCoordinate = new DoublePoint(pixelCoord.x / numTiles,
            pixelCoord.y / numTiles);
    return worldCoordinate;
}

/**
 * Transform the world coordinates into pixel-coordinates relative to the
 * whole tile-area. (i.e. the coordinate system that spans all tiles.)
 * 
 * 
 * Takes the resulting point as parameter, to avoid creation of new objects.
 */
private void worldToPixelCoordinates(DoublePoint worldCoord, DoublePoint result) {
    int numTiles = 1 << zoom;
    result.x = worldCoord.x * numTiles;
    result.y = worldCoord.y * numTiles;
}

private LatLng worldCoordToLatLng(DoublePoint worldCoordinate) {
    DoublePoint origin = pixelOrigin_;
    double lng = (worldCoordinate.x - origin.x) / pixelsPerLonDegree_;
    double latRadians = (worldCoordinate.y - origin.y)
            / -pixelsPerLonRadian_;
    double lat = Math.toDegrees(2 * Math.atan(Math.exp(latRadians))
            - Math.PI / 2);
    return new LatLng(lat, lng);
}

/**
 * Get the coordinates in a system describing the whole globe in a
 * coordinate range from 0 to TILE_SIZE (type double).
 * 
 * Takes the resulting point as parameter, to avoid creation of new objects.
 */
private void latLngToWorldCoordinates(LatLng latLng, DoublePoint result) {
    DoublePoint origin = pixelOrigin_;

    result.x = origin.x + latLng.longitude * pixelsPerLonDegree_;

    // Truncating to 0.9999 effectively limits latitude to 89.189. This is
    // about a third of a tile past the edge of the world tile.
    double siny = bound(Math.sin(Math.toRadians(latLng.latitude)), -0.9999,
            0.9999);
    result.y = origin.y + 0.5 * Math.log((1 + siny) / (1 - siny))
            * -pixelsPerLonRadian_;
};

/** Return value reduced to min and max if outside one of these bounds. */
private double bound(double value, double min, double max) {
    value = Math.max(value, min);
    value = Math.min(value, max);
    return value;
}

/** A Point in an x/y coordinate system with coordinates of type double */
public static class DoublePoint {
    double x;
    double y;

    public DoublePoint(double x, double y) {
        this.x = x;
        this.y = y;
    }
}

}

最后,您需要检查一下 LatLng 坐标上的点击是否位于您的段内。 因此,我将通过 LatLng 坐标列表来近似该线段,在您的情况下,一个简单的三角形可能就足够了。对于每个 LatLng 坐标列表,即每个线段,您可以调用如下所示的内容:

private static boolean isPointInsidePolygon(List<LatLng> vertices, LatLng point) {
    /**
     * Test is based on a horizontal ray, starting from point to the right.
     * If the ray is crossed by an even number of polygon-sides, the point
     * is inside the polygon, otherwise it is outside.
     */
    int i, j;
    boolean inside = false;
    int size = vertices.size();
    for (i = 0, j = size - 1; i < size; j = i++) {
        LatLng vi = vertices.get(i);
        LatLng vj = vertices.get(j);
        if ((vi.latitude > point.latitude) != (vj.latitude > point.latitude)) {
            /* The polygonside crosses the horizontal level of the ray. */
            if (point.longitude <= vi.longitude
                    && point.longitude <= vj.longitude) {
                /*
                 * Start and end of the side is right to the point. Side
                 * crosses the ray.
                 */
                inside = !inside;
            } else if (point.longitude >= vi.longitude
                    && point.longitude >= vj.longitude) {
                /*
                 * Start and end of the side is left of the point. No
                 * crossing of the ray.
                 */
            } else {
                double crossingLongitude = (vj.longitude - vi.longitude)
                        * (point.latitude - vi.latitude)
                        / (vj.latitude - vi.latitude) + vi.longitude;
                if (point.longitude < crossingLongitude) {
                    inside = !inside;
                }
            }
        }
    }
    return inside;
}

正如您所看到的,我有一个非常相似的任务需要解决:-)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Google Maps API v2 在 MapFragment 上绘制圆的一部分 的相关文章

  • Android 中的“ffmpeg 有文本重定位”错误

    我正在构建一个 Android 视频发送应用程序 我需要在上传之前对视频进行压缩 在本例中 我选择使用 FFmpeg 的 Android 包装器 https github com hiteshsondhi88 ffmpeg android
  • 离线安装 android 很困难[已过时]

    我是非洲的一名学生 在我们的土地上 实际上存在缓慢且昂贵的互联网连接 这就是为什么每当我们听到 在线存储库 安装软件方法这个词时我们都会感到恐惧 该死 这通常意味着你必须去别处寻找 问题 如果没有将 Eclipse 连接到互联网 我无法安装
  • Android 和 Java Uuid

    我想为我的应用程序生成一个uuid 我尝试了很多东西 例如wifi mac地址 获取android id 序列号 从设备创建伪uuidandroid os Build特性 我还知道java本身有Uuid创建者类java util UUID
  • 如何在每个项目的列表视图中实现简单的点赞按钮

    我的列表视图项目中有某些条目 我有一个简单的 喜欢按钮 不是像 Facebook 的按钮 您可以看到上面提到的屏幕截图 供参考 当我点击 喜欢 按钮的那一刻 我希望更改 喜欢 按钮的颜色 并且 喜欢 按钮的颜色应保持不变 改变了喜欢 当我再
  • 用于编辑文本的电子邮件键盘

    以下代码似乎不起作用 我想要电子邮件键盘 and com显示编辑文本 emailEditText setInputType InputType TYPE TEXT VARIATION EMAIL ADDRESS 将其添加到您的布局中 and
  • Android 相机:线程?哪个应该做什么

    我试图弄清楚哪些线程应该在 Android 中执行哪些操作 我发现官方文档中唯一说明的是camera open 应该放入它自己的线程中 关于什么 camera startPreview camera stopPreview camera r
  • 如何在 Android 中正确设置 google play 登录?

    我在安卓上开发了一个游戏 我尝试实现 GooglePlay SignIn 但显示错误 我无法调试此错误 我尝试在模拟器以外的不同手机型号中安装该应用程序 Code public void startSignInIntent startAct
  • Android SQLite 查询被 Android Studio 标记为错误

    在我的一个 Android 应用程序中 我使用了一些SQLite自从我更新到以来开始出现问题的查询Android Studio 3 0 尽管我可以编译并运行该应用程序 但它们被标记为错误 这些是查询 db execSQL INSERT IN
  • 是否可以检测Android应用程序卸载?

    我的应用程序使用 Google 的 C2DM 推送通知 来通知用户朋友的新活动 一旦他们安装了应用程序 我就会向 C2DM 服务器注册设备并存储用户的电话号码 所以我知道用户正在使用我的应用程序 我可以向他 她发送推送通知 但是 如果用户卸
  • 是否可以在没有 SDK 的情况下编写 Android 应用程序?

    只是想知道 由于 Android 应用程序是 Java 程序 是否有可能在不使用 SDK 的情况下完全从头开始编写一个应用程序 如果不是 那为什么不呢 不 Android 应用程序是用 Java 编写的 但仅包含标准 Java API 的一
  • Android架构组件导航:工具栏后退按钮缺失,后退不起作用

    我正在尝试喷气背包导航 但当我移动到新片段时无法显示导航后退按钮 导航活动 kt class NavActivity AppCompatActivity override fun onCreate savedInstanceState Bu
  • Google App Engine 的示例 Android 应用程序,抛出异常

    我的 GAE 示例 Android 应用程序直到昨天都工作正常 除了在 Consts java 中添加了我的项目 ID 之外 我没有对客户端应用程序进行任何更改 现在每次我尝试插入 我的意思是发送消息 时都会抛出以下异常 06 06 09
  • 通过选中/取消选中 CheckBoxPreference 来启动/停止服务

    我正在编写一个通过选中或取消选中来启动或停止服务的应用程序CheckBoxPreference我试图找到一些信息 例如示例代码或教程 但我还没有找到 如何通过选中或取消选中来启动或停止服务CheckBoxPreference这是在Prefe
  • 在 webview 片段中实现后退按钮

    我想在我的应用程序中实现后退按钮 我正在使用每个片段显示不同的网络视图 现在 如果我按后退按钮 无论我在哪里 它都会关闭应用程序 我希望它能像浏览器一样返回 我有我的MainActivity java fragment1 java等直到fr
  • Android Widget 实现

    嗨 如果这个问题很愚蠢 我提前道歉 我对 Android 编程相当陌生 而且学得很快 我刚刚创建了一个任务提醒应用程序 并且想将该应用程序转换 实现为一个可以在主屏幕上查看的小部件 有什么方法吗 这可能吗 Thanks 如果没有更多关于您的
  • 如何使用 Android 的身份验证标签进行 GCM 加密

    我想制作一个通过 GCM 模式与 Android 身份验证标签加密数据的函数 这是我的源代码 public static byte GCMEncrypt String hexKey String hexIV byte aad throws
  • 如何暂时禁用Android按钮[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我想暂时禁
  • 将 cookie 存储在共享首选项中

    我一直在绞尽脑汁地试图弄清楚这一点 我正在制作一个 HttpsURLConnection 并使用 java net cookiemanager 来管理我的 cookie 据我所知 无法使用 android webkit cookiemana
  • 将阿拉伯语从 android 发送到 PHP 文件

    尝试使用下面的代码将阿拉伯文本从 android 发送到 PHP 文件 Button setOnClickListener new OnClickListener public void onClick View v TODO Auto g
  • 更新 android chrome 版本 65 后,应用程序无法运行,Sencha touch 和 cordova android

    更新 chrome 版本 65 后 应用程序在点击某些点击事件时再次显示启动屏幕 它是 Sencha touch 和 Cordova android 的混合应用程序 编辑 这是一个已知的 chrome 65 错误 https bugs ch

随机推荐

  • 安装magento,数据库连接错误。

    我正在尝试将 magento 安装到我的 web 主机上 在安装过程中我收到 数据库连接错误 我已正确输入所有值 已联系我的 web 主机以确保我此时陷入困境 他们说参考 magento 论坛额外的支持 我找不到修复方法 任何想法 帮助将不
  • 使用 ggplot2 仅将线段添加到一个方面

    作为一个例子 我有这个数据框 称为my data Groups FactorA FactorB FactorC N value sd se ci 1 Control Condition1 Condition1 Condition1 3 92
  • JPA - 在 persist() 之后返回自动生成的 id

    我正在使用 JPA EclipseLink 和 Spring 假设我有一个带有自动生成 ID 的简单实体 Entity public class ABC implements Serializable Id GeneratedValue s
  • 不使用 Qt 运行 .EXE

    Solution 我想运行我创建的应用程序QtSDK在没有的机器上Qt安装 我尝试复制DLL s来自BIN文件夹到我的项目的发布中 但它不起作用 我尝试了以下方法 我全部复制dll s folder d Qt Qt5 0 1 5 0 1 m
  • 我想在单独的 php 文件上运行 wp_query 以进行 ajax 调用

    例如 ul class thumbs li class li ul
  • 图像标题和换行

    在图像下方添加标题的最佳方法是什么 图像及其标题将向右浮动 并且标题上的文本需要换行 200x200px 的图像不应具有宽度为 800px 的标题 我强烈希望有一个解决方案能够让我在不更改 CSS 或标记的情况下更新图像 具有不同的宽度 由
  • 尝试从 ReadStream 读取时接收错误 Domain=kCFErrorDomainCFNetwork Code=2

    我正在尝试同步读取CFReadStream反对创建者CFStreamCreatePairWithSocketToHost 流打开得很好 但是当我尝试调用时CFReadStreamRead在循环中 CFReadStreamRead 返回 1
  • 使用 Chrome 时的 Selenium“selenium.common.exceptions.NoSuchElementException”

    我正在尝试玩QWOP在 Chrome 上使用 Selenium 但我不断收到以下错误 selenium common exceptions NoSuchElementException Message no such element Una
  • Android 扩展中的实验性功能有利于生产发布

    我正在使用 Parcelize使用 Kotlin 语言进行 Android 开发的功能 为了使用它们 我在 build gradle 文件中进行了以下修改 apply plugin kotlin android extensions the
  • 对字符串数组列表进行排序 C#

    我有一个字符串数组列表 其中数组的格式为 动物 品种 名称 Dog Golden Retriever Rex Cat Tabby Boblawblah Fish Clown Nemo Dog Pug Daisy Cat Siemese We
  • 如何将另一个项目 (Dll) 中的 UserControl 添加到我的 WPF 解决方案中?

    所以 一切都在标题中 我只想在我的 WPF 窗口中添加一个 UserControl 它看起来很简单 但 UserControl 位于同一解决方案的另一个项目 Dll 项目 中 我就是无法参考它 所以 我最好的尝试是这样的
  • 使用 By() 计算变化百分比

    我是一个没有经验的 R 用户 一直在努力使用 By 函数 非常感谢您的帮助 任务很简单 我有一个纵向数据集 如何声明一个 需要通过 ID 计算不同的指标 其中一个指标是简单的百分比变化 需要滞后 示例如下 ID Date Temp Chan
  • 如何在放大弹出插件中的弹出窗口中打开弹出窗口

    谁能告诉我如何使用 magnific popup jquery 插件 使用 ajax 在弹出窗口中打开弹出窗口 ajax popup link magnificPopup type ajax a href path to file html
  • System.Collections.Generic.Dictionary = 终极性能?

    我正在编写 Haxe C 目标 并且一直在研究 Haxe 的 std 库的性能差异 以便我们可以通过其跨平台代码提供尽可能最佳的性能 哈希表代码就是一个很好的例子 我有点不愿意使用 NET 的字典 因为它看起来很庞大 由于内存对齐问题 键
  • Hibernate 级联删除对象

    我对cascade delete 的工作原理有点困惑 我在城市映射文件中按以下方式定义了映射
  • 如何从 Android ListView 获取第一个可见视图

    有没有办法从Android中的ListView中获取第一个可见的View 我可以获取支持适配器中第一个视图的数据 但似乎无法获取 ListView 中的第一个视图 我想在滚动操作完成后更改第一个可见视图 我知道我不应该保存对视图的引用 实际
  • 持久性与非持久性 - 我应该使用哪一个?

    我的网站一直使用持久连接 根据我对它们的理解 没有理由不这样做 当连接可以重用时为什么要关闭它呢 我有一个网站总共访问大约 7 个数据库 这不是一个流量巨大的网站 但也足够大了 您对持久性有何看法 我应该使用它们吗 使用持久连接 您无法有效
  • 如何在 Rails / Capybara / Cucumber 或 Rspec 中测试帖子

    我正在使用 rspec cucumber 和 capybara 我正在寻找一种方法来测试恶意用户无法破解表单然后发布到他 她没有权限的 URL 我在 cancan 中设置了权限 这样 应该 可以工作 但是 我可以测试它的唯一方法是自己破解一
  • python网络编程[关闭]

    Closed 这个问题是基于意见的 目前不接受答案 我开始通过一些书籍和在线教程学习Python 我了解基本语法和操作 但我意识到理解该语言的正确方法是实际做一个项目 现在 当我说一个项目时 我指的是一些有用的东西 也许是一些网络应用程序
  • Google Maps API v2 在 MapFragment 上绘制圆的一部分

    我需要画这样的东西 它将被绘制并且几乎没有透明度 它还需要可点击 onTouch 事件等 我知道在 API v1 中你必须使用 Overlay 并使用画布和一些数学来扩展它 在 Google Map API v2 中最简单的方法是什么 PS