Manually translate polygon - java

public class Hexagon extends JPanel {
// Team that controls the hexagon
public int controller; // 0 neutral // 1 is team 1 // 2 is team 2
// Color of the hexagon
// /* All attributes of the board, used for size an boarder etc... */ Board board
// /* Determines where the hexagon sits on the game board */ int position
public static void main(String args[])
{
JFrame j = new JFrame();
j.setSize(350, 250);
for(int i = 0; i < 121; i++)
{
Hexagon hex = new Hexagon();
j.add(hex);
}
j.setVisible(true);
}
#Override
public void paintComponent(Graphics shape)
{
super.paintComponent(shape);
Polygon hexagon = new Polygon();
// x, y coordinate centers, r is radius from center
Double x, y;
// Define sides of polygon for hexagon
for(int i = 0; i < 6; i++)
{
x = 25 + 22 * Math.cos(i * 2 * Math.PI / 6);
y = 25 + 22 * Math.sin(i * 2 * Math.PI / 6);
hexagon.addPoint(x.intValue(), y.intValue());
}
// Automatic translate
hexagon.translate(10, 10);
// How do I manually control translate?
shape.drawPolygon(hexagon);
}
}
How do I manually translate a polygon? I need to do it to create a game board. So far I've only accomplished automatic translation of polygons which is definitely what I don't need.

