How do I discretize an SVG path with Java? - java

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.

Related

Contour lines drawing in Java with a given Delaunay triangulation

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

link points with a smooth curve

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

image enhancement of plots and other line diagrams

I am looking for library routines for the image enhancement of (scientific) plots and diagrams. Typical examples are shown in
http://www.jcheminf.com/content/pdf/1758-2946-4-11.pdf
and Figure 3 of http://en.wikipedia.org/wiki/Anti-aliasing
These have the features that:
They usually use a very small number of primitives (line, character, circle, rectangle)
They are usually monochrome (black/white) or have a very small number of block colours
The originals have no gradients or patterns.
I wish to reconstruct the primitives and am looking for an algorithm to restore clean lines in the image before the next stage of analysis (which may include line detection and OCR). The noise often comes from :
use of JPGs (the noise is often seen close to the original primitive)
antialiasing
I require Free/Open Source solutions and would ideally like existing Java libraries. If there are any which already do some of the job or reconstructing lines that would be a bonus! For characters recognition I would be happy to isolate each character at this stage and defer OCR, though pointers to that would also be appreciated.
UPDATE:
I am surprised that even with a bounty there have been no substantive replies to the question. I am therefore investigating it myself. I still invite answers but they should go beyond my own answer.
ANSWER TO OWN QUESTION
Since there there have been no answers after nearly a week here is what I now plan:
I found mention of the Canny edge-detection algorithm on another SO post and then found:
[http://www.tomgibara.com/computer-vision/canny-edge-detector][2]
from Tom Gibara.
This is very easy to use in default mode and the main program is:
public static void main(String[] args) throws Exception {
File file = new File("c.bmp");
//create the detector
CannyEdgeDetector detector = new CannyEdgeDetector();
//adjust its parameters as desired
detector.setLowThreshold(0.5f);
detector.setHighThreshold(1f);
//apply it to an image
BufferedImage img = ImageIO.read(file);
detector.setSourceImage(img);
detector.process();
BufferedImage edges = detector.getEdgesImage();
ImageIO.write(edges, "png", new File("c.png"));
}
Here ImageIO reads and writes bitmaps. The unprocessed image is read as a 24-bit BMP (ImageIO seems to fail with lower colour range). The defaults are Gibara's out-of-the-box.
The edge detection is very impressive and outlines all the lines and characters. This bitmap
is converted to the edges
So now I have two tasks:
fit straight lines to the outlines, which are essentially clean "tramlines". I expect this to be straightforward for clean diagrams. I'd be grateful for any mention of Java libraries to fit line primitives to outlines.
recognize the characters. Gibara has done an excellent job of separating them and so this is an exercise of recognising the individual glyphs. I can use the outlines to isolate the individual pixel maps for each glyph and then pass these to JavaOCR. Alternatively the outlines may be good enough to recognize the characters directly. I do NOT know what the font is, but most characters are in the 32-255 range and I believe I can build up heuristic maps.
See How do I properly load a BufferedImage in java? for loading bitmaps in Java
Java Library
OpenCV is the go-to library for computer vision tasks like this. There are Java bindings here: http://code.google.com/p/javacv/ . OpenCV covers everything from basic image processing filters to high-level object and motion detection algorithms.
Line Detection
For detecting straight lines, try the Hough Transform. The OpenCV Tutorials have a good explanation: http://opencv.itseez.com/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html#how-does-it-work
The classical Hough transform outputs infinite lines, but OpenCV also implements a variant called the Probabilistic Hough Transform that outputs line segments. It should give what you need. The original academic paper is here: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.34.9440&rep=rep1&type=pdf
Once you detect line segments, you might want to detect linked line segments and join them together. For your simple images, you will probably do just fine with a brute-force comparison of all segment endpoints. If you detect more than one endpoint within a small radius, say 2 pixels, join them together to make sure your lines are continuous. You can also measure the angle between joined line segments to detect polygons.
Circle Detection
There is another version of the Hough transform that can detect circles, explained here: http://opencv.itseez.com/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.html#hough-circle
I wish to reconstruct the primitives and am looking for an algorithm
to restore clean lines in the image before the next stage of analysis
(which may include line detection and OCR).
Have you looked at jaitools? ( http://code.google.com/p/jaitools/ ).
They have API for vectorizing graphics which are quite fast and flexible; see API and docs here: http://jaitools.org/

Algorithm to create an image of an elliptical brush?

I need to be able to accept elliptical(computed) brush parameters such as spacing, hardness, roundness, angle and diameter and then compute a bitmap image based on those attributes.
Does anyone know the algorithm(or where I can find it) to do this? I have limited experience in graphics programming and I have been unable to find it so far.
This is the kind of thing you want to use a library for, most likely the Java 2D API. It includes facilities for fills, strokes, transforms, and filters. Its model is similar to many libraries in that you trace out a path with operators moveTo and lineTo or curveTo, which are abstracted in shapes like Ellipse2D; and then you fill or stroke the resultant path with a paint operator. I highly recommend reading the Java 2D tutorial and understanding how the different parts fit together.
I would take roughly the following steps to create this drawing:
Compute the final dimensions of the rotated ellipse after blurring.
Create a BuferredImage of that size and call its createGraphics method to acquire a drawing context.
Rotate the graphics object
Draw the ellipse
Fill it with black
Implement the Gaussian blur filter. This is not built in to the API, but it includes a framework for doing filters called ConvolveOp, and you can find an algorithm for computing the Gaussian kernel in Java.
Apply the filter to the image, and then return the results.
Another option might be Apache’s Batik SVG library, since you can declaratively express the drawing you want (including transformations and filters) and have it rasterized for you.
An extremely useful list of formulas for an ellipse can be found here: Link
Think about what each formula implies about an individual pixel in your bitmap (whether it's in/out of the ellipse, whether it's near the edge) and which properties would be useful to you.

How can I draw a curve that varies in thickness along its path?

I'm capturing data from a tablet using Java (JPen library rocks) and would like to be able to paint a penstroke in a more natural way.
Currently I'm drawing the pen stroke as straight line segments each with a different Stroke thickness.
There has to be something in Java's Graphics Library that lets me to this more efficiently.
Right?
I've never done this, but here are a couple things you could try. First, you could implement a custom Stroke that creates skinny trapezoids. The width of the end caps would be a function of the pressure at the end points. If that works, you could try to make the line segments look more natural by using Bezier curves to form "curvy trapezoids". You might be able to use QuadCurve2D to help.
There's a more general solution available at least. The feature was added to Inkscape based on a recent algorithm. You can see it applied directly to your problem in some screenshots. It can extrude any shape brush along the path to mimic a paintbrush for example, but you'd have to port it to Java from the algorithm in the first link or from the Inkscape sources. Also, it's covered by patents so you'd have to release your code under the GPL (the author gives explicit permission) or buy a patent license.
PostScript RIPs often convert circles to curves and curves to a series of straight line segments. The number of segments depends on the flatness setting which defaults to one suitable for the raster display resolution.
A thick line or thick line segments can be converted to a skinny filled polygon.

Categories

Resources