I need some algorithm ideas here. I have a big set of data (~100k entries) of two-dimensional Points as objects with a third variable as the "value" at this point of the plane. Now I want to calculate the interpolated Point at some given coordinates.
My only idea so far would be to iterate over the whole dataset and collect a list of the 4 nearest Points to the one I want to calculate, and then to interpolate between them.
How do I interpolate weighted (by the point's distance in this case) between multiple data? So that Points nearer to the cross are more present in the result?
Do you have any other ideas on how to get the interpolated value at a given coordinate in this case? It should be relatively exact (but does not have to be 100%) and should not take ages to calculate, since this has to be done some 10.000 times and I don't want the user to wait too long.
About the data: The Points are nearly in a grid, and the values of the 2dimensional Points are actually height values, so the values of two near points are also nearly equal.
The Data is stored in a HashMap<Vector2f, Float> where Vector2f is a simple class consisting of 2 floats. There is nothing sorted.
This is non-obvious problem. It is a lot easier for 3 points, with 4 points you will get into situations which are ambigous. Imagine (for points surrounding your sample in square) ul and br corners having value 1, and other corners having value 5. It can be interpreted as valley with height 1 going through center, ridge with height 5 going there, or some kind of fancy spline saddle shape. If you add irregularity of grid into account, it becomes even more fun with closest 4 points being on same side of sample (so you cannot just choose 4 closest points, you need to find 4 bounding points).
For 3 point case, please check https://en.wikipedia.org/wiki/Barycentric_coordinate_system#Application:_Interpolation_on_a_triangular_unstructured_grid
For 4 point case on regular grid,you can use https://en.wikipedia.org/wiki/Bilinear_interpolation to generate kind of 'fair' interpolation.
For 4 points on irregular grid, you can look into solution like
http://www.ahinson.com/algorithms_general/Sections/InterpolationRegression/InterpolationIrregularBilinear.pdf
but be careful with finding proper bounding points (as I mentioned, finding closest ones won't work)
Looks like Bilinear interpolation. There are a few general algorithms and if you have constraints on your data you might be able to use them to simplify the algorithms. Since "the Points are nearly in a grid", I made the approximation that they are ("It should be relatively exact (but does not have to be 100%) and should not take ages to calculate").
Given
2 float x, y as the point you want to interpolate.
4 objects of type Vector2f named v1 to v4, and assuming the coordinates of each can be accessed as v1.x and v1.y and that they are approximately on a grid:
v1.x == v3.x, v2.x == v4.x, v1.y == v2.y, v3.y == v4.y
That the value of each Vector2f was retrieved as float h1 = map.get(v1) (h stands for "height"), then you could write something like this:
float n1 = h1 * (v2.x - x) * (v2.y - y);
float n2 = h2 * (x - v1.x) * (v2.y - y);
float n3 = h3 * (v2.x - x) * (y - v1.y);
float n4 = h4 * (x - v1.x) * (y - v1.y);
float den = (v2.x - v1.x) * (v2.y - v1.y);
float height = (n1 + n2 + n3 + n4) / den;
As a side note, you might also want to look into making your class strictfp.
For a Java program I'm making I need to interpolate 4 points, to calculate the y-value of a 5th point, at given x-value.
Say I have the following points:
p1(0, 0)
p2(1, 2)
p3(2, 4)
p4(3, 3)
// The x-values will always be 0, 1, 2, and 3
Now I want to interpolate these points to find what the y-value should be for given x, say x=1.2 (this x value will always be between point 2 and point 3)
Can anyone help me to make a Java method for finding the y coordinate of this fifth point?
Generally given two points (x0,y0) and (x1,y1), for x0 < x < x1, by interpolation,
y = y0 + (x - x0)/(x1 - x0) * (y1 - y0)
Here,
y = 2 + (x-1) * 2
There are an infinite number of lines that can go through all four of your points.
For example, you could assume that at each point the slope is zero and then draw simple s shaped curves between them, or you could assume that the slope is calculated from the neighboring points (with some special decisions about the ends), or you could assume that the slope at the points is 2, etc.
And it doesn't stop there, you could effectively draw a curve that will encapsulate your points and any other point you could imagine while still meeting the requirement of being continuous (as you call, smooth).
I think you need to start off with a formula you wish to fit against the points, and then choose the technique you use to minimize the error of the fit. Without you making more decisions, it is very likely that it will be very hard to give more direction.
I think that the Title of this question does not explain clearly my question, I'll explain it better.
I have a Java program that plot graphs using JFreeChart. Now I need to do something to get these points from the graph:
In these points, the X coordinate is zero. But none of these points I used to create the graph, so I'm confused if its possible to get them.
Can anyone give me some ideas to do it?
assuming that your line is defined by a sequence of (x, y) points, you know that the line crossed x = 0 when two consecutive points have x-values of different sign. Then you can determine the value of y where the line crosses x = 0. Assuming linear interpolation between two consecutive points (x1, y1), (x2, y2), x1 * x2 < 0:
y0 = y2 - x2 * (y1 - y2) / (x1 - x2)
In processing (java dialect) there are the methods screenX, screenY (and screenZ but we skip that for now).
Let's say i have a object at xyz = 50, 100, 500. Then with screenX and screenY you can now where they will apear on the canvas.
float x = screenX(50, 100, 500);
float y = screenY(50, 100, 500);
here is the reference:
http://processing.org/reference/screenX_.html
What i'm interested in is like a inverse method.
For example, i want a sphere to apear on the canvas on x=175 and y=100. The sphere should have a z of 700. Then what would the actual x and y position be at z=700 to make it apear on the canvas at 175,100?
So the method would be float unscreenX(float x, float y, float z) and it would return the x value.
My math / programming skills is not so advanced (let's call it bad) (i'm more a designer) so i'm looking for some help. I all ready asked at the processing board but often there are more people here with deeper knowledge about matrixes etc.
The normal screenX method from processing can be found here:
https://github.com/processing/processing/blob/master/core/src/processing/opengl/PGraphicsOpenGL.java
public float screenX(float x, float y, float z) {
return screenXImpl(x, y, z);
}
protected float screenXImpl(float x, float y, float z) {
float ax =
modelview.m00*x + modelview.m01*y + modelview.m02*z + modelview.m03;
float ay =
modelview.m10*x + modelview.m11*y + modelview.m12*z + modelview.m13;
float az =
modelview.m20*x + modelview.m21*y + modelview.m22*z + modelview.m23;
float aw =
modelview.m30*x + modelview.m31*y + modelview.m32*z + modelview.m33;
return screenXImpl(ax, ay, az, aw);
}
protected float screenXImpl(float x, float y, float z, float w) {
float ox =
projection.m00*x + projection.m01*y + projection.m02*z + projection.m03*w;
float ow =
projection.m30*x + projection.m31*y + projection.m32*z + projection.m33*w;
if (nonZero(ow)) {
ox /= ow;
}
float sx = width * (1 + ox) / 2.0f;
return sx;
}
Of corse there is also for the y and for the z (i don't understand the z but let's ignore that).
I thought this might give some insight in how to inverse it.
modelview and projection is a 3d matrix, the code is here:
https://github.com/processing/processing/blob/master/core/src/processing/core/PMatrix3D.java
But i guess it's pretty basic and common.
I also made a post on the processing board since you never know. It explains a litle bit different what i want.
http://forum.processing.org/topic/unscreenx-and-unscreeny
For the tags describing this post, i didn't went to specific cause i can imagine a programmer who never worked with java but did work with c++ for example and has experience in matrixes is still able to provide a good answer.
hope someone can help.
I highly recommend you study some linear algebra or matrix math for 3d graphics. It's fun and easy, but a bit longer than a SO answer. I'll try though :) Disclaimer: I have no idea about the API you are using!
It looks like you are returning 3 coordinate for a position (often called a vertex). But you also mention a projection matrix and that function has 4 coordinates. Usually a shader or API will take 4 coordinates for a vertex. x,y,z,w. To get them on screen it does something like this:
xscreen = x/w
yscreen = y/w
zbuffer = z/w
This is useful because you get to pick w. If you are just doing 2d drawing you can just put w=1. But if you are doing 3d and want some perspective effect you want to divide by distance from the camera. And that's what the projection matrix is for. It mainly takes the z of your point where z means distance to camera and puts it into w. It also might scale things around a bit, like field of view.
Looking back at the code you posted this is exactly what the last ScreenXImpl function does.
It applies a projection matrix, which mostly just moves z into w, and then divides by w. At the end it does an extra scale and offset from (-1,1) to (0,widhtinpixels) but we can ignore that.
Now, why am I rambling on about this stuff? All you want to do is to get the x,y,z coordinates for a given xscreen, yscreen, zbuffer, right? Well, the trick is just going backwards. In in order to do that you need to have a firm grasp on going forward :)
There are two problems with going backwards: 1) Do you really know or care for the zbuffer value? 2) Do you know what the projection matrix did?
For 1) Let's say we don't care. There's many possible values for that, so we might just pick one. For 2) You will have to look at what it does. Some projection matrices might just take (x,y,z,w) and output (x,y,z,1). That would be 2d. Or (x,y+z,z,1) which would be isometric. But in perspective it usually does (x,y,1,z). Plus some scaling and so on.
I just noticed your second screenXImpl already passes x,y,z,w to the next stage. That is useful sometimes, but for all practical cases that w will be 1.
At this point I realize that I am terrible at explaining things. :) You really should pick up that linear algebra book, I learned from this one: http://www.amazon.com/Elementary-Linear-Algebra-Howard-Anton but it came with a good lecture, so I don't know how useful it is on it's own.
Anyhow! Let's get more practical. Back to your code: the last function of screenXImpl. We now know that the input w=1 and that ow=~z and ox=~x; The squiggly line here means times some scale plus some offset. And the screen x we have to begin with is ~ox/ow. (+1/2,*width.. that's what squiggly lines are for). And now we are back at 1)... if you want a special oz - pick one now. Otherwise, we can pick any. For rendering it probably makes sense to pick anything in front of the camera and easy to work with. Like 1.
protected float screenXImpl(float x, float y, float z, float w==1) {
float ox = 1*x + 0*y + 0*z + 0*w; // == x
float ow = 0*x + 0*y + 1*z + 0*w; // == z == 1
ox /= ow; // == ox
float sx = width * (1 + ox) / 2.0f;
return sx;
}
WTF? sx = width * (1+ox)/2 ? Why didn't I just say so? Well, all the zeros I put in there are probably not zero. But it's going to end up just as simple. Ones might not be ones. I tried to show the important assumptions you have to make to be able to go back. Now it should be as easy as going back from sx to ox.
That was the hard part! But you still have to go from the last function to the second one. I guess the second to the first is easy. :) That function is doing a linear matrix transform. Which is good for us. It takes an input of four values (x,y,z) and (w=1) implicit and outputs four other values (ax,ay,az,aw). We could figure out how to go back there manually! I had to do that in school.. four unknowns, four equations. You know ax,ay,az,aw... solve for x,y,z and you get w=1 for free! Very possible and a good exercise but also tedious. The good news is that the way those equations are written is called a matrix. (x,y,z,1) * MODELMATRIX = (ax,ay,az,aw). Really convenient because we can find MODELMATRIX^-1. It's called the inverse! Just like 1/2 is the inverse of 2 for multiplying real numbers or -1 is the inverse of 1 for addition. You really should read up on this it's fun and not hard, btw :).
Anyhow, use any standard library to get the inverse of your model matrix. Probably something like modelView.Inverse(). And then do the same function with that and you go backwards. Easy!
Now, why did we not do the same thing with the PROJECTION matrix earlier? Glad you asked! That one takes 4 inputs(x,y,z,w) and spits out only three outputs (screenx,screeny,zbufferz). So without making some assumptions we could not solve it! An intuitive way to look at that is that if you have a 3d point, that you project on a 2d screen, there's going to be a lot of possible solutions. So we have to pick something. And we can not use the convenient matrix inverse function.
Let me know if this was somewhat helpful or not. I have a feeling that it's not, but I had fun writing it! Also google for unproject in processing gives this: http://forum.processing.org/topic/read-3d-positions-gluunproject
You'd need to know the project matrix before you can make this work, which Processing doesn't supply you with. However, we can work it out ourselves by checking the screenX/Y/Z values for for the three vectors (1,0,0), (0,1,0) and (0,0,1). From those we can work out what the plane formula is for our screen (which is technically just a cropped flat 2D surface running through the 3D space). Then, given an (x,y) coordinate on the "screen" surface, and a predetermined z value, we could find the intersection between the normal line through our screen plane, and the plane at z=....
However, this is not what you want to do, because you can simply reset the coordinate system for anything you want to do. Use pushMatrix to "save" your current 3D transforms, resetMatrix to set everything back to "straight", and then draw your sphere based on the fact that your world axes and view axes are aligned. Then when you're done, call popMatrix to restore your earlier world transform and done. Save yourself the headache of implementing the math =)
You can figure this out with simple trigonometry. What you need is, h, the distance of the eye from the center of the canvas, and the cx and cy representing the center of the canvas. For simplicity, assume cx and cy are 0. Note that it is not the distance of your actual eye but the distance of the virtual eye used to construct the perspective on your 3d scene.
Next, given sx and sy, compute the distance to center, b = sqrt(sx * sx + sy * sy)
Now, you have a right-angled triangle with base b and height h. This triangle is formed by the "eye", the center on canvas, and the desired position of the object on the screen: (sx, sy).
This triangle forms the top part of another right-angled triangle formed by the "eye", the center on canvas pushed back by given depth z and the object itself: (x, y).
The ratio of the base and height of the triangles is exactly the same, so it should be trivial to calculate the base of the larger triangle bb given its height hh = z or hh = h + z depending on whether the z value is from the eye or from the canvas. The equation to use is b / h = bb / hh where you know b, h and hh
From there you can easily compute (x, y) because the two bases are at the same angle from the horizontal. I. e. sy / sx = y / x.
The only messy part will be to extract the distance of eye to canvas and the center of the canvas from the 3d setup.
Overview of Transforming 3d point onto your 2d screen
When you have a 3d representation of your object (x,y,z), you want to 'project' this onto your monitor, which is in 2d. To do this, there is a transformation function that takes in your 3d coordinates, and spits out the 2d coordinates. Under the hood, (at least in openGL), the transformation function that takes place is a special matrix. To do the transformation, you take your point (represented by a vector), and do a simple matrix multiplication.
For some nice fancy diagrams, and a derivation (if you are curious, it isn't necessary), check this out: http://www.songho.ca/opengl/gl_projectionmatrix.html
To me, screenXImpl looks like it is doing the matrix multiplication.
Doing the reverse
The reverse transformation is simply the inverse matrix of the original transformation.
How would I go about changing points that are 'near' linear (within a threshold), actually linear?
I have some code that checks if 3 points are linear to one another (give or take), and I want to replace those coordinates with new ones that are 100% inline.
double distance = (x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3);
double threshold = 4;
if (Math.abs(distance) <= threshold) {
// is Near line
return true;
}
else
return false;
This is an EXTENSION of another post of mine... This is NOT a repost, simply a related topic:
Java - Average Linear Graph Plots
The technical term for snapping a point to a line is projecting a point to a line(-segment)
The only question that remains: Should the points projected to the line or to the line segment? (A line segment is only between two points, the line has infinity length and goes through both points)
The code below solves both:
To allow also projecting points to th epart of the line that is outside of points A->B, the code would be much simpler, but this is covered in the link below, too.
See http://forums.codeguru.com/showthread.php?194400-Distance-between-point-and-line-segment
The projected point is in the variables (xx,yy):
(xx,yy) is the point on the lineSegment closest to (cx,cy)