Centering 2D Shapes in Java - java

I'm a novice programmer trying to overlay two 2D circles on top of each other. Each circle has different dimensions and I understand that adding or subrtracting from xCenter and yCenter will move the shape on an axis, but how do I know with certainty they are centered? Unfortunately I am a novice without many tools under my belt, so the simplest information possible would be greatly appreciated. Thank you!
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class RedCross extends JPanel
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
int xCenter = getWidth() / 2;
int yCenter = getHeight() / 2;
g.setColor(Color.BLUE);
g.fillOval(xCenter, yCenter, 40, 40);
g.setColor(Color.RED);
g.fillOval(xCenter, yCenter, 10, 10);
}
public static void main(String[] args)
{
JFrame window = new JFrame("Target");
window.setBounds(300, 300, 200, 200);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
RedCross panel = new Target();
panel.setBackground(Color.WHITE);
Container c = window.getContentPane();
c.add(panel);
window.setVisible(true);
}
}

The center of an object is window/2 - self/2
In code:
int xPanel = getWidth();
int yPanel = getHeight();
int sizeCircleOne = 40;
int sizeCircleTwo = 10;
// Drawing circle 1
g.setColor(Color.BLUE);
g.fillOval(
xPanel/2 - sizeCircleOne/2,
yPanel/2 - sizeCircleOne/2,
sizeCircleOne,
sizeCircleOne
);
// Drawing circle 2
g.setColor(Color.RED);
g.fillOval(
xPanel/2 - sizeCircleTwo/2,
yPanel/2 - sizeCircleTwo/2,
sizeCircleTwo,
sizeCircleTwo
);
Let me know if it works.
Happy coding :) -Charlie

The method you use to center your circles is how one should center objects. Just take a point on half of the width, and half of the height, and that's your center. This is because the center of a circle has all points on the circle equidistant from the center point. That's the definition of a circle.

Related

Draw random dots inside a circle

I would like to draw 50 random dots within a given circle. The problem is the dots are not contained in the circle. Here is a runnable example:
package mygraphicsshapehomework;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
public class MyGraphicsShapeHomeWork extends JFrame {
public static void main(String[] args) {
new MyGraphicsShapeHomeWork();
}
public MyGraphicsShapeHomeWork() {
super("Title");
setBounds(600, 400, 700, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
g2.drawOval(40, 40, 90, 90);
Color newColor = new Color(255, 0, 0);
g2.setColor(newColor);
for (int i = 0; i < 50; i++) {
int x = (int) Math.ceil(Math.random() * 10);
int y = (int) Math.ceil(Math.random() * 10);
g2.fillOval(i+x, i+y, 3, 3); // ???
}
}
}
Here is the result it produces:
How can I draw the dots within the circle only?
To get a random point in a circle with radius R find a random angle and a random radius:
double a = random() * 2 * PI;
double r = R * sqrt(random());
Then the coordinates of the point are:
double x = r * cos(a)
double y = r * sin(a)
Here are some notes about the drawing part. You should not paint directly on top level container such as JFrame. Instead, use JComponent or JPanel. Override paintComponent() for painting rather than paint() and don't forget to call super.paintComponent(g)
Take a look at Performing Custom Painting tutorial for more information.
Do not use setBounds(), override panel's getPreferredSize() and pack() the frame. Also, you rarely need to extend JFrame.
Here is a basic example that demonstrates drawing with a sub-pixel precision:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TestDots extends JPanel{
public static final int POINTS_NUM = 1000;
public static final Color POINT_COLOR = Color.RED;
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
double padding = 10;
double radius = Math.min(this.getWidth(), this.getHeight()) / 2 - padding * 2;
g2.draw(new Ellipse2D.Double(padding, padding, radius * 2, radius * 2));
g2.setColor(POINT_COLOR);
for (int i = 0; i < POINTS_NUM; i++) {
double a = Math.random() * 2 * Math.PI;
double r = radius * Math.sqrt(Math.random());
double x = r * Math.cos(a) + radius + padding;
double y = r * Math.sin(a) + radius + padding;
g2.draw(new Ellipse2D.Double(x, y, 1, 1));
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("TestDots");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationByPlatform(true);
frame.add(new TestDots());
frame.pack();
frame.setVisible(true);
}
});
}
}
Here is a result:
For the position of the dots, generate random coordinates within the bounds of the outer circle. In order to generate these coordinates, the radius of the point from the center of the circle must be less than that of the outer circle. Get a random angle using
float a = Math.random() * Math.PI * 2;
Then, subtract a random value from the outer radius:
outerR - (Math.sqrt(Math.random()) * outerR)
and assign the positions to:
double x = Math.cos(a)*newR;
double y = Math.sin(a)*newR;
I'm sure there is a more mathematical approach to this, but this was the simplest in my opinion.

