Java 旋转多边形使其变形
Java rotating a Polgon deforms it
我写了一个方法,它随机生成多边形形状,然后在屏幕上旋转和移动。因为我想检测与这些形状的碰撞,所以我没有使用 Graphics2D 旋转它们,而是使用 AffineTransform 来旋转它们。但出于某种原因,某些形状会因旋转而变得混乱,而其他形状则不受影响。以下是导致问题的形状之一的示例。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class Test extends JLabel{
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
private static final long serialVersionUID = 1L;
Polygon poly;
Point center;
Point source[];
Point dest[];
JFrame jf;
public Test() {
init();
createPolygon();
Timer timer = new Timer(20, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
rotatePoly();
repaint();
}});
timer.start();
}
public void rotatePoly() {
AffineTransform transf = AffineTransform.getRotateInstance(Math.toRadians(2), center.x, center.y);
transf.transform(source, 0, dest, 0, source.length);
poly = toPolygon(dest);
}
public Polygon toPolygon(Point[] points) {
Polygon polygon = new Polygon();
for (int i = 0; i < points.length; i++) {
polygon.addPoint(points[i].x, points[i].y);
}
return polygon;
}
public void createPolygon() {
Point points[] = new Point[7];
points[0] = new Point(20, 97);
points[1] = new Point(82, 70);
points[2] = new Point(134, 70);
points[3] = new Point(210, 88);
points[4] = new Point(210, 106);
points[5] = new Point(144, 125);
points[6] = new Point(82, 125);
source = points;
dest = points;
poly = toPolygon(points);
center = new Point(poly.getBounds().x + poly.getBounds().width / 2, poly.getBounds().y + poly.getBounds().height / 2);
}
public void init() {
setVisible(true);
setSize(260, 260);
jf = new JFrame();
jf.setVisible(true);
jf.setSize(260, 260);
jf.setContentPane(new JLabel());
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setLocation((screenSize.width / 2) - (getWidth() / 2), (screenSize.height / 2) - (getHeight() / 2));
jf.add(this);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.drawPolygon(poly);
}
}
如果用以下线条替换点,形状基本保持不变。下面的形状当然是对称的,但是旋转方法确实适用于其他随机生成的不均匀形状。
points[0] = new Point(10, 130);
points[1] = new Point(100, 10);
points[2] = new Point(160, 10);
points[3] = new Point(250, 100);
points[4] = new Point(250, 160);
points[5] = new Point(160, 250);
points[6] = new Point(100, 250);
这适用于您的 AffineTransform。它 returns 一个变形的形状而不是修改坐标。我还推荐:
JFrame.setLocationRelativeTo(null);
用于屏幕居中。
- 使用
RenderingHints
并启用抗锯齿来平滑图形。
- 由于 Polygon 实现了 Shape,因此需要重新输入一些位置。
class Text extends JLabel{
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
private static final long serialVersionUID = 1L;
Shape poly;
Point center;
Point source[];
Point dest[];
JFrame jf;
public static void main(String[] args) {
new Text();
}
public Text() {
init();
createPolygon();
Timer timer = new Timer(20, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
rotatePoly();
repaint();
}});
timer.start();
}
public void rotatePoly() {
AffineTransform transf =
AffineTransform.getRotateInstance(Math.toRadians(2), center.x, center.y);
poly = transf.createTransformedShape(poly);
}
public Shape toPolygon(Point[] points) {
Polygon polygon = new Polygon();
for (int i = 0; i < points.length; i++) {
polygon.addPoint(points[i].x, points[i].y);
}
return polygon;
}
public void createPolygon() {
Point points[] = new Point[7];
points[0] = new Point(20, 97);
points[1] = new Point(82, 70);
points[2] = new Point(134, 70);
points[3] = new Point(210, 88);
points[4] = new Point(210, 106);
points[5] = new Point(144, 125);
points[6] = new Point(82, 125);
source = points;
dest = points;
poly = toPolygon(points);
center = new Point(poly.getBounds().x + poly.getBounds().width / 2, poly.getBounds().y + poly.getBounds().height / 2);
}
public void init() {
setVisible(true);
setSize(260, 260);
jf = new JFrame();
jf.setVisible(true);
jf.setSize(260, 260);
jf.setContentPane(new JLabel());
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setLocation((screenSize.width / 2) - (getWidth() / 2), (screenSize.height / 2) - (getHeight() / 2));
jf.add(this);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.draw(poly);
}
}
问题主要是由于多边形使用整数坐标引起的。
不是在多边形本身中累积旋转,而是使用一个变量来保存角度,并在每次更改角度时根据原始多边形计算一个新的多边形。原来的多边形没有改变。
我尽量保持原代码1:
package cfh.test.sf;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class PolygonTest extends JLabel{
public static void main(String[] args) {
new PolygonTest();
}
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
private static final long serialVersionUID = 1L;
Polygon poly;
Shape rotated;
Point center;
int angle = 0;
JFrame jf;
public PolygonTest() {
init();
createPolygon();
Timer timer = new Timer(20, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
rotatePoly();
repaint();
}});
timer.start();
}
public void rotatePoly() {
angle += 2;
AffineTransform transf = AffineTransform.getRotateInstance(Math.toRadians(angle), center.x, center.y);
rotated = transf.createTransformedShape(poly);
}
public Polygon toPolygon(Point[] points) {
Polygon polygon = new Polygon();
for (int i = 0; i < points.length; i++) {
polygon.addPoint(points[i].x, points[i].y);
}
return polygon;
}
public void createPolygon() {
Point points[] = new Point[7];
points[0] = new Point(20, 97);
points[1] = new Point(82, 70);
points[2] = new Point(134, 70);
points[3] = new Point(210, 88);
points[4] = new Point(210, 106);
points[5] = new Point(144, 125);
points[6] = new Point(82, 125);
poly = toPolygon(points);
rotated = poly;
center = new Point(poly.getBounds().x + poly.getBounds().width / 2, poly.getBounds().y + poly.getBounds().height / 2);
}
public void init() {
setVisible(true);
setSize(260, 260);
jf = new JFrame();
jf.setVisible(true);
jf.setSize(260, 260);
jf.setContentPane(new JLabel());
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setLocation((screenSize.width / 2) - (getWidth() / 2), (screenSize.height / 2) - (getHeight() / 2));
jf.add(this);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.draw(rotated);
}
}
1 - 我宁愿在 paintComponent
内创建旋转形状,而不是在字段中添加其他形状。不确定 是否与程序的其余部分冲突(例如计算交集)
备选方案,未测试:使用 Point2D.Float
或 Point2D.Double
而不是 Point
作为坐标。
我写了一个方法,它随机生成多边形形状,然后在屏幕上旋转和移动。因为我想检测与这些形状的碰撞,所以我没有使用 Graphics2D 旋转它们,而是使用 AffineTransform 来旋转它们。但出于某种原因,某些形状会因旋转而变得混乱,而其他形状则不受影响。以下是导致问题的形状之一的示例。
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class Test extends JLabel{
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
private static final long serialVersionUID = 1L;
Polygon poly;
Point center;
Point source[];
Point dest[];
JFrame jf;
public Test() {
init();
createPolygon();
Timer timer = new Timer(20, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
rotatePoly();
repaint();
}});
timer.start();
}
public void rotatePoly() {
AffineTransform transf = AffineTransform.getRotateInstance(Math.toRadians(2), center.x, center.y);
transf.transform(source, 0, dest, 0, source.length);
poly = toPolygon(dest);
}
public Polygon toPolygon(Point[] points) {
Polygon polygon = new Polygon();
for (int i = 0; i < points.length; i++) {
polygon.addPoint(points[i].x, points[i].y);
}
return polygon;
}
public void createPolygon() {
Point points[] = new Point[7];
points[0] = new Point(20, 97);
points[1] = new Point(82, 70);
points[2] = new Point(134, 70);
points[3] = new Point(210, 88);
points[4] = new Point(210, 106);
points[5] = new Point(144, 125);
points[6] = new Point(82, 125);
source = points;
dest = points;
poly = toPolygon(points);
center = new Point(poly.getBounds().x + poly.getBounds().width / 2, poly.getBounds().y + poly.getBounds().height / 2);
}
public void init() {
setVisible(true);
setSize(260, 260);
jf = new JFrame();
jf.setVisible(true);
jf.setSize(260, 260);
jf.setContentPane(new JLabel());
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setLocation((screenSize.width / 2) - (getWidth() / 2), (screenSize.height / 2) - (getHeight() / 2));
jf.add(this);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.drawPolygon(poly);
}
}
如果用以下线条替换点,形状基本保持不变。下面的形状当然是对称的,但是旋转方法确实适用于其他随机生成的不均匀形状。
points[0] = new Point(10, 130);
points[1] = new Point(100, 10);
points[2] = new Point(160, 10);
points[3] = new Point(250, 100);
points[4] = new Point(250, 160);
points[5] = new Point(160, 250);
points[6] = new Point(100, 250);
这适用于您的 AffineTransform。它 returns 一个变形的形状而不是修改坐标。我还推荐:
JFrame.setLocationRelativeTo(null);
用于屏幕居中。- 使用
RenderingHints
并启用抗锯齿来平滑图形。 - 由于 Polygon 实现了 Shape,因此需要重新输入一些位置。
class Text extends JLabel{
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
private static final long serialVersionUID = 1L;
Shape poly;
Point center;
Point source[];
Point dest[];
JFrame jf;
public static void main(String[] args) {
new Text();
}
public Text() {
init();
createPolygon();
Timer timer = new Timer(20, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
rotatePoly();
repaint();
}});
timer.start();
}
public void rotatePoly() {
AffineTransform transf =
AffineTransform.getRotateInstance(Math.toRadians(2), center.x, center.y);
poly = transf.createTransformedShape(poly);
}
public Shape toPolygon(Point[] points) {
Polygon polygon = new Polygon();
for (int i = 0; i < points.length; i++) {
polygon.addPoint(points[i].x, points[i].y);
}
return polygon;
}
public void createPolygon() {
Point points[] = new Point[7];
points[0] = new Point(20, 97);
points[1] = new Point(82, 70);
points[2] = new Point(134, 70);
points[3] = new Point(210, 88);
points[4] = new Point(210, 106);
points[5] = new Point(144, 125);
points[6] = new Point(82, 125);
source = points;
dest = points;
poly = toPolygon(points);
center = new Point(poly.getBounds().x + poly.getBounds().width / 2, poly.getBounds().y + poly.getBounds().height / 2);
}
public void init() {
setVisible(true);
setSize(260, 260);
jf = new JFrame();
jf.setVisible(true);
jf.setSize(260, 260);
jf.setContentPane(new JLabel());
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setLocation((screenSize.width / 2) - (getWidth() / 2), (screenSize.height / 2) - (getHeight() / 2));
jf.add(this);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.draw(poly);
}
}
问题主要是由于多边形使用整数坐标引起的。
不是在多边形本身中累积旋转,而是使用一个变量来保存角度,并在每次更改角度时根据原始多边形计算一个新的多边形。原来的多边形没有改变。
我尽量保持原代码1:
package cfh.test.sf;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class PolygonTest extends JLabel{
public static void main(String[] args) {
new PolygonTest();
}
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
private static final long serialVersionUID = 1L;
Polygon poly;
Shape rotated;
Point center;
int angle = 0;
JFrame jf;
public PolygonTest() {
init();
createPolygon();
Timer timer = new Timer(20, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
rotatePoly();
repaint();
}});
timer.start();
}
public void rotatePoly() {
angle += 2;
AffineTransform transf = AffineTransform.getRotateInstance(Math.toRadians(angle), center.x, center.y);
rotated = transf.createTransformedShape(poly);
}
public Polygon toPolygon(Point[] points) {
Polygon polygon = new Polygon();
for (int i = 0; i < points.length; i++) {
polygon.addPoint(points[i].x, points[i].y);
}
return polygon;
}
public void createPolygon() {
Point points[] = new Point[7];
points[0] = new Point(20, 97);
points[1] = new Point(82, 70);
points[2] = new Point(134, 70);
points[3] = new Point(210, 88);
points[4] = new Point(210, 106);
points[5] = new Point(144, 125);
points[6] = new Point(82, 125);
poly = toPolygon(points);
rotated = poly;
center = new Point(poly.getBounds().x + poly.getBounds().width / 2, poly.getBounds().y + poly.getBounds().height / 2);
}
public void init() {
setVisible(true);
setSize(260, 260);
jf = new JFrame();
jf.setVisible(true);
jf.setSize(260, 260);
jf.setContentPane(new JLabel());
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setLocation((screenSize.width / 2) - (getWidth() / 2), (screenSize.height / 2) - (getHeight() / 2));
jf.add(this);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
g2d.draw(rotated);
}
}
1 - 我宁愿在 paintComponent
内创建旋转形状,而不是在字段中添加其他形状。不确定 是否与程序的其余部分冲突(例如计算交集)
备选方案,未测试:使用 Point2D.Float
或 Point2D.Double
而不是 Point
作为坐标。