Creating interactive contour plots on Android - java

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 maximum 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.

Related

Rigid transformation of two shapes with OpenCV in Java

As the title says, I'm trying to find a way to generate a transformation matrix to best best align two images (the solution with the smallest error value computed with an arbitrary metric - for example the SAD of all distances between corresponding points). Example provided below:
This is just an example in the sense that the outer contour can be any shape, the "holes" can be any shape, any size and any number.
The "from" image was drawn by hand in order to show that the shape is not perfect, but rather a contour extracted from a camera acquired image.
The API function that seems to be what I need is Video.estimateRigidTransform but I ran into a couple of issues and I'm stuck:
The transformation must be rigid in the strongest sense, meaning it must not do any kind of scaling, only translation and rotation.
Since the shapes in the "from" image are not perfect, the number of points in the contour are not the same as the ones in the "To" image, and the function above need two sets of corresponding points. In order to bypass this I have tried another approach: I have calculated the centroids of the holes and outer contour and tried aligning those. There are two issues here:
I need alignment even if one of the holes is missing in the "from" image.
The points must be in the same order in both lists passed to Video.estimateRigidTransform and there is no guarantee that function findContours will provide them in the same order in both shapes.
I have yet to try to run a feature extractor and matcher to obtain some corresponding points but I'm not very confident in this method, especially since the "From" image is a natural image with irregularities.
Any ideas would be greatly appreciated.

Linear Interpolation of Scattered 2D Data

So I have some irregularly spaced data that I want to interpolate onto a regular grid. (I want to do exactly this but in Java) Here's a picture:
Basically I have the x and y coordinates of each point and a z value associated with each point and I want to interpolate between them and fill in the center of my image.
What is the best way to do this using Java? Is there a built in 2D interpolation library I can use or should I try a "roll my own" approach?
This post and this one also seem to be trying to do about what I am but their answers don't quite apply.
Someone else with the same problem but no solution.
Note: I am using JavaFX-2 so if I could somehow use their Interpolator class that'd be great.
.
.
EDIT:
If anyone stumbles upon this and wants to know what I ended up using, it was a Delaunay Triangulation implementation from BGU:
Main Site
Code API
If linear interpolation is sufficient, I suggest you to use a 3d mesh with Gouraud Shading for drawing:
Convert the 2d point cloud to a mesh (you can google for existing algorithms)
Mapping the z value of each point to the vertex' color
Using Gouraud Shading to enable linear interpolation between the vertex colors
Creating a camera on top to the mesh and using a othonormal projection (to avoid perspective)
You say that you can use JavaFX. JavaFX supports 3d scenes and you can build your own meshes. But looking into the JavaDoc of TriangleMesh, I can't find any method to set the vertex color I found only a method to set the (x,y,z) and (u,v) (texture coordinates) coordinates.

Path2D.intersect() Similar to Area.intersect()

I have played around with Area.intersect() and was wondering if there is a way to create a method much like this one using Path2D because I noticed a performance jump when using Path2D as a shape. In other words take a portion of a large Path2D and create a smaller Path2D from that portion.
Map Drawing
In-Game View
Note: Using the below hashmap a I render tiled shapes to the viewing area according to each "Object" which in this case would be the different image types : Ocean, Grass, Obsidian, Rock, Sand, & Dirt...
LinkedHashMap<Point, LinkedHashMap<Object, Path2D.Double>>
EDIT : Each image type has an entire map area of its own that is 10000px by 100000px my tiles that intersect are 100px by 100px which are shoved into the linked hash map by point as its given type as a Path2D.Double and rendered onto the screen by the points in the current viewing area.
It's not clear what SDK you're working with which offers Area.intersect(). Depanding on what you intend to intersect your path with, however, it may be a complex problem - notice that a path2D intersected with a polygon may turn into several paths!
However, there are some known algorithm for intersecting a path with a polygon, such as Cyrus-Beck or Sutherland-Cohen.
I found this piece of code for Cohen-Sutherland in Java:
http://worldofenggcodes.blogspot.co.il/2013/10/cohen-sutherland-line-clipping-algorithm.html
Which seems OK, although you might need to extract the code into a more usable function. Cyrus-Beck would probably be a better option, though I could only find pseudo-code:
http://www.moreprocess.com/computer-graphics/cyrus-beck-line-clipping-algorithm
Once you've implemented either, you need to apply it to every line in your path, to get a new list of lines which intersect with the square.

Java2D best way to pick various image with Alpha background overlapped?