I mean like parameterize it so that it's not always 10.
Then you need parameters for your class:
Create a method in your class like `setTranslation(int x, int y) and save the x/y values to instance variables.
In the paintComponent() method you reference these instance variables
Then when you create the Hexagon you can manually set the translation.
Something like:
public void setTranslation(int translationX, int translationY)
{
this.translationX = translationX;
this.translationY = translationY;
}
...
//hexagon.translate(10, 10);
hexagon.translate(translateX, translateY);
...
Hexagon hex = new Hexagon();
hex.setTranslation(10, 10);
Or, you can just pass the translation values as parameters to the constructor of your Hexagon class. The point is you need to have custom properties in your Hexagon class if you want each Hexagon to have a different translation.

Related

How would I implement a display showing points within a triangle in java?

So I am trying to make an iterative program to show the chaos game with sierpinski's triangle. You start at (0,0) and randomly go half-way to either (0, 0), (1, sqrt(3)) or (2, 0). Repeating leaves a fractal pattern. My code in java would roughly be:
public class Sierpinski {
public static void main(String[] args) {
double x = 0;
double y = 0;
int n = 0;
while(true) {
// point on at (x,y) - this is what I need help with
// generates random number from 0 to 2
n = (int)(3 * Math.random())
// x and y randomly go halfway to one point
x += ((n == 1) ? 1 : 0) + ((n == 2) ? 2: 0);
y += ((n == 1) ? Math.sqrt(3) : 0);
x /= 2;
y /= 2;
}
}
}
How would I implement a graph with bounds 0 to 2 in x and y direction that displays these points at each iteration?
Thanks
By the way, it's a nice project ;)
To make a window in Java and draw graphics, you need two things: A JFrame and a Canvas.
JFrame is the frame of your app, just like when you are opening a a Windows app.
Canvas is a surface where we can draw graphics on it. It has a width and an height
in pixels.
To simplify things, I made a Window class that manage both of them. Here is the code:
import java.awt.Graphics;
import javax.swing.JFrame;
import java.awt.Canvas;
import java.awt.Color;
public class Window
{
//width and height of the canvas
private static final int WIDTH = 600;
private static final int HEIGHT = 600;
JFrame frame;
Canvas canvas;
public Window()
{
JFrame frame = new JFrame();
canvas = new Canvas();
canvas.setSize(WIDTH, HEIGHT);
//We add the canvas inside of the frame
frame.add(canvas);
//make the frame to fit the size of the canvas
frame.pack();
//click on the X button to close the app
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//set the app in the middle of the screen
frame.setLocationRelativeTo(null);
frame.setTitle("Sierpinski");
frame.setVisible(true);
}
//We call this method from your code
public void paint(double x, double y)
{
/*
Since your numbers range is between 0 and 2,
We need to adapt it to the size of the canvas.
The result would be random coordinates on the canvas.
*/
int coordX = (int)(x / 2 * WIDTH);
/*
Because in Java Y axe is reversed, we need to convert into its reversed value on the screen. Ex:
pixel (0,0) => pixel (0,599)
pixel (0,10) => pixel (0,589)
*/
int coordY = HEIGHT - ((int)(y / 2 * HEIGHT) + 1);
/*
Graphics is like a paintbrush for a specific object.
We are asking the canvas to give us his paintbrush.
*/
Graphics g = canvas.getGraphics();
//Try to execute the line below!
//g.setColor(Color.BLUE);
/*
Draw a rectangle of width and height of 1 pixel.
*/
g.fillRect(coordX, coordY, 1, 1);
}
}
finally, we need to create this Window object within your code, and call the paint method:
public class Sierpinski {
public static void main(String[] args) {
Window window = new Window();
double x = 0;
double y = 0;
int n = 0;
while(true) {
// point on at (x,y) - this is what I need help with
// generates random number from 0 to 2
n = (int)(3 * Math.random());
// x and y randomly go halfway to one point
x += ((n == 1) ? 1 : 0) + ((n == 2) ? 2: 0);
y += ((n == 1) ? Math.sqrt(3) : 0);
x /= 2;
y /= 2;
window.paint(x, y);
}
}
}
You should get a result like this:
The result expected
There is much you can do with it. You can check official documentation on Oracle web site or look at some tutorials on Youtube.
Canvas documentation
Graphics documentation
JFrame documentation
Have fun!

how to add numbers to clock from 1 to 12, i just create circle

import java.awt.Color;
import acm.graphics.GOval;
import acm.program.GraphicsProgram;
public class Clock extends GraphicsProgram {
private static final long serialVersionUID = 1L;
public void run() {
GOval tofig = createFilledCircle(getWidth()/2, getHeight()/2, 200, Color.black);
add(tofig);
GOval lala = createFilledCircle(getWidth()/2, getHeight()/2, 180, Color.white);
add(lala);
}
private GOval createFilledCircle(double x, double y, double r, Color color) {
GOval circle = new GOval(x - r, y - r, 2 * r, 2 * r);
circle.setFilled(true);
circle.setColor(color);
return circle;
}
// Ignore this;
public static void main(String[] args) {
new Clock().start();
}
}
Here's the code for the trigonometry part of what you're trying to do that you and I have kinda worked on together:
public class DrawCircle {
static final double twopi = Math.PI * 2;
static final double fudge = 0.000001;
private static void drawHourLabels(double center_x, double center_y, double radius) {
int steps = 12;
for (double angle = 0.0; angle < (twopi - fudge); angle += twopi/steps) {
double x_offset = Math.sin(angle) * radius;
double y_offset = Math.cos(angle) * radius;
double x = center_x + x_offset;
double y = center_y + y_offset;
// Here you'd do the actual drawing of each hour label at the coordinates x,y. We'll just print them for now.
System.out.println(String.format("%f %f", x, y));
}
}
public static void main(String... args) {
// drawHourLabels(getWidth()/2, getHeight()/2, 220); // <-- you'd do something like this in your "run" method.
// Draw clock labels around circle with center at 400x200 of radius 220
drawHourLabels(400, 600, 220);
}
}
The 'fudge' value is used because floating point arithmetic isn't perfectly precise. By the time we've added 12 floating point values together to get to 2 * Math.PI, we might be a little over or under. We want to make sure we don't process the 12:00 position again at the end of the loop because we computed a value just a little smaller than 2 * Math.PI. So we add a "fudge factor" that's really small, but guaranteed to be bigger than any floating point inaccuracy we've accumulated.
Take a look at this simple example from me.
/**
* Draw text elements from 1 to 12 inside a circle
* #return a group of text elements from 1 to 12
*/
public strictfp static Group drawText() {
//a list for storing text numbers
List<Text> numbersInClock = new ArrayList<>();
//create a group of shapes
Group group = new Group();
//set it to x,y positions
group.setLayoutX(150);
group.setLayoutY(150);
//numbers corresponding to angle calculations
int[] numbers = {3,4,5,6,7,8,9,10,11,12,1,2};
double[] angles = {0, 0.166666666667, 0.333333333334,0.5, 0.666666666667, 0.833333333334, 1, 1.166666666667, 1.33333333334, 1.5, 1.666666666667, 1.83333333334};
int i = 0;
for (double angle : angles) {
//Calculated formula for x,y positions of each number within a circle
//(x,y) = (rcos(angle),rsin(angle))
int r = 90; // length of radius, a bit shorter to put it inside a circle
//calculate x and y positions based on formula for numbers within a circle
double x = r * Math.cos(angle*Math.PI);
double y = r * Math.sin(angle*Math.PI);
//create a text element consiting a coressponding number
Text text = new Text(x, y, String.valueOf(numbers[i++]));
//add it to a list
numbersInClock.add(text);
}
//add all text elements to a group
group.getChildren().addAll(numbersInClock);
//return a group
return group;
}
Full code can be acquired from here: https://github.com/MomirSarac/JavaFX-Circle-Clock-Image
You can use sin and cos to know where to set your text.
Sine and Cosine are two math operators that take in an angle in radians and give out number beetween -1 and 1 to know how to multiply to get coordinates
you can learn more here

How to use AffineTransform with very little coordinates?

I have a set of two dimensions points. Their X and Y are greater than -2 and lesser than 2. Such point could be : (-0.00012 ; 1.2334 ).
I would want to display these points on a graph, using rectangles (a rectangle illustrates a point, and has its coordinates set to its point's ones - moreover, it has a size of 10*10).
Rectangles like (... ; Y) should be displayed above any rectangles like (... ; Y-1) (positive Y direction is up). Thus, I must set the graph's origin not at the top-left hand-corner, but somewhere else.
I'm trying to use Graphics2D's AffineTransform to do that.
I get the minimal value for all the X coordinates
I get the minimal value for all the Y coordinates
I get the maximal value for all the X coordinates
I get the maximal value for all the Y coordinates
I get the distance xmax-xmin and ymax-ymin
Then, I wrote the code I give you below.
Screenshots
Some days ago, using my own method to scale, I had this graph:
(so as I explained, Y are inverted and that's not a good thing)
For the moment, i.e., with the code I give you below, I have only one point that takes all the graph's place! Not good at all.
I would want to have:
(without lines, and without graph's axis. The important here is that points are correctly displayed, according to their coordinates).
Code
To get min and max coordinates value:
x_min = Double.parseDouble((String) list_all_points.get(0).get(0));
x_max = Double.parseDouble((String) list_all_points.get(0).get(0));
y_min = Double.parseDouble((String) list_all_points.get(0).get(1));
y_max = Double.parseDouble((String) list_all_points.get(0).get(1));
for(StorableData s : list_all_points) {
if(Double.parseDouble((String) s.get(0)) < x_min) {
x_min = Double.parseDouble((String) s.get(0));
}
if(Double.parseDouble((String) s.get(0)) > x_max) {
x_max = Double.parseDouble((String) s.get(0));
}
if(Double.parseDouble((String) s.get(1)) < y_min) {
y_min = Double.parseDouble((String) s.get(1));
}
if(Double.parseDouble((String) s.get(1)) > y_max) {
y_max = Double.parseDouble((String) s.get(1));
}
}
To draw a point:
int x, y;
private void drawPoint(Cupple storable_data) {
//x = (int) (storable_data.getNumber(0) * scaling_coef + move_x);
//y = (int) (storable_data.getNumber(1) * scaling_coef + move_y);
x = storable_data.getNumber(0).intValue();
y = storable_data.getNumber(1).intValue();
graphics.fillRect(x, y, 10, 10);
graphics.drawString(storable_data.toString(), x - 5, y - 5);
}
To paint the graph:
#Override
public void paint(Graphics graphics) {
this.graphics = graphics;
Graphics2D graphics_2d = ((Graphics2D) this.graphics);
AffineTransform affine_transform = graphics_2d.getTransform();
affine_transform.scale(getWidth()/(x_max - x_min), getHeight()/(y_max - y_min));
affine_transform.translate(x_min, y_min);
graphics_2d.transform(affine_transform);
for(StorableData storable_data : list_all_points) {
graphics_2d.setColor(Color.WHITE);
this.drawPoint((Cupple) storable_data);
}
I suggest you map each data point to a point on the screen, thus avoiding the following coordinate system pitfalls. Take your list of points and create from them a list of points to draw. Take into account that:
The drawing is pixel-based, so you will want to scale your points (or you would have rectangles 1 to 4 pixels wide...).
You will need to translate all your points because negative values will be outside the boundaries of the component on which you draw.
The direction of the y axis is reversed in the drawing coordinates.
Once that is done, use the new list of points for the drawing and the initial one for calculations. Here is an example:
public class Graph extends JPanel {
private static int gridSize = 6;
private static int scale = 100;
private static int size = gridSize * scale;
private static int translate = size / 2;
private static int pointSize = 10;
List<Point> dataPoints, scaledPoints;
Graph() {
setBackground(Color.WHITE);
// points taken from your example
Point p1 = new Point(-1, -2);
Point p2 = new Point(-1, 0);
Point p3 = new Point(1, 0);
Point p4 = new Point(1, -2);
dataPoints = Arrays.asList(p1, p2, p3, p4);
scaledPoints = dataPoints.stream()
.map(p -> new Point(p.x * scale + translate, -p.y * scale + translate))
.collect(Collectors.toList());
}
#Override
public Dimension getPreferredSize() {
return new Dimension(size, size);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// draw a grid
for (int i = 0; i < gridSize; i++) {
g2d.drawLine(i * scale, 0, i * scale, size);
g2d.drawLine(0, i * scale, size, i * scale);
}
// draw the rectangle
g2d.setPaint(Color.RED);
g2d.drawPolygon(scaledPoints.stream().mapToInt(p -> p.x).toArray(),
scaledPoints.stream().mapToInt(p -> p.y).toArray(),
scaledPoints.size());
// draw the points
g2d.setPaint(Color.BLUE);
// origin
g2d.fillRect(translate, translate, pointSize, pointSize);
g2d.drawString("(0, 0)", translate, translate);
// data
for (int i = 0; i < dataPoints.size(); i++) {
Point sp = scaledPoints.get(i);
Point dp = dataPoints.get(i);
g2d.fillRect(sp.x, sp.y, pointSize, pointSize);
g2d.drawString("(" + dp.x + ", " + dp.y + ")", sp.x, sp.y);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setContentPane(new Graph());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
And another:
You might want to have the points aligned on the grid intersections and not below and to the right of them. I trust you will figure this one out.
Also, I ordered the points so that drawPolygon will paint the lines in the correct order. If your points are arbitrarily arranged, look for ways to find the outline. If you want lines between all points like in your example, iterate over all combinations of them with drawLine.

Swing drawing sometimes works

I'm trying to draw functions using Java Swing and AWT. The problem is not always all of the 300 points of the graph are drawn. When I loop over the first points of the graph in debug mode, there is much more change the graph is drawn completely. I use the following code to create a JFrame and set the graphics object to the class member g.
jFrame = new JFrame();
jFrame.setSize(WIDTH, HEIGHT);
jFrame.setVisible(true);
g = jFrame.getContentPane().getGraphics();
Then I call this method for every function I want to draw.
private void drawGraph(IGraph graph, Bounds bounds, Ratios ratios) {
//contains visual information about the graph
GraphVisuals visuals = graph.getVisuals();
g.setColor(visuals.color);
//the previous point is remembered, to be able to draw a line from one point to the next
int previousXi = 0;
int previousYi = 0;
//a loop over every point of the graph. The graph object contains two arrays: the x values and the y values
for (int i = 0; i < graph.getSize(); ++i) {
//calculate the x value using the ratio between the graph's size on the x-axis and the window size and the starting point on the x-axis
int xi = (int) (ratios.xRatio * (graph.getX(i) - bounds.xMin) + 0.5);
//analogous for the y axis
int yi = HEIGHT - (int) (ratios.yRatio * (graph.getY(i) - bounds.yMin) + 0.5);
//draw
if (visuals.hasBullets) {
g.fillOval(xi, yi, visuals.bulletSize, visuals.bulletSize);
}
if (visuals.hasLine) {
if (i != 0) {
g.drawLine(previousXi, previousYi, xi, yi);
}
}
previousXi = xi;
previousYi = yi;
}
}

Drawing a triangle in java

So a section of my assignment is to make a triangle class to be linked to various buttons...but I'm not sure how to make one in eclipse. The specific instructions say this:
Create a triangle class
Data fields: Point[] coords;
constructors
Implement all abstract methods defined in superclass
Getters and setters for each data field
Override public void paint(Graphics arg0) method
I have everything set up in the other classes..except for the triangle class. I'm confused on how to create a triangle using an array of points...Do I need to use Point x,y or somehow store 3 (x,y) coordinate pairs in that one array variable coords? I imagine to create it you would use drawPolygon...but I'm not certain. Any tips?
Here is an example class for Triangle
public class Triangle {
private Point[] coords;
// Null object constructor
public Triangle() {
this.coords = null;
}
// Constructor with point array
public Triangle(Point[] coords) {
this.coords = coords;
}
// Constructor with multiple points
public Triangle(Point a, Point b, Point c) {
this.coords = new Point[3];
coords[0] = a;
coords[1] = b;
coords[2] = c;
}
// The actual paint method
public void paint(Graphics arg0) {
// Setup local variables to hold the coordinates
int[] x = new int[3];
int[] y = new int[3];
// Loop through our points
for (int i = 0; i < coords.length; i++) {
Point point = coords[i];
// Parse out the coordinates as integers and store to our local variables
x[i] = Double.valueOf(point.getX()).intValue();
y[i] = Double.valueOf(point.getY()).intValue();
}
// Actually commit to our polygon
arg0.drawPolygon(x, y, 3);
}
}
Not sure what exactly this class is supposed to be extending, so nothing is marked as an override or anything, and it is missing setters and accessors, but you should be able to make it work.
Use the g.drawPolygon that takes an array of Points as it's args.
Did something similar, where I drew a polygon of three sides. Might help..
for (int i = 0; i < 3; i++){
polygon1.addPoint(
(int) (40 + 50 * Math.cos(i * 2 * Math.PI / 3)),
(int) (150 + 50 * Math.sin(i * 2 * Math.PI / 3))
);
}
g.drawPolygon(polygon1);

Categories

Resources