import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
public class RotatingTriangle extends JPanel {
private Point[] triangleVertices1;
private Point[] triangleVertices2;
private Point rotationCenter = new Point(200, 200); // 旋转中心点
private double angle1 = 0; // 第一个三角形的旋转角度
private double angle2 = 0; // 第二个三角形的旋转角度
private final int ROTATION_SPEED1 = 2; // 第一个三角形的旋转速度(度/帧)
private final int ROTATION_SPEED2 = 4; // 第二个三角形的旋转速度(度/帧) - 设为2倍
private final int sideLength = 100;
private int currentVertexIndex = 0; // 当前使用的顶点索引(0,1,2)
public RotatingTriangle() {
// 初始化三角形顶点
triangleVertices1 = calculateTriangleVertices1(rotationCenter, sideLength);
triangleVertices2 = calculateTriangleVertices2(triangleVertices1[currentVertexIndex], sideLength);
// 创建动画定时器
Timer timer = new Timer(50, e -> {
angle1 = (angle1 + ROTATION_SPEED1) % 360;
angle2 = (angle2 + ROTATION_SPEED2) % 360;
// 获取旋转后的顶点位置
Point rotatedVertex = getRotatedPoint(triangleVertices1[currentVertexIndex], rotationCenter, angle1);
triangleVertices2 = calculateTriangleVertices2(rotatedVertex, sideLength);
// 获取旋转后的三角形1的所有顶点
Point[] rotatedTriangle1 = new Point[3];
for (int i = 0; i < 3; i++) {
rotatedTriangle1[i] = getRotatedPoint(triangleVertices1[i], rotationCenter, angle1);
}
// 获取旋转后的三角形2的所有顶点
Point[] rotatedTriangle2 = new Point[3];
for (int i = 0; i < 3; i++) {
rotatedTriangle2[i] = getRotatedPoint(triangleVertices2[i], rotatedVertex, angle2);
}
// 检查非旋转顶点是否重合
boolean shouldSwitch = false;
for (int i = 0; i < 3; i++) {
if (i == currentVertexIndex) continue; // 跳过旋转顶点
for (int j = 0; j < 3; j++) {
if (j == 0) continue; // 跳过旋转顶点
if (distance(rotatedTriangle1[i], rotatedTriangle2[j]) < 5) {
shouldSwitch = true;
break;
}
}
if (shouldSwitch) break;
}
if (shouldSwitch) {
currentVertexIndex = (currentVertexIndex + 1) % 3; // 切换到下一个顶点
rotatedVertex = getRotatedPoint(triangleVertices1[currentVertexIndex], rotationCenter, angle1);
triangleVertices2 = calculateTriangleVertices2(rotatedVertex, sideLength);
}
repaint();
});
timer.start();
}
// 计算两点之间的距离
private double distance(Point p1, Point p2) {
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
}
// 计算旋转后的点
private Point getRotatedPoint(Point original, Point center, double angleDegrees) {
double angleRad = Math.toRadians(angleDegrees);
double sin = Math.sin(angleRad);
double cos = Math.cos(angleRad);
// 平移点到原点
int translatedX = original.x - center.x;
int translatedY = original.y - center.y;
// 应用旋转
int rotatedX = (int)(translatedX * cos - translatedY * sin);
int rotatedY = (int)(translatedX * sin + translatedY * cos);
// 平移回原位置
return new Point(rotatedX + center.x, rotatedY + center.y);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// 启用抗锯齿
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// 绘制第一个三角形
Path2D path1 = new Path2D.Double();
path1.moveTo(triangleVertices1[0].x, triangleVertices1[0].y);
path1.lineTo(triangleVertices1[1].x, triangleVertices1[1].y);
path1.lineTo(triangleVertices1[2].x, triangleVertices1[2].y);
path1.closePath();
// 绘制第二个三角形
Path2D path2 = new Path2D.Double();
path2.moveTo(triangleVertices2[0].x, triangleVertices2[0].y);
path2.lineTo(triangleVertices2[1].x, triangleVertices2[1].y);
path2.lineTo(triangleVertices2[2].x, triangleVertices2[2].y);
path2.closePath();
// 保存原始变换
AffineTransform oldTransform = g2d.getTransform();
// 应用第一个三角形的旋转变换
g2d.rotate(Math.toRadians(angle1), rotationCenter.x, rotationCenter.y);
// 绘制旋转后的第一个三角形
g2d.setColor(new Color(70, 130, 180, 150)); // 半透明钢蓝色
g2d.fill(path1);
g2d.setColor(Color.BLUE);
g2d.draw(path1);
// 恢复原始变换
g2d.setTransform(oldTransform);
// 应用第二个三角形的旋转变换(基于当前选定的顶点)
Point rotatedVertex = getRotatedPoint(triangleVertices1[currentVertexIndex], rotationCenter, angle1);
g2d.rotate(Math.toRadians(angle2), rotatedVertex.x, rotatedVertex.y);
// 绘制旋转后的第二个三角形
g2d.setColor(new Color(180, 70, 130, 150)); // 不同颜色
g2d.fill(path2);
g2d.setColor(Color.RED);
g2d.draw(path2);
// 恢复原始变换
g2d.setTransform(oldTransform);
// 标记旋转中心(红色)
g2d.setColor(Color.RED);
g2d.fillOval(rotationCenter.x-5, rotationCenter.y-5, 10, 10);
// 显示当前角度和旋转点
g2d.setColor(Color.BLACK);
g2d.drawString("大三角形角度: " + (int)angle1 + "°", 10, 20);
g2d.drawString("小三角形角度: " + (int)angle2 + "°", 10, 40);
g2d.drawString("当前旋转点: 顶点" + (currentVertexIndex + 1), 10, 60);
}
private Point[] calculateTriangleVertices1(Point center, int sideLength) {
Point[] vertices = new Point[3];
double height = (Math.sqrt(3) / 2) * sideLength;
vertices[0] = new Point(center.x, center.y - (int)(height * 2 / 3));
vertices[1] = new Point(center.x + sideLength / 2, center.y + (int)(height / 3));
vertices[2] = new Point(center.x - sideLength / 2, center.y + (int)(height / 3));
return vertices;
}
private Point[] calculateTriangleVertices2(Point vertex, int sideLength) {
Point[] vertices = new Point[3];
double height = (Math.sqrt(3) / 2) * sideLength;
vertices[0] = new Point(vertex.x, vertex.y);
vertices[1] = new Point(vertex.x + sideLength / 2, vertex.y + (int)height);
vertices[2] = new Point(vertex.x - sideLength / 2, vertex.y + (int)height);
return vertices;
}
public static void main(String[] args) {
JFrame frame = new JFrame("双三角形旋转");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.add(new RotatingTriangle());
frame.setVisible(true);
}
}