Perlin Noise shows lines between unit squares - java

As said in the title, my problem is that my perlin noise is showing clear lines between the unit squares instead of flowing smoothly. My code, which is very basic, is shown below. It is based on the simple explanation from this site: http://flafla2.github.io/2014/08/09/perlinnoise.html
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
//System.out.print(unitX + " " + unitY + " ");
// bad pseudorandom gradient
int units = unitX+unitY;
//System.out.println(units + " added ");
int[] gradTL = grads[(units)%8];
int[] gradTR = grads[(units+1)%8];
int[] gradBL = grads[(units+1)%8];
int[] gradBR = grads[(units+2)%8];
// distance from edges to point, relative x and y inside the unit square
double[] vecTL = {relX,relY};
double[] vecTR = {1-relX,relY};
double[] vecBL = {relX,1-relY};
double[] vecBR = {1-relX,1-relY};
double tl = dot(gradTL,vecTL);
double tr = dot(gradTR,vecTR);
double bl = dot(gradBL,vecBL);
double br = dot(gradBR,vecBR);
double u = fade(relX);
double v = fade(relY);
double x1 = lerp(tl,tr,u);
double y1 = lerp(bl,br,u);
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);
}
I am using a flow field to visualize the noise, which I know is probably just overcomplicated but it is the end goal of this project. Example As you can see, there are obvious lines that are showing the grid of the perlin noise.
Here is what I'm inputting into the function.
double val = p.perlin((x/width)*2, (y/height)*2);
I want to try and make the noise flow smoothly between the unit squares. Also yes, I understand that simplex noise is considered to be better, but I am not trying to make perlin noise, not simplex noise.

This part looks wrong to me:
// distance from edges to point, relative x and y inside the unit square
double[] vecTL = {relX,relY};
double[] vecTR = {1-relX,relY};
double[] vecBL = {relX,1-relY};
double[] vecBR = {1-relX,1-relY};
I think you want
double[] vecTL = {relX,relY};
double[] vecTR = {relX-1,relY};
double[] vecBL = {relX,relY-1};
double[] vecBR = {relX-1,relY-1};

Related

Eccentricity Vector in Java not accurate as orbit moves along

