Friday, April 7, 2017

Friday Fun XLVI - Image Matrix

Aloha,

Last weekend when sitting in my hotel room in Singapore I had the idea to test the performance of my DotMatrix control again. So I thought what about pixelating an image and visualize it using the control.
Well to be honest it was just too easy to do...so here is the result...



On the left side you see the original picture and on the right side the related pixelated matrix image.
So I thought why not adding some text and figured out that when I draw the text on the DotMatrix control I usually set all "transparent" pixels to the dotOffColor which doesn't look good in this example.
Therefor I've added another method to the DotMatrix control which only draws the pixels in a character that are "on". The method is called

  • setCharAtWithBackground()

So with this it was easy to add some text on top of the pixelated image without destroying the existing background pixels.
Now that this was done I decided it might be nice to be able to simply shift the DotMatrix in each direction. Long story short I've implemented for additional methods which are

  • shiftLeft()
  • shiftRight()
  • shiftUp()
  • shiftDown()

When calling one of this methods the whole DotMatrix will be shifted by one dot in the choosen direction and redraws itself.
Now I could really test the capability of the DotMatrix by calling for example the shiftLeft method in an AnimationTimer with an update rate of 10ms. So the result was nice as you can see in the following video...



You could also combine the calls like first calling shiftLeft() and after that shiftUp(). It's not perfect because both times the drawMatrix() method will be called but even with this little drawback the DotMatrix is fast enough to create a smooth scrolling effect.

Please keep in mind that you should not go crazy with the no of dots in the DotMatrix control. You will definitely see a decrease in performance if you go to a high number of columns and rows. In the video I use 100x85 dots for the DotMatrix which I think is good enough to use it also for images.

So I don't have any use case for the DotMatrix control at the moment but maybe one of you has and therefor you can find the source code as always over at github.

You will also find 2 other demos in the source code (Main2 and Main3). In Main2 I show you how to create one DotMatrix out of two images and in Main3 I show you how to use two images and draw them alternating on the DotMatrix...so have fun playing around with it :)

Well that's it for today...like always I wish you a nice weekend and never forget...keep coding... ;)

Friday, March 31, 2017

Friday Fun XLV - StockTicker

Aloha,

On my way back from Singapore last time I've created a little Demo that shows the new StockTileSkin of my TilesFX library.
In principle the StockTileSkin is very similar to the SparkLineTileSkin with the difference that it always shows the increase/decrease of the reference value in percentage and as a number.

So in the demo I get the current stock quote of Oracle and IBM once a minute from the NYSE. Because I'm not really into the broker and banking business I have no idea if that makes sense, so forgive me if this idea is totally stupid :)

To understand how this Skin works it needs some more explanation...
First of all you have to define the so called averaging period, this number represents the number of values that you would like to show in the line graph.

In this example I've decided to poll the stock quote every minute and set the averaging period to 120 which means the graph will show the last 2 hours when filled up
If no value is present the min and max values will be taken from Tile.getMinValue() and Tile.getMaxValue(). You also have to make sure that these values are in a usable range because values in Tile will be clamped to the min- and maxValue (I might change this for this specific skin in the future).

For a real good demo I should preload the line chart with the data of the previous day but I did not had the time to extend the demo to this.
Means if you start the demo and the NYSE is closed at that time you won't see any change in the value at all. But if you start it during the trading hours of the NYSE you might see some changes over time (but keep in mind that I only poll once a 1 minute).
If you did not set the reference value, the first value of the data list will be taken to calculate the increase of decrease of the current value. 
If you would like to stick your manual set reference value you might want to set autoReferenceValue property to false.
The reference value will be visualized using a dashed line color with the tresholdColor.

In addition to the StockTileSkin I thought it might be nice to make use of my DotMatrix control and create and add a scrolling ticker too.
To give you an idea what I'm talking about, here is a screenshot of the demo...



The service that I use to get the stock quotes can be found at http://dev.markitondemand.com and is nice for testing some things. The problem is that first of all the data is not available for all companies so it took me some time to figure out two quotes that are updated regularly which made me end up with Oracle and IBM :)

If you would like to add another company stock symbol you can simply add it to the list of symbols in the Main.class. For example let's add Microsoft to the list


public class Main extends Application {
    private static final List<String> SYMBOLS;
    static {
        SYMBOLS = new ArrayList<>();
        SYMBOLS.add("IBM");
        SYMBOLS.add("ORCL");
        SYMBOLS.add("MSFT"); // Simply add it to the list
    }

Be aware that I did not spend much time in layouting mulitple stock items...means I've tried it with 2 and 3 stock symbols...it might look bad with 4 but you will figure out how to make it better ;)

I hope that the StockTileSkin is somehow useful and if you have suggestions on how to improve it...please let me know :)

