【问题标题】:Java Rectangle Rotation issueJava矩形旋转问题
【发布时间】:2015-09-02 00:20:01
【问题描述】:

我正在尝试制作可旋转的矩形,但矩形没有显示在我期望的位置。

黑色和蓝色矩形应该围绕红点旋转,但由于某种原因它们偏离了中心。红色矩形应该是黑色矩形。

sscce:

package test;

import java.awt.Dimension;
import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Color;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import javax.swing.SwingUtilities;
import java.util.List;
import java.util.ArrayList;

public class RectangleTest
{
    public RectangleTest()
    {
        SwingUtilities.invokeLater( new Runnable()
        {
            @Override
            public void run()
            {
                JFrame frame = new JFrame( "Rectangle Test" );
                frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

                JPanel panel = new VTPanel();
                frame.add( panel );

                frame.pack();
                frame.setVisible( true );
            }
        });
    }

    public static void main( String[] args )
    {
        new RectangleTest();
    }
}

class VTPanel extends JPanel
{
    private List<RotatableRectangle> rectlist;

    public VTPanel()
    {
        int angle = 45;
        Location start = new Location( 200 , 200 );
        int w = 50;
        int h = 25;
        rectlist = new ArrayList<>();
        for( int i=0;i<2;i++)
        {
            rectlist.add( new RotatableRectangle( start , w , h , angle ) );
            angle += angle;
        }       
    }

    @Override
    protected void paintComponent( Graphics g )
    {
        super.paintComponent( g );
        Graphics2D g2 = (Graphics2D) g;

        g2.setColor( Color.BLUE );
        for( RotatableRectangle rr : rectlist )
        {
            g2.draw( rr.getPath() );
            g2.setColor( Color.BLACK );
        }
        g2.setColor(Color.RED);
        g2.fill( new Rectangle2D.Double( 200,200,1,1) );
        g2.draw( new Rectangle2D.Double( 175,187.5,50,25) );
    }

    @Override
    public Dimension getPreferredSize()
    {
        return new Dimension( 800 , 600 );
    }
}

class RotatableRectangle
{
    private Path2D path;
    private Location center;
    private int width;
    private int height;

    public RotatableRectangle( Location center, int width , int height , int angle )
    {
        this.center = center;
        this.width = width;
        this.height = height;
        path = createPath( angle );
    }

    public Path2D getPath()
    {
        return path;
    }

    public void setAngle( int angle )
    {
        path = createPath( angle );
    }

    private Path2D createPath( int angle )
    {
        Path2D p = new Path2D.Double( Path2D.WIND_EVEN_ODD );
        boolean flip = false;
        Location start = getStart( angle );
        p.moveTo( start.X , start.Y );
        for( int i=0;i<4;i++)
        {
            int length;
            if( flip )
            {
                length = height;
            }
            else
            {
                length = width;
            }
            Location next = getEnd( length , angle , start );
            p.lineTo( next.X , next.Y);
            angle = ( angle + 90 ) % 360;
            start = next;
            flip = !flip;
        }
        p.closePath();
        return p;
    }

    private Location getStart( int angle )
    {
        double a = width / 2.0;
        double b = height / 2.0;
        double c = Math.sqrt( ( a * a ) + ( b * b ) );
        int angle2 = ( angle + 180 + 45 ) % 360;
        return getEnd( c , angle2 , center );
    }

    private Location getEnd( double length , int angle , Location start )
    {
        int w = (int) Math.round( Math.sin( Math.toRadians( angle ) ) * length );
        int h = (int) Math.round( Math.cos( Math.toRadians( angle ) ) * length );
        int x = start.X + w;
        int y = start.Y - h;        
        return new Location( x , y );
    }
}

class Location
{
    public final int X, Y;

    public Location( int x , int y )
    {
        X = x;
        Y = y;
    }   
}

问题很可能出在 getStart 或 getEnd 函数中,但我不知道哪里出错了。

【问题讨论】:

  • 仅供参考,您正在重新实现 Java 中已经存在的类。查看矩形、点(与位置)及其 2D 版本
  • 我平时使用的位置比较宽泛一些,正常的矩形类不旋转
  • 您应该在某个时候从度数切换到弧度或圆(即 360 度 = 1 个圆)。 360 度是来自 4000 年巴比伦历法的神器,用于跟踪一年中的哪一天(日历是 360 天)
  • 仅供参考,jere 是我为操纵 Areas: sourceforge.net/p/tus/code/HEAD/tree/tjacobs/ui/shape 而放在一起的软件包,我认为可能对你很有帮助

标签: java swing awt


【解决方案1】:

你在 getStart(int angle) 方法中错了,这里:

int angle2 = ( angle + 180 + 45 ) % 360;

您假设每个矩形都是正方形(添加 45° 度!)。事实上,如果您使用正方形(宽度 = 高度),您的代码是正确的。 您必须将 c 的 angle2 计算为 a/b 的 aTan。

因此,要修复您的代码,getStart 方法将是:

 private Location getStart( int angle )
        {
            double a = width / 2.0;
            double b = height / 2.0;
            double c = Math.sqrt( ( a * a ) + ( b * b ) );

            int ang= (int) Math.toDegrees(Math.atan( Math.min(a,b)/Math.max(a,b))) ;

            int angle2 = ( angle + 180 + ang ) % 360;
            return getEnd( c , angle2 , center );
        }

希望能帮到你!

【讨论】:

  • 我知道它是那么小。谢谢。
猜你喜欢
  • 1970-01-01
  • 2011-05-07
  • 1970-01-01
  • 2013-07-12
  • 2012-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多