I have data in the form of a 2D array of intensities that should be plotted in a contour plot. In the end it should look like a topographic map with contour lines like the following image:
The idea is that the typical multitouch gestures (pinch for zooming, dragging for moving around) can be used to navigate the contour plot. The maxi开发者_运维问答mum size of the data should be around 4k*4k points, each 4 bytes big.
Is there some plotting library that I can use, or do I have to start from scratch? Is there an easily implemented algorithm for that?
I don't know of any plotting libraries for Android (or Java for that matter), but I do know a thing or two about plotting in general:
An easy algorithm for creating contours would be Marching Squares. Marching squares creates polygons from your array of data. There should be plenty of examples of this algorithm in Java (try Google Code Search, but read licenses before you use).
If you want to zoom in far you probably want to create bezier curves from these polygons to smooth them out, an example algorithm (with code that should be easily ported to Java) can be found here.
Note: If you want to fill the contours with a color you should consider using a fragment shader instead of creating polygons. Send the data to the shader as a texture and use the intensity to assign a color to each pixel. For this you should know some OpenGL.
As @Markus Johnsson said, one way to visualize your two-dimensional array of data is to use the Marching Squares algorithm. But in your case, it seems you need its implementation based on isolines instead of isobands (which use polygons Markus mentioned about).
Implementation based on isolines is easier to write it from scratch. It is mainly due to the fact, that you have to check only whether a given value is under, or above specific isovalue (vs below-within-above specific range in isoband implementation). This results only in 16 possible configurations of lines drawn in a single isocell (vs 80 polygon configurations in isobands implementation).
It is often desirable to interpolate your data before using it in the creation of the contour map. One way to do so, is to use Bicubic Interpolation.
I've written recently a simple implementation of the filled two-dimensional contour plot based on the Marching Squares algorithm and its isoband variant. This implementation also use mentioned Bicubic Interpolation for smoothening the data. You can find this simple package here. It is written under GNU GPLv3 license (or later). In order to use it in your project you have to copy and paste org.contour2dplot.*
to the project's location.
All you need to do in order to draw a contour map with the use of the aforementioned package is to prepare a double[][] data
and create a Contour2DMap
object. Example use can look like this:
// Specify in the constructor width and height of the contour map.
Contour2DMap contour2DMap = new Contour2DMap(600, 600);
// Specify size for the contour map container.
contour2DMap.setPrefSize(600, 600);
// Set data.
contour2DMap.setData(data);
// Set iso factor, which is a step between subsequent iso values.
contour2DMap.setIsoFactor(1.0);
// Set interpolation factor.
contour2DMap.setInterpolationFactor(10);
// Set contour map color scale - "Color" or "Monochromatic".
contour2DMap.setMapColorScale("Color");
// Draw all elements on the contour map.
contour2DMap.draw();
Contour2DMap
object inherits from javafx.scene.layout.Pane
, so you can nest it in other javafx.scene.layout.*
objects, such as BorderPane
.
In order to make contour map interactive you may consider overwriting the javafx.scene.chart.Chart
object and nesting Contour2DMap
in it.
You may also consider rewriting org.contour2dplot.*
for the isolines variant of the Marching Squares algorithm.
Below are two screenshots of Contour2DMap
for setMapColorScale("Color")
and setMapColorScale("Monochromatic")
respectively.
精彩评论