If you are interested in the source code of this demo you can find it as always on github.

And at last here is a little video that shows the StockTicker Demo in action after it ran for some time.



That's it for today...cheers from Singapore and...keep coding... :)

Friday, March 24, 2017

Friday Fun XLIV - The Matrix

Aloha,

Last weekend I was thinking about a dot matrix display and remembered that this was always something I would like to do in JavaFX. Well after spending nearly 2 weeks in Singapore working on infrastructure documentation etc. I really needed some coding and because of the jetlag I had enough time during the early mornings to create a little control.
To give you an idea what I'm talking about here is a little screenshot of the control...



So as you can see this is not a really fancy control but more something simple and there is a reason for that. I remember that I've once started to create some kind of matrix control for JavaFX but that was in the early JavaFX 2 days and we had no Canvas node which was the reason why I've used nodes for each dot in the old version. But with this amount of dots the whole thing became really slow and because of that I simply never tried again.
But when I thought about it over the weekend the Canvas node came to my mind again and so I've started a new approach with the dot matrix control.
So this version runs completely in one Canvas node and is based on an integer array to make it fast. The main idea behind the dot matrix display was to create some kind of animated stock ticker.
This idea lead to 3 requirements

  1. the matrix size has to be configurable
  2. it must be fast enough for animation
  3. it must be possible to set colors for each dot
  4. it should be possible to show text

So let's take a short look at each requirement.

1. To make the matrix size configurable it is in principle only needed to define the number of dots per column and row you would like to see in the dot matrix. But there is one drawback here, if the control should be resizable you will also need to define the preferred size of the control to be able to resize it with the right aspect ratio.
Therefor you will find a constructor that not only takes the number of columns and rows but also the preferredWidth and preferredHeight. In addition you could also add a color for the dot on and dot off state. 
So to create a DotMatrix with a size of 128x16 dots and a dot on color of red and a dot off color of dark gray you have to write the following code...


DotMatrix m = new DotMatrix(128, 16, 264, 33, Color.RED, Color.DARKGRAY);

or if you prefer using the DotMatrixBuilder it will look like follows...


DotMatrix m = DotMatrixBuilder.create()
                              .prefSize(264, 33)
                              .colsAndRows(128, 16)
                              .dotOnColor(Color.RED)
                              .dotOffColor(Color.DARKGRAY)
                              .build();

2. To make the dot matrix fast enough for animation I've tried to avoid as much overhead as possible. With overhead I mean things like 

  • many nodes on the scene graph
  • crazy graphics (e.g. each dot has light reflection etc.)
  • complex drawing method

To avoid as many nodes on the scene graph as possible the best solution is to make use of the Canvas node. This represents only one node on the scenegraph, can contain complex graphics and the redraw is more or less under your control (immediate mode rendering).
And in addition the Canvas node is really fast :)
A picture explains more than 1000 words...so here is a screenshot of a former matrix that I did in Enzo...



I think you now understand what I mean with crazy graphics...I mean it looks nice but for a bigger display this is simply overkill. For this control I used nodes for each dot...or better each LED.
Because when animating the control I have to call the drawing method a lot and therefor this drawing method has to be as short and simple as possible. So let's take a look at the drawing method in the DotMatrix control...


private void drawMatrix() {
    ctx.clearRect(0, 0, width, height);
    for (int y = 0; y < rows; y++) {
        for (int x = 0; x < cols; x++) {
            ctx.setFill(convertToColor(matrix[x][y]));
            ctx.fillOval(x * dotSize + spacer, y * dotSize + spacer, 
                         dotSizeMinusDoubleSpacer, dotSizeMinusDoubleSpacer);
        }
    }
}

That's all, I clear the canvas, then simply iterate over the rows and columns, set the fill for the current dot and draw a circle at the current position defined by x and y.
Keeping things simple makes the drawing fast enough to do some animation.