I am writing a small libgdx program in java that was inspired by Kerbal Space Program and I am now writing the class that controls objects that will have forces acted on them. Each of these objects have a velocity vector that is changed by a forces vector.
The program runs around 60 frames per second and every frame the calculations done on the force to change velocity are done 1000 times. ( I have played with this number a lot however). Right now the program is incredibly simple and the only force that is exerted and calculated every iteration is from the planet.
forcedub = ((gravConstanat*parentBody.getMass())/Math.pow(loc.distance(parentBody.getLoc()),2));
force = new Point2D(((-1)*forcedub*Math.cos(a)),((-1)*forcedub*Math.sin(a)));
This changes the velocity sightly, the position is adjusted and the loop continues. The process works very well and seems stable. I haven't run it for days on end, but the orbit even at relatively high eccentricities seems stable. UNFORTUNATELY I need to be able to speed this process up so it doesn't take 2 days real time to get to the moon. So I needed a system that puts the orbit "on rails" and doesn't need to recalculate the forces each iterations. Once the multiplier value there gets set too high the orbit falls apart.
Good news is I already have this system in place, I just can't switch between the two.
I need a few values from the orbit to do this in my system. (I know some values are a bit redundant but it is what it is).
The semi major axis
the semi minor axis
the eccentricity vector
eccentricity
true anomaly
focus information.
To cut to the chase, the biggest issue is the eccentricity vector / eccentricity. My 'bake' function is the one that attempts to compute the values from the state vectors of the orbit every iteration and the value of the eccentricity varies drastically where it should stay the same in a standard orbit.The direction the vector is all over the place as well.
I have hard coded a single object that should have an eccentricity of about .62 and the eccentricity vector should point to pi, but the value wanders between .25 and .88 and the direction wanders between pi and pi / 3 ish.
Here are two versions of how to get the eccvecc from the state vectors, and I have tried them both. They both give the exact same results:
https://space.stackexchange.com/questions/37331/why-does-the-eccentricity-vector-equation-always-equal-1
https://en.wikipedia.org/wiki/Eccentricity_vector
public void bake(){
double velSq = Math.pow(vel.distance(0,0),2);
double r = loc.distance(parentBody.getLoc());
double gm = gravConstanat*parentBody.getMass();
Point2D posr = new Point2D(loc.getX()-parentBody.getX(), loc.getY()-parentBody.getY());
Point2D calc1 = posr.scale((velSq/gm));
Point2D calc2 = vel.scale((dotProd(posr,vel)/gm));
Point2D calc3 = posr.scale(1/r);
Point2D eccVecc = (calc1.minus(calc2)).minus(calc3);
ecc = eccVecc.distance(0,0);
w = Math.toRadians(90)-(Math.atan2(eccVecc.x(),eccVecc.y()));
semiA = (gm*r)/(2*gm - r*velSq);
semiB = semiA*(Math.sqrt((1-Math.pow(ecc,2))));
focus = findFocus(semiA,semiB);
System.out.println("ecc " + ecc + " W " + w + " SEMI A " + semiA);
System.out.println();
}
Here is the entire class:
**initial distance is about 900,000 to the left of the parent body
**parent mass is 5.3*Math.pow(10,22)
public class Klobject {
String name;
TextureAtlas textureAtlas;
Sprite sprite;
Cbody parentBody;
Point2D loc;
Point2D vel;
public boolean acceleration;
double MULTIPLIER;
static double gravConstanat = 6.67*Math.pow(10,-11);
double semiA, semiB, ecc, w;
protected double t;
protected double mass;
protected double rotateRate;
protected double focus;
public Klobject(Cbody cb){
mass = 1;
MULTIPLIER = 1;
rotateRate = 0;
parentBody = cb;
acceleration = false;
cb.addKlob(this);
loc = new Point2D((parentBody.getX() - 900_000f ),
(parentBody.getY()));
vel = new Point2D(0,2526.733);
sprite = textureAtlas.createSprite(name);
sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2);
bake();
}
public void update(float dt){
oneXupdate(dt);
bake();
}
private void oneXupdate(float dt){
int timesLooped = 1000;
double a;
double forcedub;
Point2D force;
Point2D velout;
double dx;
double dy;
dt = dt/timesLooped;
for (int i = 0; i < timesLooped; i++){
velout = vel.scale(MULTIPLIER);
dx = (dt*velout.getX());
dy = (dt*velout.getY());
loc = new Point2D(loc.getX()+dx, loc.getY()+dy);
a = Math.atan2(loc.getX()-parentBody.getX(), loc.getY()-parentBody.getY());
a = Math.toRadians(90)-a;
forcedub = ((gravConstanat*parentBody.getMass())/Math.pow(loc.distance(parentBody.getLoc()),2));
force = new Point2D(((-1)*forcedub*Math.cos(a)),((-1)*forcedub*Math.sin(a)));
force = force.scale(MULTIPLIER*MULTIPLIER);
velout = velout.plus(new Point2D(force.getX()*dt,force.getY()*dt));
vel = velout.scale(1/MULTIPLIER);
}
}
public void bake(){
double velSq = Math.pow(vel.distance(0,0),2);
double r = loc.distance(parentBody.getLoc());
double gm = gravConstanat*parentBody.getMass();
Point2D posr = new Point2D(loc.getX()-parentBody.getX(), loc.getY()-parentBody.getY());
Point2D calc1 = posr.scale((velSq/gm));
Point2D calc2 = vel.scale((dotProd(posr,vel)/gm));
Point2D calc3 = posr.scale(1/r);
Point2D eccVecc = (calc1.minus(calc2)).minus(calc3);
ecc = eccVecc.distance(0,0);
w = Math.toRadians(90)-(Math.atan2(eccVecc.x(),eccVecc.y()));
semiA = (gm*r)/(2*gm - r*velSq);
semiB = semiA*(Math.sqrt((1-Math.pow(ecc,2))));
focus = findFocus(semiA,semiB);
System.out.println("ecc " + ecc + " W " + w + " SEMI A " + semiA);
System.out.println();
}
public double findFocus(double a, double b){
return Math.sqrt(a*a - b*b);
}
public double getX(){
return loc.getX();
}
public double getY(){
return loc.getY();
}
public void setRotateRate(double rr){rotateRate = rr;}
public String getName(){
return name;
}
public Sprite getSprite(){
return sprite;
}
public void setMultiplier(double mult){
MULTIPLIER = mult;
}
public Point2D getLoc(){
return loc;
}
public void setLoc(Point2D newLoc){
loc = newLoc;
}
public double dotProd(Point2D a, Point2D b){
return a.x()*b.x() + a.y()+b.y();
}
}

