Android图像变换矩阵,将触摸坐标平移回来

2024-01-11

我正在为 Android 构建一个“导航类型”应用程序。

对于导航部分,我正在构建一个活动,用户可以使用触摸事件移动和缩放地图(这是位图),并且地图还可以使用指南针围绕屏幕中心旋转。

我使用 Matrix 来缩放、转置和旋转图像,然后将其绘制到画布上。

以下是加载视图时调用的代码,以使图像在屏幕中居中:

    image = new Matrix();
    image.setScale(zoom, zoom);

    image_center = new PointF(bmp.getWidth() / 2, bmp.getHeight() / 2);

    float centerScaledWidth = image_center.x * zoom;
    float centerScaledHeigth = image_center.y * zoom;

    image.postTranslate(
            screen_center.x -  centerScaledWidth, 
            screen_center.y - centerScaledHeigth);

图像的旋转是使用后旋转 method.

然后在onDraw()我只调用的方法

  canvas.drawBitmap(bmp, image, drawPaint);

问题是,当用户触摸屏幕时,我想要触摸图像上的点,但显然我无法获得正确的位置。 我试图反转image矩阵并平移触摸点,它不起作用。

有人知道如何翻译点坐标吗?

EDIT

我正在使用此代码进行翻译。dx and dy翻译值是从onTouch听众。 *new_center* 是一个浮点值数组,格式为 {x0, y0, x1, y1...}

  Matrix translated = new Matrix();
  Matrix inverted = new Matrix();

  translated.set(image);
  translated.postTranslate(dx, dy);

  translated.invert(inverted);
  inverted.mapPoints(new_center);
  translated.mapPoints(new_center);

  Log.i("new_center", new_center[0]+" "+new_center[1]);

实际上我尝试使用 as *new_center = {0,0}*:

仅应用翻译的矩阵,我得到了预期的 bmp 的 (0,0) 点和屏幕的 (0,0) 点之间的距离,但它似乎没有考虑旋转。

应用inverted矩阵到我得到这些结果的点,以各种可能的方式移动图像。

  12-26 13:26:08.481: I/new_center(11537): 1.9073486E-6 -1.4901161E-7
  12-26 13:26:08.581: I/new_center(11537): 0.0 -3.874302E-7
  12-26 13:26:08.631: I/new_center(11537): 1.9073486E-6 1.2516975E-6
  12-26 13:26:08.781: I/new_center(11537): -1.9073486E-6 -5.364418E-7
  12-26 13:26:08.951: I/new_center(11537): 0.0 2.682209E-7
  12-26 13:26:09.093: I/new_center(11537): 0.0 7.003546E-7

相反,我期待的是图像上翻译的坐标。

我的思路正确吗?


好的我明白了。

首先,我将旋转与图像的平移和缩放分开。

因为我创建了一个自定义 ImageView,所以这很简单。我将旋转应用于canvasImageView 的图像,以及图像矩阵的其他转换。

我通过全局矩阵变量获取画布矩阵的踪迹。

一些代码:

为相应的设置正确的运动onTouch事件,首先我“旋转回”从onTouch (start and stop点)使用矩阵的逆canvas

然后我计算 x 和 y 之间的差,并将其应用于image matrix.

  float[] movement = {start.x, start.y, stop.x, stop.y};

  Matrix c_t = new Matrix();
  canvas.invert(c_t);
  c_t.mapPoints(movement);

  float dx = movement[2] - movement[0];
  float dy = movement[3] - movement[1];

  image.postTranslate(dx, dy);

相反,如果您想检查图像移动是否超出其大小,请在image.postTranslate(dx, dy);你把这个代码:

  float[] new_center = {screen_center.x, screen_center.y};

  Matrix copy = new Matrix();
  copy.set(image);
  copy.postTranslate(dx, dy);

  Matrix translated = new Matrix();
  copy.invert(translated);
  translated.mapPoints(new_center);

  if ((new_center[0] > 0) && (new_center[0] < bmp.getWidth()) && 
    (new_center[1] > 0) && (new_center[1] < bmp.getHeight())) {

        // you can remove the image.postTranslate and copy the "copy" matrix instead
        image.set(copy);
  ...

需要注意的是:

A) 图像的旋转中心是屏幕的中心,因此在画布旋转过程中不会改变坐标

B) 您可以使用屏幕中心的坐标来获取图像的旋转中心。

通过这种方法,您还可以将每个触摸事件转换为图像坐标。

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

Android图像变换矩阵,将触摸坐标平移回来 的相关文章

