0

0

高效实现二维数组点的圆形模式检索与动画

聖光之護

聖光之護

发布时间:2025-09-08 10:29:01

|

796人浏览过

|

来源于php中文网

原创

高效实现二维数组点的圆形模式检索与动画

本文详细介绍了如何在Android应用中生成并管理一个二维点阵网格,并着重阐述了如何高效地从该网格中检索位于特定圆形模式内的点。通过预处理计算点到中心点的距离并进行分组,我们能够实现从中心向外扩散的圆形动画效果,有效解决了重复计算距离的效率问题,并提供了具体的代码实现与优化建议。

1. 点阵网格的生成与存储

android应用中,为了创建动态背景或进行特定视觉效果,我们常常需要生成一个规则的点阵网格。以下代码片段展示了如何计算合适的填充、网格尺寸,并生成一个 point_matrix 来存储每个点的屏幕坐标。

// 定义点间距常量
constant = 60; 

// 计算X轴方向的填充,确保点阵居中
int padding_X = (int) Math.floor((width % constant)/2f);
if (padding_X == 0) {
    padding_X = (int) Math.floor(constant / 2);
}
// 计算Y轴方向的填充
int padding_Y = (int) Math.floor((height % constant)/2f);
if (padding_Y == 0) {
    padding_Y = (int) Math.floor(constant/2);
}

System.out.println("padding X: "+padding_X);
System.out.println("padding Y: "+padding_Y);

// 计算网格中X和Y方向的最大索引
int max_xn = Math.round((width-(padding_X*2)) / constant);
int max_yn = Math.round((height-(padding_Y*2)) / constant);

System.out.println("max xn: "+max_xn);
System.out.println("max yn: "+max_yn);

// 初始化三维数组,用于存储点的索引和屏幕坐标
// point_matrix[xn][yn][0] 存储X坐标
// point_matrix[xn][yn][1] 存储Y坐标
point_matrix = new int[max_xn+1][max_yn+1][2];
lens = new int[2];

// 遍历生成所有点并绘制到Canvas上,同时存储其坐标
for (int yn = 0; yn <= max_yn; yn++) {
    int y = (int) (padding_Y + (yn*constant));
    for (int xn = 0; xn <= max_xn; xn++) {
        int x = (int) (padding_X + (xn*constant));

        System.out.println("point @ x: "+x+" y: "+y);
        canvas.setPixel(x,y,Color.parseColor("#ffffff")); // 在Canvas上绘制点

        point_matrix[xn][yn][0] = x; // 存储X坐标
        point_matrix[xn][yn][1] = y; // 存储Y坐标
    }
}

// 在UI线程更新ImageView显示Bitmap
runOnUiThread(() -> {
    iv0.setImageBitmap(canvas);
});

// 存储网格的维度
lens[0] = max_xn+1;
lens[1] = max_yn+1;

这段代码首先确定了点阵的间距 constant,然后计算了 padding_X 和 padding_Y 以确保点阵在屏幕上居中。接着,它计算了网格在X和Y方向上的最大索引 max_xn 和 max_yn。最后,通过嵌套循环遍历这些索引,计算每个点的实际屏幕坐标 (x, y),将其绘制到 canvas 上,并存储在 point_matrix 数组中。

2. 核心挑战:高效的圆形模式点检索与动画

我们的目标是实现一个动画效果:让这些点从屏幕中心开始,以圆形模式向外逐渐消失,并在不同的“半径间隔”之间有延迟。最初的设想是重复遍历整个 point_matrix,对每个点计算其到中心的距离,这种方法在需要频繁查询时效率较低。

3. 解决方案:预处理与分组策略

为了解决效率问题,我们可以采用“预处理”的策略:在动画开始前,一次性计算所有点到中心点的距离,并根据距离将点进行分组。这样,在动画执行时,我们只需按顺序遍历这些分组即可。

3.1 确定动画中心点