How to draw a triangle with border with Java Graphics

I'm trying to draw a triangle with a border using the Graphics.drawPolygon() method
The triangle is properly drawn, but how can I calculate the 3 points of the border?
I already did it with a circle, but I can't seem to find a solution for triangle.
A requirement of the instructor as that it cannot use Graphics2D.
My code:
if (xPoints != null && yPoints != null) {
int[] nXPoints = new int[] { xPoints[0] - borderThickness, xPoints[1] - borderThickness,
xPoints[2] - borderThickness };
int[] nYPoints = new int[] { yPoints[0] - borderThickness, yPoints[1] - borderThickness,
yPoints[2] - borderThickness };
g.setColor(borderColor);
g.fillPolygon(nXPoints, nYPoints, 3);
g.setColor(fillColor);
g.fillPolygon(xPoints, yPoints, 3);
}
Edit:
Expected result
Use the Graphics methods drawPolygon() to render the outline and fillPolygon() to fill its interior; both have the required signature, as shown here.
Because "operations that draw the outline of a figure operate by traversing an infinitely thin path between pixels with a pixel-sized pen," cast the graphics context to Graphics2D so that you can use draw() and fill() on the corresponding Shape. This will allow you to specify the outline using setStroke(), illustrated here.
I need it to have a custom thickness…I also don't want to use Graphics2D.
Custom thickness is not supported in the Graphics API. As suggested here, the actual graphics context received by paintComponent() is an instance of Graphics2D, which does support custom stroke geometry.
The things is teacher haven't taught me Graphics2D, so I'm not supposed to use it.
Then simply paint the larger triangle and then the smaller. If this isn't working, then you have an error in you calculation of the larger triangle, and you should edit your question to include a complete example.
I'm looking for a way to do it without Graphics2D…a guy has interpreted the question properly in this comment.
As #Marco13 observes, you need a triangle that is larger than the original one by the borderThickness. You can use AffineTransform to do the scaling. While Graphics can't fill() an arbitrary Shape, such as one created by AffineTransform, it can clip the rendering as required. In the example below, a unit triangle is translated and scaled to the center of an N x N panel; a copy is enlarged by delta. Note how rendering is clipped first to the larger background figure and then to the smaller foreground figure.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* #see https://stackoverflow.com/a/39812618/230513
*/
public class GraphicsBorder {
private static class GraphicsPanel extends JPanel {
private static final int N = 256;
private static final Color FILL = new Color(0x990099);
private static final Color BORDER = new Color(0x66FFB2);
private final Shape fore;
private final Shape back;
public GraphicsPanel(Polygon polygon, int delta) {
AffineTransform a1 = new AffineTransform();
a1.translate(N / 2, N / 2);
a1.scale(N / 3, N / 3);
fore = a1.createTransformedShape(polygon);
AffineTransform a2 = new AffineTransform();
a2.translate(N / 2, N / 2 - delta / 3);
a2.scale(N / 3 + delta, N / 3 + delta);
back = a2.createTransformedShape(polygon);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(BORDER);
g.setClip(back);
g.fillRect(0, 0, N, N);
g.setColor(FILL);
g.setClip(fore);
g.fillRect(0, 0, N, N);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(N, N);
}
}
private void display() {
JFrame f = new JFrame("GraphicsBorder");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Polygon p = new Polygon();
p.addPoint(0, -1);
p.addPoint(1, 1);
p.addPoint(-1, 1);
f.add(new GraphicsPanel(p, 16));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new GraphicsBorder()::display);
}
}

Java JPanel Scaling

