仅使用线条和仿射变换来绘制多边形

Posted

技术标签:

【中文标题】仅使用线条和仿射变换来绘制多边形【英文标题】:Using only lines and affine transforms to draw polygons 【发布时间】:2019-12-23 19:08:43 【问题描述】:

所以基本上我想要做的是仅使用仿射变换和单个绘制语句绘制具有任意边数的多边形:g2.draw(new Line2D(0,0,1,0)。是的,我知道有一个drawPolygon 函数——这不是这个问题的重点。为简单起见,多边形是“规则”多边形,这意味着它的所有边和边之间的角度都相同。

主要问题是我不完全理解如何让点正确对齐:

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class PolygonDrawer extends JComponent implements Runnable, ChangeListener 

    JFrame jframe;

    public PolygonDrawer() 
        SwingUtilities.invokeLater(this);
    

    public static void main(String[] args) 
        System.setProperty("awt.useSystemAAFontSettings","on");
        new PolygonDrawer();
    

    public Dimension getPreferredSize() 
        return new Dimension(200, 200);
    

    public void run() 
        jframe = new JFrame("PolygonDrawer");
        jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel mainpanel = new JPanel();
        mainpanel.setLayout(new BorderLayout());
        mainpanel.add(this, BorderLayout.CENTER);
        jframe.getContentPane().add(mainpanel);
        jframe.setVisible(true);
        jframe.pack();
    

    @Override
    public void stateChanged(ChangeEvent e) 
        repaint();
    

    @Override
    protected void paintComponent(Graphics g) 
        // Configuration stuff
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        Dimension dim = this.getSize();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        // Fill background
        g2.setColor(Color.white);
        g2.fillRect(0, 0, dim.width, dim.height);

        g2.setColor(Color.black);
        AffineTransform save = g2.getTransform();
        // Example polygon is a regular square
        int noVertices = 4;
        int rotationAngleInDegrees = 90;

        for (int i = 0; i < noVertices; i++) 
            g2.setTransform(save);
            AffineTransform at = new AffineTransform();
            at.rotate(Math.toRadians(i + 1) * rotationAngleInDegrees);
            at.translate(save.getTranslateX(), save.getTranslateY());
            at.scale(100, 1);
            g2.setTransform(at);
            g2.draw(new Line2D.Double(0.0,0.0,1.0,0.0));
            save = g2.getTransform();
        
    

我想要的只是在我的屏幕上绘制的一个正方形。然而,这些线条到处都是……我猜这与save 的使用方式有关。

【问题讨论】:

这看起来很奇怪:at.rotate(Math.toRadians(i + 1) * rotationAngleInDegrees);你用的是弧度还是度数?我认为这是括号的错误。 所以您想绘制一条线,然后使用AffineTransform 创建构成所需多边形的剩余线,对吗? 如需更好的帮助,请edit添加minimal reproducible example或Short, Self Contained, Correct Example。 @Abra 这是正确的。 你见过How to rotate a line based on a given number of degrees 吗? 【参考方案1】:

这使用了 affineTransforms 和一个 draw 语句。希望对您有所帮助。


    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.geom.AffineTransform;
    import java.awt.geom.Line2D;

    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;

    public class PolygonDrawer extends JPanel 

       JFrame jframe;
       int    WIDTH  = 500;
       int    HEIGHT = 500;
       int    AX     = 100; 
       int    AY     = 100;

       public static void main(String[] args) 
          SwingUtilities.invokeLater(() -> new PolygonDrawer().start());
       
       public void start() 
          jframe = new JFrame("PolygonDrawer");
          jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          setPreferredSize(new Dimension(WIDTH, HEIGHT));
          jframe.add(this);
          jframe.pack();
          jframe.setLocationRelativeTo(null);
          jframe.setVisible(true);
       

       @Override
       protected void paintComponent(Graphics g) 
          // Configuration stuff
          super.paintComponent(g);
          Graphics2D g2d = (Graphics2D) g.create();
          Dimension dim = this.getSize();
          g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
          // Fill background
          g2d.setColor(Color.white);
          g2d.fillRect(0, 0, dim.width, dim.height);

          g2d.setColor(Color.black);
          AffineTransform af = g2d.getTransform();

          int noVertices = 6;
          double rotationAngle = ((2 * Math.PI) / noVertices);
          double x1 = WIDTH / 2 - AX;
          double y1 = HEIGHT / 2 - AY;
          af.translate(x1, y1);
          for (int i = 0; i < noVertices; i++) 
             af.rotate(rotationAngle, AX, AY);
             double x2 = af.getTranslateX();
             double y2 = af.getTranslateY();
             g2d.draw(new Line2D.Double(x1, y1, x2, y2));
             x1 = x2;
             y1 = y2;
          
       
    

【讨论】:

以上是关于仅使用线条和仿射变换来绘制多边形的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL基础仿射变换原理解析

Halcon二维仿射变换实例探究

仿射变换

对图像的仿射变换

【转】仿射变换及其变换矩阵的理解

OpenCV图像变换(仿射变换与透视变换)