Trying to draw polygons with JFrame - java

I want to code a program in java that utilises loops and JFrame to create various polygons around one another.
ie. Triangle, then Square, then Pentagon etc...
Refrence image of example
super.paintComponent(g);
int y = 0;
int z = 0;
g2D.setPaint(Color.CYAN);
Polygon p = new Polygon();
for (int x = 4; x < 10; x++) {
y = y + 50;
z = z + 100;
System.out.println("y = "+y);
System.out.println("z = " + z);
for (int i = 0; i < 10; i++) {
p.addPoint((int) (z + y * Math.cos(i * 2 * Math.PI / x)),
(int) (z + y * Math.sin(i * 2 * Math.PI / x)));
}
g2D.drawPolygon(p);
}
}
Output of Code
Any help would be much appreciated.

Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay close attention to the Performing Custom Painting section.
This is a picture of what the OP is supposed to draw.
The only regular polygon in the picture is the square. At least, I think it's a square.
The triangle is an isosceles triangle.
I'm not sure how you would define the pentagon. The five sides are not equal in length. The side two segments are shorter than the bottom segment. The top two segments appear to be longer than the bottom segment.
You can't use the center point and angle of rotation math to create the polygons. The triangle is not an equilateral triangle.
You have to create this by calculating line segments. I'm assuming that the three polygons share the same base. Calculate one line segment at a time and test your code. You're going to run hundreds of tests before you're done.
I'd start by calculating the square first. A square is made up of four equal length line segments. To start, I'd take 1/2 of the width of the drawing area to be the length of the line segment. The first two X values are at the 1/4 and 3/4 points. The Y value can be 20 pixels off the bottom.
Now that you've drawn one line segment, calculate the line segments for the square. Draw the square.
Find the midpoint of the top square line segment. calculate the triangle line segments. Draw the triangle.
For the pentagon, the side line segments are shorter than the line segments of the square. Each angle of a regular pentagon is 108 degrees from the previous line segment. This polygon has slightly different angles at each point.
You'll have to experiment with the pentagon line segment lengths until the top two segments just intersect the square line segments. You could probably do the math, but I suspect it would be easier to just keep guessing until you get an acceptable drawing.
Edited to add:
I created the following GUI.
Calculating the pentagon line segments took the most time.
The side line segments are 85% of the line length of the bottom line segment. I used a 105 degree angle to calculate the end points of the side line segments.
I used a slope formula to calculate the y point of the top line segments. I'd already calculated the start point and the intersect point to draw the pentagon side line segments and the square, respectively. This calculation took most of my debugging time.
Edited to add:
I don't want to just give you the complete code. Part of learning is struggling with the code and learning how to solve problems as they come up. As I said, you should be writing a little bit of code at a time and testing each little bit of code to see what it does.
Here are two methods I wrote to calculate the four additional pentagon line segments. The Point class is java.awt.Point.
private Point calculateSideSegment(Point start, int radius, int angle) {
double theta = Math.toRadians(angle);
int x = (int) Math.round(Math.cos(theta) * radius) + start.x;
int y = (int) Math.round(Math.sin(theta) * radius) + start.y;
return new Point(x, y);
}
private int calculateTopSegment(Point start, Point intersect, int x) {
int yDiff = start.y - intersect.y;
int xDiff1 = start.x - intersect.x;
int xDiff2 = start.x - x;
double slope = (double) yDiff / xDiff1;
double y = Math.round(slope * xDiff2);
return start.y - (int) y;
}

Related

Drawing Spiral Using Java in Processing