Hey Guys I have succesfully made a GUI in java that will scale polygons and circles using a slider. Everything works but I was wondering if there is a way to change the Origin point(Where it scales from). Right now it scales from the corner and I would like it to scale from the middle so I can start it in the middle and it scales out evenly. Also, If anyone could tell me an easy way to replace the Rectangle I have with an Image of some kind so you can scale the Picture up and down would be great! Thank you! Here is my code:
import javax.swing.*;
public class Fred
{
public static void main(String[] args)
{
TheWindow w = new TheWindow();
w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //X wont close the window with out this line
w.setSize(375,375);
w.setVisible(true);
}
}
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
public class TheWindow extends JFrame
{
private JSlider slider; //declare slider
private drawRect myPanel; //declare/ create panel
public TheWindow()
{
super("Slider Example"); //make title
myPanel = new drawRect();
myPanel.setBackground(Color.green); //change background color
slider = new JSlider(SwingConstants.VERTICAL, 0, 315, 10);// restrains the slider from scaling square to 0-300 pixels
slider.setMajorTickSpacing(20); //will set tick marks every 10 pixels
slider.setPaintTicks(true); //this actually paints the ticks on the screen
slider.addChangeListener
(
new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
myPanel.setD(slider.getValue()); //Wherever you set the slider, it will pass that value and that will paint on the screen
}
}
);
add(slider, BorderLayout.WEST); //similar to init method, adds slider and panel to GUI
add(myPanel, BorderLayout.CENTER);
}
}
import java.awt.*;
import javax.swing.*;
public class drawRect extends JPanel
{
private int d = 25; //this determines the beginning length of the rect.
public void paintComponent(Graphics g)//paints circle on the screen
{
super.paintComponent(g); //prepares graphic object for drawing
g.fillRect(15,15, d, d); //paints rectangle on screen
//x , y, width, height
}
public void setD(int newD)
{
d = (newD >= 0 ? newD : 10); //if number is less than zero it will use 10 for diameter(compressed if statement)
repaint();
}
public Dimension getPrefferedSize()
{
return new Dimension(200, 200);
}
public Dimension getMinimumSize()
{
return getPrefferedSize();
}
}
Changing the "origin point" so it becomes the center of the "zoom" is basically just the process of subtract half of d from the center point.
So, assuming the the center point is 28 ((25 / 2) + 15), you would simply then subtract d / 2 (25 / 2) from this point, 28 - (25 / 2) = 15 or near enough...
I modified the paintComponent method for testing, so the rectangle is always at the center of the panel, but you can supply arbitrary values in place of the originX and originY
#Override
public void paintComponent(Graphics g)//paints circle on the screen
{
super.paintComponent(g); //prepares graphic object for drawing
int originX = getWidth() / 2;
int originY = getHeight() / 2;
int x = originX - (d / 2);
int y = originY - (d / 2);
System.out.println(x + "x" + y);
g.fillRect(x, y, d, d); //paints rectangle on screen
//x , y, width, height
}
As for scaling an image, you should look at Graphics#drawImage(Image img, int x, int y, int width, int height, ImageObserver observer), beware though, this will scaling the image to the absolute size, it won't keep the image ratio.
A better solution might be to use a double value of between 0 and 1 and multiple the various elements by this value to get the absolute values you want

Connecting points with lines to create a line graph

Hello I am fairly new to java and have been stuck on this problem for awhile so hopefully someone will be able to save me. Basically I am creating a program that can graph an equation and right now I'm testing out x^2 between -10 and 10. I can get the points to graph in the right spots but I can't figure out how to fill in the spots in between the points so it looks like a real graph.
Here's my code:
import java.util.Scanner;
import javax.swing.JFrame;
import java.awt.*;
class PlotGraph extends JFrame{
public void paint(Graphics l){
l.drawLine(50, 300, 550, 300); //x axis
l.drawLine(300, 550, 300, 50); //y axis
//Orignin x = 300 y = 300
int xmin, xmax, y, tmin, tmax;
xmin =(-10);
xmax = 10;
int x_bet, y_bet;
while(xmin<=xmax){
y = 300-(xmin*xmin);
l.drawLine(xmin+300, y, xmin+300, y);
//while(x_bet>xmin){
//l.drawLine(, , , );
//}
xmin++;
}
}
public static void main(String [] args) {
PlotGraph graph = new PlotGraph();
graph.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
graph.setSize(600, 600);
graph.setVisible(true);
graph.setTitle("PlotGraph");
}
}
Another way to do it is to create a GeneralPath, like this.
import javax.swing.JFrame;
import java.awt.*;
import java.awt.geom.*;
class PlotGraph extends JFrame{
public void paint(Graphics l){
l.drawLine(50, 300, 550, 300); //x axis
l.drawLine(300, 550, 300, 50); //y axis
int xmin, xmax, y, tmin, tmax;
xmin =(-10);
xmax = 10;
int x_bet, y_bet;
GeneralPath gp = new GeneralPath();
y = 300-(xmin*xmin);
gp.moveTo((double)xmin+300, (double)y);
while(xmin<=xmax){
y = 300-(xmin*xmin);
gp.lineTo((double)xmin+300, (double)y);
xmin++;
}
Graphics2D g2 = (Graphics2D)l;
g2.setColor(Color.RED);
g2.draw(gp);
}
public static void main(String [] args) {
PlotGraph graph = new PlotGraph();
graph.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
graph.setSize(600, 600);
graph.setVisible(true);
graph.setTitle("PlotGraph");
}
}
This source still has problems though:
GUI updates should be done on the EDT.
Custom painting is either best done in a JPanel/JComponent or a BufferedImage displayed in a JLabel.
The 'graph component' should declare a preferred size, rather than setting a size for the frame..
Maybe try this:
int x = xmin;
int last_y = 300-(x*x);
for (x = xmin+1; x<=xmax; x++);
y = 300-(x*x);
l.drawLine(x-1, last_y, x, y);
last_y = y;
}
You want the line to be drawn between previous x and y coordinates and the current ones. That's what last_y is for.
There are several ways to do this. If this is an assignment then I'm guessing that your professor is looking to see what methods you come up with. At the most basic level you just draw a line from the last point to the current point. How else could you accomplish this? Maybe a polyline in a different color? Maybe use a little math to draw larger circles a then run a line through them?
Here is one simple way to address the specific problem. I wouldn't recommend turning this in (if it's an assignment) but it shows you the basic principle.
import java.util.Scanner;
import javax.swing.JFrame;
import java.awt.*;
class PlotGraph extends JFrame{
public void paint(Graphics l){
l.drawLine(50, 300, 550, 300); //x axis
l.drawLine(300, 550, 300, 50); //y axis
int xmin, xmax, y, tmin, tmax;
int z = 0;
xmin =(-10);
xmax = 10;
int x_bet, y_bet;
while(xmin<=xmax){
y = 300-(xmin*xmin);
l.drawLine(xmin+300, y, xmin+300, y);
if(z!=0)
l.drawLine(xmin+300, y, xmin+300, z);
z=y;
xmin++;
}
}
public static void main(String [] args) {
PlotGraph graph = new PlotGraph();
graph.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
graph.setSize(600, 600);
graph.setVisible(true);
graph.setTitle("PlotGraph");
}
}

