
在处理二维图形和动画时,我们经常需要管理大量的离散点。本场景中,点被组织成一个二维网格(或点阵),并存储在一个三维数组 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"));
}
}要检索圆形区域内的点,首先需要确定圆心坐标和半径。圆心可以是画布的几何中心,也可以是点阵的逻辑中心。
确定圆心: 如果以画布中心为圆心: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;
}有了距离计算方法,检索指定半径内的点就变得简单直接。我们只需遍历 point_matrix 中的所有点,对每个点计算其到圆心的平方距离,并与目标半径的平方进行比较。
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); // 打印所有点
}
}要实现点从中心向外以圆形模式逐渐消失的动画效果,我们需要将点根据其到中心的距离进行分组。
分层半径区间: 我们可以定义一系列递增的半径区间,例如 [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中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号