https://blog.csdn.net/qq_39081315/article/details/121393597
先生成一个点,每生成一个点判断距离,角度,满足加入存点的容器,直到容器大小为4。
随机生成点:
分区域:最大距离20,以20为正方形划分区域为20*20网格,产生点时,先随机挑选一个网格,每次挑选的网格不能是同一个,后续挑选的网格,不能同一列,同一行,且网格之间间隔至少一个网格(不用判断距离)。挑选出网格后在再网格中随机挑选一个点,但还需要判断角度,通过这样缩小随机范围,避免多次尝试。
效果
代码(直接随机版,无网格)
package org.example.Other;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* @Description: TODO
* @Author: sats@jz
* @Date: 2025/1/13 14:04
**/
public class TrajectoryDrawingApp extends JFrame {
private final int WIDTH = 400;
private final int HEIGHT = 400;
/*
*距离
*/
private final int MIN_DISTANCE = 30;
/*
* 角度
*/
private final int MAX_JD = 20;
/*
* 产生点的信息
*/
private List<Point> fixedPoints;
/*
* 用户轨迹
*/
private List<Point> userTrajectory;
public TrajectoryDrawingApp() {
setTitle("轨迹绘制,按照点绘制");
setSize(WIDTH, HEIGHT);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
fixedPoints = generatePoints(4);
userTrajectory = new ArrayList<>();
DrawingPanel panel = new DrawingPanel();
add(panel);
setVisible(true);
}
private List<Point> generatePoints(int numPoints) {
List<Point> points = new ArrayList<>();
while (points.size() < numPoints) {
Point newPoint = Point(points);
if (isValidPoint(newPoint, points)) {
points.add(newPoint);
}
}
System.out.println("产生点的信息: " + points);
return points;
}
/* 根据已经产生的点
* 缩小随机数范围, 待续
*/
private Point Point(List<Point> pointList){
Random random = new Random();
return new Point(random.nextInt(WIDTH), random.nextInt(HEIGHT));
}
private boolean isValidPoint(Point point, List<Point> points) {
// 距离
for (Point p : points) {
if (point.distance(p) < MIN_DISTANCE) {
return false;
}
}
// 角度
if (points.size() >= 2) {
Point p1 = points.get(points.size() - 2);
Point p2 = points.get(points.size() - 1);
double angle = calculateAngle(p1, p2, point);
if (Math.abs(angle - 180) < MAX_JD) {
return false;
}
}
return true;
}
/*
* 计算三个点的角度
* 向量p2,p1
* 向量p3,p2
* 注意传点先后顺序
*/
private static double calculateAngle(Point p1, Point p2, Point p3) {
double v1x = p2.x - p1.x, v1y = p2.y - p1.y;
double v2x = p3.x - p2.x, v2y = p3.y - p2.y;
double dotProduct = v1x * v2x + v1y * v2y;
double mag1 = Math.sqrt(v1x * v1x + v1y * v1y);
double mag2 = Math.sqrt(v2x * v2x + v2y * v2y);
return Math.toDegrees(Math.acos(dotProduct / (mag1 * mag2)));
}
private class DrawingPanel extends JPanel {
public DrawingPanel() {
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
userTrajectory.clear();
}
@Override
public void mouseReleased(MouseEvent e) {
System.out.println("鼠标轨迹:");
for (Point p : userTrajectory) {
System.out.println("(" + p.x + ", " + p.y + ")");
}
}
});
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
userTrajectory.add(e.getPoint());
repaint();
}
});
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// 产生的点
g.setColor(Color.RED);
for (int i = 0; i < fixedPoints.size(); i++) {
Point p = fixedPoints.get(i);
g.fillOval(p.x - 5, p.y - 5, 10, 10);
// int labelX = Math.min(p.x + 10, WIDTH - 30); // 文字右边界离画布边缘留出空间
// int labelY = Math.max(p.y, 10);
g.drawString("P" + (i + 1), p.x + 10, p.y);
}
// 鼠标
g.setColor(Color.BLUE);
for (int i = 1; i < userTrajectory.size(); i++) {
Point p1 = userTrajectory.get(i - 1);
Point p2 = userTrajectory.get(i);
g.drawLine(p1.x, p1.y, p2.x, p2.y);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(TrajectoryDrawingApp::new);
}
}