Creating Gauge Visualizations with TeeChart Pro VCL / FMX in your Applications

Gauges are increasingly used in our applications. Their capability to show different data sets, whether static or moving over time, makes gauges a valuable chart for dashboards or any other application which visually represents data.

 

First impressions count, and it’s important to understand data at a quick glance. For this reason dashboards are on the up and becoming increasingly more prevalent in modern data applications, hence we are seeing the many different types of gauges playing a vital role in dashboard design.

 

In this blog article, we’re going to look at the possibilities that TeeChart VCL/FMX offer us to simplify and speed up the creation of this type of data visualisation.

 

TeeChart Pro for VCL and FireMonkey include numerous professional chart styles, amongst which we find a wide range of gauges. It’s easy to start adding gauges to your Apps with the TeeChart components library. We can create the panel or dashboard we are referring to without the need to write a single line of code, and what’s more we can do so for all platforms supported by Embarcadero, making it an important cross-platform tool.

 

Note that all the functionality contained in the TeeChart Pro library of components is cross-platform compatible.

 

To begin with, let’s take a look at all the gauge types available with TeeChart Pro:

image1

 

If we create a new application, display its form and add a TeeChart Chart to it from the component library, we can then double-click on the Chart to open the Chart Editor. From here we can add Series to the Chart and personalise them to our taste, all at designtime. To add a new Gauge Series we select ‘Add’ from the ‘Series’ section and go to the Gauges tab in the gallery that has opened, as you can see in Image 1.

Types of Gauges:

Numeric Gauge Linear Gauge Vertical Gauge
     

 

Circular Gauge Knob Gauge Clock Gauge
 
 
 

Each Gauge type has its own characteristics and functionality.

In this example, we’re going to add as many charts as there are gauge types available and we’ll change the appearance of each one of them via each of their respective editors.

 

TeeChart allows us to personalise each Series from the Object Inspector (and in VCL also from its own Editor dialogue).

 

image2

 

We can download the demo from the Steema area on GitHub:

Using Gauges sample at GitHub

 

Using TeeChart we can always create any type of Gauge or Chart personalised to our requirements, that being because the TeeChart Canvas allows us to paint any object on it.

For example, if what we want is to create a type of Gauge of the style ‘Radial Gauge’ we can easily create it via a Donut Series. We’ll simply need to set a total angle (for example, 180º), position the Donut in the centre of the Chart via the 3D editor tab (using horizontal and vertical offset), adding an annotation tool in the centre for the dynamic percentage information.

 

Having done that, it’s only left for us to add values to the Series (for example 15 and 85). The result being:

Get more info and download the latest TeeChart Pro for VCL and FMX version at :

https://www.steema.com/product/vcl

 

RAD Studio 10.1 Berlin, add TeeChart to “FireUI Live Preview”

Studio 10.1 Berlin has just been released and includes the FireUI Live Preview tool to visualize forms at design-time in mobile devices and desktop (Windows / Mac OSX) machines.

Studio10_1_Berlin_TeeChart_FireUI_Live_Preview

The default application does not provide support for TeeChart control, but its very easy to add !

  • Open the LivePreview.dproj project in Studio 10.1 from:  c:\Program Files (x86)\Embarcadero\Studio\18.0\source\Tools\FireUIAppPreview
  • Edit the project’s Regs.pas unit to add the TeeChart related units (see code below)
  • Run the app (without debugging)
  • Create a new Firemonkey project, add a TChart control to see it at Live Preview (connect to your ide machine first)

There is only a minor caveat that should be easy to solve:

When adding series of data to TChart, they appear filled with random points at design-time.
However, Live Preview displays component contents without the “csDesigning” ComponentState property so the series appear empty.

Modifications to Regs.pas unit (displayed in bold font) :


unit Regs;

interface