I have a Java program written in Processing I made that draws a spiral in processing but I am not sure how some of the lines of code work. I wrote them based on a tutorial. I added comments in capital letters to the lines I do not understand. The comments in lowercase are lines that I do understand. If you understand how those lines work, please explain in very simple terms! Thank you so much.
void setup()
{
size(500,500);
frameRate(15);
}
void draw()
{
background(0); //fills background with black
noStroke(); //gets rid of stroke
int circlenumber = 999;// determines how many circles will be drawn
float radius = 5; //radius of each small circle
float area = (radius) * (radius) * PI; //area of each small circle
float total = 0; //total areas of circles already drawn
float offset = frameCount * 0.01; //HOW DOES IT WORK & WHAT DOES IT DO
for (int i = 1; i <= circlenumber; ++i) { // loops through all of the circles making up the pattern
float angle = i*19 + offset; //HOW DOES IT WORK & WHAT DOES IT DO
total += area; // adds up the areas of all the small circles that have already been drawn
float amplitude = sqrt( total / PI ); //amplitude of trigonometric spiral
float x = width/2 + cos(angle) * amplitude;//HOW DOES IT WORK & WHAT DOES IT DO
float hue = i;//determines circle color based on circle number
fill(hue, 44, 255);//fills circle with that color
ellipse(x, 1*i, radius*2, radius*2); //draws circle
}
}
Essentially what this is doing is doing a vertical cosine curve with a changing amplitude. Here is a link to a similar thing to what the program is doing. https://www.desmos.com/calculator/p9lwmvknkh
Here is an explanation of this different parts in order. I'm gonna reference some of the variables from the link I provided:
float offset = frameCount * 0.01
What this is doing is determining how quickly the cosine curve is animating. It is the "a" value from desmos. To have the program run, each ellipse must change its angle in the cosine function just a little bit each frame so that it moves. frameCount is a variable that stores the current amount of frames that the animation/sketch has run for, and it goes up every frame, similar to the a-value being animated.
for (int i = 1; i <= circlenumber; ++i) {
float angle = i*19 + offset;
This here is responsible for determining how far from the top the current ellipse should be, modified by a stretching factor. It's increasing each time so that each ellipse is slightly further along in the cosine curve. This is equivalent to the 5(y+a) from desmos. The y-value is the i as it is the dependent variable. That is the case because for each ellipse we need to determine how far it is from the top and then how far it is from the centre. The offset is the a-value because of the reasons discussed above.
float x = width/2 + cos(angle) * amplitude
This calculates how far the ellipse is from the centre of the screen (x-centre, y value is determined for each ellipse by which ellipse it is). The width/2 is simply moving all of the ellipses around the centre line. If you notice on Desmos, the center line is y-axis. Since in Processing, if something goes off screen (either below 0 or above width), we don't actually see it, the tutorial said to offset it so the whole thing shows. The cos(angle)*amplitude is essentially the whole function on Desmos. cos(angle) is the cosine part, while amplitude is the stuff before that. What this can be treated as is essentially just a scaled version of the dependent variable. On desmos, what I'm doing is sqrt(-y+4) while the tutorial essentially did sqrt(25*i). Every frame, the total (area) is reset to 0. Every time we draw a circle, we increase it by the pi * r^2 (area of circle). That is where the dependent variable (i) comes in. If you notice, they write float amplitude = sqrt( total / PI ); so the pi from the area is cancelled out.
One thing to keep in mind is that the circles aren't actually moving down, it's all an illusion. To demonstrate this, here is some modified code that will draw lines. If you track a circle along the line, you'll notice that it doesn't actually move down.
void setup()
{
size(500,500);
frameRate(15);
}
void draw()
{
background(0); //fills background with black
noStroke(); //gets rid of stroke
int circlenumber = 999;// determines how many circles will be drawn
float radius = 5; //radius of each small circle
float area = (radius) * (radius) * PI; //area of each small circle
float total = 0; //total areas of circles already drawn
float offset = frameCount * 0.01; //HOW DOES IT WORK & WHAT DOES IT DO
for (int i = 1; i <= circlenumber; ++i) { // loops through all of the circles making up the pattern
float angle = i*19 + offset; //HOW DOES IT WORK & WHAT DOES IT DO
total += area; // adds up the areas of all the small circles that have already been drawn
float amplitude = sqrt( total / PI ); //amplitude of trigonometric spiral
float x = width/2 + cos(angle) * amplitude;//HOW DOES IT WORK & WHAT DOES IT DO
float hue = i;//determines circle color based on circle number
fill(hue, 44, 255);//fills circle with that color
stroke(hue,44,255);
if(i%30 == 0)
line(0,i,width,i);
ellipse(x, i, radius*2, radius*2); //draws circle
}
}
Hopefully this helps clarify some of the issues with understanding.

How can a draw a circle in java pixel by pixel using a graphical app?

The applet used is like the first quadrant of a Cartisian Plane with the domain and range (0, 200). My assignment is to draw a house and a sun in this applet.
I am trying to draw the circle for the sun. I really have no idea where to start. We are learning about for loops and nested loops so it probably pertains to that. We haven't got to arrays and general functions like draw.circle do not exist for this applet. If it helps, here is how I drew my roof for the house (two right triangles): Notice it is drawn pixel by pixel. I suspect my teacher wants the same kind of thing for the circle.
//roof
//left side
double starty = 100;
for(double x = 16; x <= 63; x++){
for(int y = 100; y <= starty; y++){
img.set(x, y, JRaster.purple);
}
starty += 1;
}
//right side
double startx = 110;
for(int y = 100; y <= 147; y++){
for(double x = 63; x <= startx; x++){
img.set(x , y, JRaster.purple);
}
startx -= 1;
}
Here's how I would draw the north-east quarter of a circle, pixel by pixel. You can just repeat this with slight variations for the other three quarters. No trigonometry required!
Start by drawing the eastern most point of the circle. Then you'll draw more pixels, moving northwards and westwards, until you get to the northern most point of the circle.
Calculate the distance of the point you've just drawn from the centre. If it's more than the radius, then your next pixel will be one to the left, otherwise, your next pixel will be the one above.
Repeat the previous step till you get to the northern most point.
Post a comment if you get stuck, with converting this to Java, or with adjusting it for the other three quarters of the circle.
I won't give you code, but you should remember how a circle is made. Going from theta=0 to theta=2*pi, the circle is traced by x=cos x, y=sin x.
So, using a for loop that increments a double(here called theta) by something like 0.01 until 2*pi(2*Math.PI or roughly 6.28) plot off Math.cos(theta), Math.sin(theta).

Java - How to check of a point is inside a sliceof a circle

I have a circle drawn, and I want to make it so I can have more slices than four. I can easily do four quadrants because I just check if the mouse in in the circle and inside a box.
This is how I am checking if the point is in the circle.
if( Math.sqrt((xx-x)*(xx-x) + (yy-y)*(yy-y)) <= radius)
{
return true;
}
else
{
return false;
}
How can I modify this if the circle is divided into more than 4 regions?
For radial slices (circular sectors), you have a couple of alternatives:
Use Math.atan2 to calculate the 4-quadrant angle of the line from the circle center to the point. Compare to the slice angles to determine the slice index.
For a particular slice, you can test which side of each slice edge the point falls. Classify the point accordingly. This is more complicated to calculate but probably faster (for a single slice) than calling Math.atan2.
The following sample code calculates the slice index for a particular point:
int sliceIndex(double xx, double yy, double x, double y, int nSlices) {
double angle = Math.atan2(yy - y, xx - x);
double sliceAngle = 2.0 * Math.PI / nSlices;
return (int) (angle / sliceAngle);
}
The above code makes the following assumptions:
slices are all the same (angular) width
slices are indexed counter-clockwise
slice 0 starts at the +x axis
slices own their right edge but not their left edge
You can adjust the calculations if these assumptions do not apply. (For instance, you can subtract the start angle from angle to eliminate assumption 3.)
First we can check that the point is within the circle as you did. But I woudln't combine this with a check for which quadrant (is that why you have radius/2 ?)
if( (xx-x)*(xx-x) + (yy-y)*(yy-y) > radius*radius)
return false;
Now we can look to see which region the point is in by using the atan2 function. atan2 is like Arctan except the Arctangent function always returns a value between -pi/2 and pi/2 (-90 and +90 degrees). We need the actual angle in polar coordinate fashion. Now assuming that (x,y) is the center of your circle and we are interested in the location of the point (xx,yy) we have
double theta = Math.atan2(yy-y,xx-x);
//theta is now in the range -Math.PI to Math.PI
if(theta<0)
theta = Math.PI - theta;
//Now theta is in the range [0, 2*pi]
//Use this value to determine which slice of the circle the point resides in.
//For example:
int numSlices = 8;
int whichSlice = 0;
double sliceSize = Math.PI*2 / numSlices;
double sliceStart;
for(int i=1; i<=numSlices; i++) {
sliceStart = i*sliceSize;
if(theta < sliceStart) {
whichSlice = i;
break;
}
}
//whichSlice should now be a number from 1 to 8 representing which part of the circle
// the point is in, where the slices are numbered 1 to numSlices starting with
// the right middle (positive x-axis if the center is (0,0).
It is more a trig problem Try something like this.
int numberOfSlices=8;
double angleInDegrees=(Math.toDegrees(Math.atan2(xx-x ,yy-y)));
long slice= Math.round(( numberOfSlices*angleInDegrees )/360 );

Put points round into circular arc used in java

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.

Draw a line at a specific angle in Java

Let's say I have an (x,y) that is always the same for the start point of a line and an (x,y) that changes for the end point of that same line. The line is also always 40px long. At the start of the program the line originates in a vertical orientation (lets call it 0 degrees). Based on a user input I need the line to be redrawn a specific number of degrees from its origin by changing only the end (x,y).
SOME MORE FOOD FOR THOUGHT IF YOU NEED IT:
I'm in a rut trying to calculate this and make it work in Java. I can make the math work to calculate the point based on the arc length of a circle segment, but I don't know how to make Java do it.
I think it would work easier based off a triangle angles since I will always know the length of two sides of a triangle (one side formed by the 40px long line and the other side formed by the start point of that line and the border of the JPanel) and the angle those two lines form. Still, my brain is mush from trying to figure it out. Any help would be much appreciated.
UPDATE:
#casablanca got me on the right track. I brushed up on my trig functions and here is how I made it work.
First off, I didn't realize that 90 degrees was straight up, but once I did realize that I made my solution reflect that fact. I was drawing my line starting at the bottom center of the frame going out. Since the opposite side of the triangle is on the right side of the screen when the angle given by my user is less than 90 degrees and is on the left side of the screen when the angle given by my user is greater than 90 degrees I had to adjust the formula to account for that fact, thus I have four methods, one for the x coordinate on the left side of the screen (when the user given angle is greater than 90 degrees), one for the y coordinate on the left side of the screen (when the user given angle is greater than 90 degrees) and the same thing for the right side of the screen when the user given angle is less than 90 degrees. The int length in all methods is the length of the hypotenuse. Thanks again for your help #casablanca!
public double leftSideX(double angle, int length){
double x = frameWidth/2 - (length * Math.cos(Math.toRadians(90-(Math.toDegrees(angle)-90))));
return x;
}
public double leftSideY(double angle, int length){
double y = frameHeight - (length * Math.sin(Math.toRadians(90-(Math.toDegrees(angle)-90))));
return y;
}
public double rightSideX(double angle, int length){
double x = frameWidth/2 + (length * Math.cos(angle));
return x;
}
public double rightSideY(double angle, int length){
double y = frameHeight - (length * Math.sin(angle));
return y;
}
Is this what you're looking for?
startX = x;
startY = y;
endX = x + 40 * Math.sin(angle);
endY = y + 40 * Math.cos(angle);
And draw a line from (startX, startY) to (endX, endY) in whatever API you're using.
Also note that angle is in radians. If you had it in degrees, you need to convert it first:
angle = angle * Math.PI / 180;

Categories

Resources