Reputation: 426
I'm trying to make rotatable rectangles but the rectangles don't show up where I expect them to be.
The black and blue rectangles are supposed to be rotating around the red dot but they are off center for some reason. The red rectangle is where the black one is supposed to be.
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;
}
}
The problem is most likely in the getStart or getEnd functions but I have no idea where I went wrong.
Upvotes: 0
Views: 116
Reputation: 551
You wrong in the getStart(int angle) methods, here:
int angle2 = ( angle + 180 + 45 ) % 360;
You assume that every rectangle is a square ( you add 45° degrees!). Infact your code is right if you use square (widht=height). You have to calculate the angle2 of c as the aTan of a/b.
So, to fix your code, the getStart method will be:
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 );
}
Hope I helped you!
Upvotes: 3