I am trying to find an algorithm to draw a smooth curve passing through n points in Java.
I read a lot about the subject, but I only find examples with 3 or 4 points. I don't get how I am supposed to generalize the process with more points.
For instance, I found that answer that shows how to make a Bezier curve with 3 points. But if I repeat the process with the 3 next points, the 2 curves will not join smoothly.
I also found this interesting pdf that describes in details the process. The part I'm interested in is the 5th chapter about interpolation by cubic splines. It explains how to achieve what I want, but for 6 points. There isn't a generalization for n points.
If you see an easier approach, I would gladly take it. I just don't want Lagrange interpolation. As shown in the linked pdf, it doesn't give good results...
You can find both short introduction into cubic splines and good practical implementation in this chapter of the book Numerical Methods in C.
You can also use Catmull-Rom splines (they provide smoothness only for the first derivative)
One more simple approach for interpolation with Bezier curves proposed by Maxim Shemanarev
You did not mention what means smooth for you (what continuity c0,c1,c2...?) but in most cases for visual smoothness cubics are enough (4 point curves).
If you want your curve going through all the points then you want interpolation instead approximation so BEZIER/SPLINE is not a way (unless some additional computations are introduced).
So your question boils to 2 things. What polynomial curve to use and how to smoothly join more of them together. To achieve that you need to sequence the control points in a specific manner. Booth of these questions are answered here:
Proper implementation of cubic spline interpolation
The interpolation polynomial used there is constructed in a way that it goes through all control points and 1st derivation is smoothly connected on both ends if more such curves are put together. The point call sequence is the same as for BEZIER/SPLINE cubics.
If you want/need to use BEZIER instead interpolation (for example to use GDI for rendering it) and still want the curve going through all the points you can convert that interpolation cubics of mine into BEZIER (it is form of Catmull-Rom splines) you just convert the control points into new ones so BEZIER matches the same shape. It is easily done like this:
how to convert interpolation cubic polynomial to cubic BEZIER
Here you can find example images how the joined curves looks like
SVG Paths and the Catmull-Rom algorithm
Related
Please see the image below.
This path object is created using 4 Bezier curve on each side.
Currently I am facing a problem when I try to get bounds of this path object created using cubic brazier curves. As you can see top and bottom sides have control point away from the curve which makes bounds totally inaccurate.
So my question is is it possible to create a jigsaw puzzle piece like in the image having all control points on or at the level of the curve. ( That is creating a curve and perfect mirror of it, all points within the bounds of the curve)
Don't calculate the bounds by using the control points, then. At least if you need tight bounds and don't want a quick check for potential visibility in a given clipping rectangle.
This awesome site can help a lot with common Bézier curve calculations, including bounding box.
Alternatively, switch to splines where the control points are on the curve, but then you could end up with the opposite effect where the curve extends beyond the bounds imposed by its control points.
You can easily convert your BEZIER cubic control points into Interpolation cubic. Just by reversing this:
BEZIER vs. interpolation cubic
so:
/* bezier = interpol
1 | ( x0)=X1;
t | (3.0*x1)-(3.0*x0)=(0.5*(X2-X0));
tt | (3.0*x2)-(6.0*x1)+(3.0*x0)=(3.0*(X2-X1))-(X2-X0)-(0.5*(X3-X1));
ttt|( x3)-(3.0*x2)+(3.0*x1)-( x0)=(0.5*(X2-X0))+(0.5*(X3-X1))+(2.0*(-X2+X1));
1 | ( y0)=Y1;
t | (3.0*y1)-(3.0*y0)=(0.5*(Y2-Y0));
tt | (3.0*y2)-(6.0*y1)+(3.0*y0)=(3.0*(Y2-Y1))-(Y2-Y0)-(0.5*(Y3-Y1));
ttt|( y3)-(3.0*y2)+(3.0*y1)-( y0)=(0.5*(Y2-Y0))+(0.5*(Y3-Y1))+(2.0*(-Y2+Y1));
*/
// input: x0,y0,..x3,y3 ... Bezier control points
// output: X0,Y0,..X3,Y3 ... interpolation control points
double x0,y0,x1,y1,x2,y2,x3,y3,m=1.0/9.0;
X0=x0-(x1-x0)/m; Y0=y0-(y1-y0)/m;
X1=x0; Y1=y0;
X2=x3; Y2=y3;
X3=x3+(x3-x2)/m; Y3=y3+(y3-y2)/m;
Hope I did not make any algebraic mistake. This will move all control points into your curves directly while the shape will be unchanged. Beware that for BBOX computation you should only use (X1,Y1) and (X2,Y2) as the used parameter t=<0,1> is interpolating between them !!!.
But even this can provide inaccuracy as you can have some extremes without control point. In case even that is a problem (The BBOX is a bit smaller than should) you can re-sample your shape to set of points (for example 10 per cubic) on the curve with some step (0.1) and do the BBOX from those points. That will be much more precise but slower of coarse...
One property of Bezier curves is that as you split them, the distance between the smooth curve and the CVs shrinks.
So, one way to fix those CVs on the top and bottom is to split the related Bezier into two Beziers using the De Casteljau algorithm.
You could even do this algorithmically:
Find tight bounding box and CV-based bounding box.
If the difference is greater than your tolerance, find the max/min CVs and their related Bezier curves
Split all of the related Bezier curves into two Bezier curves each
Repeat
Eventually you'll hit your tolerance. You might have a lot of Beziers by then though if you have a very tight tolerance or tricky data.
I'm currently working on my master's thesis where I get:
A Delaunay triangulation drawn for me with given n points in (x, y, z) form.
My task is to use this triangulation and make contour lines at given z values.
I have been nearly successful at doing this by implementing the wikipedia spline interpolation : https://en.wikipedia.org/wiki/Spline_interpolation
My problem is that I get contour lines crossing each other when implementing the splines while of course the linear drawings doesn't cross.
Parametric cubic spline interpolated contour lines
If you look at the bottom part of the screen you see two contour lines crossing, I don't have enough reputation points to show that the linear drawings doesn't. You can also see that from point to point that the edges are way too rounded.
What I've tried is to interpolate more points between any pair of points to make more knot points along the lines, this to restrict them further, but to get non-crossing lines the splines look too much like a linear drawing which isn't satisfactory to the eye.
What I'd like to know, is not actual code implementation of the how, but maybe a pointer to how, readings and so forth.
(NB, I'm going to make this from scratch, no libraries).
Question: How to make a higher degree polynomial function which doesn't curve too much outside its linear counterpart. By too much I mean that a given contour at let's say 50 meters, that it doesn't cross a contour at 60 meters.
Any help is highly appreciated.
You can try a weighted delaunay triangulation. It's defined as the euklidian distance minus the weight.
Couples of years ago I solved similar task.
Here are some of my working notes. Probably it would help you.
Refer to XoomCode AcidMaps plugin, on github:
https://github.com/XoomCode/AcidMaps/tree/master/examples/isolines
Here is a demo:
http://ams.xoomcode.com/flex/index.html
Set, for example, the renderer type "Sparse" and interpolation strategy as "Linear", then press the "Update" button.
Refer to VividSolutions JTS Java library:
http://www.vividsolutions.com/jts/download.htm
http://mike.teczno.com/notes/curves-through-points.html
http://blog.csdn.net/xsolver/article/details/8913390
In Java, how can I read in the d attribute of an SVG path, and discretize it such that all Bezier curves are properly subdivided into discrete points, allowing me to specify a threshold to account for sharp angles?
The only solution I've found after a ton of searching is to use Apache Batik to traverse the path in short intervals, and sample points uniformly, but that generates a bunch of unnecessary points along straight lines and doesn't handle the case of sharp angles.
I implemented an algorithm to convert a quadratic bezier into a set of straight lines (vertices) in Javascript a while back. Its here in action
It's not Java but it should not be too hard to convert, You should filter out the bezier curves yourself by regexing on [Q,q,C,c,S,s]
Some discription is here.
i want to find a circular object(Iris of eye, i have used Haar Cascase with viola Jones algorithm). so i found that hough circle would be the correct way to do it. can anybody explain me how to implement Hough circle in Java or any other easy implementation to find iris with Java.
Thanks,
Duda and Hart (1971) has a pretty clear explanation of the Hough transform and a worked example. It's not difficult to produce an implementation directly from that paper, so it's a good place for you to start.
ImageJ provides a Hough Circle plugin. I've been playing around with it several times in the past.
You could take a look at the source code if you want or need to modify it.
If you want to find an iris you should be straightforward about this. The part of the iris you are after is actually called a limbus. Also note that the contrast of the limbus is much lower than the one of the pupil so if image resolution permits pupil is a better target. Java is not a good option as programming language here since 1. It is slow while processing is intense; 2. Since classic Hough circle requires 3D accumulator and Java probably means using a cell phone the memory requirements will be tough.
What you can do is to use a fact that there is probably a single (or only a few) Limbuses in the image. First thing to do is to reduce the dimensionality of the problem from 3 to 2 by using oriented edges: extract horizontal and vertical edges that together represent edge orientation (they can be considered as horizontal and vertical components of edge vector). The simple idea is that the dominant intersection of edge vectors is the center of your limbus. To find the intersection you only need two oriented edges instead of three points that define a circle. Hence dimensionality reduction from 3 to 2.
You also don’t need to use a classical Hough circle transform with a huge accumulator and numerous calculations to find this intersection. A Randomized Hough will be much faster. Here is how it works (~ to RANSAC): you select a minimum number of oriented edges at random (in your case 2), find the intersection, then find all the edges that intersect at approximately the same location. These are inliers. You just iterate 10-30 times choosing a different random sample of 2 edges to settle in a set with maximum number of inliers. Hopefully, these inliers lie on the limbus. The median of inlier ray intersections will give you the center of the circle and the median distance to the inliers from the center is the radius.
In the picture below bright colors correspond to inliers and orientation is shown with little line segment. The set of original edges is shown in the middle (horizontal only). While original edges lie along an ellipse, Hough edges were transformed by an Affine transform to make those belonging to limbus to lie on a circle. Also note that edge orientations are pretty noisy.
I have been using Affine Transform to rotate a String in my java project, and I am not an experienced programmer yet, so it has taking me a long time to do a seemingly small task.. To rotate a string.
Now I have finally gotten it to work more or less as I had hoped, except it is not as precisely done as I want... yet.
Since it took a lot of trial and error and reading the description of the affine transform I am still not quite sure what it really does. What I think I know at the moment, is that I take a string, and define the center of the string (or the point which I want to rotate around), but where does matrices come into this? (Apparently I do not know that hehe)
Could anyone try and explain to me how affine transform works, in other words than the java doc? Maybe it can help me tweak my implementation and also, I just would really like to know :)
Thanks in advance.
To understand what is affine transform and how it works see the wikipedia article.
In general, it is a linear transformation (like scaling or reflecting) which can be implemented as a multiplication by specific matrix, and then followed by translation (moving) which is done by adding a vector. So to calculate for each pixel [x,y] its new location you need to multiply it by specific matrix (do the linear transform) and then add then add a specific vector (do the translation).
In addition to the other answers, a higher level view:
Points on the screen have a x and a y coordinate, i.e. can be written as a vector (x,y). More complex geometric objects can be thought of being described by a collection of points.
Vectors (point) can be multiplied by a matrix and the result is another vector (point).
There are special (ie cleverly constructed) matrices that when multiplied with a vector have the effect that the resulting vector is equivalent to a rotation, scaling, skewing or with a bit of trickery translation of the input point.
That's all there is to it, basically. There are a few more fancy features of this approach:
If you multiply 2 matrices you get a matrix again (at least in this case; stop nit-picking ;-) ).
If you multiply 2 matrices that are equivalent to 2 geometric transformations, the resulting matrix is equivalent to doing the 2 geometric transformations one after the other (the order matters btw).
This means you can encode an arbitrary chain of these geometric transformations in a single matrix. And you can create this matrix by multiplying the individual matrices.
Btw this also works in 3D.
For more details see the other answers.
Apart from the answers already given by other I want to show a practical tip namely a pattern I usually apply when rotating strings or other objects:
move the point of rotation (x,y) to the origin of space by applying translate(-x,-y).
do the rotation rotate(angle) (possible also scaling will be done here)
move everything back to the original point by translate(x,y).
Remember that you have to apply these steps in reverse order (see answer of trashgod).
For strings with the first translation I normally move the center of the bounding box to the origin and with the last translate move the string to the actual point on screen where the center should appear. Then I can simply draw the string at whatever position I like.
Rectangle2D r = g.getFontMetrics().getStringBounds(text, g);
g.translate(final_x, final_y);
g.rotate(-angle);
g.translate(-r.getCenterX(), -r.getCenterY());
g.drawString(text, 0, 0);
or alternatively
Rectangle2D r = g.getFontMetrics().getStringBounds(text, g);
AffineTransform trans = AffineTransform.getTranslateInstance(final_x, final_y);
trans.concatenate(AffineTransform.getRotateInstance(-angle));
trans.concatenate(AffineTransform.getTranslateInstance(-r.getCenterX(), -r.getCenterY()));
g.setTransform(trans);
g.drawString(text, 0, 0);
As a practical matter, I found two things helpful in understanding AffineTransform:
You can transform either a graphics context, Graphics2D, or any class that implements the Shape interface, as discussed here.
Concatenated transformations have an apparent last-specified-first-applied order, also mentioned here.
Here is purely mathematical video guide how to design a transformation matrix for your needs http://www.khanacademy.org/video/linear-transformation-examples--scaling-and-reflections?topic=linear-algebra
You will probably have to watch previous videos to understand how and why this matrices work though. Anyhow, it's a good resource to learn linear algebra if you have enough patience.