uses
  System.Classes, FMX.Controls, FMX.ImgList,

  FMXTee.Constants,

  {$IF TeeMsg_TeeChartPalette='TeeChart'}
  {$DEFINE TEEPRO} 
  {$ENDIF}

  {$IFDEF TEEPRO}
  FMXTee.Editor.Pro,  // <-- if you have the Pro version of TeeChart
  {$ENDIF}

  FMXTee.Chart, FMXTee.Series;

implementation

initialization

  // Register here any component that is not previously registered by the framework

  RegisterClass(FMX.ImgList.TImageList);
  RegisterClass(FMX.Controls.TStyleBook);

  RegisterClass(FMXTee.Chart.TChart);
  RegisterTeeStandardSeries;

end.

Big files: XML or JSON ? TeeBI !!

TeeBI Dashboards

 

Introduction

XML and JSON are very typical text formats used to store data, designed to be more comfortable than plain old “csv” text and allowing hierarchical (parent -> child) relationships.

However, even if there are many wonderful standard libraries to process them, there is still a speed problem when loading big quantities of data (say, hundreds or thousands of megabytes).

Content has to be parsed and stored into memory structures representing the “tree” nature of data nodes and attributes, which can be very fast (milliseconds) for small files, but terribly slow (minutes !) for big ones.

TeeBI core base class (TDataItem) is an “agnostic” memory structure providing parent -> child connections, using simple arrays to store data (one array per field or column).

Pseudo-code:


TDataItem = class
Name : String;
Items : Array of TDataItem;   // <--- Children
Kind : TDataKind;  // <-- Integer, String, Float, DateTime, Boolean, or "List of TDataItem"
Data : Array of ...    //  <--  one array for each Kind: "Int32Data : Array of Int32"
end

 

With a TDataItem, loading and saving big quantities of data is insanely fast (0.2 seconds to load or save 1 million rows with 4 columns on a normal PC).

The arrays are saved / loaded to / from Streams directly in one Write / Read operation.

That means we can import data from XML or JSON (or any other format like database datasets, server connections, Excel, etc, etc) into a TDataItem and then save it to a binary TeeBI file for later reuse.


Data := TDataItemPersistence.Load( 'my data.bi ')

 

Once a TDataItem is created or loaded, we can use it in many ways:

  • Search and modify data, re-structure columns
  • Sort data by multiple fields, and by custom expressions
  • Run ultra-fast SQL-like queries and summaries against TDataItems
  • Set master -> detail relationships between different TDataItems
  • Filter rows by code or using expressions (as strings or as TExpression classes)
  • Create calculated columns (using code or expressions)
  • Merge several TDataItems
  • Compare the structure and / or full data of TDataItems to obtain difference sets
  • Present TDataItems using Grids, Charts, Dashboards and PDF output
  • Connect TDataItems to a super-fast TBIDataset (a normal memory TDataset class)
  • Export to any other format (for example XML to JSON and vice-versa)
  • Access remote TDataItems from web servers transparently
  • Apply machine-learning algorithms using R or Python Scikit-learn
  • Access basic statistics of any TDataItem or child item

 

Note to TeeChart developers:

TeeBI includes a new TBIChart control (derived from TChart) that is capable of automatically creating new chart series and fill them from any TDataItem.

BIChart1.Data := MyDataItem;

A planned new feature is to integrate the Data property editor dialog inside the normal TeeChart editor, for design-time support (zero code charting !)

 

TeeBI library is available for download at the following link:

https://github.com/Steema/BI

Supported development environments:

  • Embarcadero Studio (Delphi, C++) from XE4 version and up
  • Lazarus FreePascal
  • …and soon for Microsoft Visual Studio .NET

Several 3rd party products can be optionally used with TeeBI:

https://github.com/Steema/BI/wiki/3rd-party-supported-products

 

For more information:

Please visit the TeeBI community at Google+ and the TeeBI home website for more information and technical details.

 

 

What’s New in TeeChart VCL/FMX v2015.16

Build 2015.16.150901

Release September 2015