3. To make it possible to set the color for each dot you need a 2d data structure which defines the position and stores the color. You can think of all possible combinations of Lists, Maps and custom Objects to realize that but if you would like to keep it simple you could simply stick with a simple 2-dimensional integer array. This will contain the x and y coordinates of each dot and you could use a 1 to enable the dot or a 0 to disable the dot.
This works and is simple and fast BUT how to enable custom colors for each dot???
For this it would be great to represent a color as an integer value but if you take a look at the javafx.scene.paint.Color class you will find all sorts of methods but unfortunately no method that returns the color as an integer value. Lucky me I remembered that the java.awt.Color class had such a method and so it was easy to take a look at the source code of OpenJDK (it's so nice to be able to have the source code of Java available).
To convert a color into an integer you simply can make use of some bit-shifting and the code to convert a color into an integer looks as follows...


public int convertToInt(final float R, final float G, final float B, final float A) {
    int red   = Math.round(255 * R);
    int green = Math.round(255 * G);
    int blue  = Math.round(255 * B);
    int alpha = Math.round(255 * A);
    return (alpha << 24) | (red << 16) | (green << 8) | blue;
}

Now with this in place it was easy to store the color value as integer in the 2-dimensional array of the matrix. Oh and of course it would also be nice to have a method to convert an integer back to a Color, so here it is...


public static Color convertToColor(final int COLOR_VALUE) {
    return Color.rgb((COLOR_VALUE & RED_MASK) >> 16, 
                     (COLOR_VALUE & GREEN_MASK) >> 8, 
                     (COLOR_VALUE & BLUE_MASK), 
                     ALPHA_FACTOR * ((COLOR_VALUE & ALPHA_MASK) >>> 24));
}

In JavaFX the opacity is defined by a double compared to an int in the AWT color which is the reason for the ALPHA_FACTOR multiplication here.
So now we can define for each dot in the matrix the location and the color by simply using a 2-dimensional integer array which is good for the performance.
Means most of the work in the drawing method is done by converting an integer back to a Color. But because all of the operations used for the conversion are mainly bit-shifting and object creation this is not a problem.

4. To be able to show text on the DotMatrix I needed to create some mapping of characters to dots. So my idea was to keep the DotMatrix close to a real hardware DotMatrix where you can define the xy position of the dot and a color. Means in the DotMatrix control switching on a dot is done by calling the method


public void setPixel(final int X, final int Y, final int COLOR_VALUE) {
    if (X >= cols || X < 0) return;
    if (Y >= rows || Y < 0) return;
    matrix[X][Y] = COLOR_VALUE;
}

As you can see I don't call the drawMatrix() method automatically which means I leave that up to you. So first one can set all the pixels needed and then you can call the drawMatrix() method. With this approach you can avoid a redraw after set a pixel.
This is a big advantage when doing some kind of dot matrix ticker where text is moving from right to left. In this case you can first set a vertical line of pixels before you really draw them.
But if you would like to automatically redraw after a pixel was set you will also find a method called setPixelWithRedraw() which does exactly this.
Now back to the character mapping, here I've decided to create an 8x8 font for the ASCII characters between 32 - 126. And if you only need numbers I've also created an 8x8 font that only contains the numbers from 0 - 9.
Again the goal was to keep it as simple as possible which was the reason to define each character by an integer array. So for example the digit 0 looks like this...


{
    0b00111000,
    0b01000100,
    0b01000100,
    0b01000100,
    0b01000100,
    0b01000100,
    0b01000100,
    0b00111000
}

As you can see I used the binary literals which is nice to represent a matrix of dots.
Now the only thing I had to do was to read out each bit of each row and do some math related to the dot position.
These calculations can be found in the setCharAt() and setDigitAt() methods in the DotMatrix control. 
A demo of how to use the DotMatrix control for a running text display can be found in the Demo class in the source code.

I will definitely add this control also to TilesFX because it could be handy as a stock ticker on a dashboard.
So that's it for today, I hope this control will be useful for someone except me :)

UPDATE:
I've removed the plain digits and added another MatrixFont which is 8x11 pixels. So now you can choose between 

  • MatrixFont8x8
  • MatrixFont8x11

In addition I've also added the possibility to set the dot shape to either DotShape.ROUND which is default or to DotShape.SQUARE.

Here is a little video which shows the control in action...


Please find the source code as usual at github.

More examples can be found here

Enjoy the upcoming weekend and keep coding... 

Tuesday, February 28, 2017

Donuts for everyone...

Aloha,

Last weekend I was looking for visualizations that could be useful in TilesFX and I stumbled upon some charts called either doughnut, ring our donut charts. Nothing really special but not available in the standard JavaFX charts. So here is an example of what I'm talking about...



So we have a visualization of values in percentage so the sum of all values is always 100%. And the nice thing about using this donut like visualization is that we can use the inner part of the donut for additional information (e.g. like the value of the sum etc.).
Because on a dashboard you would really like to focus on the important parts (means you don't want to show a donut chart with 20 sections but maybe with 3 or 4) I can keep the whole thing really simple.
Because of the space constraints the legend will only appear if the width of the chart is larger than 1.2 x the height.
For the visualization I've decided to show the value inside of each segment, the percentage close to each segment on the inside of the ring and the sum of all values in the center of the donut chart. So the result looks like this...



Like in the last chart that I've added (the RadialChart) I've again made use of the JavaFX Canvas node which is perfect for graphics like this. Also animating this chart is really easy because of the good performance of the Canvas node.
The source of this little DonutChart can be found on github as always, so feel free to fork it :)
And like with the RadialChart I've decided to add the DonutChart as a separate skin to the TilesFX library. Means since release 1.3.6 of TilesFX you are able to make use of it.
Here are also some screenshots of the DonutChart in TilesFX...










I hope this will be useful for some of you, that's it for today...so keep coding... :)

Friday, February 24, 2017

A little MapTile update

Aloha,

After playing around with the MapTileSkin in the TilesFX project I thought it might make sense to add the ability to also visualize points of interest and a track...and so I've added those features :)
I've also added the ability to set the color of the current location marker and the color of the track (it's only one track supported at the moment).
To realize this behavior the Location class now also contains a color property.
For the colors I also decided to offer a defined set of colors which are the ones that you can find in Tile.TileColor

  • GRAY
  • RED
  • GREEN
  • BLUE
  • ORANGE
  • YELLOW_ORANGE
  • YELLOW
  • MAGENTA