首先,我们需要确定动画的中心点 (cx, cy)。通常,这会是屏幕的中心或点阵的几何中心。 例如: cx = width / 2;cy = height / 2; 或者,如果点阵有自己的逻辑中心: cx = padding_X + (max_xn * constant / 2);cy = padding_Y + (max_yn * constant / 2);

3.2 距离计算与点分组

对于 point_matrix 中的每个点 (x, y),我们可以使用勾股定理计算其到中心点 (cx, cy) 的欧几里得距离: distance = sqrt((x - cx)^2 + (y - cy)^2)

为了方便分组,我们可以将距离四舍五入或按一定间隔进行分段,然后将点存储在一个 Map 中,其中键是距离(或距离区间),值是该距离上的点列表。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// 假设Point类或类似的结构,用于存储点的坐标
class GridPoint {
    int x;
    int y;
    int xn; // 网格X索引
    int yn; // 网格Y索引

    public GridPoint(int x, int y, int xn, int yn) {
        this.x = x;
        this.y = y;
        this.xn = xn;
        this.yn = yn;
    }

    // 可根据需要添加其他方法,例如获取屏幕坐标
}

// ... 在你的Activity或类中 ...

// 假设width和height已定义,point_matrix已填充
// 假设centerX和centerY是动画的中心点
int centerX = width / 2; 
int centerY = height / 2;

// 使用Map来存储按距离分组的点
// Key: 距离(四舍五入或按间隔取整)
// Value: 该距离上的点列表
Map> pointsByRadius = new HashMap<>();

// 遍历point_matrix,计算距离并分组
for (int yn = 0; yn <= max_yn; yn++) {
    for (int xn = 0; xn <= max_xn; xn++) {
        int pointX = point_matrix[xn][yn][0];
        int pointY = point_matrix[xn][yn][1];

        // 计算点到中心点的距离
        double distance = Math.sqrt(Math.pow(pointX - centerX, 2) + Math.pow(pointY - centerY, 2));

        // 将距离四舍五入为整数,作为Map的键
        int roundedDistance = (int) Math.round(distance); 
        // 或者可以按固定间隔分组,例如 (int) (distance / 10) * 10

        // 将点添加到对应的距离组中
        pointsByRadius.computeIfAbsent(roundedDistance, k -> new ArrayList<>())
                      .add(new GridPoint(pointX, pointY, xn, yn));
    }
}

3.3 实现圆形消失动画

有了按距离分组的点,实现圆形消失动画就变得非常简单和高效。我们只需按递增的距离(Map的键)遍历这些分组,对每个分组中的点执行消失操作,并在处理不同半径间隔的组之间引入延迟。

论论App
论论App

AI文献搜索、学术讨论平台,涵盖了各类学术期刊、学位、会议论文,助力科研。

下载
import android.os.Handler;
import android.os.Looper;

// ... 在你的Activity或类中 ...

// 获取所有距离键并排序,以便按半径从小到大处理
List sortedRadii = new ArrayList<>(pointsByRadius.keySet());
sortedRadii.sort(Integer::compare); // 升序排序

Handler handler = new Handler(Looper.getMainLooper()); // 用于在主线程调度UI更新

long currentDelay = 0;
long delayIncrement = 50; // 每个半径间隔的延迟增量,单位毫秒