This technical document describes all changes made to TeeChart component library (FireMonkey and VCL versions) since the release of April 2015.

 

New Supported IDEs

  • Embarcadero RAD Studio 10 Seattle.
    Full support for Delphi and C++ Builder 10 Seattle for all platform projects.

 

‘Detail’ property

Series ‘master-detail’ functionality, with a new ‘Detail’ property and ‘Add’ method overload in the Series class to enable the ‘drill-down’ of Series data.
Example demo available at http://www.teechart.net/files/public/support/SeriesDetailSample.zip

 

TChartLayout component

TChartLayout component, a scrollable panel which will automatically arrange multiple charts into a viewable state.

 

GDI+ canvas Scale property

Creates smoother looking charts. Default value is 1 and can be changed at design and runtime through the Chart editor 3D render dialog.

 

Third legend column support

Support for a third legend column accompanied by a new TextStyle value:
ltsXAndValueAndText.
This shows each point X, Y, and Text label at legend.

 

New Firemonkey dashboard project showcasing TeeChart standard series types

Full sources also available at GitHub:
https://github.com/Steema/TeeChart-for-FireMonkey-applications-samples/tree/master/StandardSeriesDemo

TeeBI Web Server returning a summary chart

TeeBI teaser

Small teaser of TeeBI.

This is the custom web server calculating a query and returning a chart. The only dependencies are TeeChart and Indy http web server component.

TeeBI Web Server returning a summary chart

 

Data is in column-oriented, memory-based custom format for speed reasons, no database or FireDac, etc are necessary. Data is imported from many sources (excel, text files, firedac or any other datasets, etc) to the custom format, which is then transparent to the user apps.

The web server is optional if data is not remote, and it can also return binary streams to normal desktop (vcl or fmx), or mobile apps (fmx).

A table of 2000×5 cells takes 180msec via web. For visual display, an fmx or vcl dbgrid easily handles 1 or more million rows with a custom “TBIDataset” linked to an in-memory data, allowing grouping, filtering and sorting using complex expressions involving columns from the same table or foreign-key(s) fields.

This speed is the basis for a next-coming set of machine-learning and data-mining algorithms, currently under development.

 

Delphi Gestures with TeeChart

Since Embarcadero introduced touch screen support, the way gestures are being handled has evolved. Now that we are in the RAD Studio XE8 days, it has become pretty straightforward as documented in their “Gesturing Overview” article.

DelphiGestures

That article lays out the foundation on how to work with touch gestures and controls. Applying that to TeeChart, means we’ll need TChart and TGestureManager components. TGestureManager, which manages all the gestures that can be used by the control, will have to be associated to TChart’s Touch property. There you can choose which gestures will be associated with the control. There are three kinds of gestures: standard, custom and interactive. The example discussed is based on Delphi’s interactive gestures example.

Here you can download the full project used for the article. Now I’ll explain how to create it. Before starting to write code, please do the following at design-time: add a TChart component, add a TGestureManger component, passing the gesture manager to TChart‘s Touch property and enable Zoom, Pan and DoubleTap interactive gestures on it.

Once this is done, it’s time to start typing code. First of all we’ll deactivate some TeeChart standard interactions so they don’t interfere with the functionality gestures will implement. So we will disable default zoom and panning in form’s OnCreate event:

procedure TForm1.FormCreate(Sender: TObject);
var
  Series1: TSurfaceSeries;
begin
  Series1 := TSurfaceSeries.Create(Self);
  Series1.FillSampleValues(10);
  Series1.UseColorRange := False;
  Series1.UsePalette := True;
  Series1.PaletteStyle := psStrong;

  Chart1.AddSeries(Series1);
  Chart1.Zoom.Allow := False;
  Chart1.Panning.Active := False;
  Chart1.Chart3DPercent := 50;

  with TFlatTheme.Create(Chart1) do
  try
    Apply;
  finally
    Free;
  end;
end;

After that, it’s the turn of TChart‘s OnGesture event implementation:

procedure TForm1.Chart1Gesture(Sender: TObject;
  const EventInfo: TGestureEventInfo; var Handled: Boolean);
begin
  if EventInfo.GestureID = igiZoom then
    handleZoom(EventInfo)
  else if EventInfo.GestureID = igiPan then
    handlePan(EventInfo)
  else if EventInfo.GestureID = igiDoubleTap then
    handleDoubleTap(EventInfo);

  Handled := True;
end;

We are checking for TInteractiveGestures gestures performed on the chart, using event’s TGestureEventInfo, and implement a specific gesture handler method for each one. Finally, we set the Handled parameter to True so that the event is not propagated further.

Let’s speak about gesture handler methods now, starting with zoom:

procedure TForm1.handleZoom(EventInfo: TGestureEventInfo);
var
  LObj: IControl;
  chart: TChart;
  zoom: Double;
begin
  LObj := Self.ObjectAtPoint(ClientToScreen(EventInfo.Location));
  if LObj is TChart then
  begin
    if not(TInteractiveGestureFlag.gfBegin in EventInfo.Flags) then
    begin
      chart := TChart(LObj.GetObject);
      zoom := (EventInfo.Distance / FLastDIstance) * chart.Aspect.ZoomFloat;
      chart.Aspect.ZoomFloat := Max(10, zoom);
    end;
  end;
  FLastDIstance := EventInfo.Distance;
end;

Here we are implementing something different and simpler than the standard zoom in TeeChart. It’s based on the difference between the current distance and pinch that the gesture provides and the distance saved from previous calls, not allowing a zoom factor smaller than 10% of the original size.

Let’s continue with the pan gesture which, in this example, will be used for rotating the chart instead of panning it:

procedure TForm1.handlePan(eventInfo: TGestureEventInfo);
var
  LObj: IControl;
  chart: TChart;
begin
  LObj := Self.ObjectAtPoint(ClientToScreen(EventInfo.Location));
  if LObj is TChart then
  begin
    if not(TInteractiveGestureFlag.gfBegin in EventInfo.Flags) then
    begin
      chart := TChart(LObj.GetObject);

      chart.Aspect.Orthogonal := False;
      chart.Aspect.RotationFloat := chart.Aspect.RotationFloat + (EventInfo.Location.X - FLastPosition.X);
      chart.Aspect.ElevationFloat := chart.Aspect.ElevationFloat - (EventInfo.Location.Y - FLastPosition.Y);
    end;

    FLastPosition := EventInfo.Location;
  end;
end;

Similar to the pinch zoom gesture, here displacement (calculated from the screen position) is being used to rotate and elevate the chart.

Finally, the double tap gesture:

procedure TForm1.handleDoubleTap(eventInfo: TGestureEventInfo);
var
  LObj: IControl;
begin
  LObj := Self.ObjectAtPoint(ClientToScreen(EventInfo.Location));
  if LObj is TChart then
    ResetChart(TChart(LObj.GetObject));
end;

procedure TForm1.ResetChart(chart: TChart);
begin
  chart.Aspect.Orthogonal := True;
  chart.Aspect.ZoomFloat:=100;
  chart.Aspect.ElevationFloat:=345;
  chart.Aspect.RotationFloat:=345;
end;

It’s only used for resetting chart properties to their original values.

I hope this example is useful to illustrate the possibilities TeeChart has with multi-touch gesture on touch devices. It only covers a few cases but this opens up the possibility to a new world of charting interactions.

Here’s the complete code listing for the example discussed in this article:

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  FMX.Controls.Presentation, FMX.StdCtrls, FMXTee.Engine, FMXTee.Procs,
  FMXTee.Chart, FMXTee.Series, FMXTee.Commander, FMX.Gestures,
  FMXTee.Series.Surface, FMXTee.Themes;