I am developing an isometric game in Java2D. I.e, note that I do not have direct access to hardware pixel shaders (real-time software pixel shaders aren't practical. I can do a single pass on every entity texture without a noticeable hit on performance)
I know the typical method would be to somehow encode the depth of the individual pixels into a depth buffer and look that up. However, I don't know how I can do that efficiently in Java2D. How would I store the depth buffer? How would I filter out the alpha in an image? Etc.
Up until now I have just been reversing the projection matrix I use to calculate the tile-coordinates. However, that doesn't work well when you have entities that render outside of those tile's bounds.
Another method I considered was using a color-map, however I have the same problems with this as I do with the depth buffer (and if I can get the depth buffer working I'd much rather use that.)
Here is a picture of what I am working with:
I've resolved this quite nicely. The solution is actually very simple, just unconventional.
The graphics are depth sorted via a TreeMap, and then rendered to the screen. One can simply traverse this TreeMap in reverse (and keep it until the next render cycle) to translate the cursor location to the proper image it falls over (by testing the pixels [in reverse render order] and checking if they are transparent.)
The solution is in the open-source project, under the io.github.jevaengine.world.World class, pick method. https://github.com/JeremyWildsmith/JevaEngine/blob/master/jevaengine/src/main/java/io/github/jevaengine/world/World.java

Getting boundary information from a 3d array

Hey, I'm currently trying to extract information from a 3d array, where each entry represents a coordinate in order to draw something out of it. The problem is that the array is ridiculously large (and there are several of them) meaning I can't actually draw all of it.
What I'm trying to accomplish then, is just to draw a representation of the outside coordinates, a shell of the array if you'd like. This array is not full, can have large empty spaces with only a few pixels set, or have large clusters of pixel data grouped together. I do not know what kind of shape to expect (could be a simple cube, or a complex concave mesh), and am struggling to come up with an algorithm to effectively extract the border. This array effectively stores a set of points in a 3d space.
I thought of creating 6 2d meshes (one for each side of the 3d array), and getting the shallowest point they can find for each position, and then drawing them separetly. As I said however, this 3d shape could be concave, which creates problems with this approach. Imagine a cone with a circle on top (said circle bigger than the cone's base). While the top and side meshes would get the correct depth info out of the shape, the bottom mesh would connect the base to the circle through vertical lines, making me effectivelly loose the conical shape.
Then I thought of annalysing the array slice by slice, and creating 2 meshes from the slice data. I believe this should work for any type of shape, however I'm struggling to find an algorithm which accuratly gives me the border info for each slice. Once again, if you just try to create height maps from the slices, you will run into problems if they have any concavities. I also throught of some sort of edge tracking algorithm, but the array does not provide continuous data, and there is almost certainly not a continuous edge along each slice.
I tried looking into volume rendering, as used in medical imaging and such, as it deals with similar problems to the one I have, but couldn't really find anything that I could use.
If anyone has any experience with this sort of problem, or any valuable input, could you please point me in the right direction.
P.S. I would prefer to get a closed representation of the shell, thus my earlier 2d mesh approach. However, an approach that simply gives me the shell points, without any connection between them, that would still be extremely helpful.
Thank you,
Ze
I would start by reviewing your data structure. As you observed, the array does not maintain any obvious spatial relationships between points. An octree is a pretty good representation for data like you described. Depending upon the complexity of you point set, you may be able to find the crust using just the octree - assuming you have some connectivity between near points.
Alternatively, you may then turn to more rigorous algorithms like raycasting or marching cubes.
Guess, it's a bit late by now to be truly useful to you, but for reference I'd say this is a perfect scenario for volumetric modeling (as you guessed yourself). As long as you know the bounding box of your point cloud, you can map these coordinates to a voxel space and increase the density (value) of each voxel for each data point. Once you have your volume fully defined, you can then use the Marching cubes algorithm to produce a 3D surface mesh for a given threshold value (iso value). That resulting surface doesn't need to be continuous, but will wrap all voxels with values > isovalue inside. The 2D equivalent are heatmaps... You can refine the surface quality by adjusting the iso threshold (higher means tighter) and voxel resolution.
Since you're using Java, you might like to take a look at my toxiclibs volumeutils library, which also comes with sevaral examples (for Processing) showing the general approach...
Imagine a cone with a circle on top
(said circle bigger than the cone's
base). While the top and side meshes
would get the correct depth info out
of the shape, the bottom mesh would
connect the base to the circle through
vertical lines, making me effectivelly
loose the conical shape.
Even an example as simple as this would be impossible to reconstruct manually, let alone algorithmically. The possibility of your data representing a cylinder with a cone shaped hole is as likely as the vertices representing a cone with a disk attached to the top.
I do not know what kind of shape to
expect (could be a simple cube...
Again, without further information on how the data was generated, 8 vertices arranged in the form of a cube might as well represent 2 crossed squares. If you knew that the data was generated by, for example, a rotating 3d scanner of some sort then that would at least be a start.

Categories