Why is println in a for loop printing just once and the wrong value?

I have to create a code that, given the polygon name and its vertex coordinates, prints the perimeter. Even if I change the input values, it always print 5.0 . What am I doing wrong?
I tried using a for loop and print the length of every side of a triangle, but the result is still 5.0 and printed just once. Now I tried to print the recursive sum at every step but no results
public static void main(String[] args) {
int i;
double result = 0;
double x1 = Double.valueOf(args[1]);
double y1 = Double.valueOf(args[2]);
Punto p1 = new Punto(x1, y1);
double x2 = Double.valueOf(args[3]);
double y2 = Double.valueOf(args[4]);
Punto p2 = new Punto(x2, y2);
double x3 = Double.valueOf(args[5]);
double y3 = Double.valueOf(args[6]);
Punto p3 = new Punto(x3, y3);
Punto[] punti = {p1, p2, p3};
Poligono A = new Poligono(args[0], punti);
for (i = 0; i < punti.length - 1; i++) {
double xa = Punto.getX(punti[i++]);
double xb = Punto.getX(punti[i]);
double ya = Punto.getY(punti[i++]);
double yb = Punto.getY(punti[i]);
result = result + Math.sqrt(Math.pow(Math.abs(xa - xb), 2) + Math.pow(Math.abs(ya - yb), 2));
System.out.println(result);
}
}
(Punto means point) The right answer is 12, but it always prints 5 and just once
You should probably replace double xa = Punto.getX(punti[i++]); with double xa = Punto.getX(punti[i + 1]); so that you don't modify i as it is used to iterate through the array.
The correct answer to your question is already there by #devgianlu!
However, I would like to add that, when something apparently not-reasonable happens, try to debug your code (executing step by step the lines, for example). You will discover that the machine always does what we say to do. Sometimes we think to declare a specific task but, in reality, we are declaring unintentionally something else.

Why does this recursive peak filter written in Java not filter the chosen frequency

