首页 > Java > java教程 > 正文

从二维点阵中高效检索圆形区域点并实现动画效果

心靈之曲
发布: 2025-09-08 12:13:20
原创
921人浏览过

从二维点阵中高效检索圆形区域点并实现动画效果

本教程详细介绍了如何从预定义的二维点阵中,高效地检索出位于特定圆形区域内的点。文章将阐述基于距离的筛选方法,包括性能优化技巧,并进一步指导如何利用这些点实现中心向外扩散或消失的动画效果。同时,还将介绍使用三角函数生成圆周点的方法,以辅助理解和实现更复杂的圆形图案。

1. 理解点阵数据结构

在处理二维图形和动画时,我们经常需要管理大量的离散点。本场景中,点被组织成一个二维网格(或点阵),并存储在一个三维数组 point_matrix 中。

point_matrix 的结构如下: point_matrix[xn][yn][0] 存储对应网格点在屏幕上的 x 坐标。 point_matrix[xn][yn][1] 存储对应网格点在屏幕上的 y 坐标。 其中,xn 和 yn 分别是点在网格中的逻辑索引。

初始点阵的生成代码示例如下:

int constant = 60; // 点之间的间距
int width = 1080; // 画布宽度
int height = 1920; // 画布高度

// 计算填充,使点阵居中
int padding_X = (int) Math.floor((width % constant) / 2f);
if (padding_X == 0) {
    padding_X = (int) Math.floor(constant / 2);
}
int padding_Y = (int) Math.floor((height % constant) / 2f);
if (padding_Y == 0) {
    padding_Y = (int) Math.floor(constant / 2);
}

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

// 初始化点阵存储
// point_matrix[网格x索引][网格y索引][0:x坐标, 1:y坐标]
int[][][] point_matrix = new int[max_xn + 1][max_yn + 1][2];

// 填充点阵
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));
        point_matrix[xn][yn][0] = x;
        point_matrix[xn][yn][1] = y;
        // 实际应用中,这里可能会进行绘制或其他操作
        // canvas.setPixel(x, y, Color.parseColor("#ffffff"));
    }
}
登录后复制

2. 中心点与距离计算

要检索圆形区域内的点,首先需要确定圆心坐标和半径。圆心可以是画布的几何中心,也可以是点阵的逻辑中心。

确定圆心: 如果以画布中心为圆心:centerX = width / 2; centerY = height / 2; 如果以点阵的中心点为圆心:centerX = point_matrix[max_xn / 2][max_yn / 2][0]; centerY = point_matrix[max_xn / 2][max_yn / 2][1];

距离计算(欧几里得距离): 任意点 (x, y) 到圆心 (cx, cy) 的距离 d 可以通过勾股定理计算: d = sqrt((x - cx)^2 + (y - cy)^2)

性能优化:使用平方距离 在判断一个点是否在某个半径 R 范围内时,我们实际上只需要比较 d 和 R 的大小。由于 sqrt 运算相对耗时,我们可以比较它们的平方: d^2 = (x - cx)^2 + (y - cy)^2 如果 d^2 <= R^2,则点在半径 R 范围内。这样可以避免不必要的开方运算,提高效率。

/**
 * 计算点 (x, y) 到中心 (cx, cy) 的平方距离。
 * @param x 点的x坐标
 * @param y 点的y坐标
 * @param cx 中心的x坐标
 * @param cy 中心的y坐标
 * @return 平方距离
 */
public static long calculateSquaredDistance(int x, int y, int cx, int cy) {
    long dx = x - cx;
    long dy = y - cy;
    return dx * dx + dy * dy;
}
登录后复制

3. 检索指定半径内的点

有了距离计算方法,检索指定半径内的点就变得简单直接。我们只需遍历 point_matrix 中的所有点,对每个点计算其到圆心的平方距离,并与目标半径的平方进行比较。

造点AI
造点AI

夸克 · 造点AI

造点AI 325
查看详情 造点AI
import java.util.ArrayList;
import java.util.List;

// 假设 point_matrix, max_xn, max_yn, width, height 已定义

public class PointRetrieval {

    // 定义一个简单的点类,用于存储坐标
    static class Point {
        int x;
        int y;
        int gridX; // 原始网格X索引
        int gridY; // 原始网格Y索引

        public Point(int x, int y, int gridX, int gridY) {
            this.x = x;
            this.y = y;
            this.gridX = gridX;
            this.gridY = gridY;
        }

        @Override
        public String toString() {
            return "(" + x + ", " + y + ") [Grid: " + gridX + "," + gridY + "]";
        }
    }