type
  TForm1 = class(TForm)
    Chart1: TChart;
    GestureManager1: TGestureManager;
    procedure FormCreate(Sender: TObject);
    procedure Chart1Gesture(Sender: TObject; const EventInfo: TGestureEventInfo;
      var Handled: Boolean);
  private
    { Private declarations }
    FLastPosition: TPointF;
    FLastDistance: Integer;
    procedure handleZoom(eventInfo: TGestureEventInfo);
    procedure handlePan(eventInfo: TGestureEventInfo);
    procedure handleDoubleTap(eventInfo: TGestureEventInfo);
    procedure ResetChart(chart: TChart);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

uses System.Math;

procedure TForm1.Chart1Gesture(Sender: TObject;
  const EventInfo: TGestureEventInfo; var Handled: Boolean);
begin
  if EventInfo.GestureID = igiZoom then
    handleZoom(EventInfo)
  else if EventInfo.GestureID = igiPan then
    handlePan(EventInfo)
  else if EventInfo.GestureID = igiDoubleTap then
    handleDoubleTap(EventInfo);

  Handled := True;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Series1: TSurfaceSeries;
begin
  Series1 := TSurfaceSeries.Create(Self);
  Series1.FillSampleValues(10);
  Series1.UseColorRange := False;
  Series1.UsePalette := True;
  Series1.PaletteStyle := psStrong;

  Chart1.AddSeries(Series1);
  Chart1.Zoom.Allow := False;
  Chart1.Panning.Active := False;
  Chart1.Chart3DPercent := 50;

  with TFlatTheme.Create(Chart1) do
  try
    Apply;
  finally
    Free;
  end;
end;

procedure TForm1.handleDoubleTap(eventInfo: TGestureEventInfo);
var
  LObj: IControl;
begin
  LObj := Self.ObjectAtPoint(ClientToScreen(EventInfo.Location));
  if LObj is TChart then
    ResetChart(TChart(LObj.GetObject));
end;

procedure TForm1.handlePan(eventInfo: TGestureEventInfo);
var
  LObj: IControl;
  chart: TChart;
begin
  LObj := Self.ObjectAtPoint(ClientToScreen(EventInfo.Location));
  if LObj is TChart then
  begin
    if not(TInteractiveGestureFlag.gfBegin in EventInfo.Flags) then
    begin
      chart := TChart(LObj.GetObject);

      chart.Aspect.Orthogonal := False;
      chart.Aspect.RotationFloat := chart.Aspect.RotationFloat + (EventInfo.Location.X - FLastPosition.X);
      chart.Aspect.ElevationFloat := chart.Aspect.ElevationFloat - (EventInfo.Location.Y - FLastPosition.Y);
    end;

    FLastPosition := EventInfo.Location;
  end;
end;

procedure TForm1.handleZoom(EventInfo: TGestureEventInfo);
var
  LObj: IControl;
  chart: TChart;
  zoom: Double;
begin
  LObj := Self.ObjectAtPoint(ClientToScreen(EventInfo.Location));
  if LObj is TChart then
  begin
    if not(TInteractiveGestureFlag.gfBegin in EventInfo.Flags) then
    begin
      chart := TChart(LObj.GetObject);
      zoom := (EventInfo.Distance / FLastDIstance) * chart.Aspect.ZoomFloat;
      chart.Aspect.ZoomFloat := Max(10, zoom);
    end;
  end;
  FLastDIstance := EventInfo.Distance;
end;

procedure TForm1.ResetChart(chart: TChart);
begin
  chart.Aspect.Orthogonal := True;
  chart.Aspect.ZoomFloat:=100;
  chart.Aspect.ElevationFloat:=345;
  chart.Aspect.RotationFloat:=345;
end;

end.

Clustering visualization

TeeChart Pro includes classes and components to perform “clustering” on your data, and optionally visualize the results using a chart “Tool” component.

Clustering is the process of grouping data automatically, according to how well related are the individual items.

As an unsupervised algorithm, its widely used in data-mining / machine-learning / B.I. (Business Intelligence) applications.

 

