I need to draw a fill square, that square must be painted with lines from center.
we can't use java shapes
We have a center point and the pen must draw a line from center to the square edge in each angle.
The problem here is the Maths, what can i use to calculate the distance needed to paint. Because if i use always same distance it will draw a circle.
Thanks
When drawing the square you can think of the length you need to draw at any angle as being the length of the hypoteneuse of a right-angled triangle. You can solve this with trigonometric ratios easily enough. The tricky part is that the base of the triangle moves around.
Taking the example of a line at 45 degrees shown in the left half of the diagram below:
You need to work out the length of the red line (hyp). You can use
trigonometry to work out the length of hyp based on its angle to
adj and the length of the
adj. The length of the adj side is half the height of the
square.
The formula to use is:
cos(angle) = adj/hyp
rearranged:
hyp = adj/cos(angle)
The code would look something like this:
public static double calculateLengthToPaint(double angle, double heightOfSquare){
return (heightOfSquare/2.0) / Math.cos(Math.toRadians(angle));
}
Unfortunately that's not all though. This works perfectly for the first 45 degrees, but when angle > 45 degrees then the adjacent side of the triangle changes place (as can be seen in the right half of the diagram below). It keeps flipping over every 45 degrees.
To handle this flipping you need to use the angle that's passed into the method (the angle around the square from the 12 o'clock position) to work out the angle of the triangle we are imagining. I've modified the method above to add logic to work out the corrected angle.
public static double calculateLengthToPaint(double angle, double heightOfSquare){
double flippy = angle % 90;
if (flippy > 45.0){
flippy -= 90;
flippy = Math.abs(flippy);
}
return (heightOfSquare/2.0) / Math.cos(Math.toRadians(flippy));
}
Notes: This code takes it's angle in degrees and only works for positive angles. Also, if you want to have the lines meet the square at even increments around the perimiter then you need to come up with a solution that uses the pythagorean theorem to work out the length of the hypoteneuse and then use trigonometry to work out the angle to draw it at.
Hope that helps.
Just use java.awt.Graphics.fillRect(int, int, int, int).
I would say something like this
for(int i = sideLength * -1; i < sideLength; i++) {
for(int j = sideLength * -1; j < sideLength; j++) {
graphics.drawLine(centerX + i, centerY + j);
}
}
That way, it will paint a line to every point in your square that you're trying to make. I'm not sure if this is what you wanted, but it will work.
Related
public void turnLeft(double degrees) {
for (int i = 0; i < degrees; i++) {
this.left(degrees);
}
}
This code helps my turtle turn how many ever degrees I want it to, but when I put in like 180 degrees it only turns 90.
I can only guess that your implementation of the left method rotates turtle on degrees number, specified with method parameter.
In your case (calling of the turnLeft(180)) the loop will do the following:
this.left(1);
this.left(2);
...
this.left(180);
so... it very similar with calling the turnLeft method with number of degrees equals 1+2+3+...+180 it is 16110
So in this case your turtle makes 16110 div 360 = 44 whole cycles and then rotate on 16110 mod 360 = 270 degrees. So it will be in 90 degrees from your initial state.
But it is only my guess what could be happen.
I'm trying to draw a recursive tree, but I'm already stuck at the beginning. I've been trying to figure this out, for a while now, and I just can't seem to get it right.
I am using the StdDraw library. Here's what I want to do:
I've already drawn the trunk (black line). But I need to draw the red line too.
In the main function I've set the canvas size to 500x500px and I've set the x and y limit from 0-500.
StdDraw.setCanvasSize(500, 500);
StdDraw.setScale(0, 500);
The tree parameters that I receive are the tree length (d) and the angle (sine). There are also some others (needed for recursion, but not relevant for this simple problem)
I've drawn the trunk using the following code:
StdDraw.line(250, 150, 250, 150+d);
If you're not familiar with StdDraw it's: StdDraw.line(x0, y0, x1, y1)
Now for the red line I've been struggling with some basic trigonometry, but I don't know where I'm wrong. Here's the code:
//The length of the red line is 3/4 the length of the trunk(given in instructions)
double hypotenuse = (3/4)*d;
//We get the opposite by multiplying the sine * hypotenuse, correct?
double opposite = Math.sin(alpha) * hypotenuse;
//Pythagorean Theorem to get the adjacent
double adjacent = Math.sqrt(Math.pow(hypotenuse, 2)-Math.pow(opposite, 2));
//We draw the line from the last x position minus adjacent to move to the left
//and from last y position upwards by 150+d(previous position)+opposite
StdDraw.line(250,150+d,250-adjacent,150+d+opposite);
I create a new Tree object in main with d=110, alpha=40 to test it.
If I remove the trunk and only try to draw the red line (using StdDraw.line(250,150+d,250-adjacent,150+d+opposite)). I only get a black dot, like this:
All your sides are getting set to zero, because here:
double hypotenuse = (3/4)*d;
(3/4) equals 0. Change to:
double hypotenuse = (3/4.0)*d;
or:
double hypotenuse = 0.75 * d;
I'm meant to draw a pentagon with lines going from the vertices to the centre. These 'arms' are being drawn correctly but when I try to connect the vertices it is being drawn incorrectly. To connect the lines I placed another draw function in the loop as below, which should take the end point coordinates of the first line drawn as the starting point, and the end point coordinates of the next 'arm' that is drawn in the iteration, as its end point. Am I missing something here? Am I wrong the use 'i+angle' in the second draw?
for (int i = 0; i < arms; i += angle) {
double endPointX = armLength * Math.cos(i*angle-Math.PI/2);
double endPointY = armLength * Math.sin(i*angle-Math.PI/2);
double endPointX2 = armLength * Math.cos((i+angle)*angle-Math.PI/2);
double endPointY2 = armLength * Math.sin((i+angle)*angle-Math.PI/2);
g2d.drawLine(centreX, centreY,centreX+ (int) endPointX,centreY+ (int) endPointY);
g2d.drawLine(centreX+ (int) endPointX,centreY+ (int) endPointY, (int) endPointX2,(int) endPointY2);
}
I have a solution for this here in PolygonFactory
Abstractly, the way to generate a regular polygon with n points is to put these points on the unit circle. So:
Calculate your angle step, which is 2 * pi / #vertices
Calculate your radius
Starting at angle 0 (or an offset if you want) use Math.sin(angle) and Math.cos(angle) to calculate the x and y coordinates of your vertices
Store the vertex points somewhere / somehow. If you look at the Polygon class or the class I wrote, you can get some ideas on how to do this in a way that is friendly to converting to a java.awt.Polygon.
I have a float[] newCoords variable that has a size of 9. The first 3 entries represent one vertex, the next 3 represent the second vertex and the last 3 represent the last vertex.
I have some code that is supposed to rotate a triangle anywhere in space when I feed it the coordinates. It looks like this:
float s = (float) Math.sin(0.5);
float c = (float) Math.cos(0.5);
float[] centroid = getCentroid(newCoords);
newCoords[0] -= centroid[0];
newCoords[1] -= centroid[1];
newCoords[3] -= centroid[0];
newCoords[4] -= centroid[1];
newCoords[6] -= centroid[0];
newCoords[7] -= centroid[1];
newCoords[0] = (newCoords[0] * c) - (newCoords[1] * s);
newCoords[1] = (newCoords[0] * s) + (newCoords[1] * c);
newCoords[3] = (newCoords[3] * c) - (newCoords[4] * s);
newCoords[4] = (newCoords[3] * s) + (newCoords[4] * c);
newCoords[6] = (newCoords[6] * c) - (newCoords[7] * s);
newCoords[7] = (newCoords[6] * s) + (newCoords[7] * c);
newCoords[0] += centroid[0];
newCoords[1] += centroid[1];
newCoords[3] += centroid[0];
newCoords[4] += centroid[1];
newCoords[6] += centroid[0];
newCoords[7] += centroid[1];
The problem is, its not rotating it properly, the triangles are spinning and getting smaller and smaller until they disappear for some reason, can anyone see why this is happening?
EDIT: whoops, almost forgot, here is my getCentroid() method.
private float[] getCentroid(float[] p1) {
float[] newCoords = new float[] {(p1[0] + p1[3] + p1[6]) / 3.0f,
(p1[1] + p1[4] + p1[7]) / 3.0f, 0};
return newCoords;
}
I see two problems with your code. Both are fixed with a little change.
You try to apply a rotation operation, taking X and Y coordinates as input and having the new X and Y as output. For every vertex you rotate, you have two lines of code: the first computes the X, the second the Y coordinate. But when computing the Y coordinate, you use the already rotated X coordinate! That's wrong.
There is also a numerical problem. You reuse the old values again and again, resulting in a chain of rotation computations a value makes though, so the numerical errors sum up. Never rely on such computations to work as expected. Instead, you should work with the original values and increase the angle in each frame. This makes sure that each value only participated in a single rotation computation.
For fixing both problems, keep the original coordinates somewhere in your code, I call them coords, and rewrite the code such that you take that array as input (keep newCoords as the output). Increase the rotation angle in each frame to achieve a rotation animation.
This fixes both problems because you get rid of that chain and also you have different arrays for input and output in your rotation function.
Pseudo-code:
// initial:
angle = 0.0;
coords = (initial coordinates)
// per frame:
angle += 0.5;
newCoords = rotate(coords, angle);
draw(newCoords);
Also, please note that 0.5 is a large angle if you want to rotate by that angle frame by frame. The math functions expect angle in radians (not degrees), so you might want to use a lower value depending on what you want to visualize in particular.
You might wonder why I reuse the old angle in each frame, as according to the above mentioned problem 2., it should introduce numerical problems, since it's also a chain of computations. That's not a problem with the rotation angle, as a simple summation doesn't show such bad numerical errors you experience with applying rotations. Yet it has some problems, but they only show up at very long running times when the angle reaches some billions. The reason why such a summation in general is not that bad is because you're changing the variable in the same direction in each frame as well as a slightly off rotation angle isn't noticed very much by the user.
Im trying to get into some basic JavaFX game development and I'm getting confused with some circle maths.
I have a circle at (x:250, y:250) with a radius of 50.
My objective is to make a smaller circle to be placed on the circumference of the above circle based on the position of the mouse.
Where Im getting confused is with the coordinate space and the Trig behind it all.
My issues come from the fact that the X/Y space on the screen is not centered at 0,0. But the top left of the screen is 0,0 and the bottom right is 500,500.
My calculations are:
var xpos:Number = mouseEvent.getX();
var ypos:Number = mouseEvent.getY();
var center_pos_x:Number = 250;
var center_pos_y:Number = 250;
var length = ypos - center_pos_y;
var height = xpos - center_pos_x;
var angle_deg = Math.toDegrees(Math.atan(height / length));
var angle_rad = Math.toRadians(angle_deg);
var radius = 50;
moving_circ_xpos = (radius * Math.cos(angle_rad)) + center_pos_x;
moving_circ_ypos = (radius * Math.sin(angle_rad)) + center_pos_y;
I made the app print out the angle (angle_deg) that I have calculated when I move the mouse and my output is below:
When the mouse is (in degrees moving anti-clockwise):
directly above the circle and horizontally inline with the center, the angle is -0
to the left and vertically centered, the angle is -90
directly below the circle and horizontally inline with the center, the angle is 0
to the right and vertically centered, the angle is 90
So, what can I do to make it 0, 90, 180, 270??
I know it must be something small, but I just cant think of what it is...
Thanks for any help
(and no, this is not an assignment)
atan(height/length) is not enough to get the angle. You need to compensate for each quadrant, as well as the possibility of "division-by-zero". Most programming language libraries supply a method called atan2 which take two arguments; y and x. This method does this calculation for you.
More information on Wikipedia: atan2
You can get away without calculating the angle. Instead, use the center of your circle (250,250) and the position of the mouse (xpos,ypos) to define a line. The line intersects your circle when its length is equal to the radius of your circle:
// Calculate distance from center to mouse.
xlen = xpos - x_center_pos;
ylen = ypos - y_center_pos;
line_len = sqrt(xlen*xlen + ylen*ylen); // Pythagoras: x^2 + y^2 = distance^2
// Find the intersection with the circle.
moving_circ_xpos = x_center_pos + (xlen * radius / line_len);
moving_circ_ypos = y_center_pos + (ylen * radius / line_len);
Just verify that the mouse isn't at the center of your circle, or the line_len will be zero and the mouse will be sucked into a black hole.
There's a great book called "Graphics Gems" that can help with this kind of problem. It is a cookbook of algorithms and source code (in C I think), and allows you to quickly solve a problem using tested functionality. I would totally recommend getting your hands on it - it saved me big time when I quickly needed to add code to do fairly complex operations with normals to surfaces, and collision detections.