Java矩形轮换问题

时间:2015-09-01 14:18:09

标签: java swing awt

我试图制作可旋转的矩形,但矩形不会显示在我期望的位置。

screenshot of the problem

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

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函数中,但我不知道我哪里出错了。

1 个答案:

答案 0 :(得分:3)

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

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

您假设每个矩形都是正方形(您添加45°度!)。事实上,如果你使用square(widht = height)你的代码是正确的。 您必须将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 );
        }

希望我帮助过你!