I'm creating a Ray Tracer in java and I just need to print out each of the three Spheres that I have made.
I created 3 sphere objects and stored them in an arraylist in my main which I am now passing to my camera so that I can create an image.
To do this I need to figure out:
If the intersection point isn't null, get the distance between the ray's origin and the intersection point.
If this is the first sphere in inner loop, set a variable to this distance – if not see if this distance is less than the previously measured distance – if so save this distance to compare to other spheres and set the index of the closest sphere to the index of the sphere being evaluated (the counter used in the inner loop going through the spheres).
Outside of this inner loop write the pixel back to the buffered image – but when calling
localReflectionModel use the sphere that is closest (using the index of the closest sphere you saved in the inner loop).
Code:
for(int x = 0; x < filmResolutionX; x++) {
for(int y =0; y < filmResolutionY; y++) {
for (int z = 0; z < s.size(); z++) {
double planeX = -0.5+ x / (double) filmResolutionX;
double planeY = 0.5 - y / (double) filmResolutionY;
double planeZ = 1;
Coord3D planes = new Coord3D(planeX, planeY, planeZ);
Coord3D Origin = new Coord3D(0,0,0);
Ray plane = new Ray(Origin, planes);
Coord3D iPoint = plane.intersectionPoint(s.get(z));
Color colorSphere = new Color(0xD72448);
if (iPoint != null){
double distance = plane.getOrigin().distanceBetween(iPoint);
}
if (z == 0) {
double distanceCheck1 = plane.getOrigin().distanceBetween(iPoint);
} else if (z != 0) {
}
if (iPoint == null) {
newImage.setRGB(x, y, 0);
} else {
colorSphere = s.get(z).localReflectionModel(iPoint, l, plane);
int rgb = colorSphere.getRGB();
newImage.setRGB(x, y, rgb);
}
}
}
}
return newImage;
}
}
I am having problems trying to compare the distances from the previous spheres. When I try to reference the variables distance or distance check 1 I get an error saying that distance cannot be resolved to a variable
It looks like you're having difficulties with scope.
If you declare variables inside a block, like you do in the case of if (something) { double x = ...; }, the variables are visible only inside the declared block.
If you later want to access these variables, you have to change the scope so that they are visible in the block you want to use them in. Of course you could just declare them at the global level, but the art lies in finding the smallest effective scope.
Related
I have a BufferedImage that I want to loop through. I want to loop through all pixels inside a circle with radius radius which has a center x and y at x,y.
I do not want to loop through it in a square fashion. It would also be nice if I could do this and cut O complexity in the process, but this is not needed. Since area of a circle is pi * r^2 and square would be 4 * r^2 that would mean I could get 4 / pi better O complexity if I looped in a perfect circle. If the circle at x,y with a radius of radius would happen to be larger than the dimensions of the BufferedImage, then prevent going out of bounds (this can be done with an if statement I believe to prevent going out of bounds at each check).
Examples: O means a recorded pixel while X means it was not looped over.
Radius 1
X O X
O O O
X O X
Radius 2
X X O X X
X O O O X
O O O O O
X O O O X
X X O X X
I think the proper way to do this is with trigonometric functions but I can't quite get it in my head. I know one easy part is that all Pixels up, left, right, and down in radius from the origin are added. Would like some advice incase anyone has any.
private LinkedList<Integer> getPixelColorsInCircle(final int x, final int y, final int radius)
{
final BufferedImage img; // Obtained somewhere else in the program via function call.
final LinkedList<Integer> ll = new Linkedlist<>();
for (...)
for (...)
{
int x = ...;
int y = ...;
ll.add(img.getRGB(x, y)); // Add the pixel
}
}
Having the center of the circle O(x,y) and the radius r the following coordinates (j,i) will cover the circle.
for (int i = y-r; i < y+r; i++) {
for (int j = x; (j-x)^2 + (i-y)^2 <= r^2; j--) {
//in the circle
}
for (int j = x+1; (j-x)*(j-x) + (i-y)*(i-y) <= r*r; j++) {
//in the circle
}
}
Description of the approach:
Go from the top to the bottom perpendicularly through the line which goes through the circle center.
Move horizontally till you reach the coordinate outside the circle, so you only hit two pixels which are outside of the circle in each row.
Move till the lowest row.
As it's only the approximation of a circle, prepare for it might look like a square for small rs
Ah, and in terms of Big-O, making 4 times less operations doesn't change complexity.
Big-O =/= complexity
While xentero's answer works, I wanted to check its actual performance (inCircle1) against the algorithm that OP thinks is too complex (inCircle2):
public static ArrayList<Point> inCircle1(Point c, int r) {
ArrayList<Point> points = new ArrayList<>(r*r); // pre-allocate
int r2 = r*r;
// iterate through all x-coordinates
for (int i = c.y-r; i <= c.y+r; i++) {
// test upper half of circle, stopping when top reached
for (int j = c.x; (j-c.x)*(j-c.x) + (i-c.y)*(i-c.y) <= r2; j--) {
points.add(new Point(j, i));
}
// test bottom half of circle, stopping when bottom reached
for (int j = c.x+1; (j-c.x)*(j-c.x) + (i-c.y)*(i-c.y) <= r2; j++) {
points.add(new Point(j, i));
}
}
return points;
}
public static ArrayList<Point> inCircle2(Point c, int r) {
ArrayList<Point> points = new ArrayList<>(r*r); // pre-allocate
int r2 = r*r;
// iterate through all x-coordinates
for (int i = c.y-r; i <= c.y+r; i++) {
int di2 = (i-c.y)*(i-c.y);
// iterate through all y-coordinates
for (int j = c.x-r; j <= c.x+r; j++) {
// test if in-circle
if ((j-c.x)*(j-c.x) + di2 <= r2) {
points.add(new Point(j, i));
}
}
}
return points;
}
public static <R extends Collection> R timing(Supplier<R> operation) {
long start = System.nanoTime();
R result = operation.get();
System.out.printf("%d points found in %dns\n", result.size(),
TimeUnit.NANOSECONDS.toNanos(System.nanoTime() - start));
return result;
}
public static void testCircles(int r, int x, int y) {
Point center = new Point(x, y);
ArrayList<Point> in1 = timing(() -> inCircle1(center, r));
ArrayList<Point> in2 = timing(() -> inCircle2(center, r));
HashSet<Point> all = new HashSet<>(in1);
assert(all.size() == in1.size()); // no duplicates
assert(in1.size() == in2.size()); // both are same size
all.removeAll(in2);
assert(all.isEmpty()); // both are equal
}
public static void main(String ... args) {
for (int i=100; i<200; i++) {
int x = i/2, y = i+1;
System.out.println("r = " + i + " c = [" + x + ", " + y + "]");
testCircles(i, x, y);
}
}
While this is by no means a precise benchmark (not much warm-up, machine doing other things, not smoothing outliers via n-fold repetition), the results on my machine are as follows:
[snip]
119433 points found in 785873ns
119433 points found in 609290ns
r = 196 c = [98, 197]
120649 points found in 612985ns
120649 points found in 584814ns
r = 197 c = [98, 198]
121905 points found in 619738ns
121905 points found in 572035ns
r = 198 c = [99, 199]
123121 points found in 664703ns
123121 points found in 778216ns
r = 199 c = [99, 200]
124381 points found in 617287ns
124381 points found in 572154ns
That is, there is no significant difference between both, and the "complex" one is often faster. My explanation is that integer operations are really, really fast - and examining a few extra points on the corners of a square that do not fall into the circle is really fast, compared to the cost of processing all those points that do fall into the circle (= the expensive part is calling points.add, and it is called the exact same number of times in both variants).
In the words of Knuth:
programmers have spent far too much time worrying about efficiency in
the wrong places and at the wrong times; premature optimization is the
root of all evil (or at least most of it) in programming
Then again, if you really need an optimal way of iterating the points of a circle, may I suggest using Bresenham's Circle Drawing Algorithm, which can provide all points of a circumference with minimal operations. It will again be premature optimization if you are actually going do anything with the O(n^2) points inside the circle, though.
I am looking for some help with some game code i have inherited from a flight sim. The code below simulates bombs exploding on the ground, it works fine but i am trying to refine it.
At the moment it takes a random value for x and y as a start point and then adds another random value between -20 and 20 to this. It works ok, but doesn't simulate bombs dropping very well as the pattern does not lay along a straight line/
What i would like to achieve though is all x and y points after the first random values, to lay along a straight line, so that the effects called for all appear to lay in a line. It doesn't matter which way the line is orientated.
Thanks for any help
slipper
public static class BombUnit extends CandCGeneric
{
public boolean danger()
{
Point3d point3d = new Point3d();
pos.getAbs(point3d);
Vector3d vector3d = new Vector3d();
Random random = new Random();
Aircraft aircraft = War.GetNearestEnemyAircraft(this, 10000F, 9);
if(counter > 10)
{
counter = 0;
startpoint.set(point3d.x + (double)(random.nextInt(1000) - 500), point3d.y + (double)(random.nextInt(1000) - 500), point3d.z);
}
if(aircraft != null && (aircraft instanceof TypeBomber) && aircraft.getArmy() != myArmy)
{
World.MaxVisualDistance = 50000F;
counter++;
String s = "weapon.bomb_std";
startpoint.x += random.nextInt(40) - 20;
startpoint.y += random.nextInt(40) - 20;
Explosions.generate(this, startpoint, 7F, 0, 30F, !Mission.isNet());
startpoint.z = World.land().HQ(startpoint.x, startpoint.y);
MsgExplosion.send(this, s, startpoint, getOwner(), 0.0F, 7F, 0, 30F);
Engine.land();
int i = Landscape.getPixelMapT(Engine.land().WORLD2PIXX(startpoint.x), Engine.land().WORLD2PIXY(startpoint.y));
if(firecounter < 100 && i >= 16 && i < 20)
{
Eff3DActor.New(null, null, new Loc(startpoint.x, startpoint.y, startpoint.z + 5D, 0.0F, 90F, 0.0F), 1.0F, "Effects/Smokes/CityFire3.eff", 300F);
firecounter++;
}
super.setTimer(15);
}
return true;
}
private static Point3d startpoint = new Point3d();
private int counter;
private int firecounter;
public BombUnit()
{
counter = 11;
firecounter = 0;
Timer1 = Timer2 = 0.05F;
}
}
The code in the question is a mess, but ignoring this and trying to focus on the relevant parts: You can generate a random position for the first point, and a random direction, and then walk along this direction in several steps.
(This still raises the question of whether the direction is really not important. Wouldn't it matter if only the first bomb was dropped in the "valid" area, and the remaining ones outside of the screen?)
However, the relevant code could roughly look like this:
class Bombs
{
private final Random random = new Random(0);
int getScreenSizeX() { ... }
int getScreenSizeY() { ... }
// Method to drop a single bomb at the given position
void dropBombAt(double x, double y) { ... }
void dropBombs(int numberOfBombs, double distanceBetweenBombs)
{
// Create a random position in the screen
double currentX = random.nextDouble() * getScreenSizeX();
double currentY = random.nextDouble() * getScreenSizeY();
// Create a random step size
double directionX = random.nextDouble();
double directionY = random.nextDouble();
double invLength = 1.0 / Math.hypot(directionX, directionY);
double stepX = directionX * invLength * distanceBetweenBombs;
double stepY = directionY * invLength * distanceBetweenBombs;
// Drop the bombs
for (int i=0; i<numberOfBombs; i++)
{
dropBombAt(currentX, currentY);
currentX += stepX;
currentY += stepY;
}
}
}
I am assuming your startpoint is a StartPoint class with x,y,z coordinates as integers in it.
I hope I have understood your problem correctly. It looks like you either want to create a vertical explosion or a horizontal explosion. Since an explosion always occurs on ground, the z coordinate will be zero. Now you can vary one of x or y coordinate to give you a random explosion along a straight line. Whether you choose x or y could be fixed or could be randomized itself. A potential randomized solution below:
public boolean danger() {
// stuff
int orientation = Random.nextInt(2);
if(aircraft != null && (aircraft instanceof TypeBomber) && aircraft.getArmy() != myArmy)
{
// stuff
startPoint = randomizeStartPoint(orientation, startPoint);
// stuff
}
}
StartPoint randomizeStartPoint(int orientation, StartPoint startPoint) {
if(orientation == 0) {
startPoint.x += random.nextInt(40) - 20;
}
else {
startPoint.y += random.nextInt(40) - 20;
}
return startPoint;
}
In response to the image you uploaded, it seems that the orientation of the explosion need not necessarily be horizontal or vertical. So the code I posted above gives a limited solution to your problem.
Since you want any random straight line, your problem boils down to two sub parts:
1. Generate a random straight line equation.
2. Generate random point along this line.
Now, a straight line equation in coordinate geometry is y = mx + c where m is the slope and c is the constant where the line crosses the y-axis. The problem with c is that it gives rise to irrational coordinates. I am assuming you are looking for integer coordinates only, since this will ensure that your points are accurately plotted. (You could do with rational fractions, but then a fraction like 1/3 will still result in loss of accuracy). The best way to get rid of this irrational problem is to get rid of c. So now your straight line always looks like y = mx. So for step one, you have to generate a random m.
Then for step 2, you can either generate a random x or random y. It doesn't matter which one, since either one will result in random coordinates.
Here is a possible code for the solution:
int generateRandomSlope() {
return Random.nextInt(100); // arbitrarily chose 100.
}
int randomizeStartPoint(int m, StartPoint startPoint) { // takes the slope we generated earlier. without the slope, your points will never be on a straight line!
startPoint.x += random.nextInt(40) - 20;
startPoint.y += x * m; // because a line equation is y = mx
return startPoint;
}
public boolean danger() {
// stuff
int m = generateRandomSlope(); // you may want to generate this elsewhere so that it doesn't change each time danger() is called.
if(aircraft != null && (aircraft instanceof TypeBomber) && aircraft.getArmy() != myArmy)
{
// stuff
startPoint = randomizeStartPoint(m, startPoint);
// stuff
}
}
Again, this is not a complete or the best solution.
Rotating Asteroids ( Polygons )
I am trying to rotate asteroids(polygons) so that they look nice. I am doing this through multiple mathematical equations. To start I give the individual asteroid a rotation velocity:
rotVel = ((Math.random()-0.5)*Math.PI/16);
Then I create the polygon shape,
this.shape = new Polygon();
Followed by generating the points,
for (j = 0; j < s; j++) {
theta = 2 * Math.PI / s * j;
r = MIN_ROCK_SIZE + (int) (Math.random() * (MAX_ROCK_SIZE - MIN_ROCK_SIZE));
x = (int) -Math.round(r * Math.sin(theta)) + asteroidData[0];
y = (int) Math.round(r * Math.cos(theta)) + asteroidData[1];
shape.addPoint(x, y);
}
Finally, in a loop a method is being called in which it attempts to move the polygon and its points down as well as rotating them. (I'm just pasting the rotating part as the other one is working)
for (int i = 0; i < shape.npoints; i++) {
// Subtract asteroid's x and y position
double x = shape.xpoints[i] - asteroidData[0];
double y = shape.ypoints[i] - asteroidData[1];
double temp_x = ((x * Math.cos(rotVel)) - (y * Math.sin(rotVel)));
double temp_y = ((x * Math.sin(rotVel)) + (y * Math.cos(rotVel)));
shape.xpoints[i] = (int) Math.round(temp_x + asteroidData[0]);
shape.ypoints[i] = (int) Math.round(temp_y + asteroidData[1]);
}
now, the problem is that when it prints to the screen the asteroids appear to 'warp' or rather the x and y positions on some of the polygon points 'float' off course.
I've noticed that when I make 'rotVel' be a whole number the problem is solved however the asteroid will rotate at mach speeds. So I've concluded that the problem has to be in the rounding but no matter what I do I can't seem to find a way to get it to work as the Polygon object requires an array of ints.
Does anyone know how to fix this?
Currently your asteroids rotate around (0 , 0) as far as i can see. Correct would be to rotate them around the center of the shape, which would be (n , m), where n is the average of all x-coordinates of the shape, and m is the average of all y-coordinates of the shape.
Your problem is definitely caused by rounding to int! The first improvement is to make all shape coordinates to be of type double. This will solve most of your unwanted 'effects'.
But even with double you might experience nasty rounding errors in case you do a lot of very small updates of the coordinates. The solution is simple: Just avoid iterative updates of the asteroid points. Every time, you update the coordinates based on the previous coordinates, the rounding error will get worse.
Instead, add a field for the rotation angle to the shape and increment it instead of the points themselves. Not until drawing the shape, you compute the final positions by applying the rotation to the points. Note that this will never change the points themselves.
You can extend this concept to other transformations (e.g. translation) too. What you get is some kind of local coordinate system for every shape/object. The points of the shape are defined in the local coordinate system. By moving and rotating this system, you can reposition the entire object anywhere in space.
public class Shape {
// rotation and position of the local coordinate system
private double rot, x, y;
// points of the shape in local coordinate system
private double[] xp, yp;
private int npoints;
// points of the shape in world coordinates
private int[][] wxp, wyp;
private boolean valid;
public void setRotation(double r) { this.rot = r; valid = false; }
public void setPosition(double x, double y) { this.x = x; this.y = y; valid = false; }
public void addPoint(double x, double y) {
// TODO: add point to xp, yp
valid = false;
}
public void draw(...) {
if (!valid) {
computeWorldCoordinates(wxp, wyp);
valid = true;
}
// TODO: draw shape at world coordaintes wxp and wyp
}
protected void computeWorldCoordinates(int[] xcoord, int[] ycoord) {
for (int i = 0; i < npoints; i++) {
double temp_x = xp[i] * Math.cos(rot) - yp[i] * Math.sin(rot);
double temp_y = xp[i] * Math.sin(rot) + yp[i] * Math.cos(rot);
xcoord[i] = (int) Math.round(x + temp_x);
ycoord[i] = (int) Math.round(y + temp_y);
}
}
}
I have a circle that moves from point A to a random point B. When the object nears point B, a new random target location gets chosen. If the circle is moving parallel to the X-axis or Y-axis the object goes through all the pixels in the way and leaves a solid trace. But if the circle moves diagonally, it skips pixels and shakes slightly, making the animation not smooth and leaves a trace with unpainted pixels.
My algorithm is:
calculate the X and Y distances
check if the circle is near
if so, choose the new destination
if 2. is true, find the real distance using Pythagoras' theorem
if 2. is true, calculate the X and Y speed (the change of the coordinates)
set the new coordinates (no matter if 2. is true or not)
And here is the code:
public void move ()//движение
{
//finds the X and Y distance to the destination
int triangleX = nextLocationX - coorX;
int triangleY = nextLocationY - coorY;
//if too near the coordinates of the destination changes
if (Math.abs(triangleX) <= Math.abs(speedX) || Math.abs(triangleY) <= Math.abs(speedY))//setting the new target
{
//setting the new destinatio
int randInt;
for (;;)//I don't want the the new destination to be that same spot
{
randInt= randGen.nextInt(appletX);
if (randInt != nextLocationX)
{
nextLocationX = randInt + radius;
break;
}
}
for (;;)
{
randInt = randGen.nextInt(appletY);
if (randInt != nextLocationY)
{
nextLocationY = randInt + radius;
break;
}
}
//calculating the change of the circle's X and Y coordinates
triangleX = nextLocationX - coorX;
triangleY = nextLocationY - coorY;
speedX = ((double)(speed * triangleX) / (Math.sqrt (Math.pow(triangleX, 2) + Math.pow(triangleY, 2))));
speedY = ((double)(speed * triangleY) / (Math.sqrt (Math.pow(triangleX, 2) + Math.pow(triangleY, 2))));
}
//the realCoor variables are from type double
//they are the exact coordinates of the circle
//If I only use integers, the circle almost
//never reaches it's destination
//unless the change of the coordinates gets calculated
//after every time they change
realCoorX = realCoorX + speedX;
realCoorY = realCoorY + speedY;
coorX = (int)Math.round(realCoorX);
coorY = (int)Math.round(realCoorY);
}
I suspect that the problem is in the calculation of the change of the coordinates.
For me this sounds like a Aliasing problem. You would have the same problem if you draw(!) a line that is not aligned with the coordinate axis. As you know, i.e. diagonal lines need "half filled" pixels to look smooth.
Solution for you would be (depending on the technology for rendering) to use floating point position calculation.
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?