teechart_clustering

For more information on clustering visit the following Wikipedia link: http://en.wikipedia.org/wiki/Cluster_analysis

An executable example:

http://www.steema.us/files/public/teechart/vcl/demos/clustering/TeeChart_Clustering.zip

The clustering algorithm can be processed on custom data, not necessarily on TeeChart “Series” data.

 

Classes and Units

The TeeClustering.pas unit, for both VCL and Firemonkey, contains abstract “engine” classes that perform the clustering algorithms.

Three different clustering methods are provided:

• TKMeansClustering

• THierarchicalClustering

• TQTClustering (Quality Threshold)

These classes derive from a common abstract class: TBaseClustering.

Each clustering method has its own properties that determine how will the clusters be calculated. After calculating, you can access the Clusters property, which is a TList of TCluster objects.

A TCluster contains child clusters (Items[ ]), so you can check which input data items belong to which cluster, or in the case of the Hierarchical type, access the tree structure (clusters and sub-clusters).

The input data (your data) is not contained by the above classes.

Data is passed to the clustering engine through a “provider” class. There is currently one kind of data provider (TSeriesProvider) to cluster XY or XYZ Series points.

This class is implemented in the TeeClusteringTool.pas unit, together with a charting Tool class (TClusteringTool) to make things easier and more automatic.

 

Basic Example

Example runtime code (it can be done at design-time too, without coding) :

uses TeeClusteringTool;

var tool : TClusteringTool;

tool:=TClusteringTool.Create(Self);

tool.ParentChart:=Chart1;

tool.Series:=Series1; // your series

tool.Method:=cmKMeans;

tool.KMeans.NumClusters:=5;

tool.Execute;

 

After execution, you can loop on the resulting output clusters, for example:

var t : Integer;

for t:=0 to tool.Clusters.Count-1 do
Memo1.Lines.Add( ‘Cluster: ‘+IntToStr(t)+’ contains:  ‘+
IntToStr(tool.Clusters[t].Count)+’ points’ );

 

 

TClusteringTool

This tool automatically performs clustering using the choosen method and parameters, and optionally paints each source series point with a different color indicating which cluster they belong to, and/or draws polygons around each group of cluster’s items, among other things.

Properties:

ClusteringTool1.Method := cmHierarchical;

ClusteringTool1.ColorEach := True; // paint Series with one color per cluster

ClusteringTool1.ShowBounds := True; // draws convex polygons bounding each cluster points

ClusteringTool1.Centers.Visible := True; // shows cluster centers

ClusteringTool1.Centroids.Visible := True; // shows cluster centroids

Other properties include Brush, Pen and Transparency, used when drawing cluster polygon boundaries.

Methods:

Several helper methods are provided:

// Obtain cluster’s center and centroid XY points in Series scales:

var P : TPointFloat;

P:=ClusteringTool1.GetClusterCenter( ClusteringTool1.Clusters[3] );

P:=ClusteringTool1.GetClusterCentroid( ClusteringTool1.Clusters[2] );

// Obtain an array of XY points (in screen pixel coordinates), that belong to cluster:

var PP : TPointArray;

ClusteringTool1.GetClusterPoints( ClusteringTool1.Clusters[4], PP);

PP:=nil;

// Get cluster statistics:

var S : TClusterStats;

S:=ClusteringTool1.GetStats( ClusteringTool1.Clusters[0] );

 

Calculation parameters

Each clustering algorithm needs different parameters:

K-Means:

ClusteringTool1.KMeans.NumClusters := 10; // Number of minimum clusters (“K”)

ClusteringTool1.KMeans.MaxIterations := 1000; // Maximum number of iterations before stopping

Hierarchical:

ClusteringTool1.Hierarchical.NumClusters := 8; // Number of tree root clusters

QT:

ClusteringTool1.QTClustering.MinCount := 30; // Minimum number of points to form a cluster