for (Integer radius : sortedRadii) {
    List pointsToAnimate = pointsByRadius.get(radius);
    if (pointsToAnimate != null && !pointsToAnimate.isEmpty()) {
        handler.postDelayed(() -> {
            // 在主线程执行UI更新
            for (GridPoint gp : pointsToAnimate) {
                // 假设你有一个方法来使点消失,例如改变颜色或移除
                // 这里我们只是打印,实际应用中会更新Canvas或View的状态
                System.out.println("Disappearing point at (" + gp.x + ", " + gp.y + ") at radius " + radius);
                // 示例:从Canvas上移除点或改变其颜色为透明
                // canvas.setPixel(gp.x, gp.y, Color.TRANSPARENT); 
                // iv0.setImageBitmap(canvas); // 每次更新都要刷新ImageView
            }
            // 实际应用中,你可能需要一次性更新UI,而不是每个点都更新
            // 例如,在一个半径间隔的所有点处理完后,调用一次 iv0.setImageBitmap(canvas);
            runOnUiThread(() -> {
                // 刷新UI,显示当前半径的点已消失
                iv0.setImageBitmap(canvas); 
            });

        }, currentDelay);
    }
    currentDelay += delayIncrement; // 增加下一次动画的延迟
}

注意事项:

  • UI线程: 在Android中,所有UI操作必须在主线程(UI线程)上执行。使用 Handler.postDelayed() 可以确保动画逻辑在主线程中按计划执行。
  • Canvas更新: 如果你的点是通过 canvas.setPixel() 绘制的,那么每次修改 canvas 后,都需要调用 iv0.setImageBitmap(canvas) 来刷新 ImageView 以显示变化。为了提高效率,可以考虑在一个 handler.postDelayed 回调中处理完一个半径间隔的所有点后,再统一刷新一次UI。

4. 圆形几何基础:三角函数应用

原始问题中提供了一个使用三角函数生成圆周上点的示例。虽然这与从现有网格中检索点有所不同,但它展示了如何利用 Math.sin 和 Math.cos 来理解和生成圆形轨迹。

static double i = 0;
static double pi = Math.PI;
static int q = 5;     // 圆的半径 (half size of array)
static double x;
static double y;
static double cx = 5; // 圆心X坐标 (offset center x) 
static double cy = 5; // 圆心Y坐标 (offset center y) 
public static void main(String[] args) {
    while (i < pi * 2) {    // pi*2 是一个完整的圆周角度 (360度)
        // 使用sin和cos计算圆周上的点坐标
        x = Math.round (cx + Math.sin(i) * q);
        y = Math.round (cy + Math.cos(i) * q);
        System.out.print(String.format("X = %4f", x) + String.format("Y = %4f", y) + "\n");
        i+=pi/180; // 每次增加1度(pi/180弧度)
    }
}

这段代码通过从0到 2*pi 弧度遍历角度 i,并结合圆心 (cx, cy) 和半径 q,使用 x = cx + r*sin(angle) 和 y = cy + r*cos(angle) 公式来计算圆周上的点。这在需要动态生成圆形路径、绘制圆形边界或进行圆形碰撞检测等场景中非常有用。

对于从预设网格中检索点并实现圆形动画,我们更侧重于点的距离计算和分组。然而,理解三角函数在圆形几何中的应用,有助于我们更灵活地处理与圆形相关的视觉效果。

5. 优化与注意事项

  • 半径间隔粒度: `

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

525

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

525

2023.08.10

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

75

2025.09.05

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

36

2025.11.16

golang map原理
golang map原理

本专题整合了golang map相关内容,阅读专题下面的文章了解更多详细内容。

61

2025.11.17

java判断map相关教程
java判断map相关教程

本专题整合了java判断map相关教程,阅读专题下面的文章了解更多详细内容。

42

2025.11.27

html5动画制作有哪些制作方法
html5动画制作有哪些制作方法

html5动画制作方法有使用CSS3动画、使用JavaScript动画库、使用HTML5 Canvas等。想了解更多html5动画制作方法相关内容,可以阅读本专题下面的文章。

514

2023.10.23

android开发三大框架
android开发三大框架

android开发三大框架是XUtil框架、volley框架、ImageLoader框架。本专题为大家提供android开发三大框架相关的各种文章、以及下载和课程。

291

2023.08.14

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

32

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3万人学习

C# 教程
C# 教程

共94课时 | 8.1万人学习

Java 教程
Java 教程

共578课时 | 54万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号