I need help with Translating, Rotating, and Scaling a Yin-Yang Symbol in Java. Can anyone provide suggestions I'll post the code below. I'm trying to use affine transformation does anyone have a way to make sure every part follows suit when I decide to move rotate, translate, scale?
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
public class ScaleTranslationRotation extends JFrame
{
public void paint(Graphics g){
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
int xLeft,yUpper,width, height;
xLeft = this.getInsets().left;
yUpper = this.getInsets().top;
width = this.getWidth()-xLeft-this.getInsets().right;
height = this.getHeight()-this.getInsets().top-this.getInsets().bottom;
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
int radius = (int)(Math.min(getWidth(), getHeight()) * 0.2);
int x = xCenter - radius;
int y = yCenter - radius;
AffineTransform yUp = new AffineTransform();
g.setColor(Color.blue);
g.fillOval(x, y, 2 * radius, 2 * radius);
g.setColor(Color.cyan);
g.drawOval(x, y, 2 * radius, 2 * radius);
g.setColor(Color.cyan);
g.fillArc(x, y, 2 * radius, 2 * radius, 270, 180);
g.setColor(Color.blue);
g.fillOval(x + (radius / 2), y, radius, radius);
g.setColor(Color.cyan);
g.fillOval(x + (radius / 2), y + radius, radius, radius);
g.setColor(Color.cyan);
g.fillOval(x + radius - (radius / 4), y + radius / 4, radius / 2, radius / 2);
g.setColor(Color.blue);
g.fillOval(x + radius - (radius / 4), y + radius + radius / 4, radius / 2, radius / 2);
g2d.setStroke(new BasicStroke(1.0f));
g.setColor(Color.red);
drawSimpleCoordinateSystem(width,height, g2d);
grid(width, height, g2d);
}
public static void drawSimpleCoordinateSystem(int x, int y, Graphics2D g2d){
int xOffset = 30;
int yOffset = 50;
int step = 20;
String s;
//Remember the actual font.
Font fo = g2d.getFont();
//Use a small font.
g2d.setFont(new Font("sansserif",Font.PLAIN,9));
//x-axis.
g2d.drawLine(xOffset,yOffset,x,yOffset);
//Marks and labels for the x-axis.
for (int i=xOffset+step; i<=x; i=i+step)
{
g2d.drawLine(i,yOffset-2,i,yOffset+2);
g2d.drawString(String.valueOf(i),i-7,yOffset-7);
}
//y-axis.
g2d.drawLine(xOffset,yOffset,xOffset,y);
//Marks and labels for the y-axis.
s=" "; //for indention of numbers < 100
for (int i=yOffset+step; i<=y; i=i+step){
g2d.drawLine(xOffset-2,i,xOffset+2,i);
if (i>99){s="";}
g2d.drawString(s+String.valueOf(i),xOffset-25,i+5);
}
//Reset to the original font.
g2d.setFont(fo);
}
public void grid(int x, int y, Graphics2D g2d){
int xOffset = 30;
int yOffset = 50;
int step = 20;
g2d.drawLine(xOffset, yOffset, x, yOffset);
for(int i = xOffset+step; i<= x; i = i+step){
g2d.drawLine(i, yOffset, i, y);
}
g2d.drawLine(xOffset, yOffset, xOffset, y);
for(int i = yOffset+step; i<=y; i = i+step){
g2d.drawLine(xOffset, i, x, i);
}
}
public static void main(String[] args)
{
ScaleTranslationRotation f = new ScaleTranslationRotation();
f.setTitle("STR");
f.setSize(1920,1020);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Just put your code yin-yang symbol code in a method
private void drawSymbol(int x, int y, int radius, Graphics g) {
g.setColor(Color.blue);
g.fillOval(x, y, 2 * radius, 2 * radius);
g.setColor(Color.cyan);
g.drawOval(x, y, 2 * radius, 2 * radius);
g.setColor(Color.cyan);
g.fillArc(x, y, 2 * radius, 2 * radius, 270, 180);
g.setColor(Color.blue);
g.fillOval(x + (radius / 2), y, radius, radius);
g.setColor(Color.cyan);
g.fillOval(x + (radius / 2), y + radius, radius, radius);
g.setColor(Color.cyan);
g.fillOval(x + radius - (radius / 4), y + radius / 4, radius / 2, radius / 2);
g.setColor(Color.blue);
g.fillOval(x + radius - (radius / 4), y + radius + radius / 4, radius / 2, radius / 2);
}
And then use an Affine transformation before calling the method to perform the requested transformation.
In the following I draw the symbol three times with different transformation
Remember to restore the original affine transformation to the initial value:
drawSymbol(x,y,radius,g);
//save original transformation
AffineTransform oldt=((Graphics2D) g).getTransform();
//create new transformation and apply it
AffineTransform yUp = new AffineTransform();
yUp.translate(0,-100);
((Graphics2D) g).setTransform(yUp);
drawSymbol(x,y,radius,g);
//create anothernew transformation and apply it
yUp = new AffineTransform();
yUp.translate(-100,0);
((Graphics2D) g).setTransform(yUp);
drawSymbol(x,y,radius,g);
//restore old transforamtion
((Graphics2D) g).setTransform(oldt);
g2d.setStroke(new BasicStroke(1.0f));
g.setColor(Color.red);
drawSimpleCoordinateSystem(width,height, g2d);
grid(width, height, g2d);
Related
I am trying to understand the use of Java's Arc2D. Don't know how to calculate the start angle and extent when creating an arc out of an ellipse (not a circle). I want an arc of an ellipse with ry = 2 * rx where the start angle is at 45 deg and the extent is 90 deg. But instead I have to send a start angle of ~26 deg and an extent of ~127 deg to get what I expect. The included code generates an image with 3 arcs: green is a circle arc which behaves as expected, red is an ellipse arc with the expected parameters but unexpected results and blue is an arc with unexpected parameters but the expected result. Am I misinterpreting something here? In addition, at start angle of 0 deg and extent 90 deg the results are as expected??? Thx.
package example;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Arc2D;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
public class ExampleArc2D {
public static void main(String[] args) {
try {
int width = 800;
int height = 800;
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D gfx2D = bi.createGraphics();
gfx2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
gfx2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
gfx2D.setFont(new Font(Font.MONOSPACED, Font.BOLD, 16));
FontMetrics fm = gfx2D.getFontMetrics();
gfx2D.setColor(Color.BLACK);
gfx2D.fillRect(0, 0, bi.getWidth(), bi.getHeight());
gfx2D.setStroke(new BasicStroke(2f));
int x = 5;
int y = 0;
int centerX = width / 2;
int centerY = height / 2 + 200;
int circleRadius = 200;
int ellipseRadiusX = circleRadius;
int ellipseRadiusY = 2 * circleRadius;
// gfx2D.setColor(new Color(255, 255, 255, 50));
// gfx2D.draw(new Ellipse2D.Double(centerX - circleRadius, centerY - circleRadius, 2 * circleRadius, 2 * circleRadius));
// gfx2D.draw(new Ellipse2D.Double(centerX - ellipseRadiusY, centerY - ellipseRadiusY, 2 * ellipseRadiusY, 2 * ellipseRadiusY));
// gfx2D.draw(new Ellipse2D.Double(centerX - ellipseRadiusX, centerY - ellipseRadiusY, 2 * ellipseRadiusX, 2 * ellipseRadiusY));
double startAngle = 45.0;
double extent = 90.0;
Arc2D circle = new Arc2D.Double(centerX - circleRadius, centerY - circleRadius, 2 * circleRadius, 2 * circleRadius, startAngle, extent, Arc2D.PIE);
gfx2D.setColor(Color.GREEN);
gfx2D.draw(circle);
y += fm.getAscent();
gfx2D.drawString("ARC FROM CIRCLE WITH EXPECTED PARMS AND RESULT:", x, y);
y += fm.getAscent();
gfx2D.drawString(String.format("start angle %.1f° and extent %.1f°", startAngle, extent), x, y);
startAngle = 45.0;
extent = 90.0;
Arc2D unexpectedEllipse = new Arc2D.Double(centerX - ellipseRadiusX, centerY - ellipseRadiusY, 2 * ellipseRadiusX, 2 * ellipseRadiusY, startAngle, extent, Arc2D.PIE);
gfx2D.setColor(Color.RED);
gfx2D.draw(unexpectedEllipse);
y += fm.getAscent();
gfx2D.drawString("UNEXPECTED ARC FROM ELLIPSE WITH EXPECTED PARMS AND UNEXPECTED RESULT:", x, y);
y += fm.getAscent();
gfx2D.drawString(String.format("start angle %.1f° and extent %.1f°", startAngle, extent), x, y);
startAngle = 26.4;
extent = 127.2;
Arc2D expectedEllipse = new Arc2D.Double(centerX - ellipseRadiusX, centerY - ellipseRadiusY, 2 * ellipseRadiusX, 2 * ellipseRadiusY, startAngle, extent, Arc2D.PIE);
gfx2D.setColor(Color.BLUE);
gfx2D.draw(expectedEllipse);
y += fm.getAscent();
gfx2D.drawString("EXPECTED ARC FROM ELLIPSE WITH UNEXPECTED PARMS AND EXPECTED RESULT:", x, y);
y += fm.getAscent();
gfx2D.drawString(String.format("start angle %.1f° and extent %.1f°", startAngle, extent), x, y);
y += fm.getAscent();
gfx2D.drawString("even though it is clear that the start angle is at 45° and the extent is 90°???", x, y);
gfx2D.setColor(Color.YELLOW);
gfx2D.drawRect(centerX - ellipseRadiusX, centerY - ellipseRadiusY, ellipseRadiusX * 2, ellipseRadiusY * 2);
gfx2D.setColor(Color.ORANGE);
gfx2D.drawLine(centerX, centerY, centerX + ellipseRadiusX, centerY - ellipseRadiusY);
x = centerX + ellipseRadiusX + 5;
y = centerY - ellipseRadiusY;
gfx2D.drawString("this is 45° as far", x, y);
y += fm.getAscent();
gfx2D.drawString("as the ellipse is", x, y);
y += fm.getAscent();
gfx2D.drawString("concerned!", x, y);
gfx2D.dispose();
JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(bi)));
// ImageIO.write(bi, "png", new File("examplearc2d.png"));
}
catch(Throwable t) {
t.printStackTrace();
}
}
}
UPDATE: Found a way to get the angles but it was too clunky so took another approach. I used a clipping area to solve the problem. I solved my problem but didn't really answer the question. Won't pursue it any further. So basically I draw the ellipse but apply a clipping area so only the arc is drawn.
package example;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class ExampleArc2D3
extends JFrame {
private Canvas canvas;
private JSlider ryrxSld;
private JSlider startAngleSld;
private JSlider extentSld;
private JSlider angleSld;
public ExampleArc2D3() {
super("Example Arc2D");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container cp = getContentPane();
cp.add(canvas = new Canvas(), BorderLayout.CENTER);
JPanel southPanel = new JPanel(new BorderLayout());
southPanel.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
cp.add(southPanel, BorderLayout.SOUTH);
JPanel labelsPanel = new JPanel(new GridLayout(0, 1, 0, 0));
southPanel.add(labelsPanel, BorderLayout.WEST);
JPanel fieldsPanel = new JPanel(new GridLayout(0, 1, 0, 0));
southPanel.add(fieldsPanel, BorderLayout.CENTER);
labelsPanel.add(new JLabel("ry/rx: "));
fieldsPanel.add(ryrxSld = new JSlider(10, 25, 20));
labelsPanel.add(new JLabel("Start Angle: "));
fieldsPanel.add(startAngleSld = new JSlider(0, 3600, 0));
labelsPanel.add(new JLabel("Extent: "));
fieldsPanel.add(extentSld = new JSlider(0, 3600, 300));
labelsPanel.add(new JLabel("Protractor: "));
fieldsPanel.add(angleSld = new JSlider(0, 3600, 0));
ChangeHandler ch = new ChangeHandler();
ryrxSld.addChangeListener(ch);
startAngleSld.addChangeListener(ch);
extentSld.addChangeListener(ch);
angleSld.addChangeListener(ch);
setSize(1000, 1020);
setVisible(true);
}
private class Canvas
extends JComponent {
public void refresh() {
invalidate();
repaint();
}
#Override
public void paintComponent(Graphics gfx) {
super.paintComponent(gfx);
Graphics2D gfx2D = (Graphics2D) gfx;
Dimension size = getSize();
try {
int width = size.width;
int height = size.height;
gfx2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
gfx2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
gfx2D.setFont(new Font(Font.MONOSPACED, Font.BOLD, 16));
FontMetrics fm = gfx2D.getFontMetrics();
gfx2D.setColor(Color.BLACK);
gfx2D.fillRect(0, 0, width, height);
double startAngle = startAngleSld.getValue() / 10.0;
double extent = extentSld.getValue() / 10.0;
int x = 5;
int y = 0;
gfx2D.setColor(Color.WHITE);
y += fm.getAscent();
gfx2D.drawString(String.format("ry/rx: %.1f", ryrxSld.getValue() / 10.0), x, y);
y += fm.getAscent();
gfx2D.drawString(String.format("start angle %.1f° and extent %.1f°", startAngle, extent), x, y);
int centerX = width / 2;
int centerY = 460;
double ellipseRadiusX = 200;
double ellipseRadiusY = ryrxSld.getValue() * ellipseRadiusX / 10.0;
gfx2D.setColor(new Color(255, 255, 255, 60));
gfx2D.setStroke(new BasicStroke(1f));
gfx2D.draw(new Ellipse2D.Double(centerX - ellipseRadiusX, centerY - ellipseRadiusX, 2 * ellipseRadiusX, 2 * ellipseRadiusX));
gfx2D.draw(new Ellipse2D.Double(centerX - ellipseRadiusY, centerY - ellipseRadiusY, 2 * ellipseRadiusY, 2 * ellipseRadiusY));
gfx2D.draw(new Ellipse2D.Double(centerX - ellipseRadiusX, centerY - ellipseRadiusY, 2 * ellipseRadiusX, 2 * ellipseRadiusY));
gfx2D.setStroke(new BasicStroke(2f));
gfx2D.setStroke(new BasicStroke(1f));
gfx2D.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 10));
fm = gfx2D.getFontMetrics();
// clip area
Shape clipArea = buildClipArea(centerX, centerY, ellipseRadiusX, ellipseRadiusY, startAngle, extent);
gfx2D.setColor(new Color(255, 0, 0, 120));
gfx2D.draw(clipArea);
Shape oldClip = gfx2D.getClip();
gfx2D.setClip(clipArea);
gfx2D.setColor(Color.BLUE);
gfx2D.setStroke(new BasicStroke(2f));
gfx2D.draw(new Ellipse2D.Double(centerX - ellipseRadiusX, centerY - ellipseRadiusY, 2 * ellipseRadiusX, 2 * ellipseRadiusY));
gfx2D.setClip(oldClip);
double angle = angleSld.getValue() / 10.0;
gfx2D.setColor(Color.CYAN);
double len = 800.0;
gfx2D.draw(new Line2D.Double(centerX, centerY, centerX + len * Math.cos(Math.toRadians(angle)), centerY - len * Math.sin(Math.toRadians(angle))));
gfx2D.drawString(String.format("%.1f°", angle), centerX + 5, centerY + fm.getAscent());
}
catch(Throwable t) {
t.printStackTrace();
}
}
private Shape buildClipArea(double centerX,
double centerY,
double ellipseRadiusX,
double ellipseRadiusY,
double startAngle,
double extent) {
double radius = Math.max(ellipseRadiusX, ellipseRadiusY);
Arc2D arc = new Arc2D.Double(centerX - radius, centerY - radius, 2 * radius, 2 * radius, 0, extent, Arc2D.PIE);
AffineTransform at = new AffineTransform();
at.rotate(Math.toRadians(-startAngle), centerX, centerY);
return at.createTransformedShape(arc);
}
}
private class ChangeHandler
implements ChangeListener {
#Override
public void stateChanged(ChangeEvent e) {
canvas.refresh();
}
}
public static void main(String[] args) {
Runnable runner = new Runnable() {
#Override
public void run() {
new ExampleArc2D3();
}
};
SwingUtilities.invokeLater(runner);
}
}
The API for the Arc2D class states:
The angles are specified relative to the non-square framing rectangle such that 45 degrees always falls on the line from the center of the ellipse to the upper right corner of the framing rectangle
Not really sure what that means or how that provides insight on how to calculate the appropriate angles to use to achieve your desired result
However, it can be demonstrated by adding the following code at the bottom of your class:
gfx2D.setColor( Color.YELLOW );
gfx2D.drawRect(centerX - ellipseRadiusX, centerY - ellipseRadiusY, ellipseRadiusX * 2, ellipseRadiusY * 2);
gfx2D.setColor( Color.ORANGE );
gfx2D.drawLine(centerX, centerY, centerX + ellipseRadiusX, centerY - ellipseRadiusY);
hello i'm having trouble drawing arrows from center of a circle to center of the next one, each circle is from a xml elsewhere let's consider size is 14.
why does my code seems not to do the trick?
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.AffineTransform;
import java.io.File;
import java.io.IOException;
import java.util.Vector;
import javax.swing.JFrame;
Just setting the frame
public class GRAPHICS_REPRESENTATION extends JFrame {
private Vector<Point> point_tab;
public GRAPHICS_REPRESENTATION() {
super("graphic");
point_tab = new Vector<Point>(0);
setSize(800, 800);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
Drawing a circle (found and reworked from here)
// Convenience method to draw from center with radius
public void drawCircle(Graphics cg, int xCenter, int yCenter, int r) {
Graphics2D cg2 = (Graphics2D) cg.create();
cg2.drawOval(xCenter - r, yCenter - r, r, r);
}// end drawCircle
the problem method
private void disposeScene(Graphics g1, int x1, int y1, int r) {
Graphics2D g = (Graphics2D) g1.create();
AffineTransform at = g.getTransform();
AffineTransform at2 = new AffineTransform();
at2 = AffineTransform.getScaleInstance(0.5, 0.5); // scaling à faire en 1er
g.transform(at2); // prise en compte de la matrice
at2 = AffineTransform.getTranslateInstance(getWidth() / 2 + x1 + r / 2, getHeight() / 2 - y1 - r / 2); // centrage
g.transform(at2);
double angle = (double) Math.cos(0);
for (int i = 0; i < 14; i++) {
angle = Math.rint(angle / (i + 1));
g.setColor(Color.RED);
drawCircle(g, 0, 0, 2 * r);
Point center = new Point();
center.setLocation(g.getTransform().getTranslateX() / 2 + r / 2 + x1 / 2,
g.getTransform().getTranslateY() / 2 - r / 2 - y1 / 2);
point_tab.add(center);
at2.concatenate(AffineTransform.getRotateInstance(angle)); // rotation autour d'un centre
g.transform(at2);
System.out.println(point_tab.elementAt(i).getX() + "," + point_tab.elementAt(i).getY());
g.setColor(Color.BLUE);
if (i + 1 < point_tab.size()) {
drawArrow(g, point_tab.elementAt(i).getX(), point_tab.elementAt(i).getY(),
point_tab.elementAt(i + 1).getX(), point_tab.elementAt(i + 1).getY());
} else {
drawArrow(g, point_tab.elementAt(i).getX(), point_tab.elementAt(i).getY(),
point_tab.elementAt(0).getX(), point_tab.elementAt(0).getY());
}
}
g.setTransform(at);
}
drawing an arrow from src to dst (found here and reworked)
private final int ARR_SIZE = 4;
private void drawArrow(Graphics g1, double xsrc, double ysrc, double xdst, double ydst) {
Graphics2D g = (Graphics2D) g1.create();
double dx = xdst - xsrc, dy = ydst - ysrc; // distances
double angle = Math.atan2(dy, dx);
int len = (int) Math.sqrt(dx * dx + dy * dy);
AffineTransform at = g.getTransform();
AffineTransform at2 = new AffineTransform();
at2=AffineTransform.getTranslateInstance(xsrc, ysrc);
at2.concatenate(AffineTransform.getRotateInstance(angle));
g.transform(at2);
// Draw horizontal arrow starting in (0, 0)
g.drawLine(0, 0, len, 0);
g.fillPolygon(new int[] { len, len - ARR_SIZE, len - ARR_SIZE, len }, new int[] { 0, -ARR_SIZE, ARR_SIZE, 0 },
4);
g.setTransform(at);
}
main method
public void paint(Graphics g) {
disposeScene(g, getWidth()/4,getHeight()/4,40);
}
Here the solution I found by myself
/**
* #brief draw the scene with all shapes set up
* #param g1
* #param x1
* #param y1
* #param xtg
* #param r
*/
private void disposeScene(Graphics g1, int x1, int y1, XML_TO_GRAPH xtg, int r) {
Graphics2D g = (Graphics2D) g1.create();
g.translate(getWidth() / 2, getHeight() / 2);
drawCircle(g, 0, 0, (x1+y1)/2); // cercle fictif
for (int i = 0; i < xtg.getsceneVector().size(); i++) {
double angle = Math.toRadians(360.0); // radian mieux 2pi
angle = (angle*i / xtg.getsceneVector().size());
System.out.println("angle(" + i + ")=" + angle);
g.setColor(Color.RED);
drawCircle(g, (int) (Math.cos(angle) * x1), (int) (Math.sin(angle) * y1), r);
Point center_big_circle = new Point();
center_big_circle.setLocation((0), (0)); // centre du grand cercle fictif
Point center_little_circle = new Point();
center_little_circle.setLocation((Math.cos(angle) * (x1)), (Math.sin(angle) * (y1))); // décalage vers les
// bords
System.out.println("centre(" + i + ")=" + center_little_circle.getX() + "," + center_little_circle.getY());
point_tab.add(center_little_circle);
g.setColor(Color.BLACK);
drawString(g, (int) center_little_circle.getX()-r, (int) center_little_circle.getY()-r, 16, "scène : " + i);
System.out.println(point_tab.elementAt(i).getX() + "," + point_tab.elementAt(i).getY());
g.setColor(Color.BLUE);
if (i + 1 < point_tab.size()) {// si existe
drawArrow(g, point_tab.elementAt(i).getX(), point_tab.elementAt(i).getY(),
point_tab.elementAt(i + 1).getX(), point_tab.elementAt(i + 1).getY());
// g.setColor(Color.BLACK);
// drawString(g, (int)(( point_tab.elementAt(i+1).getX()-
point_tab.elementAt(i).getX())/2), (int) ((point_tab.elementAt(i+1).getY()-
point_tab.elementAt(i).getY())/2), 16, "X : " +
xtg.getcount_occurence().toString());
//idem
drawArrow(g, point_tab.elementAt(i+1).getX(), point_tab.elementAt(i+1).getY(),
point_tab.elementAt(i).getX(), point_tab.elementAt(i).getY());
// drawString(g, (int)(( point_tab.elementAt(i).getX()-
point_tab.elementAt(i+1).getX())/2), (int) ((point_tab.elementAt(i).getY()-
point_tab.elementAt(i+1).getY())/2), 16, "X : " +
xtg.getcount_occurence().toString());
}
}
}
and
// Convenience method to draw from center with radius
/**
*
* #param cg
* #param xCenter
* #param yCenter
* #param r
*/
public void drawCircle(Graphics cg, int xCenter, int yCenter, int r) {
Graphics2D cg2 = (Graphics2D) cg.create();
System.out.println("Center at: " + (xCenter - r) + "," + (yCenter - r));
cg2.drawOval(xCenter - r, yCenter - r, 2 * r, 2 * r);
}// end drawCircle
and convenient drawString method :
/**
*
* #param g1
* #param x
* #param y
* #param size
* #param str
*/
private void drawString(Graphics g1, int x, int y, int size, String str) {
Graphics2D g = (Graphics2D) g1.create();
g.setFont(new Font("Times New Roman", Font.PLAIN, size));
g.drawString(str, x, y);
}
and paint :
public void paint(Graphics g) {
disposeScene(g, (int) (getWidth() / 3), (int) (getHeight() / 3), 20);
}
I do not understand the significance of multiplying by 0.4 in this line:
int radius = (int)(Math.min(getWidth(), getHeight()) * 0.4)
in the code below. how are they calculating the radius beneath
//Displaying fan blades in Java
package graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
#SuppressWarnings("serial")
class DrawFan extends JFrame {
public DrawFan() {
setTitle("The Four Fan Blades");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
add(new BladesPanel());
}
class BladesPanel extends JPanel {
protected void paintComponent(Graphics g){
super.paintComponent(g);
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
int radius = (int)(Math.min(getWidth(), getHeight()) * 0.4);
int x = xCenter - radius;
int y = yCenter - radius;
g.fillArc(x, y, 2 * radius, 2 * radius, 0, 30);
g.fillArc(x, y, 2 * radius, 2 * radius, 90, 30);
g.fillArc(x, y, 2 * radius, 2 * radius, 180, 30);
g.fillArc(x, y, 2 * radius, 2 * radius, 270, 30);
}
}
public static void main(String[] args) {
DrawArcs2 fanBlades = new DrawArcs2();
fanBlades.setSize(300,300);
fanBlades.setVisible(true);
}
}
In this line:
int radius = (int)(Math.min(getWidth(), getHeight()) * 0.4);
They first get what number is bigger in your JPanel: the width or the height with this part (Math.min(getWidth(), getHeight())
Imagine height is 400 and width 300. 400 is going to be selected. Now, you want to paint a circle inside this 400-wide rectangle. To fit your circle you need to make it at least 1/2 400 points. That's the same as 400*0.5. To fit better the circle inside, they choose to multiply by 0.4 (or 40% the size of the taller width/height)
Just for fun I thought I would create the game Asteroids. I'm a little bit stuck on the the fact I can't get the player to always look where the mouse is. Here is the player class below.
public class Player extends GameObject {
private int size;
public Player(float x, float y, int width, int height) {
super(x, y, width, height);
size = width / 2 + height / 2;
}
public void update() {
}
public void render(Graphics g) {
Point mouse = MouseInfo.getPointerInfo().getLocation();
int centerX = (int) (mouse.getX() - getX());
int centerY = (int) (mouse.getY() - getY());
double angle = Math.toDegrees(Math.atan2(centerY, centerX));
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.white);
g2d.rotate(angle, (int) getX() + getWidth() / 2, (int) getY() + getHeight() / 2);
g2d.drawLine((int) getX() + getWidth() / 2, (int) getY(), (int) getX(), (int) getY() + getHeight());
g2d.drawLine((int) getX() + getWidth() / 2, (int) getY(), (int) getX() + getWidth(), (int) getY() + getHeight());
g2d.drawLine((int) getX(), (int) getY() + getHeight(), (int) getX() + getWidth() / 2, (int) getY() + getHeight() - size / 6);
g2d.drawLine((int) getX() + getWidth(), (int) getY() + getHeight(), (int) getX() + getWidth() / 2, (int) getY() + getHeight() - size / 6);
}
public Rectangle getBounds() {
return new Rectangle((int) getX(), (int) getY(), getWidth(), getHeight());
}
public void setSize(int size) {
this.size = size;
}
public int getSize() {
return size;
}
}
I guess it sort of works in the fact that if I move my mouse the player does rotate but it rotate pretty fast. So I ask am I doing anything wrong? Before you ask, I have looked it up on Google and found some question like this one but none have helped me.
The argument to Graphics2D.rotate is in radians, not degrees. Try removing Math.toDegrees from the computation of angle. Reference here.
Updated:
Per this comment, getLocation gives the mouse position in screen coordinates, not in the user coordinates of your Graphics2D. You need to convert the coordinates, but how to do that will be specific to your game library.
Updated 2: Assuming GameObject extends java.awt.Component somehow, try getLocationOnScreen (reference here, from the comment noted above):
Point me_absolute = getLocationOnScreen()
int centerX = (int) (mouse.getX() - me_absolute.getX());
int centerY = (int) (mouse.getY() - me_absolute.getY());
I have to display four "fans" or arcs that are outlined by a circle, i have the fanblades/arcs set and looking the way i would like but i cannot figure out how to get them outlined by a circle, any ideas? Thanks in advance.
package chap15;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Fans extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
int radius = (int)(Math.min(getWidth(), getHeight()) * 0.4);
int x = xCenter - radius;
int y = yCenter - radius;
g.fillArc(x, y, 2 * radius, 2 * radius, 0, 30);
g.fillArc(x, y, 2 * radius, 2 * radius, 90, 30);
g.fillArc(x, y, 2 * radius, 2 * radius, 180, 30);
g.fillArc(x, y, 2 * radius, 2 * radius, 270, 30);
}
}
drawArc?