ClusteringTool1.QTClustering.MaxDiameter := 100; // Maximum “diameter” a cluster can grow

 

Common parameters:

Distance

Cluster calculation is based on the “distance” between a data item and the other data items. There are several ways to calculate the “distance” between items.

The algorithms are agnostic, they call the Provider (ie: Series provider) to obtain the distances.

For example, on a XY scatter plot, the distance between points can be for example the hypotenuse (Pythagoras’ theorem), that is, the simple Euclidean distance between a point XY and another XY.

Distance calculations implemented:

dmEuclidean
dmSquaredEuclidean
dmManhattan
dmMinkowski
dmSorensen
dmChebyshev

 

Example:

ClusteringTool1.Distance := dmMinkowski;

ClusteringTool1.MinkowskiLambda := 4;

 

Linkage

There are several ways to calculate the “distance” between clusters when one or the two clusters have more than one item.

This is called “linkage”.

The most simple way is using each cluster “center” (this means no linkage occurs).

Other linkage styles implemented:

lmSingle

Also called “minimum”.

The distance between cluster A and B is the minimum distance between all items in cluster A and all items in cluster B.

lmComplete

Also called “maximum”.

The distance between cluster A and B is the maximum distance between all items in cluster A and all items in cluster B.

lmAverage

The distance between cluster A and B is the average distance between all items in cluster A and all items in cluster B.

lmWard

The result is the increase on “error sum of squares” when adding cluster B items to cluster A.

 

Calculation speed

Clustering is a slow process by nature. Each clustering method has different performance bottlenecks, proportional to the number of input data items.

The TeeClustering.pas unit has been greatly fine-tuned to optimize the speed of each algorithm, although much work is needed to find more advanced techniques that require less CPU cycles.

The QT Threshold algorithm benefits of parallelism, when multiple CPUs can be used together.

Speed examples (revisited):

(Time in milliseconds, Windows 8.1 x64 on Intel i7 4770 @ 3.4Ghz)

IDE XE8 Delphi, Win32, 5000 data points

Algorithm      Single CPU   Multiple CPU

K-Means              47                     31
Hierarchical    4328                4156
QT                     2859                  703

Notes:

x64 bit executables are a little bit faster than 32bit.

Speed is also very dependant on the “distance” calculation method that is used to compare data.  The default Euclidean calculation has a quite big CPU cost as it calculates the Hypotenuse between two data XY value pairs.

 

 

Theme persistence

2015 brings some aesthetic improvements for TeeChart VCL/FMX and .NET versions with the intention to make it easier for our users to create visually appealing charts. In this article I’m going to speak about different aspects about new theme usage and possibilities in TeeChart VCL/FMX to accomplish that objective. The concept and the result is almost the same in TeeChart .NET. The only differences are mostly internal and hence transparent to the user. We’ve started by creating two new themes: Lookout and Andros, with their associated color palettes: Lookout and Seawash respectively. This is how those themes look when displaying the full color palette or single color series:
LookoutExample2
Lookout theme example with one single color series
LookoutExample
Lookout theme example showing all the colors in the so called Lookout palette
SeaWashExample
Andros theme example showing all the colors in the associated Seawash palette
AndrosExample
Andros theme example showing a series with one single color from the Seawash palette.
However, this is only the tip of the iceberg because new themes also come with more theme related internal functionality. That is, when a custom theme is applied to a chart, new objects (series, axes and tools) added to it will also inherit the aspect of those themed objects which already exist in the chart. This didn’t occur before. So, for example, if you add a new series to a chart with one of those themes, series in in the chart will perpetuate their settings to additional series added afterwards. An example can be seen in the chart below, an additional series to a chart with the Andros theme will set the series marks to be exactly in the same format without having to perform any custom setting by the user.
Andros2Series
All series in this chart share series marks custom settings without the need of any specific code.
In the VCL/FMX version this applies to series, tools and custom axes, for now. Going even further, users can add their own themes by exporting the charts they created to the TeeChart native template  format (.tee files). There’s just one thing they should bear in mind is that for series to be “themed” they should be of a special type in the custom theme file, TThemedSeries. For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  //Add themed series
  Chart1.AddSeries(TThemedSeries.Create(Self)).FillSampleValues;
  
  for i:=0 to Chart.SeriesCount-1 do
  begin
    Chart[i].Marks.Arrow.Visible:=False;
    Chart[i].Marks.Transparent:=True;
    Chart[i].Marks.Font.Color:=clWhite;
    Chart[i].Marks.Font.Name:='Verdana';
    Chart[i].Marks.Font.Size:=9;
  end;
 
  //Export theme
  SaveTeeToFile(Chart1, SourceFolder + 'TeeAndrosTheme.tee');
  //Add themed series
  Chart1.AddSeries(TThemedSeries.Create(Self)).FillSampleValues;
  
  for i:=0 to Chart.SeriesCount-1 do
  begin
    Chart[i].Marks.Arrow.Visible:=False;
    Chart[i].Marks.Transparent:=True;
    Chart[i].Marks.Font.Color:=clWhite;
    Chart[i].Marks.Font.Name:='Verdana';
    Chart[i].Marks.Font.Size:=9;
  end;

  //Export theme
  SaveTeeToFile(Chart1, SourceFolder + 'TeeAndrosTheme.tee');
