当前位置: 首页 > 知识库问答 >
问题:

Java旋转多边形使其变形

傅浩漫
2023-03-14

我写了一个方法,随机生成多边形形状,然后在屏幕上旋转和移动。因为我想检测与这些形状的碰撞,所以我没有使用Graphics2D旋转它们,而是使用仿射变换来旋转它们。但由于某些原因,某些形状被旋转弄得一团糟,而其他形状则不受影响。下面是一个导致问题的形状示例。

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);

共有2个答案

卞嘉许
2023-03-14

该问题主要是由于对多边形使用整数坐标引起的
不是累积多边形本身的旋转,而是使用一个变量来保持角度,并在每次角度更改时基于原始多边形计算新多边形。原始多边形不变。

我试图尽可能地维护原始代码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);

    }
}

我宁愿在paintComponent中创建旋转的形状,而不是在字段中创建其他形状。不确定这是否与程序的其余部分冲突(例如计算交叉点)

替代方法,未经测试:使用Point2D. FloatPoint2D. Double代替Point作为坐标。

田仲卿
2023-03-14

这适用于仿射变换。它返回变换后的形状,而不是修改坐标。我还建议:

  • <代码>JFrame。setLocationRelativeTo(空) 用于在屏幕上居中
  • 使用启用抗锯齿的渲染提示来平滑图形
  • 由于多边形实现形状,因此需要重新键入一些位置
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);

    }
}
 类似资料:
  • 我可以轻松地做0度和180度的旋转。我可以从旋转60度几次得到60度的其他倍数。 但我想不出一个算法来做到这一点。

  • 问题内容: 我到处搜索,但找不到答案。 如何在Java中旋转矩形? 这是我的一些代码: 我尝试了g2d.rotate(100D); 但它没有用。提前致谢。 这是我编辑的代码: 问题答案: 对于图像,必须将Graphics2D的drawImage方法与相对的AffineTransform一起使用。 对于形状,您可以旋转Graphics2D本身: 顺便说一句,您应该重写paintComponent方法

  • 问题内容: 我需要创建围绕其中心旋转的矩形(因此它们不必平行于坐标系的轴)。因此,基本上每个矩形都可以由 center-X , center-Y , width , height 和 angle定义 。然后,我要做的是对这些矩形中是否包含某些点进行计算(因此不会涉及任何绘图)。我想我不能使用该类,因为这些矩形将始终与坐标系的x和y轴平行。是通过编写自己的矩形类来获得此功能的唯一方法,还是可以使用任

  • 我正在寻找一种方法来创建一组多边形(rechtangles),沿着一条线在多个多边形中创建一组多边形(rechtangles),并将其水平隔开,如图所示。 我尝试生成点并将其用作多边形的中点,但问题是,通过创建等间距的点光栅,除了180度之外,不可能以任何其他方向旋转。 例子 给出了一个多多边形形状的对象和由宽度和高度以及每个多边形之间的垂直和水平间距定义的多边形。多边形应仅放置在多多边形内,且不

  • 返回顶点的输入数组,并且附有一些其他方法,如下面所描述 polygon.area() 返回此多边形的标定区域。如果顶点是逆时针顺序,面积为正,否则为负。 polygon.centroid() 返回一个表示此多边形的质心的两元素数组。 polygon.clip(subject) 对这个多边形剪切主题多边形。换句话说,返回一个多边形表示这个多边形和主题多边形的交集。假定剪切的多边形是逆时针方向以及凸多

  • 我希望通过一条线串拆分一个多多边形(代表一个有岛屿的国家),从而将该县一分为二。 此结果是GeometryCollection对象中的一组多边形。如何将结果分组为两个多多边形对象,每个对象都包含各自一半的多边形? 使现代化 问题:确定分裂形状几何的“左”和“右”侧提供了一个很好的解决方案,其中从结果中的每个多边形中提取一个点,看看当与分裂的LineString结合时,它是否形成顺时针或逆时针线串。