I have a couple of questions regarding the use of nested for loops. In this example in the book it uses nested for loops to draw a typical checkerboard.
1) Is my understanding correct when I assume the code below says the sequence of drawing the checkerboard squares will be vertically down from left to right until the entire checkerboard is drawn?
2) I'm have some questions about the purpose of double x, and double y inside the inner most for loop. Are they being calculated for the purpose of spacing one square to the next? Can you expand on the purpose of double x and double y and what occurs each cycle of one loop?
import acm.program.*;
import acm.graphics.*;
public class checkerBoard extends GraphicsProgram{
public void run(){
double sqSize = getHeight() / N_ROWS;
for ( int i = 0; i < N_ROWS; i++){
for (int j = 0; j < N_COLUMNS; j++){
double x = j * sqSize;
double y = i * sqSize;
GRect rect = new GRect(x, y, sqSize, sqSize);
rect.setFilled((i+ j) % 2 !=0);
add(rect);
}
}
}
private static final int N_ROWS = 8;
private static final int N_COLUMNS = 8;
}
1) Is my understanding correct when I assume the code below says the
sequence of drawing the checkerboard squares will be vertically down
from left to right until the entire checkerboard is drawn?
This is correct. Row by row, left to right, top to bottom.
2) I'm have some questions about the purpose of double x, and double y
inside the inner most for loop. Are they being calculated for the
purpose of spacing one square to the next? Can you expand on the
purpose of double x and double y and what occurs each cycle of one
loop?
They are the coordinates of the location where to draw the next square. Specifically, they are the coordinate for the upper left part of the square. You can figure out the start points for all squares by simply multiplying by the width of the squares, as they have done.
Related
I made a program where user enters number of rectangles to be drawn and coordinates at which the rectangles are drawn. My rectangles are currently drawn like this:
and I want to achieve this:
This is the code I use to draw the rectangles:
int povecaj_kvadrat=0;
for(int x=0;x<broj_kvadrata;x++) {
Rectangle2D.Float kvadrat=new Rectangle2D.Float(brojevi_koordinate[0],brojevi_koordinate[1],50+povecaj_kvadrat,50+povecaj_kvadrat);
ploca.draw((kvadrat));
povecaj_kvadrat=povecaj_kvadrat+15;
}
}
How do I set the coordinates of the rectangles so that they are drawn like in the second image?
You will have to take into account the additional size of each Rectangle, along with its position within the loop to compute the correct coordinates of each rectangle.
The additional size has been moved as a variable (diffSize), so that your loop can use its value.
The difference in coordinates between two iterations will be half this diff size, multiplied by the inverse of the position in the loop, because the lower the increment (x) and the Rectangle size, the bigger the coordinates .
int gap = 0;
int maxNumber = 3;
int diffSize = 20;
int[] coordinates = { 10, 10 };
for (int x = 0; x <= maxNumber; x++) {
Rectangle2D.Float rectangle = new Rectangle2D.Float(
coordinates[0] + ((diffSize / 2) * (maxNumber - x)),
coordinates[1] + ((diffSize / 2) * (maxNumber - x)),
50 + gap, 50 + gap);
g2d.draw((rectangle));
gap = gap + diffSize;
}
Note that I am unsure of the correct behaviour if diffSize is odd (because (diffSize / 2) will be rounded down to the nearest int value), so I would keep an even value for diffSize.
I have a quick question, that in most languages (such as python) would be straightforward.
I am looking to obtain the integral (area of curve) from an 1D-array of fixed points. Java apparently has many numerical integration libraries, all of which seem to require a function (f {double(x)}) as input.
However I can not seem to find any which accommodate arrays (double []) such as [1,4,10,11]. I would be integrating over the entirety of the array (x values 1-n, where n represents the size of the array)
Any help is greatly appreciated
Well, they expect functions because its normal to use them with a continuity.
Since you have only a different height every step (1,2,3,4...?) you have rectangles with triangles on top of them. the height of the triangles is the difference between the current height and the previous height. therefore the rectangle s height is the current pint height minus triangle height.
Write a function which calculates and adds both areas.
Do this for every point/item in your Array and you will get the integral of your "function".
EDIT: I wrote a little code. no guarantee, I just coded some easy to understand code of the idea of this integral prob. Further improvements have to be done.
public static double getIntegralFromArray(double[] ar, double xDist)
{
double base = 0;
double prev = 0;
double triHeight = 0;
double rectHeight = 0;
double tri = 0;
double rect = 0;
double integral = 0;
for (int i = 0; i < ar.length; i++) {
triHeight=Math.abs(ar[i]-prev); // get Height Triangle
tri = xDist*triHeight/2; // get Area Triangle
if(ar[i]<=prev){
rectHeight = Math.abs(base-ar[i]); // get Height Rectangle
}else {
rectHeight = Math.abs(base-(ar[i]-triHeight)); // get Height Rectangle
}
rect = xDist*rectHeight; // get Area Rectangle
integral += (rect + tri); // add Whole Area to Integral
prev=ar[i];
}
return integral;
}
double[] ar = new double[]{1,2,3,2,2,3,1,3,0,3,3};
System.out.println(MyMath.getIntegralFromArray(ar, 1));
Area under 'curve': 21.5
By using trapezoidal rule you can simply call below method to get area under a graph(approx.)
public static double trapz(double ar[],double xDist){
if (ar.length==1 || ar.length==0)
return 0;
double integral=0;
double prev=ar[0];
for (int i=1;i<ar.length;i++)
{
integral+=xDist*(prev+ar[i])/2.0;
prev=ar[i];
}
return integral;
}
This is an extension to my previous question posted here -- Java Swing GUI for equation 5((θ/β) - cos(2πθ/β))
I have implemented the Java program based on the answers provided in the post an here is my program:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class DisplacementFunctionNew extends JFrame {
public DisplacementFunctionNew() {
setLayout(new BorderLayout());
add(new CosGraph(), BorderLayout.CENTER);
}
public static void main(String[] args) {
DisplacementFunctionNew frame = new DisplacementFunctionNew();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(6000, 6000);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setTitle("SineWave");
}
class CosGraph extends JPanel {
public void paintComponent(Graphics g) {
int graphHeight = 5; // Declared this to set the height of graph based on the value given here.
super.paintComponent(g);
int xBase = 100;
int top = 100;
int yScale = 100;
int xAxis = 360;
int yBase = top + yScale;
g.drawLine(xBase, top, xBase, top + 2 * yScale);
g.drawLine(xBase, yBase, xBase + xAxis, yBase);
g.setColor(Color.red);
double maxY = 0;
for (int i = 0; i < 360; i++) {
maxY = Math.max(maxY, Math.abs(getValue(i)));
}
int x, y;
for (int i = 0; i < 360; i++) {
x = xBase + i;
y = yBase - (int) (getValue(i)*graphHeight / maxY * yScale);
g.drawLine(x, y, x, y);
}
}
private double getValue(int theta) {
int beta = 45;
double b = (theta / (double) beta);
double angle = 2 * Math.PI * (b);
double c = Math.cos(angle);
double s = (b - c);
return s;
}
}
}
Now in this program I want to have a variable called graphHeight that helps to increase the height of the graph. If I give the value of the variable as 1 then I can see the output like this:
Now if I try to increase the height to 5 then I get the graph but it is not shown smoothly or continuous curve, I get the output like this:
Can someone please help me how to get the output as smooth continuous curve?
You are drawing a curve using points. You are placing one point at each location on the x axis -- this makes sense to do.
When the graph is small, it looks fine, because the y separation of these points is relatively small. However, as you increase the graph size, this flaw becomes more noticeable.
The solution here is to fill in the vertical space with lines. You have a few options for the exact implementation of this:
Draw a line from [x(i), y(i)] to [x(i+1),y(i+1)] -- this is easy, but may not look the way you want.
Draw a line from [x(i), y(i)] to [x(i),y(i+1)] -- this is still pretty easy, but it won't be quite correct: you're continuing up so that you could be an entire pixel off.
Draw a line from [x(i), y(i)] to [x(i),(y(i)+y(i+1))/2], and then from [x(i+1), (y(i)+y(i+1))/2] to [x(i+1),y(i+1)] -- this is what 1 should do (neglecting anti-aliasing), and will be the most correct of your possible options.
I would suggest number 3. Note that you can implement this with a loop of the form:
int lastY = yBase - (int) (getValue(0)*graphHeight / maxY * yScale);
for (int i = 1; i < 360; i++) {
x = xBase + i;
y = yBase - (int) (getValue(i)*graphHeight / maxY * yScale);
g.drawLine(x-1, lastY, x-1, (y+lastY)/2);
g.drawLine(x, (y+lastY)/2, x, y);
}
If the one pixel overlap bothers you, you can make it a bit more complex such that the second line starts at +/- 1 pixel (depending on if the function is increasing or decreasing).
Alternatively, you can implement number 3 by manually drawing the line, using a for loop, and basically write a special-case version of Bresenham's line algorithm.
You use graphHeight to define the y of the next point to be painted with g.drawLine(x, y, x, y);. The distance between drawn points will be related to the graphHeight variable
This is what I want to accomplish for homework: Design and implement a program that draws circles, with the radius and location of each circle determined at random. If a circle does not overlap with any other circle, draw that circle in black. If a circle overlaps one or more circles, draw it in cyan. Use an array to store a representation of each circle, then determine the color of each circle. Two circles overlap if the distance between their center points is less than the sum of their radii.
I am really close, but I just cannot figure out how to use the sqrt formula in order to compare the radii of the circles that overlap and then to redraw that circle in cyan. I've tried to figure this out in two other posts here: drawing random circles, storing their coorindates in an array and here: draw random circles, first storing the points in an array. I got some pointers, so can anyone give me specific pointers to figure out how to make my for loop use the Math.sqrt function properly in order to compare the radii and then redraw an overlapping circle in cyan? Thank you very much.
UPDATE: I have gotten the Math.sqrt forumla working, but I can't figure out how to structure my for loop in order to only make the circle that overlaps be filled in. I tried to do this using a nested for loop with a boolean in it, but that is making all of the circles fill in. Thank you for your recommendations so far.
Here is the code that I have so far:
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.*;
import java.awt.event.*;
import java.math.*;
public class RandomCircles extends JPanel
{
private int[] sizeArray = new int [5]; // radius of each circle
private int[] xArray = new int [5]; //array to store x coordinates of circles
private int[] yArray = new int [5]; //array to store y coordinates of circles
private int x1, x2, y1, y2;
private boolean overlap = false;
public RandomCircles()
{
Random r = new Random();
for (int i = 0; i<xArray.length; i++){
//random numbers from 1 to 20;
xArray[i] = r.nextInt(200) + 1;
}
for (int i = 0; i<yArray.length; i++){
yArray[i] = r.nextInt(200) + 1;
}
for (int i = 0; i<sizeArray.length; i++){
sizeArray[i] = r.nextInt(100) +1;
}
setBackground (Color.blue);
setPreferredSize (new Dimension(300, 200));
}
// generates all of the circles stored in the array.
public void paintComponent (Graphics page)
{
super.paintComponent(page);
for (int i = 0 ;i<xArray.length; i++) //this is an iterator that draws the circles and checks for overlapping radii
for (int j = 0 ;j<xArray.length; j++)
{
//boolean overlap = false;
//is supposed to compare radii of circles to check if they overlap
{
if (Math.sqrt((xArray[i]-xArray[j])*(xArray[i]-xArray[j])+(yArray[i]-yArray[j])*(yArray[i]-yArray[j])) >sizeArray[i]-sizeArray[j]);
boolean overlap = true;
page.fillOval(xArray[i], yArray[i], sizeArray[i], sizeArray[i]);
page.setColor (Color.cyan);
repaint();
} //draws the circles that are stored in the array
page.drawOval(xArray[i], yArray[i], sizeArray[i], sizeArray[i]);//outer for loop
}
}
public static void main (String[] args)
{
JFrame frame = new JFrame ("Circles");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add (new RandomCircles());
frame.pack();
frame.setVisible(true);
}
}
//Math.sqrt((x1-x2)*(x1-x2)-(y1-y2)*(y1-y2)), go back and read chapter 7
should be
Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
(You need to take the square root of the sum of the squared X and Y distances, not the difference.)
Update:
There are a couple of problems with the overlap detection. Two circles overlap if
the sum of their radii is greater than the distance between their centers, but
you're taking the difference of the radii and checking if it's less than the
distance between the centers.
Also, you should skip the overlap check whenever i == j (since every circle overlaps
with itself; you're only interested in overlaps between different circles).
I'm a first year programmer. I'm trying to create a squircle. (square with round corners).
So far i have managed to get. I have been given the constants of a,b and r. If anyone could help i would be really thankful. I'm a total noob to this. So be nice :)
package squircle;
import java.awt.*;
import javax.swing.*;
import java.lang.Math;
public class Main extends javax.swing.JApplet {
public void paint(Graphics g){
// (x-a)^4 + (y-b)^4 = r^4
// y = quadroot( r^4 - (x-a)^4 + b)
// x values must fall within a-r < x < a+r
int[] xPoints = new int[200];
int[] yPoints = new int[200];
int[] mypoints = new int[200];
for(int c = 0; c <200; c++){
int a = 100;
int r = 100;
int b = 100;
double x = c ;
double temp = (r*r*r*r);
double temp2 = x-a;
double temp3 = ((temp2)*(temp2)*(temp2)*(temp2));
double temp6 = Math.sqrt(temp-temp3);
double y = (Math.sqrt(temp6) + b );
double z = (y*-1)+300;
mypoints[c]=(int)z;
// if (c>100){
// y = y*1;
// }
// else if(c<100){
// y = y*1;
// }
xPoints[c]=(int)x;
yPoints[c]=(int)y;
// change the equation to find x co-ordinates
// change it to find y co-ordinates.
// r is the minor radius
// (a,b) is the location of the centre
// a = 100
// b = 100
// r = 100
// x value must fall within 0 or 200
}
g.drawPolygon(xPoints, yPoints, xPoints.length);
g.drawPolygon(xPoints, (mypoints), xPoints.length);
}
}
Is it homework or is there some other reason why you're not using Graphics#drawRoundRect()?
If you are submitting this as homework there are some elements of style that may help you. What are the roles of 200, 100 and 300? These are "magic constants" which should be avoided. Are they related or is it just chance that they have these values? Suggest you use symbols such as:
int NPOINTS = 200;
or
double radius = 100.0
That would reveal whether the 300 was actually the value you want. I haven't checked.
Personally I wouldn't write
y*-1
but
-y
as it's too easy to mistype the former.
I would also print out the 200 points as floats and see if you can tell by eye where the error is. It's highly likely that the spurious lines are either drawn at the start or end of the calculation - it's easy to make "end-effect" errors where exactly one point is omitted or calculated twice.
Also it's cheap to experiment. Try iterating c from 0 to 100. or 0 to 10, or 0 to 198 or 1 to 200. Does your spurious line/triangle always occur?
UPDATE Here is what I think is wrong and how to tackle it. You have made a very natural graphics error and a fence-post error (http://en.wikipedia.org/wiki/Off-by-one_error) and it's hard to detect what is wrong because your variable names are poorly chosen.
What is mypoints? I believe it is the bottom half of the squircle - if you had called it bottomHalf then those replying woulod have spotted the problem quicker :-).
Your graphics problem is that you are drawing TWO HALF-squircles. Your are drawing CLOSED curves - when you get to the last point (c==199) the polygon is closed by drawing back to c==0. That makes a D-shape. You have TWO D-shapes, one with the bulge UP and one DOWN. Each has a horizontal line closing the polygon.
Your fence-post error is that you are drawing points from 0 to 199. For the half-squircle you want to draw from 0 to 200. That's 201 points! The loss of one point means that you have a very slightly sloping line. The bottom lines slopes in tghe opposite direction from the top. That gives you a very then wedge shape, which you refer to as a triangle. I'm guessing that your triangle is not actually closed but like a slice from a pie but very then/sharp.
(The code below could be prettier and more compact. However it is often useful to break symmetrical problems into quadrants or octants. It would also be interesting to use an anngle to sweep out the polygon).
You actually want ONE polygon. The code should be something like:
int NQUADRANT = 100;
int NPOINTS = 4*NQUADRANT ; // closed polygon
double[] xpoints = new double[NPOINTS];
double[] ypoints = new double[NPOINTS];
Your squircle is at 100, 100 with radius 100. I have chosen different values here
to emphasize they aren't related. By using symbolic names you can easily vary them.
double xcenter = 500.0;
double ycentre = 200.0;
double radius = 100.;
double deltax = radius/(double) NQUADRANT;
// let's assume squircle is centered on 0,0 and add offsets later
// this code is NOT complete or correct but should show the way
// I might have time later
for (int i = 0; i < NPOINTS; i++) {
if (i < NQUADRANT) {
double x0 = -radius + i* deltax;
double y0 = fourthRoot(radius, x0);
x[i] = x0+xcenter;
y[i] = y0+ycenter;
}else if (i < 2*NQUADRANT) {
double x0 = (i-NQUADRANT)* deltax;
double y0 = fourthRoot(radius, x0);
x[i] = x0+xcenter;
y[i] = y0+ycenter;
}else if (i < 3*NQUADRANT) {
double x0 = (i-2*NQUADRANT)* deltax;
double y0 = -fourthRoot(radius, x0);
x[i] = x0+xcenter;
y[i] = y0+ycenter;
}else {
double x0 = -radius + (i-3*NQUADRANT)* deltax;
double y0 = -fourthRoot(radius, x0);
x[i] = x0+xcenter;
y[i] = y0+ycenter;
}
}
// draw single polygon
private double fourthRoot(double radius, double x) {
return Math.sqrt(Math.sqrt(radius*radius*radius*radius - x*x*x*x));
}
There is a javascript version here. You can view the source and "compare notes" to potentially see what you are doing wrong.
Ok, upon further investigation here is why you are getting the "triangle intersecting it". When you drawPolygon the points are drawn and the last point connects the first point, closing the points and making the polygon. Since you draw one half it is drawn (then connected to itself) and then the same happens for the other side.
As a test of this change your last couple lines to this:
for( int i = 0; i < yPoints.length; i++ ) {
g.drawString( "*", xPoints[ i ], yPoints[ i ] );
}
for( int i = 0; i < mypoints.length; i++ ) {
g.drawString( "*", xPoints[ i ], mypoints[ i ] );
}
// g.drawPolygon( xPoints, yPoints, xPoints.length );
// g.drawPolygon( xPoints, ( mypoints ), xPoints.length );
It is a little crude, but I think you'll get the point. There are lots of solutions out there, personally I would try using an array of the Point class and then sort it when done, but I don't know the specifics of what you can and can not do.
Wow, are you guys overthinking this, or what! Why not just use drawLine() four times to draw the straight parts of the rectangle and then use drawArc() to draw the rounded corners?