随机推荐

  • struts2 将 URL 传递给 Action

    我读了struts手册通配符映射 http struts apache org 2 1 8 1 docs wildcard mappings html并决定自己测试一些例子 我有一个行动指向
  • 创建 Liferay portlet 配置页面

    我正在尝试为 Liferay portlet 创建一个配置页面 以便我可以为其设置一些参数 例如 我想选择控制器在查看时应显示哪个页面 配置应位于此处 所以我为配置创建了一个控制器 如下所示 import com liferay porta
  • 学习WPF和MVVM

    我最近加入了一个新的开发项目 使用 WPF 和 MVVM 构建胖客户端应用程序 我在各种 NET 框架 从 1 1 到 3 5 以及所有主要技术中开发过应用程序 WebForms MVC 和 WinForms 在我所有的项目中 我都很享受其
  • 如何仅在 3 边应用盒子阴影? [复制]

    这个问题在这里已经有答案了 我在下面使用我的 CSS 页面 他在 4 边应用了方框阴影 我希望它只应用于右侧 底部和左侧 如何仅在 3 边应用框阴影 webkit box shadow 0 0 10px rgba 0 0 0 0 22 mo
  • 显示格式 ApplyFormatInEditMode

    我在 C 中使用 MVC 3 我有一个具有此属性的类 DisplayFormat DataFormatString 0 dd MMM yyyy ApplyFormatInEditMode true 我想在用户处于状态时强制执行验证EDIT
  • 将 cout 和 stdout 重定向到 C++ 中的字符串以进行单元测试

    我正在努力在单元测试下获取一些遗留代码 有时感知现有程序行为的唯一方法是从控制台输出 我在网上看到很多关于如何将 stdout 重定向到 C 中的另一个文件的示例 但是有没有办法可以将其重定向到内存中的流 以便我的测试不必依赖于磁盘 我希望
  • YouTube Iframe API onError 事件近几个月没有触发

    我非常确定 YouTube Iframe API onError 事件过去会触发 因为我运行一个基于此 API 的项目 但最近 onError 事件不会触发 即使是最简单的错误 这是一个基于官方页面的简单示例代码 https develop
  • Android USB 枚举

    我正在编写一个 Android USB 主机应用程序 我试图枚举与平板电脑连接的设备 我遵循开发者网站的 android USB 主机文档中的代码 我的代码如下 AndroidUSB活动 public class AndroidUSBAct
  • 不允许同一用户使用多个用户名多次连接到服务器或共享资源

    使用Windows 2008 R2 在我们的服务器上 我们收到此错误 不允许同一用户使用多个用户名与服务器或共享资源建立多个连接 断开与服务器或共享资源的所有先前连接 然后重试 尝试在命令行上映射驱动器时 但是 远程计算机没有打开资源管理器
  • 自动完成参数:列出静态字段,无需输入 ClassName::

    How to make auto completion list all static fields of a certain class that has appropriate variable type when ctrl space
  • 如何在 django 中的模板标签内获取模板的渲染输出?

    免责声明 这是一个后续问题我之前的问题 https stackoverflow com questions 5332640 how can i get a django template to render itself within a
  • 需要帮助理解证书链

    目前我正在编写一个java库来访问pointhq com的REST API 在开发 Android 客户端时 我意识到默认情况下不接受 SSL 证书 因此我编写了一个自定义 TrustManager 并添加了 pointhq com 证书
  • Spring、Jackson 和定制(例如定制反序列化器)

    由于对Spring还有些陌生 我遇到了一个problem https stackoverflow com questions 3535569 jackson json throws jsonmappingexception when flo
  • 动态启用/禁用 Azure WebJob 中的触发功能

    我们有一个 Azure Web 作业 它在 Functions cs 文件中具有两个方法 这两个作业都是由 Azure 服务总线中的不同主题触发的 由于这在运行时使用反射来确定要由命中主题的消息运行 触发的函数 因此代码中没有对这些方法的引
  • Xamarin 表单获取通话时长

    我有一个 xamarin forms 应用程序 当单击标签时它将打开拨号器 我想要实现的是 用户点击标签 gt 拨号器 ios 中的电话应用程序 打开 用户调用并结束 gt 返回应用程序 单击标签时我可以打开拨号器 我可以在我的应用程序中获
  • php://input 在 PHP 5.6.16 中只能读取一次

    PHP手册 http php net manual en wrappers php php声明使用 php input 打开的流支持查找操作 并且从 PHP 5 6 开始可以多次读取 但我无法使其工作 下面的例子清楚地表明它不起作用
  • 当没有输入时,currencyconverter可以忽略$符号吗

    在数据表中 我必须将输入验证为货币 当我删除 符号后输入值时 输入组件会抛出错误
  • Kendo UI jQuery 网格服务器端过滤

    我正在使用 Kendo UI for jQuery Grid 来显示一些数据 到目前为止 我正在使用客户端过滤和分页 其中所有数据记录都在对服务器的初始调用中返回 Web API 和 Dapper 在服务器端使用 然而 由于数据源随着时间的
  • 检查 lambda 表达式中的属性是否为 null

    我有一个试图绑定到列表视图的对象列表 我按两个属性排序 存在的问题是某些记录可能不具有其中一种属性 这会导致错误 我希望它仍然绑定具有该属性的记录 IEnumerable
  • Android图像变换矩阵,将触摸坐标平移回来

    我正在为 Android 构建一个 导航类型 应用程序 对于导航部分 我正在构建一个活动 用户可以使用触摸事件移动和缩放地图 这是位图 并且地图还可以使用指南针围绕屏幕中心旋转 我使用 Matrix 来缩放 转置和旋转图像 然后将其绘制到画