    /**
     * 从点阵中检索指定半径内的所有点。
     *
     * @param pointMatrix 存储点的三维数组
     * @param maxGridX    点阵的最大X索引
     * @param maxGridY    点阵的最大Y索引
     * @param centerX     圆心的X坐标
     * @param centerY     圆心的Y坐标
     * @param radius      检索半径
     * @return 位于指定半径内的点列表
     */
    public static List<Point> getPointsInRadius(int[][][] pointMatrix, int maxGridX, int maxGridY,
                                                int centerX, int centerY, int radius) {
        List<Point> pointsInRadius = new ArrayList<>();
        long radiusSquared = (long) radius * radius; // 预计算半径的平方

        for (int xn = 0; xn <= maxGridX; xn++) {
            for (int yn = 0; yn <= maxGridY; yn++) {
                int pointX = pointMatrix[xn][yn][0];
                int pointY = pointMatrix[xn][yn][1];

                long distSquared = calculateSquaredDistance(pointX, pointY, centerX, centerY);

                if (distSquared <= radiusSquared) {
                    pointsInRadius.add(new Point(pointX, pointY, xn, yn));
                }
            }
        }
        return pointsInRadius;
    }

    // 假设 calculateSquaredDistance 方法已定义

    public static void main(String[] args) {
        // 示例:使用前文定义的点阵生成逻辑
        int constant = 60;
        int width = 1080;
        int height = 1920;

        int padding_X = (int) Math.floor((width % constant) / 2f);
        if (padding_X == 0) padding_X = (int) Math.floor(constant / 2);
        int padding_Y = (int) Math.floor((height % constant) / 2f);
        if (padding_Y == 0) padding_Y = (int) Math.floor(constant / 2);

        int max_xn = Math.round((width - (padding_X * 2)) / constant);
        int max_yn = Math.round((height - (padding_Y * 2)) / constant);

        int[][][] point_matrix = new int[max_xn + 1][max_yn + 1][2];
        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));
                point_matrix[xn][yn][0] = x;
                point_matrix[xn][yn][1] = y;
            }
        }

        // 确定圆心和半径
        int centerX = width / 2;
        int centerY = height / 2;
        int targetRadius = 300; // 示例半径

        List<Point> points = getPointsInRadius(point_matrix, max_xn, max_yn, centerX, centerY, targetRadius);

        System.out.println("Found " + points.size() + " points within radius " + targetRadius + " from center (" + centerX + "," + centerY + "):");
        // points.forEach(System.out::println); // 打印所有点
    }
}
登录后复制

4. 实现圆形扩散/消失动画

要实现点从中心向外以圆形模式逐渐消失的动画效果,我们需要将点根据其到中心的距离进行分组。

分层半径区间: 我们可以定义一系列递增的半径区间,例如 [0, r1), [r1, r2), [r2, r3) 等。然后,将每个点归类到其所属的半径区间。

import java.util.Map;
import java.util.TreeMap; // 使用TreeMap保持半径区间的顺序

// 假设 Point 类和 calculateSquaredDistance 方法已定义

public class CircularAnimation {

    /**
     * 将点按距离中心点的半径区间进行分组。
     *
     * @param pointMatrix 点阵
     * @param maxGridX    点阵最大X索引
     * @param maxGridY    点阵最大Y索引
     * @param centerX     圆心X坐标
     * @param centerY     圆心Y坐标
     * @param radiusStep  每个半径区间的步长
     * @param maxRadius   最大考虑半径
     * @return 一个Map,键为半径区间的起始值,值为该区间内的点列表
     */
    public static Map<Integer, List<PointRetrieval.Point>> groupPointsByRadiusInterval(
            int[][][] pointMatrix, int maxGridX, int maxGridY,
            int centerX, int centerY, int radiusStep, int maxRadius) {

        // 使用TreeMap确保半径区间有序
        Map<Integer, List<PointRetrieval.Point>> pointsByRadiusInterval = new TreeMap<>();

        for (int xn = 0; xn <= maxGridX; xn++) {
            for (int yn = 0; yn <= maxGridY; yn++) {
                int pointX = pointMatrix[xn][yn][0];
                int pointY = pointMatrix[xn][yn][1];

                long distSquared = calculateSquaredDistance(pointX, pointY, centerX, centerY);
                double distance = Math.sqrt(distSquared); // 这里需要实际距离来分组

                if (distance <= maxRadius) {
                    // 计算点所属的半径区间起始值
                    int intervalStart = (int) (Math.floor(distance / radiusStep) * radiusStep);
                    pointsByRadiusInterval
                            .computeIfAbsent(intervalStart, k -> new ArrayList<>())
                            .add(new PointRetrieval.Point(pointX, pointY, xn, yn));
                }
            }
        }
        return pointsByRadiusInterval;
    }

    public static void main(String[] args) throws InterruptedException {
        // ... (点阵生成代码与上文相同) ...
        int constant = 60;
        int width = 1080;
        int height = 1920;

        int padding_X = (int) Math.floor((width % constant) / 2f);
        if (padding_X == 0) padding_X = (int) Math.floor(constant / 2);
        int padding_Y = (int) Math.floor((height % constant) / 2f);
        if (padding_Y == 0) padding_Y = (int) Math.floor(constant / 2);

        int max_xn = Math.round((width - (padding_X * 2)) / constant);
        int max_yn = Math.round((height - (padding_Y * 2)) / constant);

        int[][][] point_matrix = new int[max_xn + 1][max_yn + 1][2];
        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));
                point_matrix[xn][yn][0] = x;
                point_matrix[xn][yn][1] = y;
            }
        }

        int centerX = width / 2
登录后复制

以上就是从二维点阵中高效检索圆形区域点并实现动画效果的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

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