Existing series in the chart can be switched to TThemedSeries using the self-explanatory ChangeSeriesType method. Once the custom custom .tee templates are ready, they can be applied using TThemeList.Apply method from TeeThemes unit, for example:
1
TThemesList.Apply( DestinationChart, 'MyChart.tee' );
TThemesList.Apply( DestinationChart, 'MyChart.tee' );
Worth noting that functionality described in this article is intended to be spread across all TeeChart versions in following releases throughout the year so stay tuned as new product updates start rolling out.  

Small tool to create icons and png images for iOS and Android Firemonkey applications

Yet another tool to create the *.png images required by Firemonkey iOS and Android application splash images.

Download source code  (65KB, for Embarcadero RAD Studio XE4 up to XE7)

(Main *.pas unit is aprox 200 lines of code, easy to modify to suit your needs)

Currently this tool generates 42 images of different sizes:

screenshot

Notes:

The sample project uses an FMX 3D form containing a sample “logo”. This can be replaced to use a normal image instead. Using a 3D form might produce better output quality as texts and graphics are regenerated from vector data every time for each icon dimension, instead of stretching a single “big” bitmap.

The *.ico file for Windows projects is created containing a single image.
You can use Gimp or IcoFX to create a multiple ico file using the generated *.png images.

See this great article about creating multi-icon *.ico files for Windows applications from Simon Stuart’s OTAPI.com:

http://otapi.com/2014/09/28/making-windows-icons-for-rad-studio-applications/

 

The *.icns file for Mac OSX applications is not created as it has several complex requeriments (a shell command line tool must be used in the Mac machine) explained here:

https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Optimizing/Optimizing.html#//apple_ref/doc/uid/TP40012302-CH7-SW3

 

Animated Bar Series Transitions (VCL and FMX)

A new feature in the next coming TeeChart Pro update is a new TeeAnimation class to perform animated transitions between the different Bar series stacking styles.

teechart_bar_series_transition_screenshot

Creating the animation:

var a : TSeriesTransition;

a:=TSeriesTransition.Create(Self);
a.Chart:=Chart1;

Optional animation settings:

a.Duration:=300; // milliseconds
a.TimingStyle:=atInOut;
a.Timing:=atCubic;

Playing the animation:

a.Before;
Series1.MultiBar:=mbStacked;
a.After;

Download:

Executable demos (VCL and Firemonkey) and source code.

Note: Demo sources require a new event in TCustomBarSeries class, to be provided in the next coming TeeChart Pro update (aprox Sep-2014).