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;
}
Related
My problem that my perlin noise is repeating itself very obviously in very small spaces. Here is an image of what it going on. I know that this does happen after a certain point with all perlin noise, but it seems to be happening almost immediately with mine. I believe that it is caused by my really awful pseudorandom gradient generator, but Im not sure. My code is below.
As a side note, my perlin noise seems to generate very small values, between -.2 and positive .2 and I think this is also caused by my pseudorandom gradient generator.
If anyone has any advice on improving this part of my code, please feel free to tell me. Any ideas would be helpful right now.
Thanks to everyone in advance!
public class Perlin {
int[] p = new int[255];
public Perlin() {
for(int i = 0; i < p.length; i++)
p[i] = i;
shuffle(p);
}
int grads[][] = {
{1,0},{0,1},{-1,0},{0,-1},
{1,1},{-1,1},{1,-1},{-1,-1}
};
public double perlin (double x, double y) {
int unitX = (int)Math.floor(x) & 255; // decide unit square
int unitY = (int)Math.floor(y) & 255; // decide unit square
double relX = x-Math.floor(x); // relative x position
double relY = y-Math.floor(y); // relative y position
// bad pseudorandom gradient -- what i think is causing the problems
int units = unitX+unitY;
int[] gradTL = grads[p[(units)]%(grads.length)];
int[] gradTR = grads[p[(units+1)]%(grads.length)];
int[] gradBL = grads[p[(units+1)]%(grads.length)];
int[] gradBR = grads[p[(units+2)]%(grads.length)];
// distance from edges to point, relative x and y inside the unit square
double[] vecTL = {relX,relY};
double[] vecTR = {relX-1,relY};
double[] vecBL = {relX,relY-1};
double[] vecBR = {relX-1,relY-1};
// dot product
double tl = dot(gradTL,vecTL);
double tr = dot(gradTR,vecTR);
double bl = dot(gradBL,vecBL);
double br = dot(gradBR,vecBR);
// perlins fade curve
double u = fade(relX);
double v = fade(relY);
// lerping the faded values
double x1 = lerp(tl,tr,u);
double y1 = lerp(bl,br,u);
// ditto
return lerp(x1,y1,v);
}
public double dot(int[] grad, double[] dist) {
return (grad[0]*dist[0]) + (grad[1]*dist[1]);
}
public double lerp(double start, double end, double rate){
return start+rate*(end-start);
}
public double fade(double t) {
return t*t*t*(t*(t*6-15)+10);
}
public void shuffle(int[] p) {
Random r = new Random();
for(int i = 0; i < p.length; i++) {
int n = r.nextInt(p.length - i);
// do swap thing
int place = p[i];
p[i] = p[i+n];
p[i+n] = place;
}
}
}
A side note on my gradient generator, I know Ken Perlin used 255 because he was using bits, I just randomly picked it. I dont think it has any effect on the patterns if it is changed.
Your intuition is correct. You calculate:
int units = unitX+unitY;
and then use that as the base of all your gradient table lookups. This guarantees that you get the same values along lines with slope -1, which is exactly what we see assuming (0, 0) is the upper-left corner.
I would suggest using a real hash function to combine your coordinates: xxHash, Murmur3, or even things like CRC32 (which isn't meant to be a hash) would be much better than what you're doing. You could also implement Perlin's original hash function, although it has known issues with anisotropy.
Hi I am in need of some help. I need to write a convolution method from scratch that takes in the following inputs: int[][] and BufferedImage inputImage. I can assume that the kernel has size 3x3.
My approach is to do the follow:
convolve inner pixels
convolve corner pixels
convolve outer pixels
In the program that I will post below I believe I convolve the inner pixels but I am a bit lost at how to convolve the corner and outer pixels. I am aware that corner pixels are at (0,0), (width-1,0), (0, height-1) and (width-1,height-1). I think I know to how approach the problem but not sure how to execute that in writing though. Please to aware that I am very new to programming :/ Any assistance will be very helpful to me.
import java.awt.*;
import java.awt.image.BufferedImage;
import com.programwithjava.basic.DrawingKit;
import java.util.Scanner;
public class Problem28 {
// maximum value of a sample
private static final int MAX_VALUE = 255;
//minimum value of a sample
private static final int MIN_VALUE = 0;
public BufferedImage convolve(int[][] kernel, BufferedImage inputImage) {
}
public BufferedImage convolveInner(double center, BufferedImage inputImage) {
int width = inputImage.getWidth();
int height = inputImage.getHeight();
BufferedImage inputImage1 = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
//inner pixels
for (int x = 1; x < width - 1; x++) {
for (int y = 1; y < height - 1; y ++) {
//get pixels at x, y
int colorValue = inputImage.getRGB(x, y);
Color pixelColor = new Color(colorValue);
int red = pixelColor.getRed() ;
int green = pixelColor.getGreen() ;
int blue = pixelColor.getBlue();
int innerred = (int) center*red;
int innergreen = (int) center*green;
int innerblue = (int) center*blue;
Color newPixelColor = new Color(innerred, innergreen, innerblue);
int newRgbvalue = newPixelColor.getRGB();
inputImage1.setRGB(x, y, newRgbvalue);
}
}
return inputImage1;
}
public BufferedImage convolveEdge(double edge, BufferedImage inputImage) {
int width = inputImage.getWidth();
int height = inputImage.getHeight();
BufferedImage inputImage2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
//inner pixels
for (int x = 0; x < width - 1; x++) {
for (int y = 0; y < height - 1; y ++) {
//get pixels at x, y
int colorValue = inputImage.getRGB(x, y);
Color pixelColor = new Color(colorValue);
int red = pixelColor.getRed() ;
int green = pixelColor.getGreen() ;
int blue = pixelColor.getBlue();
int innerred = (int) edge*red;
int innergreen = (int) edge*green;
int innerblue = (int) edge*blue;
Color newPixelColor = new Color(innerred, innergreen, innerblue);
int newRgbvalue = newPixelColor.getRGB();
inputImage2.setRGB(x, y, newRgbvalue);
}
}
return inputImage2;
}
public BufferedImage convolveCorner(double corner, BufferedImage inputImage) {
int width = inputImage.getWidth();
int height = inputImage.getHeight();
BufferedImage inputImage3 = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
//inner pixels
for (int x = 0; x < width - 1; x++) {
for (int y = 0; y < height - 1; y ++) {
//get pixels at x, y
int colorValue = inputImage.getRGB(x, y);
Color pixelColor = new Color(colorValue);
int red = pixelColor.getRed() ;
int green = pixelColor.getGreen() ;
int blue = pixelColor.getBlue();
int innerred = (int) corner*red;
int innergreen = (int) corner*green;
int innerblue = (int) corner*blue;
Color newPixelColor = new Color(innerred, innergreen, innerblue);
int newRgbvalue = newPixelColor.getRGB();
inputImage3.setRGB(x, y, newRgbvalue);
}
}
return inputImage3;
}
public static void main(String[] args) {
DrawingKit dk = new DrawingKit("Compositor", 1000, 1000);
BufferedImage p1 = dk.loadPicture("image/pattern1.jpg");
Problem28 c = new Problem28();
BufferedImage p5 = c.convolve();
dk.drawPicture(p5, 0, 100);
}
}
I changed the code a bit but the output comes out as black. What did I do wrong:
import java.awt.*;
import java.awt.image.BufferedImage;
import com.programwithjava.basic.DrawingKit;
import java.util.Scanner;
public class Problem28 {
// maximum value of a sample
private static final int MAX_VALUE = 255;
//minimum value of a sample
private static final int MIN_VALUE = 0;
public BufferedImage convolve(int[][] kernel, BufferedImage inputImage) {
int width = inputImage.getWidth();
int height = inputImage.getHeight();
BufferedImage inputImage1 = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
//for every pixel
for (int x = 0; x < width; x ++) {
for (int y = 0; y < height; y ++) {
int colorValue = inputImage.getRGB(x,y);
Color pixelColor = new Color(colorValue);
int red = pixelColor.getRed();
int green = pixelColor.getGreen();
int blue = pixelColor.getBlue();
double gray = 0;
//multiply every value of kernel with corresponding image pixel
for (int i = 0; i < 3; i ++) {
for (int j = 0; j < 3; j ++) {
int imageX = (x - 3/2 + i + width) % width;
int imageY = (x -3/2 + j + height) % height;
int RGB = inputImage.getRGB(imageX, imageY);
int GRAY = (RGB) & 0xff;
gray += (GRAY*kernel[i][j]);
}
}
int out;
out = (int) Math.min(Math.max(gray * 1, 0), 255);
inputImage1.setRGB(x, y, new Color(out,out,out).getRGB());
}
}
return inputImage1;
}
public static void main(String[] args) {
int[][] newArray = {{1/9, 1/9, 1/9}, {1/9, 1/9, 1/9}, {1/9, 1/9, 1/9}};
DrawingKit dk = new DrawingKit("Problem28", 1000, 1000);
BufferedImage p1 = dk.loadPicture("image/pattern1.jpg");
Problem28 c = new Problem28();
BufferedImage p2 = c.convolve(newArray, p1);
dk.drawPicture(p2, 0, 100);
}
}
Welcome ewuzz! I wrote a convolution using CUDA about a week ago, and the majority of my experience is with Java, so I feel qualified to provide advice for this problem.
Rather than writing all of the code for you, the best way to solve this large program is to discuss individual elements. You mentioned you are very new to programming. As the programs you write become more complex, it's essential to write small working snippets before combining them into a large successful program (or iteratively add snippets). With this being said, it's already apparent you're trying to debug a ~100 line program, and this approach will cost you time in most cases.
The first point to discuss is the general approach you mentioned. If you think about the program, what is the simplest and most repeated step? Obviously this is the kernel/mask step, so we can start from here. When you convolute each pixel, you are performing a similar option, regardless of the position (corner, edge, inside). While there are special steps necessary for these edge cases, they share similar underlying steps. If you try to write code for each of these cases separately, you will have to update the code in multiple (three) places with each adjustment and it will make the whole program more difficult to grasp.
To support my point above, here's what happened when I pasted your code into IntelliJ. This illustrates the (yellow) red flag of using the same code in multiple places:
The concrete way to fix this problem is to combine the three convolve methods into a single one and use if statements for edge-cases as necessary.
Our pseudocode with this change:
convolve(kernel, inputImage)
for each pixel in the image
convolve the single pixel and check edge cases
endfor
end
That seems pretty basic right? If we are able to successfully check edge cases, then this extremely simple logic will work. The reason I left it so general above to show how convolve the single pixel and check edge cases is logically grouped. This means it's a good candidate for extracting a method, which could look like:
private void convolvePixel(int x, int y, int[][] kernel, BufferedImage input, BufferedImage output)
Now to implement our method above, we will need to break it into a few steps, which we may then break into more steps if necessary. We'll need to look at the input image, if possible for each pixel accumulate the values using the kernel, and then set this in the output image. For brevity I will only write pseudocode from here.
convolvePixel(x, y, kernel, input, output)
accumulation = 0
for each row of kernel applicable pixels
for each column of kernel applicable pixels
if this neighboring pixel location is within the image boundaries then
input color = get the color at this neighboring pixel
adjusted value = input color * relative kernel mask value
accumulation += adjusted value
else
//handle this somehow, mentioned below
endif
endfor
endfor
set output pixel as accumulation, assuming this convolution method does not require normalization
end
The pseudocode above is already relatively long. When implementing you could write methods for the if and the else cases, but it you should be fine with this structure.
There are a few ways to handle the edge case of the else above. Your assignment probably specifies a requirement, but the fancy way is to tile around, and pretend like there's another instance of the same image next to this input image. Wikipedia explains three possibilities:
Extend - The nearest border pixels are conceptually extended as far as necessary to provide values for the convolution. Corner pixels are extended in 90° wedges. Other edge pixels are extended in lines.
Wrap - (The method I mentioned) The image is conceptually wrapped (or tiled) and values are taken from the opposite edge or corner.
Crop - Any pixel in the output image which would require values from beyond the edge is skipped. This method can result in the output image being slightly smaller, with the edges having been cropped.
A huge part of becoming a successful programmer is researching on your own. If you read about these methods, work through them on paper, run your convolvePixel method on single pixels, and compare the output to your results by hand, you will find success.
Summary:
Start by cleaning-up your code before anything.
Group the same code into one place.
Hammer out a small chunk (convolving a single pixel). Print out the result and the input values and verify they are correct.
Draw out edge/corner cases.
Read about ways to solve edge cases and decide what fits your needs.
Try implementing the else case through the same form of testing.
Call your convolveImage method with the loop, using the convolvePixel method you know works. Done!
You can look up pseudocode and even specific code to solve the exact problem, so I focused on providing general insight and strategies I have developed through my degree and personal experience. Good luck and please let me know if you want to discuss anything else in the comments below.
Java code for multiple blurs via convolution.
I have coded the following function to apply fast fourier transform on input image. I have got null pointer exception in line "F[2*k]= F[2*k].plus(w_ux.mul(f_even));".
Would anyone give any advice to me, please? [solved]
It takes quite a long time to finish running the transform, the time is similar to normal fourier transform. and the result image is not as expected.
private Complex[] fft(byte[] img, int width, int height) {
// M - height N - width , u - height v - width
Complex[] F = new Complex[width*height]; // one single point
Complex w;
int size = F.length;
double w_ux_exp, w_u_exp;
double f_even, f_odd;
for (int u=0; u<size/2;u++){
for (int k=0; k<size/2; k++){
f_even = (double)(img[2*k]&0xFF)*Math.pow(-1, k); // f(x) for even, centering
f_odd = (double)(img[2*k+1]&0xFF)*Math.pow(-1, k); // f(x) for odd, centering
w_u_exp =-2.0 * Math.PI*2*(img[u]&0xFF) / size;
w_ux_exp =-2.0 * Math.PI*(2*k)*(img[u]&0xFF) / size; //even
Complex w_ux = Complex.fromPolar(1, w_ux_exp);
Complex w_u = Complex.fromPolar(1, w_u_exp);
F[2*u]= F[2*u].plus(w_ux.mul(f_even));
F[2*u+1]=F[2*u+1].plus(w_u.mul(f_odd));
}
}
return F;
}
Thank you very much for your help.
I'm trying to implement water ripple effect on a polygon model / wireframe. I followed these two guides that are pretty clear: 2D Water and The Water Effect Explained
Following these guides, I ended up with (in this order)
Two arrays of floats, full of zeros after my app launches expect one to start the ripple effect
float[][] heightMapPrev = new float[101][101];
float[][] heightMapCurr = new float[101][101];
// ... filling both arrays with 0.0f ...
heightMapCurr[30][40] = -0.5f; // changing one value to start a water wave
Variable to define damping of waves as they go further
float damping = 0.4f;
The algorithm itself. I loop through all the vertices, count their new y position and smoothening/damping the effect
// Loop through all the vertices and update their vertical position values according to their surrounding vertices' vertical positions
for (int i = 1; i < 100; i++) {
for (int j = 1; j < 100; j++) {
// Count new vertical position of each vertex
heightMapCurr[i][j] = (heightMapPrev[i+1][j] +
heightMapPrev[i-1][j] +
heightMapPrev[i][j+1] +
heightMapPrev[i][j-1]) % 2.0f -
heightMapCurr[i][j];
// Count water vertical velocity
float velocity = -heightMapCurr[i][j];
// Smooth buffers every frame to waves spread out the waves
float smoothed = (heightMapPrev[i+1][j] +
heightMapPrev[i-1][j] +
heightMapPrev[i][j+1] +
heightMapPrev[i][j-1]) / 4.0f;
// Calculate new height of the water; reduce the effect with *2
heightMapCurr[i][j] = smoothed * 2 + velocity;
// Damp ripples to make them loose energy
heightMapCurr[i][j] *= damping;
}
}
(Re)drawing all the vertices, inside those two for loops
gl.glVertex3f((float)i, heightMapCurr[i][j], (float)j); // for each vertex
Finally, as the guide tells me to, I swap values in both arrays - what was in the waveMapPrev is now in waveMapCurr and vice versa
for (int i = 0; i < 101; i++) {
for (int j = 0; j < 101; j++) {
temp[i][j] = heightMapPrev[i][j];
heightMapPrev[i][j] = heightMapCurr[i][j];
heightMapCurr[i][j] = temp[i][j];
}
}
I though I'm clear about what is happening there but clearly I'm not, because there something wrong in my algorithm. Wave spreads from a certain point into distance, keeping circle shape, that is okay. However, water keeps "bubbling" also in the middle of the circle and once the water ripple reaches borders, everything is "bubbling" and it never stops. The ripple should probably not even hit all the borders.
Can you tell/explain me what I did wrong and how to correct the error? I tried for hours changing values (damping...), operators (% for /, + for -), and smoothening function, I did not succeed, though.
Update://
In the code above, I use modulus operator (%) instead of (/). The reason for this is just because I always get completely wrong heightMap values, the wave starts spreading to all directions including somewhere into the sky, never getting back down - like in the image below.
I think I've found your problem. Replace the modulus operator % with a simple divide /, as both of the links you provide suggest and see what that does.
The solution is even simpler than what the guides propose. I have found it here
This is the the body of the whole algorithm according to the latter guide provided, even simpler than anyone could expect.
// Loop through all the vertices and update their vertical position values according to their surrounding vertices' vertical positions
for (int i = 1; i < 100; i++) {
for (int j = 1; j < 100; j++) {
// Count new vertical position of each vertex
heightMapCurr[i][j] = (heightMapPrev[i+1][j] +
heightMapPrev[i-1][j] +
heightMapPrev[i][j+1] +
heightMapPrev[i][j-1]) / 2.0f -
heightMapCurr[i][j];
// Damp ripples to make them loose energy
heightMapCurr[i][j] -= heightMapCurr[i][j] * damping;
}
}
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?