So, I don't know whether I've implemented this incorrectly, or whether it's a feature of this kind of filter; but, I'd been trying to apply a peak filter to an audio signal and it wasn't working.
Some testing revealed that it wasn't filtering for the frequency I selected; but a nearby value, some of which are powers of 2, so, eg, filtering 4KHz actually filtered 4096Hz.
Here's the filter (it's from http://dspguide.com/ch19/3.htm):
SAMPLE_RATE is 88*1024
class Coefficients {
double a0=0;
double a1=0;
double a2=0;
double twoCos2piFreq=0;
double b1=0;
double b2=0;
double K=0;
double R=0;
double rSquared=0;
public Coefficients(double freq, double bandwidth)
{
twoCos2piFreq=2*Math.cos(2*Math.PI*freq);
R=1-(3*bandwidth);
rSquared=R*R;
K=(1-(R*twoCos2piFreq)+rSquared)/(2-twoCos2piFreq);
b1=R*twoCos2piFreq;
b2=-rSquared;
}
// ----------------------------------------------------------------
// Source x, result y
// y[i]=a0*x[i] + a1*x[i-1] + a2*x[i-2] + b1*y[i-1] + b2*y[i-2]
private void recursiveFilter(float[] x, float[] y)
{
double x_2 = 0.0f; // delayed x, y samples
double x_1 = 0.0f;
double y_2 = 0.0f;
double y_1 = 0.0f;
for (int i = 0; i < x.length; ++i){
double xi=x[i];
double yi=a0*xi + a1*x_1 + a2*x_2 + b1*y_1 + b2*y_2;
x_2 = x_1; // shift delayed x, y samples
y_2 = y_1;
x_1 = xi;
y_1 = yi;
y[i] = (float)yi;
}
}
// ------------------------------------------------------------
public float[] filtered(float[] signal)
{
float[] result=new float[signal.length];
recursiveFilter(signal,result);
return result;
}
}
// ----------------------------------------------------------------
class BandPassCoefficients extends Coefficients
{
public BandPassCoefficients(double freq, double bandwidth)
{
super(freq/(double)SAMPLE_RATE,bandwidth/(double)SAMPLE_RATE);
a0=1-K;
a1=(K-R)*twoCos2piFreq;
a2=rSquared-K;
}
}
and to test it, I fill a buffer with a sine wave of a range of frequencies, one at a time, apply the filter and measure the highest amplitude in the result.
Fairly obvious code, but here it is:
// ----------------------------------------------------------------
private void genTestSignal(float freq)
{
float[] leftSignal=createSinWaveBuffer(freq,ONE_SECOND);
float[] rightSignal=createSinWaveBuffer(freq,ONE_SECOND);
denormalise( leftSignal ,inputSignal, LEFT_CHANNEL);
denormalise(rightSignal,inputSignal,RIGHT_CHANNEL);
}
The denormalise and normalise functions just convert to and from interleaved signed 16-bit values to single channel floats.
This samples the start of the signal, to find the largest absolute magnitude:
private void findOptimalFreq(float[] signal, float freq)
{
float maxAmplitude=0;
int peak=0;
for(int i=(int)freq/2; i<(int)freq*3/2; i+=2){
BandPassCoefficients signalFilter=new BandPassCoefficients(i,10);
float[] normalised=signalFilter.filtered(signal);
float loudest=0;
// only scan the first part, since it's all the same
for(int j=1; j<10000; ++j){
float s=Math.abs(normalised[j]);
if(s>loudest) loudest=s;
}
if(loudest>maxAmplitude){
maxAmplitude=loudest;
peak=i;
}
}
log("freq,"+freq+","+peak);
}
And, for completion, the code which steps through the audio range, testing each frequency.
for(workingFreq=100; workingFreq<20000; workingFreq+=100){
genTestSignal(workingFreq);
inputShorts=new short[inputSignal.length/2];
ByteBuffer.wrap(inputSignal).order(bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(inputShorts);
findOptimalFreq(normalised(inputShorts,RIGHT_CHANNEL),workingFreq);
}
The output is logged to System.out, and copied to a spreadsheet, since it's CSV format.
Here's some of it, the left is the target frequency, the right is the actual frequency which the peak is at:
6200,6436
6300,6436
6400,6436
6500,6932
6600,6932
6700,6932
6800,6932
6900,6932
7000,7510
7100,7510
7200,7510
7300,7510
7400,7510
7500,7510
7600,8192
7700,8192
7800,8192
7900,8192
8000,8192
8100,8192
8200,9012
8300,9012
Any thoughts?
I've gone through the filter code over and over, and I'm fairly sure it's right; but there's no mention anywhere I've seen of this kind of "feature", so I don't know what to do next.
Didn't solve the problem; but was able to replace it with a BiQuadratic filter from this site: BiQuadDesigner
There is a link to java source:
HTH anyone else struggling with this.

Hexagonal Grid (Flat Top) Distance Calculation

I have been working on creating a hexagonal (flat top) grid for a simulation I am working on. I have attempted to work out the distance between the hexagons, from a specified target hexagon.
The solution I have works for most of the time, apart from every odd column from the target hexagon north of the target is shifted up by 1. I know that sounds confusing but I have attached an image to explain what I mean:
As you guys can see, the bottom half of the grid below the target hexagon and every other column above the target Hexagon is correct. I cannot understand why :S
Here is an explanation of the Axial & Cube Co-ords.
http://www.redblobgames.com/grids/hexagons/#coordinates
Here is the code responsible for converting the Axial Co-ords to Cube Co-ords.
public void setQR(int theQ, int theR){
this.q = theQ;
this.r = theR;
this.x = this.q;
this.z = this.r - (this.q - (this.q&1)) /2;
this.y = -(this.x + this.z);
}
And heres the code for working out distance.
FYI, the Hexagons are created from a CentrePoint (CPx, CPy).
private double distance = 0;
public double workOutDistance(Hexagon hexagon, HexagonFood target){
double targetX = target.getCPX();
double targetY = target.getCPY();
double hexagonX = hexagon.getCPX();
double hexagonY = hexagon.getCPY();
double deltaX = (targetX-hexagonX)*-1;
double deltaY = (targetY-hexagonY)*-1;
double deltaXRadius = (deltaX/(SimField.hexSize)/1.5);
double deltaYApothem = (deltaY/(SimField.hexSize/1.155)/2);
hexagon.setQR((int)deltaXRadius, (int)deltaYApothem);
ArrayList<Integer> coords = new ArrayList<>();
coords.add(
Math.abs(hexagon.getX() - target.getX())
);
coords.add(
Math.abs(hexagon.getZ() - target.getZ())
);
coords.add(
Math.abs(hexagon.getY() - target.getY())
);
System.out.println(coords);
distance = Collections.max(coords);
return distance;
}
Can anyone please tell me why this is happening ? Would be greatly appreciated.
EDIT:
After changing Int to Double as suggested by Tim, I get this.
http://i.stack.imgur.com/javZb.png
**
SOLUTION
**
after experimenting with the answers given, This small tweak solves the problem.
changing this..
public void setQR(int theQ, int theR){
this.q = theQ;
this.r = theR;
this.x = this.q;
this.z = this.r - (this.q - (this.q&1)) /2;
this.y = -(this.x + this.z);
}
to this..
public void setQR(int theQ, int theR){
this.q = theQ;
this.r = theR;
this.x = this.q;
if (this.r>0){
this.z = this.r - (this.q - (this.q&1))/2;
}
else {
this.z = this.r - (this.q + (this.q&1))/2;
}
this.y = -(this.x + this.z);
}
You're casting a double to an int when calling setQR(); are you sure that's doing what you expect? Doubles use floating point math, so the number you'd expect to be 2.0 might actually be 1.999999989, which would then be rounded down to 1 when cast to an int.
I'm also skeptical of the line that reads this.z = this.r - (this.q - (this.q&1)) /2;. You're adding 1 when the number is odd, which seems to be the failure case you're experiencing; I'd make sure that line is doing what you're expecting, too.
If you're not stepping through this with a debugger and examining the values, you're doing it wrong.
You could also take an entirely different approach to this problem. You know the X/Y (cartesian) coordinates of your two hexagons, which means you can get each hexagon's cubic coordinates relative to the origin of your hexagonal space. The distance between the two hexagons is simply the sum of the absolute values of the differences between the two hexagons' X, Y and Z cubic coordinates. (That is, dist = |h2.X - h1.X| + |h2.Y - h1.Y| + |h2.Z - h1.Z|) So rather than trying to compute the vector between the two centerpoints and then convert that into cubic coordinates, you could just compute the distance directly in cubic coordinates (just like you would if these were squares in cartesian coordinates)...
Even if you take this approach, though, I'd strongly recommend that you debug what's going on with your original approach. Even if you end up throwing away the code, the exercise of debugging will probably teach you valuable lessons that you'll be able to apply in the future.
Note to readers: "cubic" coordinates aren't 3-dimensional cartesian coordinates, they're a hexagon-specific coordinate system for which a link was provided by the OP.
The fact that the computation (that is, the conversion from offset- to cube coordinates, and the computation of the distance in cube coordinates) seems to be correct suggests that Tim was right with his assumption about the floating point errors.
You should try to change the line
hexagon.setQR((int)deltaXRadius, (int)deltaYApothem);
from your original code to something like
hexagon.setQR((int)Math.round(deltaXRadius), (int)Math.round(deltaYApothem));
Which could solve the issue in this case.
If not ... or... in any case, here's a small example, basically doing the same as you did, but as a MVCE...
import java.awt.Point;
public class HexagonsTest
{
public static void main(String[] args)
{
// Above and below
test(8,6, 8,5, 1);
test(8,6, 8,7, 1);
// Left
test(8,6, 7,5, 1);
test(8,6, 7,6, 1);
// Right
test(8,6, 9,5, 1);
test(8,6, 9,6, 1);
// The first one that was wrong:
test(8,6, 7,4, 2);
}
private static void test(int x0, int y0, int x1, int y1, int expected)
{
int distance = computeStepsDistance(x0, y0, x1, y1);
System.out.println(
"Distance of (" + x0 + "," + y0 + ") to " +
"(" + x1 + "," + y1 + ") is " + distance +
", expected " + expected);
}
private static int computeStepsDistance(int x0, int y0, int x1, int y1)
{
Point cp0 = convertOffsetToCubeCoordinates(x0, y0, null);
Point cp1 = convertOffsetToCubeCoordinates(x1, y1, null);
int cx0 = cp0.x;
int cy0 = cp0.y;
int cz0 = -cx0-cy0;
int cx1 = cp1.x;
int cy1 = cp1.y;
int cz1 = -cx1-cy1;
int dx = Math.abs(cx0 - cx1);
int dy = Math.abs(cy0 - cy1);
int dz = Math.abs(cz0 - cz1);
return Math.max(dx, Math.max(dy, dz));
}
private static Point convertOffsetToCubeCoordinates(
int ox, int oy, Point p)
{
int cx = ox;
int cz = oy - (ox - (ox&1)) / 2;
int cy = -cx-cz;
if (p == null)
{
p = new Point();
}
p.x = cx;
p.y = cy;
return p;
}
}

How to find points of intersection between ellipse and line?

I'm completely stuck.
I have an ellipse, and a line. Line is set by two points, ellipse - by bottom-left and top-right corners. I have to find their points of intersection, using java.
I tried to solve an equation system:
(1) y = kx + m;
x^2/a^2 + y^2/b^2 = 1;
but I could't make things work properly. I assume it's because of java's coordinate system, but it also may be my own mistake somewherem beacuse I'm confused with it.
Is there any better way to find points of intersection and, if not, how can I get them properly?
Thank you in advance.
Code:
double r1 = in_y2-in_y;
double r2 = in_x2-in_x;
double k = r1/r2;
double m = in_y2 - k*in_x2;
double a = Math.abs((double)x2 - (double)x)/2;
double b = Math.abs((double)y2 - (double)y)/2;
double A1 = 1/(a*a) + (k*k)/(b*b);
double B1 = (2*k*m)/b*b;
double C1 = (m*m)/(b*b);
double D = Math.sqrt(B1*B1 - 4*A1*C1);
double ex1 = (-B1 + D/(2*A1));
double ey1 = k*ex1 + m;
double ex2 = (-B1 - D/(2*A1));
double ey2 = k*ex2 + m;
This is probably no longer relevant to the original problem owner, but since I encountered the same question, let me present my answer.
There are three mistakes in the original computation that I can see: (i) the one pointed out by #mprivat, (ii) the bracketing in the assignment to B1 which should instead be
double B1 = (2*k*m)/(b*b);
and (iii) a more fundamental one: the presented computation does not correct for the origin of the ellipse. Since the ellipse is defined by itse circumscribing bounds, there is no guarantee that it is centered on (0,0).
Let's call the center (cx,cy), then the equation for the ellipse becomes
(x-cx)^2/a^2 + (y-cy)^2/b^2 = 1
rather than the original
x^2/a^2 + y^2/b^2 = 1
The simple repair, I think, is to translate the line wrt (cx,cy) and translate the results back, like so:
...
double m = (in_y2-cy) - k*(in_x2-cx);
...
double ex1 = (-B1 + D/(2*A1)) + cx;
double ey1 = k*(ex1-cx) + m + cy;
double ex2 = (-B1 - D/(2*A1)) + cx;
double ey2 = k*(ex2-cx) + m + cy;
The more elegant repair is to solve the correct equation for the ellipse instead, but this results in even more impenetrable formulas for B1 and C1:
double B1 = (2*k*(m-cy))/(b*b) - (2*cx)/(a*a);
double C1 = (m-cy)*(m-cy)/(b*b) - 1 + (cx*cx)/(a*a);
As a final remark, note that this breaks down for vertical lines, as then r2 = 0 so k isn't defined.
Java can't solve the algebra problem, but it can compute the solution once you tell it what to compute.
Sounds like you just need to replace your y in the ellipse's equation with kx+m then solve for x. Looks like it's a simply binomial equation. Write a program that computes x=... based on k, m, a and b. Java can help you compute the roots if you tell it what to compute and what the values of k, m, a and b are.
In your particular case, you want to use Java as a simple calculator...
can you please put your code so that we could see if it's correct?
anyway , here's an algorithm:
http://mathworld.wolfram.com/Ellipse-LineIntersection.html
note that since it has a square root , you might get a solution that is not precise.
Line2D.Double line = new Line2D.Double(x1,y1,x2,y2);
Ellipse2D.Double ellipse = new Ellipse2D.Double(x,y,width,height);
int resolution = 1000;
int x_distance = ellipse.getWidth()/2;
int y_distance = ellipse.getHeight()/2;
double angle = 360.0/(double)resolution;
Point center = new Point(width/2,height/2);
Point point = new Point();
for (int index = 0; index < resolution; index++)
{
int x = (center.x+x_distance)*Math.sin(Math.toRadians(angle*index)));
int y = (center.y+y_distance)*Math.cos(Math.toRadians(angle*index)));
Ellipse2D.Double dot = new Ellipse2D.Double(x,y,1,1);
if (line.intersects(dot.getBounds()))
{
point.setLocation(x,y);
index = resolution;
}
}

Categories

Resources