These colors will be used wherever possible within TilesFX to create a homogene look over all tiles.
To give you an idea how this new stuff is looking, here are some screenshots...


Map provider: Hydda

Map provider: OpenStreetMap HOT

Map provider: OpenStreetMap BlackWhite

Map provider: World Imagery


On the screenshot above you can see the current location icon (the bigger blue one), the start icon (green one at the end of the magenta track), the stop icon (the red one at the end of the magenta track) and some poi icons (the yellow, the red and the magenta one).
For the example above I've simply exported a track recorded by my Garmin watch to GPX format and imported the GPX file, converted the track points to a list of Locations and pass it to the Tile...done :)
If you are interested in the code I've used to convert the GPX file to my Location objects you can find a little gist that I've created on github which shows how it works. You simply have to provide a gpx file with the name track.gpx and put it besides the java file.
Here is the link to the gist.

Another feature that I've added is the ability to change the zoom level of the MapTileSkin via the current location. Therefor I've added a zoomLevel property to the Location class and if you change it e.g. by calling

tile.getCurrentLocation().setZoomLevel(0)

the map tile will zoom out completely. The range of zoom levels is going from 0-17.
I hope this features might be useful to create for example a fitness dashboard etc.

At the moment I've not added a live tracking feature which would create a track on the fly every time the current location changes but this would be easy to add if it's needed.

As always feedback is more than welcome, so please don't hesitate to contact me and let me know about ideas/improvements/feature requests etc.

The above mentioned features are part of the current release of TilesFX which is 1.3.5 and which can be found here

The source code at Github

The binary at Bintray

The dependency at Maven Central (it's published but might take some time to show up)

That's it for today, so keep coding...

Saturday, February 18, 2017

A little Radial Chart for some weekend fun...

Aloha,

Before I went to Singapore last week I saw some interesting radial bar graphs on the web and thought this might be a fun control to have in JavaFX.
Because in Singapore was no time for coding I've decided to do that later...which means today :)
So first let me show you what I'm talking about, the following picture should give you an idea...



I like that idea to wrap a bar graph in a circle to save some space and so I've created that control in JavaFX which now looks like follows:


If you will take a look at the control you will figure out that it's not perfect but it should be a starting point for you :)
Because it tooks me only 1.5h to create that control I thought it might also be nice to have it as a skin in TilesFX and so I've also created a RadialChartTileSkin which looks as follows...


So this was a quite productive morning so far :)
The new skin for TilesFX can be found in the current release of TilesFX which is 1.3.4 and the RadialChart control is on github as usual.

Sourcecode

So enjoy your weekend and keep coding...

Saturday, February 11, 2017

TilesFX with new sizing strategy

Aloha,
In principle I was fine with TilesFX except one minor thing...the fact that I missed to make the tiles stretch in x- and y-direction. Means nearly all tiles have been in a square format which lead to gaps in dashboard.
After someone created an issue related to the size of the demo that comes with TilesFX I've decided to rethink the sizing strategy of the tiles.
To make it more clear I've created a little video that shows the sizing behaviour of the former version 1.3.1 and the new released version 1.3.2.



As example I've used my little dashboard that I usually run in a browser via JPro on all possible devices.
So I hope the new sizing strategy will work out for those of you that use TilesFX and if you find any problems or if you have any ideas...please let me know :)

UPDATE...
Well yesterday evening I had the idea to add a map tile to TilesFX and what should I say...I've implemented it this morning. So in the latest release (1.3.3) of TilesFX you will now also find a MapTileSkin which uses a WebView and leaflet to show a map. Here is a little screenshot of the new skin...


At the moment it only shows the current location which I've added as a property to the Tile class. If you change the location the tile will update the map view. I'm also planning to add points of interest and other features to it.

So enjoy your weekend and keep coding...