java 2D drawing

im trying to make a swing app that draws a function's graph(simple for now ex. x+2)
but i'm having problems to make mathematical coordinates of my points depending on screen coordinates .
I want it to simply draw a line that goes from P1(0,1) to P2(1,2) inside my graph.
here is my code :
import java.awt.*;
import javax.swing.*;
public class Graph extends JPanel {
protected void paintComponent(Graphics g) {
int YP1,YP2;
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
int h = getHeight();
int w = getWidth();
// Draw axeX.
g2.draw(new Line2D.Double(0, h/2, w, h/2)); //to make axisX in the middle
// Draw axeY.
g2.draw(new Line2D.Double(w/2,h,w/2,0));//to make axisY in the middle of the panel
//line between P1(0,1) and P2(1,2) to draw function x+1
Point2D P1 = new Point2D.Double(w/2,(h/2)+1);
Point2D P2 = new Point2D.Double((w/2)+1,(h/2)+2);
g2.draw(new Line2D.Double(P1,P2));
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new Graphe());
f.setSize(400,400);
f.setLocation(200,200);
f.setVisible(true);
}
}
thanks.
import java.awt.*;
import javax.swing.*;
public class Graph extends JPanel {
private static final int UNIT = 20;
protected void paintComponent(Graphics g) {
int YP1,YP2;
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
int h = getHeight();
int w = getWidth();
// Draw axeX.
g2.draw(new Line2D.Double(0, h/2, w, h/2)); //to make axisX in the middle
// Draw axeY.
g2.draw(new Line2D.Double(w/2,h,w/2,0));//to make axisY in the middle of the panel
//line between P1(0,1) and P2(1,2) to draw function x+1
Point2D P1 = new Point2D.Double(w/2,(h/2)+ UNIT);
Point2D P2 = new Point2D.Double((w/2)+ UNIT,(h/2)+ 2*UNIT); //considering 20 = 1 unit in your syste,
g2.draw(new Line2D.Double(P1,P2));
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new Graphe());
f.setSize(400,400);
f.setLocation(200,200);
f.setVisible(true);
}
}
Tryout this code read comments to get the solution
The center of your coordinate system (0,0) is painted at (w/2, h/2). The missing part is the scale, in other words: how many pixels make one unit on the x axis and y axis.
So usually you multiply your unit value by the scaling factor (like 10, if you want 10 pixel per unit) and add the offset of the axis from the left or lower boundary. The annoying part is the (0,0) on screen coordinates is the upper left corner and height counts from top to bottom (reversed y axis). That makes it a bit more complicated:
xOnScreenPos = (xUnit * xScale) + xScaleOffset;
yOnScreenPos = -(yUnit * yScale) + yScaleOffset;

Categories

Resources