I have a problem with JSlider in Java I have drawn a circle A, and I want to put ANOTHER circle B inside the first circle A. I want to place the CENTRE of the second circle B at the same coordinate with the centre of the first circle A, and then I want to use JSlider to INCREASE or DECREASE the radius of circle B. The trouble is, when you increase or decrease the slider, the CENTRE of circle B does not stay aligned with the centre of A. Basically, I want two circles with the SAME centre. Can someone point out my mistake, please?
slider1 = new JSlider(JSlider.HORIZONTAL,10,100,10);
window.add(slider1);
slider1.addChangeListener(this);
Graphics paper = panel.getGraphics();
int slider1Value = slider1.getValue();
paper.setColor(Color.white);
paper.fillRect(0, 0, 500, 500);
paper.setColor(Color.pink);
paper.fillOval(20,20,100,100); // this is circle A
paper.drawOval(60,60,slider1Value,slider1Value); // this is circle B slider
Because you have to change position of top-left "corner" of circle. If you change radius, the circle is bigger/smaller so it's obvious if you don't change position of top-left cornet, centers of 2 circles won't be aligned
Theory
From Graphics.drawOval() javadoc. When you draw a circle their (x,y) coordinates are not its center but its top-left corner. In order to make your B circle aligned with A circle, you need to calculate its (x,y) coordinates relatives to the last one:
Circle A: (x,y) = (20,20); diameter = 100 ==> radius = 50; center = (x + radius, y + radius) = (70,70)
Well, you have your center now: (70,70). Now, slider1Value is your new radius so you need to calculate circle B (x,y) coordinates:
Circle B: center = (70,70); (x,y) = (centerX - radius, centerY - radius) = (70 - slider1Value, 70 - slider1Value)
Finally, circle B width and height are equals to its diameter:radius * 2 = slider1Value * 2.
Facts
Make this change and it will work like a charm:
paper.drawOval(70 - slider1Value, 70 - slider1Value, 2*slider1Value, 2*slider1Value);
Related
I'm trying to draw an arc based on two given points and a given height describing a circle segment. To acomplish this I would use the following method from java.awt.Graphics.
drawArc(int x, int y, int width, int height, int startAngle, int arcAngle)
First I observe that the x, y, width and height values describes a rectangle containing the circle.
The center of the arc is the center of the rectangle whose origin is (x, y) and whose size is specified by the width and height arguments. (http://docs.oracle.com/javase/7/docs/api/java/awt/Graphics.html)
So first I start by calculating the x,y,width and height values. The picture below describes how I would do this.
The first picture shows what values I've already got. The arc in the first picture is exactly what I'm trying to draw. In picture number two I calculate the lenght of a line between the two points. My code to perform this step would look like this:
int dx = p1.x- p2.x;
int dy = p1.y - p2.y;
double len = Math.sqrt(Math.pow((double)dx, 2) + Math.pow((double)dy, 2));
As shown in picture three I can now calculate the radius of the circle by using the following function.
radius = h/2 + len^2 / 8h
The first problem I encounter is to calculate the CenterPoint of the circle. This is partly where I need help.
If I was to calculate the Center Point I can then easily find the x, y, whith and height coordinates.
x = centerPoint.x - radius;
y = centerPoint.y - radius;
width = radius * 2;
height = radius * 2;
The last part is to calculate the startAngle and arcAngle based on the values we already calculated.
TL;DR I need help with calculating the angles and the center point.
Thanks in advance!
There's a well-known relationship (see here, for instance) between the chord half length, the height of the arc (also called the sagitta), and the radius. Let the chord length (the distance between p1 and p2 be l = 2 d, let the arc height be h, and let the radius be r. Then
r = (d 2 + h 2) / (2 h)
The center is on the perpendicular bisector of the chord, at a distance r - h from the chord, on the opposite side from the arc.1 You can then use standard inverse trig functions to get the start and end angles for the chord.
1 Note that it is not enough to know p1, p2, and h; you need some way of identifying which side of the chord has the center and which side has the arc.
What is a method in Java that draws a rectangle given the following:
The coordinates of the center of the square
The angle of the rectangle from vertical, in degrees
To draw a rectangle in the way you suggest you need to use the class AffineTransform. The class can be used to transform a shape in all manner of ways. To perform a rotation use:
int x = 200;
int y = 100;
int width = 50;
int height = 30;
double theta = Math.toRadians(45);
// create rect centred on the point we want to rotate it about
Rectangle2D rect = new Rectangle2D.Double(-width/2., -height/2., width, height);
AffineTransform transform = new AffineTransform();
transform.rotate(theta);
transform.translate(x, y);
// it's been while, you might have to perform the rotation and translate in the
// opposite order
Shape rotatedRect = transform.createTransformedShape(rect);
Graphics2D graphics = ...; // get it from whatever you're drawing to
graphics.draw(rotatedRect);
For the first point, you can just figure out the coordinates of the center of the square by using a distance formula, (int)Math.sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2)); them divide by 2. you can do this for the width and height. I don't know enough about Java draw to give you better answers based on what was in your question but I hope that helps.
For the second, you would need to just create a polygon right?
I'm trying to get a bunch of small circles that have varying shades of green to be drawn within a big circle to get a "bush" look, but I can't figure out how to get all the small circles within the shape of a big circle. I can only figure out how to get it within a rectangle.
public void paintComponent(Graphics g)
{
super.paintComponent(g);
for(int i = 0; i < 1000; i++){
int redV = (int) ((Math.random() * 100) + 27);
g.setColor(new Color(red, red + 31, red - 15));
int x = (int) ((Math.random() * 400) + 150);
int y = (int) ((Math.random() * 500) + 200);
g.fillOval(x, y, 50, 50);
}
}
I guess you have to do some geometry here, and verify whether the x and y coordinates generated randomly are within your circle. As you said, within a rectangle is easy (because you just check that x > left, x+50 < right, y > top, y+50 < bottom), however for a circle you have to use the equation of a circle and check that (x,y) and (x+50,y+50) are within it before actually doing the fillOval().
I think you have a simple way out by using the Java 2D Shape.contains(), which is implemented by Ellipse2D. So essentially you create an instance of Ellipse2D.Double or Ellipse2D.Float for the greater circle, and then just call contains() each time you generate the coordinates to check they are within it before drawing them.
I think you can just change the Color slightly, and increment/decrement x, y, width, and height slightly to get them to be within the older circle. The new oval should be painted over the old one.
Choose the point that should be the center of the big circle, and draw the big circle relative to that (e.g. using java.awt.geom.Ellipse2D).
You can then use the center of the big circle and its radius to position the other smaller circles relative to that also, inside the circumference.
I'm having a lot of trouble grasping the concept of this example in my text book. The idea is to draw a stoplight with red, yellow and green lights. I have a couple of questions. I'm having trouble figuring out what part of the code does what.
Am I right to assume cx and cy are to figure out the center of the page?
Are fx and fy to figure out the center of the frame?
I don't know what dy does and why it's divided by 4 and not 3 for 3 lights and the LAMP_RADIUS totally confuses me.
On all three add(createFilledCircle) for red, yellow and green I don't understand how their position is calculated inside the stoplight frame.
In the method createFilledCircle() I don't understand GOval circle = newGOval(x-r, y-r, 2 * r, 2 * r);. I don't understand what x-r and y-r does and how that relates to position.
import acm. graphics.*;
import acm. program.*;
import java.awt.*;
public class DrawStoplight extends GraphicsProgram {
public void run () {
double cx = getWidth() / 2;
double cy = getHeight() / 2;
double fx = cx - FRAME_WIDTH / 2;
double fy = cy- FRAME_HEIGHT / 2;
double dy = FRAME_HEIGHT / 4 + LAMP_RADIUS / 2;
GRect frame = new GRect(fx, fy, FRAME_WIDTH, FRAME_HEIGHT);
frame.setFilled(true);
frame.setColor(Color.GRAY);
add(frame);
add(createFilledCircle(cx, cy - dy, LAMP_RADIUS, Color.RED));
add(createFilledCircle(cx, cy, LAMP_RADIUS, Color.YELLOW));
add(createFilledCircle(cx, cy + dy, LAMP_RADIUS, Color.GREEN));
}
private GOval createFilledCircle(double x, double y, double r, Color color){
GOval circle = new GOval(x-r, y-r, 2 * r, 2 * r)
circle.setColor(color);
circle.setFilled(true);
return circle;
}
private static final double FRAME_WIDTH = 50;
private static final double FRAME_HEIGHT = 100;
private static final double LAMP_RADIUS = 10;
}
1. Am I right to assume cx and cy are to figure out the center of the page?
Yes
2. Are fx and fy to figure out the center of the frame?
Not exactly. They are computing the upper left hand corner of the frame. They start at the center and "back up" by half the frame size in each direction.
3. I don't know what dy does and why it's divided by 4 and not 3 for 3 lights and the LAMP_RADIUS totally confuses me.
Look farther down in the code. dy is the vertical distance between lights. The yellow light is drawn exactly at the center, the red is dy above, and the green is dy below. The divisor is 4 because the author chose to align the bottom edge of the red light with a point 1/4 of the frame height from the top of the frame. Similarly he chose to align the top of the green light with a point 1/4 of the frame height from the bottom. He could have chosen many other ways of computing dy.
4. On all three add(createFilledCircle) for red, yellow and green I don't understand how their position is calculated inside the stoplight frame.
They all have the same x-coordinate: the center of the frame. The y-coordinates are computed as explained in 3. Remember in screen coordinates, the positive direction is down, so increasing y puts a light lower. Decreasing puts it higher.
5. In the method createFilledCircle() I don't understand GOval circle = newGOval(x-r, y-r, 2 * r, 2 * r);. I don't understand what x-r and y-r does and how that relates to position.
Go read the manual definition of newGOval. It inscribes an oval shape inside a rectangle. The parameters are the upper left corner of the rectangle followed by the width and height. So if (x,y) is the center, this is giving a box with diagonal (x-r, y-r) to (x+r, y+r). When you inscribe an oval in that, you get a circle centered at (x,y) as desired.
Am I right to assume cx and cy are to figure out the center of the page?
Yes
Are fx and fy to figure out the center of the frame?
No, they're the top-left coordinate
I don't know what dy does and why it's divided by 4 and not 3 for 3 lights and the LAMP_RADIUS totally confuses me.
To fit three lights vertically inside a box you need one in the middle, one at 1/4 height, and one at 3/4 height - hence the division by four. I'm unsure why the LAMP_RADIUS comes into it. It appears to be what I'd normally call a "fudge factor" to make the lamps more widely spaced, i.e a figure that looks right, but without any good reason why it looks right...
On all three add(createFilledCircle) for red, yellow and green I don't understand how their position is calculated inside the stoplight frame.
They're just vertically spaced by dy
In the method createFilledCircle() I don't understand GOval circle = newGOval(x-r, y-r, 2 * r, 2 * r);. I don't understand what x-r and y-r does and how that relates to position.
The GOval puts a circle inside the box defined by the coordinates (x - r, y - r) with size 2r - i.e a square of side-length 2r centered on (x, y)
I have me math question: I have known a circle center and radius, and have some uncertain number of points called N, my question is how to put the points on the circular arc, I cannot like put the points around the whole circumference, other as this link: http://i.6.cn/cvbnm/2c/93/b8/05543abdd33b198146d473a43e1049e6.png
in this link, you can read point is circle center, other color is some points, you can see these points around the arc.
Edit - in short: I have known a circle center and radius, so I want to generate some point around the circle center
I am not sure, but I checked this with simple Swing JComponent and seems ok.
Point center = new Point(100, 100); // circle center
int n = 5; // N
int r = 20; // radius
for (int i = 0; i < n; i++)
{
double fi = 2*Math.PI*i/n;
double x = r*Math.sin(fi + Math.PI) + center.getX();
double y = r*Math.cos(fi + Math.PI) + center.getY();
//g2.draw(new Line2D.Double(x, y, x, y));
}
It's not entirely clear what you're trying to accomplish here. The general idea of most of it is fairly simple though. There are 2*Pi radians in a circle, so once you've decided what part of a circle you want to arrange your points over, you multiply that percentage by 2*pi, and divide that result by the number of points to get the angle (in radians) between the points.
To get from angular distances to positions, you take the cosine and sine of the angle, and multiply each by the radius of the circle to get the x and y coordinate of the point relative to the center of the circle. For this purpose, an angle of 0 radians goes directly to the right from the center, and angles progress counter-clockwise from there.